From d577d991b97ae2b5ee1af23641bcffc3f83af5b2 Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 4 Nov 2009 11:56:41 -0800 Subject: Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux. --- cd/src/COPYRIGHT | 32 + cd/src/Makefile | 19 + cd/src/README | 11 + cd/src/cd.c | 739 ++++++ cd/src/cd.def | 384 +++ cd/src/cd.dep | 120 + cd/src/cd.rc | 19 + cd/src/cd_active.c | 1006 +++++++ cd/src/cd_attributes.c | 1017 ++++++++ cd/src/cd_bitmap.c | 293 +++ cd/src/cd_image.c | 441 ++++ cd/src/cd_primitives.c | 702 +++++ cd/src/cd_text.c | 810 ++++++ cd/src/cd_util.c | 351 +++ cd/src/cd_vectortext.c | 5189 +++++++++++++++++++++++++++++++++++++ cd/src/cdcontextplus.dep | 4 + cd/src/cdcontextplus.mak | 25 + cd/src/cdlua3.mak | 12 + cd/src/cdlua5.mak | 14 + cd/src/cdlua51.dep | 28 + cd/src/cdluacontextplus5.mak | 17 + cd/src/cdluacontextplus51.dep | 3 + cd/src/cdluaim5.mak | 16 + cd/src/cdluaim51.dep | 6 + cd/src/config.mak | 47 + cd/src/drv/cd0emf.c | 17 + cd/src/drv/cd0prn.c | 17 + cd/src/drv/cd0wmf.c | 16 + cd/src/drv/cdcgm.c | 1135 ++++++++ cd/src/drv/cddebug.c | 733 ++++++ cd/src/drv/cddgn.c | 1691 ++++++++++++ cd/src/drv/cddxf.c | 1188 +++++++++ cd/src/drv/cdirgb.c | 2051 +++++++++++++++ cd/src/drv/cdmf.c | 1192 +++++++++ cd/src/drv/cdpdf.c | 1491 +++++++++++ cd/src/drv/cdpicture.c | 1133 ++++++++ cd/src/drv/cdps.c | 1838 +++++++++++++ cd/src/drv/cgm.c | 2280 ++++++++++++++++ cd/src/drv/cgm.h | 156 ++ cd/src/gdiplus/cdcontextplus.def | 9 + cd/src/gdiplus/cdwclpp.cpp | 206 ++ cd/src/gdiplus/cdwdbufp.cpp | 164 ++ cd/src/gdiplus/cdwemfp.cpp | 105 + cd/src/gdiplus/cdwgdiplus.c | 42 + cd/src/gdiplus/cdwimgp.cpp | 65 + cd/src/gdiplus/cdwinp.cpp | 2338 +++++++++++++++++ cd/src/gdiplus/cdwinp.h | 112 + cd/src/gdiplus/cdwnativep.cpp | 138 + cd/src/gdiplus/cdwprnp.cpp | 158 ++ cd/src/intcgm/bparse.c | 1660 ++++++++++++ cd/src/intcgm/bparse.h | 117 + cd/src/intcgm/circle.c | 100 + cd/src/intcgm/circle.h | 3 + cd/src/intcgm/ellipse.c | 143 + cd/src/intcgm/ellipse.h | 3 + cd/src/intcgm/intcgm.h | 84 + cd/src/intcgm/intcgm1.c | 291 +++ cd/src/intcgm/intcgm2.c | 1651 ++++++++++++ cd/src/intcgm/intcgm2.h | 52 + cd/src/intcgm/intcgm4.c | 1265 +++++++++ cd/src/intcgm/intcgm4.h | 28 + cd/src/intcgm/intcgm6.c | 253 ++ cd/src/intcgm/intcgm6.h | 15 + cd/src/intcgm/list.c | 117 + cd/src/intcgm/list.h | 30 + cd/src/intcgm/sism.c | 392 +++ cd/src/intcgm/sism.h | 3 + cd/src/intcgm/tparse.c | 1370 ++++++++++ cd/src/intcgm/tparse.h | 101 + cd/src/intcgm/types.h | 225 ++ cd/src/lua3/cdlua.c | 4366 +++++++++++++++++++++++++++++++ cd/src/lua3/cdlua.def | 7 + cd/src/lua3/cdluactx.c | 950 +++++++ cd/src/lua3/cdluapdf.c | 43 + cd/src/lua3/cdluapdf.def | 2 + cd/src/lua3/cdvoid.c | 126 + cd/src/lua3/cdvoid.h | 17 + cd/src/lua3/toluacd.c | 585 +++++ cd/src/lua3/toluawd.c | 228 ++ cd/src/lua5/cdlua5.c | 1823 +++++++++++++ cd/src/lua5/cdlua5.def | 13 + cd/src/lua5/cdlua5_active.c | 2163 ++++++++++++++++ cd/src/lua5/cdlua5_canvas.c | 2405 +++++++++++++++++ cd/src/lua5/cdlua5ctx.c | 802 ++++++ cd/src/lua5/cdluacontextplus5.c | 44 + cd/src/lua5/cdluacontextplus5.def | 4 + cd/src/lua5/cdluaim5.c | 265 ++ cd/src/lua5/cdluaim5.def | 4 + cd/src/lua5/cdluapdf5.c | 53 + cd/src/lua5/cdluapdf5.def | 4 + cd/src/lua5/cdvoid5.c | 130 + cd/src/lua5/cdvoid5.h | 18 + cd/src/make_uname | 16 + cd/src/make_uname.bat | 57 + cd/src/rgb2map.c | 976 +++++++ cd/src/sim/cd_truetype.c | 177 ++ cd/src/sim/cd_truetype.h | 46 + cd/src/sim/cdfontex.c | 646 +++++ cd/src/sim/sim.c | 326 +++ cd/src/sim/sim.h | 55 + cd/src/sim/sim_linepolyfill.c | 1000 +++++++ cd/src/sim/sim_other.c | 411 +++ cd/src/sim/sim_primitives.c | 524 ++++ cd/src/sim/truetype.h | 46 + cd/src/tecmake_compact.mak | 1172 +++++++++ cd/src/wd.c | 473 ++++ cd/src/wdhdcpy.c | 101 + cd/src/win32/cdwclp.c | 552 ++++ cd/src/win32/cdwdbuf.c | 181 ++ cd/src/win32/cdwdib.c | 662 +++++ cd/src/win32/cdwemf.c | 117 + cd/src/win32/cdwimg.c | 83 + cd/src/win32/cdwin.c | 2368 +++++++++++++++++ cd/src/win32/cdwin.h | 181 ++ cd/src/win32/cdwnative.c | 209 ++ cd/src/win32/cdwprn.c | 184 ++ cd/src/win32/cdwwmf.c | 109 + cd/src/win32/wmf_emf.c | 2121 +++++++++++++++ cd/src/x11/cdx11.c | 2446 +++++++++++++++++ cd/src/x11/cdx11.h | 85 + cd/src/x11/cdxclp.c | 136 + cd/src/x11/cdxdbuf.c | 168 ++ cd/src/x11/cdximg.c | 52 + cd/src/x11/cdxnative.c | 165 ++ cd/src/x11/xvertex.c | 1431 ++++++++++ cd/src/x11/xvertex.h | 31 + cd/src/xrender/cdxrender.c | 1137 ++++++++ cd/src/xrender/cdxrplus.c | 26 + 128 files changed, 70005 insertions(+) create mode 100755 cd/src/COPYRIGHT create mode 100755 cd/src/Makefile create mode 100755 cd/src/README create mode 100755 cd/src/cd.c create mode 100755 cd/src/cd.def create mode 100644 cd/src/cd.dep create mode 100755 cd/src/cd.rc create mode 100755 cd/src/cd_active.c create mode 100755 cd/src/cd_attributes.c create mode 100755 cd/src/cd_bitmap.c create mode 100755 cd/src/cd_image.c create mode 100755 cd/src/cd_primitives.c create mode 100755 cd/src/cd_text.c create mode 100755 cd/src/cd_util.c create mode 100755 cd/src/cd_vectortext.c create mode 100644 cd/src/cdcontextplus.dep create mode 100755 cd/src/cdcontextplus.mak create mode 100755 cd/src/cdlua3.mak create mode 100755 cd/src/cdlua5.mak create mode 100644 cd/src/cdlua51.dep create mode 100755 cd/src/cdluacontextplus5.mak create mode 100644 cd/src/cdluacontextplus51.dep create mode 100755 cd/src/cdluaim5.mak create mode 100644 cd/src/cdluaim51.dep create mode 100755 cd/src/config.mak create mode 100755 cd/src/drv/cd0emf.c create mode 100755 cd/src/drv/cd0prn.c create mode 100755 cd/src/drv/cd0wmf.c create mode 100755 cd/src/drv/cdcgm.c create mode 100755 cd/src/drv/cddebug.c create mode 100755 cd/src/drv/cddgn.c create mode 100755 cd/src/drv/cddxf.c create mode 100755 cd/src/drv/cdirgb.c create mode 100755 cd/src/drv/cdmf.c create mode 100755 cd/src/drv/cdpdf.c create mode 100755 cd/src/drv/cdpicture.c create mode 100755 cd/src/drv/cdps.c create mode 100755 cd/src/drv/cgm.c create mode 100755 cd/src/drv/cgm.h create mode 100755 cd/src/gdiplus/cdcontextplus.def create mode 100755 cd/src/gdiplus/cdwclpp.cpp create mode 100755 cd/src/gdiplus/cdwdbufp.cpp create mode 100755 cd/src/gdiplus/cdwemfp.cpp create mode 100755 cd/src/gdiplus/cdwgdiplus.c create mode 100755 cd/src/gdiplus/cdwimgp.cpp create mode 100755 cd/src/gdiplus/cdwinp.cpp create mode 100755 cd/src/gdiplus/cdwinp.h create mode 100755 cd/src/gdiplus/cdwnativep.cpp create mode 100755 cd/src/gdiplus/cdwprnp.cpp create mode 100755 cd/src/intcgm/bparse.c create mode 100755 cd/src/intcgm/bparse.h create mode 100755 cd/src/intcgm/circle.c create mode 100755 cd/src/intcgm/circle.h create mode 100755 cd/src/intcgm/ellipse.c create mode 100755 cd/src/intcgm/ellipse.h create mode 100755 cd/src/intcgm/intcgm.h create mode 100755 cd/src/intcgm/intcgm1.c create mode 100755 cd/src/intcgm/intcgm2.c create mode 100755 cd/src/intcgm/intcgm2.h create mode 100755 cd/src/intcgm/intcgm4.c create mode 100755 cd/src/intcgm/intcgm4.h create mode 100755 cd/src/intcgm/intcgm6.c create mode 100755 cd/src/intcgm/intcgm6.h create mode 100755 cd/src/intcgm/list.c create mode 100755 cd/src/intcgm/list.h create mode 100755 cd/src/intcgm/sism.c create mode 100755 cd/src/intcgm/sism.h create mode 100755 cd/src/intcgm/tparse.c create mode 100755 cd/src/intcgm/tparse.h create mode 100755 cd/src/intcgm/types.h create mode 100755 cd/src/lua3/cdlua.c create mode 100755 cd/src/lua3/cdlua.def create mode 100755 cd/src/lua3/cdluactx.c create mode 100755 cd/src/lua3/cdluapdf.c create mode 100755 cd/src/lua3/cdluapdf.def create mode 100755 cd/src/lua3/cdvoid.c create mode 100755 cd/src/lua3/cdvoid.h create mode 100755 cd/src/lua3/toluacd.c create mode 100755 cd/src/lua3/toluawd.c create mode 100755 cd/src/lua5/cdlua5.c create mode 100755 cd/src/lua5/cdlua5.def create mode 100755 cd/src/lua5/cdlua5_active.c create mode 100755 cd/src/lua5/cdlua5_canvas.c create mode 100755 cd/src/lua5/cdlua5ctx.c create mode 100755 cd/src/lua5/cdluacontextplus5.c create mode 100755 cd/src/lua5/cdluacontextplus5.def create mode 100755 cd/src/lua5/cdluaim5.c create mode 100755 cd/src/lua5/cdluaim5.def create mode 100755 cd/src/lua5/cdluapdf5.c create mode 100755 cd/src/lua5/cdluapdf5.def create mode 100755 cd/src/lua5/cdvoid5.c create mode 100755 cd/src/lua5/cdvoid5.h create mode 100755 cd/src/make_uname create mode 100755 cd/src/make_uname.bat create mode 100755 cd/src/rgb2map.c create mode 100755 cd/src/sim/cd_truetype.c create mode 100755 cd/src/sim/cd_truetype.h create mode 100755 cd/src/sim/cdfontex.c create mode 100755 cd/src/sim/sim.c create mode 100755 cd/src/sim/sim.h create mode 100755 cd/src/sim/sim_linepolyfill.c create mode 100755 cd/src/sim/sim_other.c create mode 100755 cd/src/sim/sim_primitives.c create mode 100755 cd/src/sim/truetype.h create mode 100755 cd/src/tecmake_compact.mak create mode 100755 cd/src/wd.c create mode 100755 cd/src/wdhdcpy.c create mode 100755 cd/src/win32/cdwclp.c create mode 100755 cd/src/win32/cdwdbuf.c create mode 100755 cd/src/win32/cdwdib.c create mode 100755 cd/src/win32/cdwemf.c create mode 100755 cd/src/win32/cdwimg.c create mode 100755 cd/src/win32/cdwin.c create mode 100755 cd/src/win32/cdwin.h create mode 100755 cd/src/win32/cdwnative.c create mode 100755 cd/src/win32/cdwprn.c create mode 100755 cd/src/win32/cdwwmf.c create mode 100755 cd/src/win32/wmf_emf.c create mode 100755 cd/src/x11/cdx11.c create mode 100755 cd/src/x11/cdx11.h create mode 100755 cd/src/x11/cdxclp.c create mode 100755 cd/src/x11/cdxdbuf.c create mode 100755 cd/src/x11/cdximg.c create mode 100755 cd/src/x11/cdxnative.c create mode 100755 cd/src/x11/xvertex.c create mode 100755 cd/src/x11/xvertex.h create mode 100755 cd/src/xrender/cdxrender.c create mode 100755 cd/src/xrender/cdxrplus.c (limited to 'cd/src') diff --git a/cd/src/COPYRIGHT b/cd/src/COPYRIGHT new file mode 100755 index 0000000..97eebba --- /dev/null +++ b/cd/src/COPYRIGHT @@ -0,0 +1,32 @@ +CD License +----------- + +CD is licensed under the terms of the MIT license reproduced below. +This means that CD is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +=============================================================================== + +Copyright (C) 1994-2009 Tecgraf, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/cd/src/Makefile b/cd/src/Makefile new file mode 100755 index 0000000..d12a1be --- /dev/null +++ b/cd/src/Makefile @@ -0,0 +1,19 @@ + +.PHONY: do_all cdcontextplus cdlua3 cdlua5 cdluacontextplus5 cdluaim5 +#do_all: cd_freetype cd cd_pdflib cdpdf cdcontextplus cdlua3 cdluapdf3 cdlua5 cdluapdf5 cdluacontextplus5 cdluaim5 +do_all: cd cdcontextplus cdlua5 cdluacontextplus5 cdluaim5 + +cd: + @$(MAKE) --no-print-directory -f tecmake_compact.mak +cdcontextplus: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdcontextplus +cdlua3: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdlua3 +cdlua5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdlua5 +cdluapdf5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluapdf5 +cdluacontextplus5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluacontextplus5 +cdluaim5: + @$(MAKE) --no-print-directory -f tecmake_compact.mak MF=cdluaim5 diff --git a/cd/src/README b/cd/src/README new file mode 100755 index 0000000..1eae080 --- /dev/null +++ b/cd/src/README @@ -0,0 +1,11 @@ +README for CD + + CD (Canvas Draw) is a platform-independent graphics library. It is implemented in several platforms using native graphics libraries: Microsoft Windows (GDI) and X-Windows (XLIB). + The library contains functions to support both vector and image applications, and the visualization surface can be either a window or a more abstract surface, such as Image, Clipboard, Metafile, PS, and so on. + + Build instructions and usage are available in the CD documentation. + + For complete information, visit CD's web site at http://www.tecgraf.puc-rio.br/cd + or access its documentation in the HTML folder. + +(end of README) diff --git a/cd/src/cd.c b/cd/src/cd.c new file mode 100755 index 0000000..c2045a8 --- /dev/null +++ b/cd/src/cd.c @@ -0,0 +1,739 @@ +/** \file + * \brief External API + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include + + +#include "cd.h" +#include "wd.h" +#include "cd_private.h" +#include "cdirgb.h" + +/* This appears only here to avoid changing the cd.h header fo bug fixes */ +#define CD_VERSION_FIX ".1" +#define CD_VERSION_FIX_NUMBER 1 + +const char cd_ident[] = + "$CD: " CD_VERSION CD_VERSION_FIX " " CD_COPYRIGHT " $\n" + "$URL: www.tecgraf.puc-rio.br/cd $\n"; + +static char *tecver = "TECVERID.str:CD:LIB:" CD_VERSION CD_VERSION_FIX; + +char* cdVersion(void) +{ + (void)cd_ident; + (void)tecver; + return CD_VERSION CD_VERSION_FIX; +} + +char* cdVersionDate(void) +{ + return CD_VERSION_DATE; +} + +int cdVersionNumber(void) +{ + return CD_VERSION_NUMBER+CD_VERSION_FIX_NUMBER; +} + +static void cd_setdefaultfunc(cdCanvas* canvas) +{ + canvas->cxGetTextSize = cdgettextsizeEX; + canvas->cxGetFontDim = cdgetfontdimEX; + canvas->cxRect = cdrectSIM; +} + +static void cd_setdefaultattrib(cdCanvas* canvas) +{ + /* clipping attributes */ + canvas->clip_mode = CD_CLIPOFF; + + /* color attributes */ + canvas->foreground = CD_BLACK; + canvas->background = CD_WHITE; + + canvas->back_opacity = CD_TRANSPARENT; + canvas->write_mode = CD_REPLACE; + + /* primitive attributes */ + canvas->mark_type = CD_STAR; + canvas->mark_size = 10; + + canvas->line_width = 1; + canvas->line_style = CD_CONTINUOUS; + canvas->line_cap = CD_CAPFLAT; + canvas->line_join = CD_MITER; + + canvas->hatch_style = CD_HORIZONTAL; + canvas->interior_style = CD_SOLID; + canvas->fill_mode = CD_EVENODD; + + strcpy(canvas->font_type_face, "System"); + canvas->font_style = CD_PLAIN; + canvas->font_size = CD_STANDARD; + + canvas->text_alignment = CD_BASE_LEFT; + + canvas->matrix[0] = 1; /* identity */ + canvas->matrix[3] = 1; + + /* o resto recebeu zero no memset */ +} + +static void cd_updatedefaultattrib(cdCanvas* canvas) +{ + cdCanvasActivate(canvas); + + if (canvas->cxBackground) canvas->cxBackground(canvas->ctxcanvas, canvas->background); + if (canvas->cxForeground) canvas->cxForeground(canvas->ctxcanvas, canvas->foreground); + if (canvas->cxBackOpacity) canvas->cxBackOpacity(canvas->ctxcanvas, canvas->back_opacity); + if (canvas->cxWriteMode) canvas->cxWriteMode(canvas->ctxcanvas, canvas->write_mode); + if (canvas->cxLineStyle) canvas->cxLineStyle(canvas->ctxcanvas, canvas->line_style); + if (canvas->cxLineWidth) canvas->cxLineWidth(canvas->ctxcanvas, canvas->line_width); + if (canvas->cxLineCap) canvas->cxLineCap(canvas->ctxcanvas, canvas->line_cap); + if (canvas->cxLineJoin) canvas->cxLineJoin(canvas->ctxcanvas, canvas->line_join); + if (canvas->cxHatch) canvas->cxHatch(canvas->ctxcanvas, canvas->hatch_style); + if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(canvas->ctxcanvas, canvas->interior_style); + if (canvas->cxFont) canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + if (canvas->cxTextAlignment) canvas->cxTextAlignment(canvas->ctxcanvas, canvas->text_alignment); + if (canvas->cxTextOrientation) canvas->cxTextOrientation(canvas->ctxcanvas, canvas->text_orientation); +} + +cdCanvas* cdCreateCanvasf(cdContext *context, const char* format, ...) +{ + char data[1024]; + va_list arglist; + va_start(arglist, format); + vsprintf(data, format, arglist); + + return cdCreateCanvas(context, data); +} + +cdCanvas *cdCreateCanvas(cdContext* context, void *data_str) +{ + cdCanvas *canvas; + + /* usefull for NULL drivers, that do nothing and exist only for portability */ + if (!context) + return NULL; + + { + static int first = 1; + char* env = getenv("CD_QUIET"); + if (first && env && strcmp(env, "NO")==0) + { + printf("CD " CD_VERSION CD_VERSION_FIX " " CD_COPYRIGHT "\n"); + first = 0; + } + } + + /* alocates and initialize everything with 0s */ + canvas = (cdCanvas*)malloc(sizeof(cdCanvas)); + memset(canvas, 0, sizeof(cdCanvas)); + + canvas->signature[0] = 'C'; + canvas->signature[1] = 'D'; + + canvas->vector_font = cdCreateVectorFont(canvas); + canvas->simulation = cdCreateSimulation(canvas); + + canvas->context = context; + + /* initialize default attributes, must be before creating the canvas */ + cd_setdefaultattrib(canvas); + + context->cxCreateCanvas(canvas, data_str); + if (!canvas->ctxcanvas) + { + cdKillVectorFont(canvas->vector_font); + cdKillSimulation(canvas->simulation); + memset(canvas, 0, sizeof(cdCanvas)); + free(canvas); + return NULL; + } + + /* default simulation functions */ + cd_setdefaultfunc(canvas); + + /* initialize canvas table */ + context->cxInitTable(canvas); + + /* update the default atributes, must be after InitTable */ + cd_updatedefaultattrib(canvas); + + /* must be after creating the canvas, so that we know canvas width and height */ + canvas->clip_rect.xmax = canvas->w-1; + canvas->clip_rect.ymax = canvas->h-1; + + wdSetDefaults(canvas); + + return canvas; +} + +/* re-declared here to ignore CD_NO_OLD_INTERFACE definition */ +int cdActivate(cdCanvas* canvas); +cdCanvas* cdActiveCanvas(void); + +void cdKillCanvas(cdCanvas *canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas == cdActiveCanvas()) + cdActivate(NULL); + else + cdCanvasDeactivate(canvas); + + canvas->cxKillCanvas(canvas->ctxcanvas); + + if (canvas->pattern) free(canvas->pattern); + if (canvas->stipple) free(canvas->stipple); + if (canvas->poly) free(canvas->poly); + if (canvas->clip_poly) free(canvas->clip_poly); + if (canvas->fpoly) free(canvas->fpoly); + if (canvas->clip_fpoly) free(canvas->clip_fpoly); + if (canvas->line_dashes) free(canvas->line_dashes); + + cdKillVectorFont(canvas->vector_font); + cdKillSimulation(canvas->simulation); + + memset(canvas, 0, sizeof(cdCanvas)); + free(canvas); +} + +cdContext* cdCanvasGetContext(cdCanvas *canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + return canvas->context; +} + +int cdCanvasActivate(cdCanvas *canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (!canvas->cxActivate) return CD_OK; + + if (canvas->cxActivate(canvas->ctxcanvas) == CD_ERROR) + return CD_ERROR; + + return CD_OK; +} + +void cdCanvasDeactivate(cdCanvas *canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxDeactivate) return; + canvas->cxDeactivate(canvas->ctxcanvas); +} + +unsigned long cdContextCaps(cdContext *context) +{ + if (!context) + return (unsigned long)CD_ERROR; + return context->caps; +} + +int cdCanvasSimulate(cdCanvas* canvas, int mode) +{ + int sim_mode; + cdContext* context; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + context = canvas->context; + + sim_mode = canvas->sim_mode; + if (mode == CD_QUERY || cdCanvasGetContext(canvas) == CD_IMAGERGB) + return sim_mode; + + /* default simulation functions */ + cd_setdefaultfunc(canvas); + + /* initialize canvas table */ + context->cxInitTable(canvas); + + canvas->sim_mode = mode; + if (mode == CD_SIM_NONE) + return sim_mode; + + /* when simulation is active must not set driver transform */ + canvas->cxTransform = NULL; + + if (mode & CD_SIM_LINE) + { + canvas->cxLine = cdlineSIM; + canvas->cxFLine = NULL; + } + + if (mode & CD_SIM_RECT) + { + canvas->cxRect = cdrectSIM; + canvas->cxFRect = NULL; + } + + if (mode & CD_SIM_BOX) + { + canvas->cxBox = cdboxSIM; + canvas->cxFBox = NULL; + } + + if (mode & CD_SIM_ARC) + { + canvas->cxArc = cdarcSIM; + canvas->cxFArc = NULL; + } + + if (mode & CD_SIM_SECTOR) + { + canvas->cxSector = cdsectorSIM; + canvas->cxFSector = NULL; + } + + if (mode & CD_SIM_CHORD) + { + canvas->cxChord = cdchordSIM; + canvas->cxFChord = NULL; + } + + canvas->cxFont(canvas->ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + + if (mode & CD_SIM_POLYLINE || mode & CD_SIM_POLYGON) + canvas->cxFPoly = NULL; + + return sim_mode; +} + +cdState* cdCanvasSaveState(cdCanvas* canvas) +{ + cdState* state; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + state = (cdState*)malloc(sizeof(cdState)); + memcpy(state, canvas, sizeof(cdCanvas)); + + if (state->pattern) + { + int size = state->pattern_w*state->pattern_h*sizeof(long); + state->pattern = (long*)malloc(size); + memcpy(state->pattern, canvas->pattern, size); + } + + if (state->stipple) + { + int size = state->stipple_w*state->stipple_h; + state->stipple = (unsigned char*)malloc(size); + memcpy(state->stipple, canvas->stipple, size); + } + + if (state->clip_poly) + { + int size = state->clip_poly_n*sizeof(cdPoint); + state->clip_poly = (cdPoint*)malloc(size); + memcpy(state->clip_poly, canvas->clip_poly, size); + } + + if (state->clip_fpoly) + { + int size = state->clip_poly_n*sizeof(cdfPoint); + state->clip_fpoly = (cdfPoint*)malloc(size); + memcpy(state->clip_fpoly, canvas->clip_fpoly, size); + } + + if (state->line_dashes) + { + int size = state->line_dashes_count*sizeof(int); + state->line_dashes = (int*)malloc(size); + memcpy(state->line_dashes, canvas->line_dashes, size); + } + + return state; +} + +void cdReleaseState(cdState* state) +{ + assert(state); + if (!state) return; + + if (state->stipple) + free(state->stipple); + + if (state->pattern) + free(state->pattern); + + if (state->clip_poly) + free(state->clip_poly); + + if (state->clip_fpoly) + free(state->clip_fpoly); + + if (state->line_dashes) + free(state->line_dashes); + + free(state); + free(state); +} + +void cdCanvasRestoreState(cdCanvas* canvas, cdState* state) +{ + assert(canvas); + assert(state); + if (!state || !_cdCheckCanvas(canvas)) return; + + /* clippling must be done in low level because origin and invert y axis */ + canvas->clip_poly_n = state->clip_poly_n; + + if (canvas->clip_poly) + { + free(canvas->clip_poly); + canvas->clip_poly = NULL; + } + + if (canvas->clip_fpoly) + { + free(canvas->clip_fpoly); + canvas->clip_fpoly = NULL; + } + + if (state->clip_poly) + { + int size = state->clip_poly_n*sizeof(cdPoint); + canvas->clip_poly = (cdPoint*)malloc(size); + memcpy(canvas->clip_poly, state->clip_poly, size); + } + + if (state->clip_fpoly) + { + int size = state->clip_poly_n*sizeof(cdfPoint); + canvas->clip_fpoly = (cdfPoint*)malloc(size); + memcpy(canvas->clip_fpoly, state->clip_fpoly, size); + } + + cdCanvasClip(canvas, CD_CLIPOFF); + if (canvas->clip_fpoly) + canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, state->clip_fpoly, state->clip_poly_n); + else if (canvas->clip_poly) + canvas->cxPoly(canvas->ctxcanvas, CD_CLIP, state->clip_poly, state->clip_poly_n); + cdCanvasClipArea(canvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax); + if (canvas->cxFClipArea) + canvas->cxFClipArea(canvas->ctxcanvas, state->clip_frect.xmin, state->clip_frect.xmax, state->clip_frect.ymin, state->clip_frect.ymax); + else if (canvas->cxClipArea) + canvas->cxClipArea(canvas->ctxcanvas, state->clip_rect.xmin, state->clip_rect.xmax, state->clip_rect.ymin, state->clip_rect.ymax); + cdCanvasClip(canvas, state->clip_mode); + + /* regular attributes */ + cdCanvasSetBackground(canvas, state->background); + cdCanvasSetForeground(canvas, state->foreground); + cdCanvasBackOpacity(canvas, state->back_opacity); + cdCanvasWriteMode(canvas, state->write_mode); + cdCanvasLineStyle(canvas, state->line_style); + cdCanvasLineWidth(canvas, state->line_width); + cdCanvasLineCap(canvas, state->line_cap); + cdCanvasLineJoin(canvas, state->line_join); + cdCanvasFillMode(canvas, state->fill_mode); + cdCanvasLineStyleDashes(canvas, state->line_dashes, state->line_dashes_count); + cdCanvasHatch(canvas, state->hatch_style); + if (state->stipple) cdCanvasStipple(canvas, state->stipple_w, state->stipple_h, state->stipple); + if (state->pattern) cdCanvasPattern(canvas, state->pattern_w, state->pattern_h, state->pattern); + cdCanvasInteriorStyle(canvas, state->interior_style); + if (state->native_font[0]) + cdCanvasNativeFont(canvas, state->native_font); + else + cdCanvasFont(canvas, state->font_type_face, state->font_style, state->font_size); + cdCanvasTextAlignment(canvas, state->text_alignment); + cdCanvasTextOrientation(canvas, state->text_orientation); + cdCanvasMarkType(canvas, state->mark_type); + cdCanvasMarkSize(canvas, state->mark_size); + cdCanvasOrigin(canvas, state->origin.x, state->origin.y); + if (state->use_matrix) + cdCanvasTransform(canvas, state->matrix); + wdCanvasWindow(canvas, state->window.xmin, state->window.xmax, state->window.ymin, state->window.ymax); + wdCanvasViewport(canvas, state->viewport.xmin, state->viewport.xmax, state->viewport.ymin, state->viewport.ymax); + cdCanvasSimulate(canvas, state->sim_mode); + + /* complex clipping regions are not saved */ + /* driver internal attributes are not saved */ +} + +static cdAttribute* cd_findattrib(cdCanvas *canvas, const char* name, int *a) +{ + int i; + + for (i=0; i < canvas->attrib_n; i++) + { + if (strcmp(name, canvas->attrib_list[i]->name) == 0) + { + if (a) *a = i; + return canvas->attrib_list[i]; + } + } + + return NULL; +} + +void cdRegisterAttribute(cdCanvas *canvas, cdAttribute* attrib) +{ + cdAttribute* old_attrib; + int a; + + assert(canvas); + assert(attrib); + if (!attrib || !_cdCheckCanvas(canvas)) return; + + old_attrib = cd_findattrib(canvas, attrib->name, &a); + + if (old_attrib) + canvas->attrib_list[a] = attrib; + else + { + canvas->attrib_list[canvas->attrib_n] = attrib; + canvas->attrib_n++; + } +} + +void cdCanvasSetAttribute(cdCanvas* canvas, const char* name, char *data) +{ + cdAttribute* attrib; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + attrib = cd_findattrib(canvas, name, NULL); + if (attrib && attrib->set) + attrib->set(canvas->ctxcanvas, data); +} + +void cdCanvasSetfAttribute(cdCanvas* canvas, const char* name, const char* format, ...) +{ + char data[1024]; + va_list arglist; + va_start(arglist, format); + vsprintf(data, format, arglist); + + cdCanvasSetAttribute(canvas, name, data); +} + +char* cdCanvasGetAttribute(cdCanvas* canvas, const char* name) +{ + cdAttribute* attrib; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + attrib = cd_findattrib(canvas, name, NULL); + if (attrib && attrib->get) + return attrib->get(canvas->ctxcanvas); + + return NULL; +} + +int cdCanvasPlay(cdCanvas* canvas, cdContext* context, int xmin, int xmax, int ymin, int ymax, void *data) +{ + assert(context); + assert(canvas); + if (!_cdCheckCanvas(canvas) || !context || !context->cxPlay) return CD_ERROR; + + /* the all can be 0 here, do not use cdCheckBoxSize */ + if (xmin > xmax) _cdSwapInt(xmin, xmax); + if (ymin > ymax) _cdSwapInt(ymin, ymax); + + return context->cxPlay(canvas, xmin, xmax, ymin, ymax, data); +} + +int cdContextRegisterCallback(cdContext *context, int cb, cdCallback func) +{ + assert(context); + if (!context || !context->cxRegisterCallback) return CD_ERROR; + return context->cxRegisterCallback(cb, func); +} + +void cdCanvasFlush(cdCanvas* canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxFlush) return; + canvas->cxFlush(canvas->ctxcanvas); +} + +void cdCanvasClear(cdCanvas* canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxClear) return; + canvas->cxClear(canvas->ctxcanvas); +} + +int cdCanvasUpdateYAxis(cdCanvas* canvas, int* y) +{ + assert(canvas); + assert(y); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + if(canvas->invert_yaxis) + { + *y = _cdInvertYAxis(canvas, *y); + + if (canvas->use_origin) + *y -= 2*canvas->origin.y; + } + + return *y; +} + +double cdfCanvasUpdateYAxis(cdCanvas* canvas, double* y) +{ + assert(canvas); + assert(y); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + if(canvas->invert_yaxis) + { + *y = _cdInvertYAxis(canvas, *y); + + if (canvas->use_origin) + *y -= 2*canvas->origin.y; + } + + return *y; +} + +int cdCanvasInvertYAxis(cdCanvas* canvas, int y) +{ + int yi; + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + yi = _cdInvertYAxis(canvas, y); + + if (canvas->use_origin) + yi -= 2*canvas->origin.y; + + return yi; +} + +double cdfCanvasInvertYAxis(cdCanvas* canvas, double y) +{ + double yi; + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + yi = _cdInvertYAxis(canvas, y); + + if (canvas->use_origin) + yi -= 2*canvas->origin.y; + + return yi; +} + +void cdCanvasGetSize(cdCanvas* canvas, int *width, int *height, double *width_mm, double *height_mm) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (width) *width = canvas->w; + if (height) *height = canvas->h; + if (width_mm) *width_mm = canvas->w_mm; + if (height_mm) *height_mm = canvas->h_mm; +} + +void cdCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, int *dx, int *dy) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (dx) *dx = cdRound(mm_dx*canvas->xres); + if (dy) *dy = cdRound(mm_dy*canvas->yres); +} + +void cdCanvasPixel2MM(cdCanvas* canvas, int dx, int dy, double *mm_dx, double *mm_dy) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (mm_dx) *mm_dx = ((double)dx)/canvas->xres; + if (mm_dy) *mm_dy = ((double)dy)/canvas->yres; +} + +void cdfCanvasMM2Pixel(cdCanvas* canvas, double mm_dx, double mm_dy, double *dx, double *dy) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (dx) *dx = mm_dx*canvas->xres; + if (dy) *dy = mm_dy*canvas->yres; +} + +void cdfCanvasPixel2MM(cdCanvas* canvas, double dx, double dy, double *mm_dx, double *mm_dy) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (mm_dx) *mm_dx = dx/canvas->xres; + if (mm_dy) *mm_dy = dy/canvas->yres; +} + +/***** Context Plus Functions ********/ + +static int use_context_plus = 0; +static cdContext* context_plus[NUM_CONTEXTPLUS] = {NULL, NULL, NULL, NULL, NULL, NULL}; + +int cdUseContextPlus(int use) +{ + if (use == CD_QUERY) + return use_context_plus; + + { + int old_use_context_plus = use_context_plus; + use_context_plus = use; + return old_use_context_plus; + } +} + +void cdInitContextPlusList(cdContext* ctx_list[]) +{ + int ctx; + for (ctx = 0; ctx < NUM_CONTEXTPLUS; ctx++) + if (ctx_list[ctx] != NULL) + context_plus[ctx] = ctx_list[ctx]; +} + +cdContext* cdGetContextPlus(int ctx) +{ + if (ctx < 0 || ctx >= NUM_CONTEXTPLUS) + return NULL; + + return context_plus[ctx]; +} + +/***** OLD Compatibility Functions ********/ + +int cdRegisterCallback(cdContext *context, int cb, cdCallback func) +{ + return cdContextRegisterCallback(context, cb, func); +} + +cdContext* cdGetContext(cdCanvas* canvas) +{ + return cdCanvasGetContext(canvas); +} + +int * cdGetClipPoly(int *n) +{ + if (n) *n = 0; + return NULL; +} + +double* wdGetClipPoly(int *n) +{ + if (n) *n = 0; + return NULL; +} diff --git a/cd/src/cd.def b/cd/src/cd.def new file mode 100755 index 0000000..dd2f7ed --- /dev/null +++ b/cd/src/cd.def @@ -0,0 +1,384 @@ +EXPORTS + cdContextWMF + cdContextCGM + cdContextClipboard + cdContextDGN + cdContextDXF + cdContextEMF + cdContextImage + cdContextImageRGB + cdContextPS + cdContextPrinter + cdContextNativeWindow + cdContextMetafile + cdContextDBuffer + cdContextDBufferRGB + cdContextPicture + cdContextDebug + + cdRedImage + cdGreenImage + cdBlueImage + cdAlphaImage + cdGetScreenColorPlanes + cdGetScreenSize + cdUseContextPlus + + cdinittableMF + cdkillcanvasMF + cdcreatecanvasMF + + cdVersion + cdVersionDate + cdVersionNumber + cdCreateCanvas + cdCreateCanvasf + cdKillCanvas + cdGetContext + cdContextCaps + cdActivate + cdActiveCanvas + cdSimulate + cdFlush + cdClear + cdSaveState + cdRestoreState + cdSetAttribute + cdSetfAttribute + cdGetAttribute + cdRegisterAttribute + cdReleaseState + + cdRegisterCallback + cdPlay + + cdGetCanvasSize + cdMM2Pixel + cdPixel2MM + cdOrigin + cdUpdateYAxis + cdCanvasTransform + + cdClip + cdClipArea + cdGetClipPoly + cdGetClipArea + + cdPixel + cdMark + cdLine + cdBegin + cdVertex + cdEnd + cdRect + cdBox + cdArc + cdSector + cdText + + cdBackground + cdForeground + cdBackOpacity + cdWriteMode + cdLineStyle + cdLineWidth + cdInteriorStyle + cdHatch + cdStipple + cdGetStipple + cdPattern + cdGetPattern + cdFont + cdGetFont + cdNativeFont + cdTextAlignment + cdTextOrientation + cdMarkType + cdMarkSize + + cdVectorFont + cdVectorTextDirection + cdVectorTextTransform + cdVectorTextSize + cdGetVectorTextSize + cdVectorCharSize + cdVectorText + cdMultiLineVectorText + cdGetVectorTextBounds + + cdFontDim + cdTextSize + cdTextBox + cdTextBounds + + cdGetColorPlanes + cdEncodeColor + cdDecodeColor + cdEncodeAlpha + cdDecodeAlpha + cdPalette + + cdGetImageRGB + cdPutImageRectRGB + cdPutImageRectRGBA + cdPutImageRectMap + cdRGB2Map + + cdCreateImage + cdGetImage + cdPutImageRect + cdKillImage + cdScrollArea + + cdCreateBitmap + cdInitBitmap + cdKillBitmap + cdBitmapGetData + cdBitmapSetRect + cdPutBitmap + cdGetBitmap + cdBitmapRGB2Map + + wdWindow + wdGetWindow + wdViewport + wdGetViewport + wdWorld2Canvas + wdCanvas2World + + wdClipArea + wdGetClipArea + wdGetClipPoly + + wdHardcopy + + wdPixel + wdMark + wdLine + wdVertex + wdRect + wdBox + wdArc + wdSector + wdText + + wdPutImageRect + wdPutImageRectRGB + wdPutImageRectRGBA + wdPutImageRectMap + wdPutBitmap + + wdLineWidth + wdFont + wdMarkSize + wdFontDim + wdTextSize + wdTextBox + wdTextBounds + wdStipple + wdPattern + wdGetFont + + wdVectorTextDirection + wdVectorTextSize + wdGetVectorTextSize + wdVectorCharSize + wdVectorText + wdMultiLineVectorText + wdGetVectorTextBounds + + cdwCreateCanvas + cdwInitTable + cdwKillCanvas + cdwRestoreDC + + cdLineStyleDashes + cdRegionBox + wdRegionBox + cdChord + cdOffsetRegion + cdPointInRegion + cdRegionCombineMode + cdLineJoin + cdLineCap + cdFillMode + wdChord + wdOffsetRegion + wdPointInRegion + cdGetFileName + wdWorld2CanvasSize + cdParsePangoFont + cdParseIupWinFont + cdParseXWinFont + cdGetFontSizePixels + cdGetFontSizePoints + cdStrEqualNoCase + + wdCanvasLineWidth + wdCanvasMarkSize + wdCanvasVectorCharSize + wdCanvasGetClipArea + wdCanvasIsPointInRegion + wdCanvasFont + wdCanvasArc + wdCanvasBox + wdCanvasCanvas2World + wdCanvasChord + wdCanvasClipArea + wdCanvasGetFont + wdCanvasGetFontDim + wdCanvasGetRegionBox + wdCanvasGetTextBounds + wdCanvasGetTextBox + wdCanvasGetTextSize + wdCanvasGetVectorTextBounds + wdCanvasGetVectorTextBox + wdCanvasGetVectorTextSize + wdCanvasGetViewport + wdCanvasGetWindow + wdCanvasHardcopy + wdCanvasLine + wdCanvasMark + wdCanvasMultiLineVectorText + wdCanvasOffsetRegion + wdCanvasPattern + wdCanvasPixel + wdCanvasPutBitmap + wdCanvasPutImageRect + wdCanvasPutImageRectMap + wdCanvasPutImageRectRGB + wdCanvasPutImageRectRGBA + wdCanvasRect + wdCanvasSector + wdCanvasStipple + wdCanvasText + wdCanvasVectorText + wdCanvasVectorTextDirection + wdCanvasVectorTextSize + wdCanvasVertex + wdCanvasViewport + wdCanvasWindow + wdCanvasWorld2Canvas + wdCanvasWorld2CanvasSize + + cdCanvasGetContext + cdCanvasCreateImage + cdCanvasSaveState + cdCanvasVectorFont + cdCanvasGetAttribute + cdCanvasNativeFont + cdCanvasTextOrientation + cdCanvasVectorTextTransform + cdCanvasActivate + cdCanvasSimulate + cdCanvasFillMode + cdCanvasMarkSize + cdCanvasMarkType + cdCanvasTextAlignment + cdCanvasFont + cdCanvasBackOpacity + cdCanvasClip + cdCanvasGetClipArea + cdCanvasGetColorPlanes + cdCanvasHatch + cdCanvasInteriorStyle + cdCanvasIsPointInRegion + cdCanvasLineCap + cdCanvasLineJoin + cdCanvasLineStyle + cdCanvasLineWidth + cdCanvasPlay + cdCanvasRegionCombineMode + cdCanvasVectorCharSize + cdCanvasVectorFontSize + cdCanvasGetVectorFontSize + cdCanvasWriteMode + cdCanvasUpdateYAxis + cdCanvasInvertYAxis + cdfCanvasUpdateYAxis + cdfCanvasInvertYAxis + cdContextRegisterCallback + cdCanvasBackground + cdCanvasForeground + cdCanvasGetPattern + cdCanvasGetStipple + cdCanvasDeactivate + cdCanvasClear + cdCanvasFlush + cdCanvasRestoreState + cdCanvasSetAttribute + cdCanvasSetfAttribute + cdCanvasGetFont + cdCanvasPattern + cdCanvasArc + cdCanvasBegin + cdCanvasBox + cdCanvasChord + cdCanvasClipArea + cdCanvasEnd + cdCanvasGetBitmap + cdCanvasGetFontDim + cdCanvasGetImage + cdCanvasGetImageRGB + cdCanvasGetOrigin + cdCanvasGetRegionBox + cdCanvasGetSize + cdCanvasGetTextBounds + cdCanvasGetTextBox + cdCanvasGetTextSize + cdCanvasGetVectorTextBounds + cdCanvasGetVectorTextBox + cdCanvasGetVectorTextSize + cdCanvasLine + cdCanvasLineStyleDashes + cdCanvasMark + cdCanvasMM2Pixel + cdCanvasMultiLineVectorText + cdCanvasOffsetRegion + cdCanvasOrigin + cdCanvasPalette + cdCanvasPixel + cdCanvasPixel2MM + cdCanvasPutBitmap + cdCanvasPutImageRect + cdCanvasPutImageRectMap + cdCanvasPutImageRectRGB + cdCanvasPutImageRectRGBA + cdCanvasRect + cdCanvasScrollArea + cdCanvasSector + cdCanvasStipple + cdCanvasText + cdCanvasVectorText + cdCanvasVectorTextDirection + cdCanvasVectorTextSize + cdCanvasVertex + + cdfCanvasGetClipArea + cdfCanvasArc + cdfCanvasBox + cdfCanvasChord + cdfCanvasClipArea + cdfCanvasGetOrigin + cdfCanvasLine + cdfCanvasMM2Pixel + cdfCanvasOrigin + cdfCanvasPixel2MM + cdfCanvasRect + cdfCanvasSector + cdfCanvasText + cdfCanvasVertex + cdCanvasGetTransform + cdCanvasTransformMultiply + cdCanvasTransformRotate + cdCanvasTransformScale + cdCanvasTransformTranslate + cdTextTranslatePoint + cdRotatePointY + cdCanvasSetForeground + cdCanvasSetBackground + cdCanvasTransformPoint + cdfCanvasTransformPoint + + cdInitContextPlusList + cdGetContextPlus diff --git a/cd/src/cd.dep b/cd/src/cd.dep new file mode 100644 index 0000000..e6c50ee --- /dev/null +++ b/cd/src/cd.dep @@ -0,0 +1,120 @@ +$(OBJDIR)/cd.o: cd.c ../include/cd.h ../include/wd.h ../include/cd_private.h \ + ../include/cdirgb.h +$(OBJDIR)/wd.o: wd.c ../include/cd.h ../include/wd.h ../include/cd_private.h +$(OBJDIR)/wdhdcpy.o: wdhdcpy.c ../include/cd.h ../include/wd.h +$(OBJDIR)/rgb2map.o: rgb2map.c ../include/cd.h +$(OBJDIR)/cd_vectortext.o: cd_vectortext.c ../include/cd.h ../include/wd.h \ + ../include/cd_private.h +$(OBJDIR)/cd_active.o: cd_active.c ../include/cd.h ../include/cd_old.h \ + ../include/wd.h ../include/wd_old.h +$(OBJDIR)/cd_attributes.o: cd_attributes.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/cd_bitmap.o: cd_bitmap.c ../include/cd.h ../include/cdirgb.h \ + ../include/cd_private.h +$(OBJDIR)/cd_image.o: cd_image.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/cd_primitives.o: cd_primitives.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/cd_text.o: cd_text.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/cd_util.o: cd_util.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/circle.o: intcgm/circle.c ../include/cd.h intcgm/list.h intcgm/types.h \ + intcgm/intcgm.h intcgm/intcgm6.h intcgm/circle.h +$(OBJDIR)/ellipse.o: intcgm/ellipse.c ../include/cd.h intcgm/list.h intcgm/types.h \ + intcgm/intcgm.h intcgm/intcgm6.h intcgm/ellipse.h +$(OBJDIR)/intcgm1.o: intcgm/intcgm1.c ../include/cd.h ../include/cdcgm.h \ + intcgm/list.h intcgm/types.h intcgm/intcgm2.h intcgm/intcgm.h \ + intcgm/bparse.h +$(OBJDIR)/intcgm2.o: intcgm/intcgm2.c ../include/cd.h ../include/cdcgm.h \ + intcgm/list.h intcgm/types.h intcgm/bparse.h intcgm/tparse.h \ + intcgm/intcgm.h intcgm/intcgm6.h +$(OBJDIR)/intcgm4.o: intcgm/intcgm4.c ../include/cd.h ../include/cdcgm.h \ + intcgm/list.h intcgm/types.h intcgm/intcgm.h intcgm/intcgm2.h \ + intcgm/intcgm4.h intcgm/intcgm6.h intcgm/ellipse.h intcgm/circle.h \ + intcgm/sism.h +$(OBJDIR)/intcgm6.o: intcgm/intcgm6.c ../include/cd.h intcgm/list.h intcgm/types.h \ + intcgm/intcgm.h intcgm/intcgm2.h intcgm/intcgm6.h +$(OBJDIR)/list.o: intcgm/list.c intcgm/list.h +$(OBJDIR)/sism.o: intcgm/sism.c ../include/cd.h intcgm/list.h intcgm/types.h \ + intcgm/intcgm.h intcgm/intcgm2.h intcgm/intcgm6.h +$(OBJDIR)/tparse.o: intcgm/tparse.c ../include/cd.h ../include/cdcgm.h \ + intcgm/list.h intcgm/types.h intcgm/bparse.h intcgm/intcgm.h \ + intcgm/intcgm2.h intcgm/intcgm4.h intcgm/intcgm6.h +$(OBJDIR)/bparse.o: intcgm/bparse.c ../include/cd.h ../include/cdcgm.h \ + intcgm/list.h intcgm/types.h intcgm/bparse.h intcgm/intcgm.h \ + intcgm/intcgm2.h intcgm/intcgm4.h intcgm/intcgm6.h +$(OBJDIR)/cddgn.o: drv/cddgn.c ../include/cd.h ../include/cd_private.h \ + ../include/cddgn.h +$(OBJDIR)/cdcgm.o: drv/cdcgm.c ../include/cd.h ../include/cd_private.h \ + ../include/cdcgm.h drv/cgm.h +$(OBJDIR)/cgm.o: drv/cgm.c drv/cgm.h +$(OBJDIR)/cddxf.o: drv/cddxf.c ../include/cd.h ../include/cd_private.h \ + ../include/cddxf.h +$(OBJDIR)/cdirgb.o: drv/cdirgb.c ../include/cd.h ../include/cd_private.h sim/sim.h \ + ../include/cdirgb.h +$(OBJDIR)/cdmf.o: drv/cdmf.c ../include/cd.h ../include/wd.h \ + ../include/cd_private.h ../include/cdmf.h ../include/cdmf_private.h +$(OBJDIR)/cdps.o: drv/cdps.c ../include/cd.h ../include/cd_private.h \ + ../include/cdps.h +$(OBJDIR)/cdpicture.o: drv/cdpicture.c ../include/cd.h ../include/cd_private.h \ + ../include/cdpicture.h +$(OBJDIR)/cddebug.o: drv/cddebug.c ../include/cd.h ../include/wd.h \ + ../include/cd_private.h ../include/cddebug.h +$(OBJDIR)/cdfontex.o: sim/cdfontex.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/sim.o: sim/sim.c ../include/cd.h ../include/cd_private.h \ + sim/cd_truetype.h /usr/include/freetype2/freetype/freetype.h \ + /usr/include/freetype2/freetype/config/ftconfig.h \ + /usr/include/freetype2/freetype/config/ftoption.h \ + /usr/include/freetype2/freetype/config/ftstdlib.h \ + /usr/include/freetype2/freetype/fterrors.h \ + /usr/include/freetype2/freetype/ftmoderr.h \ + /usr/include/freetype2/freetype/fterrdef.h \ + /usr/include/freetype2/freetype/fttypes.h \ + /usr/include/freetype2/freetype/ftsystem.h \ + /usr/include/freetype2/freetype/ftimage.h sim/sim.h +$(OBJDIR)/cd_truetype.o: sim/cd_truetype.c sim/cd_truetype.h \ + /usr/include/freetype2/freetype/freetype.h \ + /usr/include/freetype2/freetype/config/ftconfig.h \ + /usr/include/freetype2/freetype/config/ftoption.h \ + /usr/include/freetype2/freetype/config/ftstdlib.h \ + /usr/include/freetype2/freetype/fterrors.h \ + /usr/include/freetype2/freetype/ftmoderr.h \ + /usr/include/freetype2/freetype/fterrdef.h \ + /usr/include/freetype2/freetype/fttypes.h \ + /usr/include/freetype2/freetype/ftsystem.h \ + /usr/include/freetype2/freetype/ftimage.h +$(OBJDIR)/sim_other.o: sim/sim_other.c ../include/cd.h ../include/cd_private.h +$(OBJDIR)/sim_primitives.o: sim/sim_primitives.c ../include/cd.h \ + ../include/cd_private.h sim/cd_truetype.h \ + /usr/include/freetype2/freetype/freetype.h \ + /usr/include/freetype2/freetype/config/ftconfig.h \ + /usr/include/freetype2/freetype/config/ftoption.h \ + /usr/include/freetype2/freetype/config/ftstdlib.h \ + /usr/include/freetype2/freetype/fterrors.h \ + /usr/include/freetype2/freetype/ftmoderr.h \ + /usr/include/freetype2/freetype/fterrdef.h \ + /usr/include/freetype2/freetype/fttypes.h \ + /usr/include/freetype2/freetype/ftsystem.h \ + /usr/include/freetype2/freetype/ftimage.h sim/sim.h +$(OBJDIR)/sim_linepolyfill.o: sim/sim_linepolyfill.c ../include/cd.h \ + ../include/cd_private.h sim/cd_truetype.h \ + /usr/include/freetype2/freetype/freetype.h \ + /usr/include/freetype2/freetype/config/ftconfig.h \ + /usr/include/freetype2/freetype/config/ftoption.h \ + /usr/include/freetype2/freetype/config/ftstdlib.h \ + /usr/include/freetype2/freetype/fterrors.h \ + /usr/include/freetype2/freetype/ftmoderr.h \ + /usr/include/freetype2/freetype/fterrdef.h \ + /usr/include/freetype2/freetype/fttypes.h \ + /usr/include/freetype2/freetype/ftsystem.h \ + /usr/include/freetype2/freetype/ftimage.h sim/sim.h +$(OBJDIR)/cd0prn.o: drv/cd0prn.c ../include/cd.h ../include/cdprint.h +$(OBJDIR)/cd0emf.o: drv/cd0emf.c ../include/cd.h ../include/cdemf.h +$(OBJDIR)/cd0wmf.o: drv/cd0wmf.c ../include/cd.h ../include/cdwmf.h +$(OBJDIR)/cdx11.o: x11/cdx11.c x11/cdx11.h ../include/cd.h ../include/cd_private.h \ + x11/xvertex.h +$(OBJDIR)/cdxclp.o: x11/cdxclp.c ../include/cd.h ../include/cd_private.h \ + ../include/cdclipbd.h ../include/cdmf.h ../include/cdmf_private.h +$(OBJDIR)/cdximg.o: x11/cdximg.c x11/cdx11.h ../include/cd.h \ + ../include/cd_private.h ../include/cdimage.h +$(OBJDIR)/cdxnative.o: x11/cdxnative.c x11/cdx11.h ../include/cd.h \ + ../include/cd_private.h ../include/cdnative.h +$(OBJDIR)/cdxdbuf.o: x11/cdxdbuf.c x11/cdx11.h ../include/cd.h \ + ../include/cd_private.h ../include/cddbuf.h +$(OBJDIR)/xvertex.o: x11/xvertex.c x11/xvertex.h diff --git a/cd/src/cd.rc b/cd/src/cd.rc new file mode 100755 index 0000000..42c3f8c --- /dev/null +++ b/cd/src/cd.rc @@ -0,0 +1,19 @@ +1 VERSIONINFO + FILEVERSION 5,0,1,0 + PRODUCTVERSION 5,0,1,0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "www.tecgraf.puc-rio.br/cd\0" + VALUE "CompanyName", "Tecgraf/PUC-Rio\0" + VALUE "FileDescription", "CD - Canvas Draw, A 2D Graphics Library\0" + VALUE "FileVersion", "5.0.1\0" + VALUE "LegalCopyright", "Copyright © 1994-2008 Tecgraf, PUC-Rio.\0" + VALUE "OriginalFilename", "cd.dll\0" + VALUE "ProductName", "CD for Windows\0" + VALUE "ProductVersion", "5.0.1\0" + END + END +END diff --git a/cd/src/cd_active.c b/cd/src/cd_active.c new file mode 100755 index 0000000..f8229bd --- /dev/null +++ b/cd/src/cd_active.c @@ -0,0 +1,1006 @@ +/** \file + * \brief OLD API that needs the cdActivate call + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#ifdef CD_NO_OLD_INTERFACE +#undef CD_NO_OLD_INTERFACE +#endif + +#include "cd.h" +#include "wd.h" + +static cdCanvas *active_canvas = NULL; + +int cdActivate(cdCanvas *canvas) +{ + /* if is the active canvas, just update canvas state */ + if (active_canvas && canvas == active_canvas) + { + if (cdCanvasActivate(canvas) == CD_ERROR) + { + active_canvas = NULL; + return CD_ERROR; + } + + return CD_OK; + } + + /* if exists an active canvas, deactivate it */ + if (active_canvas) + cdCanvasDeactivate(active_canvas); + + /* allow to active a NULL canvas, the user may restore a previous canvas that was NULL */ + if (canvas == NULL) + { + active_canvas = NULL; + return CD_ERROR; + } + + /* do the activation */ + active_canvas = canvas; + + if (cdCanvasActivate(canvas) == CD_ERROR) + { + active_canvas = NULL; + return CD_ERROR; + } + + return CD_OK; +} + +cdCanvas* cdActiveCanvas(void) +{ + return active_canvas; +} + +int cdSimulate(int mode) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasSimulate(active_canvas, mode); +} + +cdState* cdSaveState(void) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasSaveState(active_canvas); +} + +void cdRestoreState(cdState* state) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasRestoreState(active_canvas, state); +} + +void cdFlush(void) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasFlush(active_canvas); +} + +void cdClear(void) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasClear(active_canvas); +} + +void cdSetAttribute(const char* name, char *data) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasSetAttribute(active_canvas, name, data); +} + +void cdSetfAttribute(const char* name, const char* format, ...) +{ + char data[1024]; + va_list arglist; + + assert(active_canvas); + if (!active_canvas) return; + + va_start(arglist, format); + vsprintf(data, format, arglist); + + cdCanvasSetAttribute(active_canvas, name, data); +} + +char* cdGetAttribute(const char* name) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasGetAttribute(active_canvas, name); +} + +int cdPlay(cdContext* context, int xmin, int xmax, int ymin, int ymax, void *data) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasPlay(active_canvas, context, xmin, xmax, ymin, ymax, data); +} + +int cdClip(int mode) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasClip(active_canvas, mode); +} + +void cdClipArea(int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasClipArea(active_canvas, xmin, xmax, ymin, ymax); +} + +int cdGetClipArea(int *xmin, int *xmax, int *ymin, int *ymax) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasGetClipArea(active_canvas, xmin, xmax, ymin, ymax); +} + +int cdPointInRegion(int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasIsPointInRegion(active_canvas, x, y); +} + +void cdOffsetRegion(int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasOffsetRegion(active_canvas, x, y); +} + +void cdRegionBox(int *xmin, int *xmax, int *ymin, int *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetRegionBox(active_canvas, xmin, xmax, ymin, ymax); +} + +void cdGetCanvasSize(int *width, int *height, double *width_mm, double *height_mm) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetSize(active_canvas, width, height, width_mm, height_mm); +} + +void cdMM2Pixel(double mm_dx, double mm_dy, int *dx, int *dy) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasMM2Pixel(active_canvas, mm_dx, mm_dy, dx, dy); +} + +void cdPixel2MM(int dx, int dy, double *mm_dx, double *mm_dy) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPixel2MM(active_canvas, dx, dy, mm_dx, mm_dy); +} + +void cdOrigin(int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasOrigin(active_canvas, x, y); +} + +int cdUpdateYAxis(int *y) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasUpdateYAxis(active_canvas, y); +} + +void cdPixel(int x, int y, long color) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPixel(active_canvas, x, y, color); +} + +void cdMark(int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasMark(active_canvas, x, y); +} + +void cdLine(int x1, int y1, int x2, int y2) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasLine(active_canvas, x1, y1, x2, y2); +} + +void cdBegin(int mode) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasBegin(active_canvas, mode); +} + +void cdVertex(int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasVertex(active_canvas, x, y); +} + +void cdEnd(void) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasEnd(active_canvas); +} + +void cdRect(int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasRect(active_canvas, xmin, xmax, ymin, ymax); +} + +void cdBox(int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasBox(active_canvas, xmin, xmax, ymin, ymax); +} + +void cdArc(int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasArc(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void cdSector(int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasSector(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void cdChord(int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasChord(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void cdText(int x, int y, const char *s) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasText(active_canvas, x, y, s); +} + +int cdBackOpacity(int opacity) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasBackOpacity(active_canvas, opacity); +} + +int cdWriteMode(int mode) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasWriteMode(active_canvas, mode); +} + +int cdLineStyle(int style) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasLineStyle(active_canvas, style); +} + +int cdLineJoin(int join) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasLineJoin(active_canvas, join); +} + +int cdLineCap(int cap) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasLineCap(active_canvas, cap); +} + +int cdRegionCombineMode(int mode) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasRegionCombineMode(active_canvas, mode); +} + +void cdLineStyleDashes(const int* dashes, int count) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasLineStyleDashes(active_canvas, dashes, count); +} + +int cdLineWidth(int width) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasLineWidth(active_canvas, width); +} + +int cdFillMode(int mode) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasFillMode(active_canvas, mode); +} + +int cdInteriorStyle (int style) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasInteriorStyle(active_canvas, style); +} + +int cdHatch(int style) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasHatch(active_canvas, style); +} + +void cdStipple(int w, int h, const unsigned char *stipple) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasStipple(active_canvas, w, h, stipple); +} + +unsigned char* cdGetStipple(int *w, int *h) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasGetStipple(active_canvas, w, h); +} + +void cdPattern(int w, int h, const long *pattern) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPattern(active_canvas, w, h, pattern); +} + +long* cdGetPattern(int* w, int* h) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasGetPattern(active_canvas, w, h); +} + +void cdFont(int type_face, int style, int size) +{ + static const char * family[] = + { + "System", /* CD_SYSTEM */ + "Courier", /* CD_COURIER */ + "Times", /* CD_TIMES_ROMAN */ + "Helvetica" /* CD_HELVETICA */ + }; + + assert(active_canvas); + assert(type_face>=CD_SYSTEM && type_face<=CD_NATIVE); + if (!active_canvas) return; + if (type_faceCD_NATIVE) return; + + if (type_face == CD_NATIVE) + { + char* native_font = cdCanvasNativeFont(active_canvas, NULL); + cdCanvasNativeFont(active_canvas, native_font); + } + else + cdCanvasFont(active_canvas, family[type_face], style, size); +} + +void cdGetFont(int *type_face, int *style, int *size) +{ + char family[1024]; + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetFont(active_canvas, family, style, size); + + if (type_face) + { + if (strcmp(family, "System")==0) + *type_face = CD_SYSTEM; + else if (strcmp(family, "Courier")==0) + *type_face = CD_COURIER; + else if (strcmp(family, "Times")==0) + *type_face = CD_TIMES_ROMAN; + else if (strcmp(family, "Helvetica")==0) + *type_face = CD_HELVETICA; + else + *type_face = CD_NATIVE; + } +} + +char* cdNativeFont(const char* font) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasNativeFont(active_canvas, font); +} + +int cdTextAlignment(int alignment) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasTextAlignment(active_canvas, alignment); +} + +double cdTextOrientation(double angle) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasTextOrientation(active_canvas, angle); +} + +int cdMarkType(int type) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasMarkType(active_canvas, type); +} + +int cdMarkSize(int size) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasMarkSize(active_canvas, size); +} + +long cdBackground(long color) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasBackground(active_canvas, color); +} + +long cdForeground(long color) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasForeground(active_canvas, color); +} + +void cdFontDim(int *max_width, int *height, int *ascent, int *descent) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetFontDim(active_canvas, max_width, height, ascent, descent); +} + +void cdTextSize(const char *s, int *width, int *height) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetTextSize(active_canvas, s, width, height); +} + +void cdTextBounds(int x, int y, const char *s, int *rect) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetTextBounds(active_canvas, x, y, s, rect); +} + +void cdTextBox(int x, int y, const char *s, int *xmin, int *xmax, int *ymin, int *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetTextBox(active_canvas, x, y, s, xmin, xmax, ymin, ymax); +} + +int cdGetColorPlanes(void) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasGetColorPlanes(active_canvas); +} + +void cdPalette(int n, const long *palette, int mode) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPalette(active_canvas, n, palette, mode); +} + +void cdGetImageRGB(unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetImageRGB(active_canvas, r, g, b, x, y, w, h); +} + +void cdPutImageRectRGB(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPutImageRectRGB(active_canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void cdPutImageRectRGBA(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPutImageRectRGBA(active_canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void cdPutImageRectMap(int iw, int ih, const unsigned char *index, const long *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPutImageRectMap(active_canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); +} + +cdImage* cdCreateImage(int w, int h) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasCreateImage(active_canvas, w, h); +} + +void cdGetImage(cdImage* image, int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetImage(active_canvas, image, x, y); +} + +void cdPutImageRect(cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPutImageRect(active_canvas, image, x, y, xmin, xmax, ymin, ymax); +} + +void cdScrollArea(int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasScrollArea(active_canvas, xmin, xmax, ymin, ymax, dx, dy); +} + +void cdPutBitmap(cdBitmap* bitmap, int x, int y, int w, int h) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasPutBitmap(active_canvas, bitmap, x, y, w, h); +} + +void cdGetBitmap(cdBitmap* bitmap, int x, int y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetBitmap(active_canvas, bitmap, x, y); +} + +void wdWindow(double xmin, double xmax, double ymin, double ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasWindow(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdGetWindow (double *xmin, double *xmax, double *ymin, double *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetWindow(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdViewport(int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasViewport(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdGetViewport (int *xmin, int *xmax, int *ymin, int *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetViewport(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdWorld2Canvas(double xw, double yw, int *xv, int *yv) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasWorld2Canvas(active_canvas, xw, yw, xv, yv); +} + +void wdWorld2CanvasSize(double hw, double vw, int *hv, int *vv) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasWorld2CanvasSize(active_canvas, hw, vw, hv, vv); +} + +void wdCanvas2World(int xv, int yv, double *xw, double *yw) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasCanvas2World(active_canvas, xv, yv, xw, yw); +} + +void wdClipArea(double xmin, double xmax, double ymin, double ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasClipArea(active_canvas, xmin, xmax, ymin, ymax); +} + +int wdPointInRegion(double x, double y) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return wdCanvasIsPointInRegion(active_canvas, x, y); +} + +void wdOffsetRegion(double x, double y) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasOffsetRegion(active_canvas, x, y); +} + +void wdRegionBox(double *xmin, double *xmax, double *ymin, double *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetRegionBox(active_canvas, xmin, xmax, ymin, ymax); +} + +int wdGetClipArea(double *xmin, double *xmax, double *ymin, double *ymax) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return wdCanvasGetClipArea(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdLine (double x1, double y1, double x2, double y2) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasLine(active_canvas, x1, y1, x2, y2); +} + +void wdBox (double xmin, double xmax, double ymin, double ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasBox(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdRect(double xmin, double xmax, double ymin, double ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasRect(active_canvas, xmin, xmax, ymin, ymax); +} + +void wdArc(double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasArc(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void wdSector(double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasSector(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void wdChord(double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasChord(active_canvas, xc, yc, w, h, angle1, angle2); +} + +void wdText(double x, double y, const char *s) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasText(active_canvas, x, y, s); +} + +void wdVertex(double x, double y) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasVertex(active_canvas, x, y); +} + +void wdMark(double x, double y) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasMark(active_canvas, x, y); +} + +void wdPixel(double x, double y, long color) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPixel(active_canvas, x, y, color); +} + +void wdPutImageRect(cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPutImageRect(active_canvas, image, x, y, xmin, xmax, ymin, ymax); +} + +void wdPutImageRectRGB(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPutImageRectRGB(active_canvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void wdPutImageRectRGBA(int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPutImageRectRGBA(active_canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void wdPutImageRectMap(int iw, int ih, const unsigned char *index, const long *colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPutImageRectMap(active_canvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void wdPutBitmap(cdBitmap* bitmap, double x, double y, double w, double h) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPutBitmap(active_canvas, bitmap, x, y, w, h); +} + +double wdLineWidth(double width_mm) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return wdCanvasLineWidth(active_canvas, width_mm); +} + +void wdFont(int type_face, int style, double size_mm) +{ + static const char * family[] = + { + "System", /* CD_SYSTEM */ + "Courier", /* CD_COURIER */ + "Times Roman", /* CD_TIMES_ROMAN */ + "Helvetica" /* CD_HELVETICA */ + }; + + assert(active_canvas); + if (!active_canvas) return; + if (type_faceCD_HELVETICA) return; + + wdCanvasFont(active_canvas, family[type_face], style, (int)(size_mm*CD_MM2PT + 0.5)); +} + +void wdGetFont(int *type_face, int *style, double *size) +{ + char family[1024]; + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetFont(active_canvas, family, style, size); + + if (type_face) + { + if (strcmp(family, "System")==0) + *type_face = CD_SYSTEM; + else if (strcmp(family, "Courier")==0) + *type_face = CD_COURIER; + else if (strcmp(family, "Times Roman")==0) + *type_face = CD_TIMES_ROMAN; + else if (strcmp(family, "Helvetica")==0) + *type_face = CD_HELVETICA; + else + *type_face = CD_NATIVE; + } +} + +double wdMarkSize(double size_mm) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return wdCanvasMarkSize(active_canvas, size_mm); +} + +void wdFontDim(double *max_width, double *height, double *ascent, double *descent) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetFontDim(active_canvas, max_width, height, ascent, descent); +} + +void wdTextSize(const char *s, double *width, double *height) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetTextSize(active_canvas, s, width, height); +} + +void wdTextBox(double x, double y, const char *s, double *xmin, double *xmax, double *ymin, double *ymax) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetTextBox(active_canvas, x, y, s, xmin, xmax, ymin, ymax); +} + +void wdTextBounds(double x, double y, const char *s, double *rect) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetTextBounds(active_canvas, x, y, s, rect); +} + +void wdPattern(int w, int h, const long *color, double w_mm, double h_mm) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasPattern(active_canvas, w, h, color, w_mm, h_mm); +} + +void wdStipple(int w, int h, const unsigned char *fgbg, double w_mm, double h_mm) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasStipple(active_canvas, w, h, fgbg, w_mm, h_mm); +} + +void wdHardcopy(cdContext* ctx, void *data, cdCanvas *canvas, void(*draw_func)(void)) +{ + wdCanvasHardcopy(canvas, ctx, data, (void(*)(cdCanvas*))draw_func); +} + +void cdVectorText(int x, int y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasVectorText(active_canvas, x, y, s); +} + +void cdMultiLineVectorText(int x, int y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasMultiLineVectorText(active_canvas, x, y, s); +} + +char *cdVectorFont(const char *filename) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasVectorFont(active_canvas, filename); +} + +void cdVectorTextDirection(int x1, int y1, int x2, int y2) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasVectorTextDirection(active_canvas, x1, y1, x2, y2); +} + +double* cdVectorTextTransform(const double* matrix) +{ + assert(active_canvas); + if (!active_canvas) return NULL; + return cdCanvasVectorTextTransform(active_canvas, matrix); +} + +void cdVectorTextSize(int size_x, int size_y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasVectorTextSize(active_canvas, size_x, size_y, s); +} + +int cdVectorCharSize(int size) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return cdCanvasVectorCharSize(active_canvas, size); +} + +void cdGetVectorTextSize(const char* s, int *x, int *y) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetVectorTextSize(active_canvas, s, x, y); +} + +void cdGetVectorTextBounds(const char* s, int x, int y, int *rect) +{ + assert(active_canvas); + if (!active_canvas) return; + cdCanvasGetVectorTextBounds(active_canvas, s, x, y, rect); +} + +void wdVectorTextDirection(double x1, double y1, double x2, double y2) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasVectorTextDirection(active_canvas, x1, y1, x2, y2); +} + +void wdVectorTextSize(double size_x, double size_y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasVectorTextSize(active_canvas, size_x, size_y, s); +} + +void wdGetVectorTextSize(const char* s, double *x, double *y) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetVectorTextSize(active_canvas, s, x, y); +} + +double wdVectorCharSize(double size) +{ + assert(active_canvas); + if (!active_canvas) return CD_ERROR; + return wdCanvasVectorCharSize(active_canvas, size); +} + +void wdVectorText(double x, double y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasVectorText(active_canvas, x, y, s); +} + +void wdMultiLineVectorText(double x, double y, const char* s) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasMultiLineVectorText(active_canvas, x, y, s); +} + +void wdGetVectorTextBounds(const char* s, double x, double y, double *rect) +{ + assert(active_canvas); + if (!active_canvas) return; + wdCanvasGetVectorTextBounds(active_canvas, s, x, y, rect); +} diff --git a/cd/src/cd_attributes.c b/cd/src/cd_attributes.c new file mode 100755 index 0000000..7b825e4 --- /dev/null +++ b/cd/src/cd_attributes.c @@ -0,0 +1,1017 @@ +/** \file + * \brief External API + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include +#include + + +#include "cd.h" +#include "cd_private.h" + + +int cdCanvasClip(cdCanvas* canvas, int mode) +{ + int clip_mode; + + assert(canvas); + assert(mode==CD_QUERY || (mode>=CD_CLIPOFF && mode<=CD_CLIPREGION)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (modeCD_CLIPREGION) return CD_ERROR; + + clip_mode = canvas->clip_mode; + + if (mode == CD_QUERY || + mode == clip_mode || + (mode == CD_CLIPPOLYGON && !canvas->clip_poly && !canvas->clip_fpoly)) + return clip_mode; + + if (canvas->cxClip) + canvas->clip_mode = canvas->cxClip(canvas->ctxcanvas, mode); + else + canvas->clip_mode = mode; + + return clip_mode; +} + +void cdCanvasClipArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->origin.x; + xmax += canvas->origin.x; + ymin += canvas->origin.y; + ymax += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + if (xmin == canvas->clip_rect.xmin && + xmax == canvas->clip_rect.xmax && + ymin == canvas->clip_rect.ymin && + ymax == canvas->clip_rect.ymax) + return; + + if (canvas->cxClipArea) + canvas->cxClipArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax); + else if (canvas->cxFClipArea) + canvas->cxFClipArea(canvas->ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); + + canvas->clip_rect.xmin = xmin; + canvas->clip_rect.xmax = xmax; + canvas->clip_rect.ymin = ymin; + canvas->clip_rect.ymax = ymax; + canvas->clip_frect.xmin = (double)xmin; + canvas->clip_frect.xmax = (double)xmax; + canvas->clip_frect.ymin = (double)ymin; + canvas->clip_frect.ymax = (double)ymax; +} + +int cdCanvasGetClipArea(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + int _xmin, _xmax, _ymin, _ymax; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + _xmin = canvas->clip_rect.xmin; + _xmax = canvas->clip_rect.xmax; + _ymin = canvas->clip_rect.ymin; + _ymax = canvas->clip_rect.ymax; + + if (canvas->invert_yaxis) + { + _ymin = _cdInvertYAxis(canvas, _ymin); + _ymax = _cdInvertYAxis(canvas, _ymax); + _cdSwapInt(_ymin, _ymax); + } + + if (canvas->use_origin) + { + _xmin -= canvas->origin.x; + _xmax -= canvas->origin.x; + _ymin -= canvas->origin.y; + _ymax -= canvas->origin.y; + } + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; + + return canvas->clip_mode; +} + +void cdfCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->forigin.x; + xmax += canvas->forigin.x; + ymin += canvas->forigin.y; + ymax += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapDouble(ymin, ymax); + } + + if (xmin == canvas->clip_frect.xmin && + xmax == canvas->clip_frect.xmax && + ymin == canvas->clip_frect.ymin && + ymax == canvas->clip_frect.ymax) + return; + + if (canvas->cxFClipArea) + canvas->cxFClipArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax); + else if (canvas->cxClipArea) + canvas->cxClipArea(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax)); + + canvas->clip_frect.xmin = xmin; + canvas->clip_frect.xmax = xmax; + canvas->clip_frect.ymin = ymin; + canvas->clip_frect.ymax = ymax; + canvas->clip_rect.xmin = _cdRound(xmin); + canvas->clip_rect.xmax = _cdRound(xmax); + canvas->clip_rect.ymin = _cdRound(ymin); + canvas->clip_rect.ymax = _cdRound(ymax); +} + +int cdfCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax) +{ + double _xmin, _xmax, _ymin, _ymax; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + _xmin = canvas->clip_frect.xmin; + _xmax = canvas->clip_frect.xmax; + _ymin = canvas->clip_frect.ymin; + _ymax = canvas->clip_frect.ymax; + + if (canvas->invert_yaxis) + { + _ymin = _cdInvertYAxis(canvas, _ymin); + _ymax = _cdInvertYAxis(canvas, _ymax); + _cdSwapDouble(_ymin, _ymax); + } + + if (canvas->use_origin) + { + _xmin -= canvas->forigin.x; + _xmax -= canvas->forigin.x; + _ymin -= canvas->forigin.y; + _ymax -= canvas->forigin.y; + } + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; + + return canvas->clip_mode; +} + +int cdCanvasIsPointInRegion(cdCanvas* canvas, int x, int y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxIsPointInRegion) return CD_ERROR; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + return canvas->cxIsPointInRegion(canvas->ctxcanvas, x, y); +} + +void cdCanvasOffsetRegion(cdCanvas* canvas, int x, int y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxOffsetRegion) return; + + if (canvas->invert_yaxis) + y = -y; + + canvas->cxOffsetRegion(canvas->ctxcanvas, x, y); +} + +void cdCanvasGetRegionBox(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + int _xmin, _xmax, _ymin, _ymax; + assert(canvas); + if (!_cdCheckCanvas(canvas) || !canvas->cxGetRegionBox) return; + + canvas->cxGetRegionBox(canvas->ctxcanvas, &_xmin, &_xmax, &_ymin, &_ymax); + + if (canvas->invert_yaxis) + { + _ymin = _cdInvertYAxis(canvas, _ymin); + _ymax = _cdInvertYAxis(canvas, _ymax); + _cdSwapInt(_ymin, _ymax); + } + + if (canvas->use_origin) + { + _xmin -= canvas->origin.x; + _xmax -= canvas->origin.x; + _ymin -= canvas->origin.y; + _ymax -= canvas->origin.y; + } + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; +} + +void cdCanvasOrigin(cdCanvas* canvas, int x, int y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + canvas->origin.x = x; + canvas->origin.y = y; + + if (canvas->origin.x == 0 && canvas->origin.y == 0) + canvas->use_origin = 0; + else + canvas->use_origin = 1; + + canvas->forigin.x = (double)canvas->origin.x; + canvas->forigin.y = (double)canvas->origin.y; +} + + +void cdfCanvasOrigin(cdCanvas* canvas, double x, double y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + canvas->forigin.x = x; + canvas->forigin.y = y; + + if (canvas->forigin.x == 0 && canvas->forigin.y == 0) + canvas->use_origin = 0; + else + canvas->use_origin = 1; + + canvas->origin.x = _cdRound(canvas->forigin.x); + canvas->origin.y = _cdRound(canvas->forigin.y); +} + +void cdCanvasGetOrigin(cdCanvas* canvas, int *x, int *y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (x) *x = canvas->origin.x; + if (y) *y = canvas->origin.y; +} + +void cdfCanvasGetOrigin(cdCanvas* canvas, double *x, double *y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (x) *x = canvas->forigin.x; + if (y) *y = canvas->forigin.y; +} + +#define CD_TRANSFORM_X(_x, _y, _matrix) (_x*_matrix[0] + _y*_matrix[2] + _matrix[4]) +#define CD_TRANSFORM_Y(_x, _y, _matrix) (_x*_matrix[1] + _y*_matrix[3] + _matrix[5]) + +void cdfMatrixTransformPoint(double* matrix, double x, double y, double *rx, double *ry) +{ + *rx = CD_TRANSFORM_X(x, y, matrix); + *ry = CD_TRANSFORM_Y(x, y, matrix); +} + +void cdMatrixTransformPoint(double* matrix, int x, int y, int *rx, int *ry) +{ + double t; + t = CD_TRANSFORM_X(x, y, matrix); *rx = _cdRound(t); + t = CD_TRANSFORM_Y(x, y, matrix); *ry = _cdRound(t); +} + +void cdCanvasTransformPoint(cdCanvas* canvas, int x, int y, int *tx, int *ty) +{ + double *matrix; + double t; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + matrix = canvas->matrix; + t = CD_TRANSFORM_X(x, y, matrix); *tx = _cdRound(t); + t = CD_TRANSFORM_Y(x, y, matrix); *ty = _cdRound(t); +} + +void cdfCanvasTransformPoint(cdCanvas* canvas, double x, double y, double *tx, double *ty) +{ + double *matrix; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + matrix = canvas->matrix; + *tx = CD_TRANSFORM_X(x, y, matrix); + *ty = CD_TRANSFORM_Y(x, y, matrix); +} + +void cdMatrixInverse(const double* matrix, double* inv_matrix) +{ + double det = matrix[0] * matrix[3] - matrix[1] * matrix[2]; + + if (fabs(det) < 0.00001) + { + inv_matrix[0] = 1; + inv_matrix[1] = 0; + inv_matrix[2] = 0; + inv_matrix[3] = 1; + inv_matrix[4] = 0; + inv_matrix[5] = 0; + return; + } + + inv_matrix[0] = matrix[3]/det; + inv_matrix[1] = -matrix[1]/det; + inv_matrix[2] = -matrix[2]/det; + inv_matrix[3] = matrix[0]/det; + inv_matrix[4] = -(matrix[4] * inv_matrix[0] + matrix[5] * inv_matrix[2]); + inv_matrix[5] = -(matrix[4] * inv_matrix[1] + matrix[5] * inv_matrix[3]); +} + +#define _cdIsIndentity(_matrix) (_matrix[0] == 1 && _matrix[1] == 0 && \ + _matrix[2] == 0 && _matrix[3] == 1 && \ + _matrix[4] == 0 && _matrix[5] == 0) + +double* cdCanvasGetTransform(cdCanvas* canvas) +{ + static double matrix[6]; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + memcpy(matrix, canvas->matrix, sizeof(double)*6); + return matrix; +} + +void cdCanvasTransform(cdCanvas* canvas, const double* matrix) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!matrix || _cdIsIndentity(matrix)) + { + canvas->use_matrix = 0; + memset(canvas->matrix, 0, sizeof(double)*6); + canvas->matrix[0] = 1; /* reset to identity */ + canvas->matrix[3] = 1; + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, NULL); + + return; + } + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, matrix); + + memcpy(canvas->matrix, matrix, sizeof(double)*6); + canvas->use_matrix = 1; +} + +/* mul_matrix = matrix * mul_matrix (left multiply) */ +void cdMatrixMultiply(const double* matrix, double* mul_matrix) +{ + double tmp_matrix[6]; + tmp_matrix[0] = matrix[0] * mul_matrix[0] + matrix[1] * mul_matrix[2]; + tmp_matrix[1] = matrix[0] * mul_matrix[1] + matrix[1] * mul_matrix[3]; + tmp_matrix[2] = matrix[2] * mul_matrix[0] + matrix[3] * mul_matrix[2]; + tmp_matrix[3] = matrix[2] * mul_matrix[1] + matrix[3] * mul_matrix[3]; + tmp_matrix[4] = matrix[4] * mul_matrix[0] + matrix[5] * mul_matrix[2] + mul_matrix[4]; + tmp_matrix[5] = matrix[4] * mul_matrix[1] + matrix[5] * mul_matrix[3] + mul_matrix[5]; + + memcpy(mul_matrix, tmp_matrix, sizeof(double)*6); +} + +void cdCanvasTransformMultiply(cdCanvas* canvas, const double* matrix) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + cdMatrixMultiply(matrix, canvas->matrix); + + if (_cdIsIndentity(canvas->matrix)) + canvas->use_matrix = 0; + else + canvas->use_matrix = 1; + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? canvas->matrix: NULL); +} + +void cdCanvasTransformRotate(cdCanvas* canvas, double angle) +{ + double tmp_matrix[4]; + double* matrix, cos_ang, sin_ang; + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + matrix = canvas->matrix; + + cos_ang = cos(angle * CD_DEG2RAD); + sin_ang = sin(angle * CD_DEG2RAD); + + tmp_matrix[0] = cos_ang * matrix[0] + sin_ang * matrix[2]; + tmp_matrix[1] = cos_ang * matrix[1] + sin_ang * matrix[3]; + tmp_matrix[2] = -sin_ang * matrix[0] + cos_ang * matrix[2]; + tmp_matrix[3] = -sin_ang * matrix[1] + cos_ang * matrix[3]; + + matrix[0] = tmp_matrix[0]; + matrix[1] = tmp_matrix[1]; + matrix[2] = tmp_matrix[2]; + matrix[3] = tmp_matrix[3]; + + if (_cdIsIndentity(matrix)) + canvas->use_matrix = 0; + else + canvas->use_matrix = 1; + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL); +} + +void cdCanvasTransformScale(cdCanvas* canvas, double sx, double sy) +{ + double* matrix; + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + matrix = canvas->matrix; + + matrix[0] = sx * matrix[0]; + matrix[1] = sx * matrix[1]; + matrix[2] = sy * matrix[2]; + matrix[3] = sy * matrix[3]; + + if (_cdIsIndentity(matrix)) + canvas->use_matrix = 0; + else + canvas->use_matrix = 1; + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL); +} + +void cdCanvasTransformTranslate(cdCanvas* canvas, double dx, double dy) +{ + double* matrix; + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + matrix = canvas->matrix; + + matrix[4] = dx * matrix[0] + dy * matrix[2] + matrix[4]; + matrix[5] = dx * matrix[1] + dy * matrix[3] + matrix[5]; + + if (_cdIsIndentity(matrix)) + canvas->use_matrix = 0; + else + canvas->use_matrix = 1; + + if (canvas->cxTransform) + canvas->cxTransform(canvas->ctxcanvas, canvas->use_matrix? matrix: NULL); +} + +int cdCanvasBackOpacity(cdCanvas* canvas, int opacity) +{ + int back_opacity; + + assert(canvas); + assert(opacity==CD_QUERY || (opacity>=CD_OPAQUE && opacity<=CD_TRANSPARENT)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (opacityCD_TRANSPARENT) return CD_ERROR; + + back_opacity = canvas->back_opacity; + + if (opacity == CD_QUERY || opacity == back_opacity) + return back_opacity; + + if (canvas->cxBackOpacity) + canvas->back_opacity = canvas->cxBackOpacity(canvas->ctxcanvas, opacity); + else + canvas->back_opacity = opacity; + + return back_opacity; +} + +int cdCanvasWriteMode(cdCanvas* canvas, int mode) +{ + int write_mode; + + assert(canvas); + assert(mode==CD_QUERY || (mode>=CD_REPLACE && mode<=CD_NOT_XOR)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (modeCD_NOT_XOR) return CD_ERROR; + + write_mode = canvas->write_mode; + + if (mode == CD_QUERY || mode == write_mode) + return write_mode; + + if (canvas->cxWriteMode) + canvas->write_mode = canvas->cxWriteMode(canvas->ctxcanvas, mode); + else + canvas->write_mode = mode; + + return write_mode; +} + +int cdCanvasLineStyle(cdCanvas* canvas, int style) +{ + int line_style; + + assert(canvas); + assert(style==CD_QUERY || (style>=CD_CONTINUOUS && style<=CD_CUSTOM)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (styleCD_CUSTOM) return CD_ERROR; + + line_style = canvas->line_style; + + if (style == CD_QUERY || style == line_style) + return line_style; + + if (style == CD_CUSTOM && !canvas->line_dashes_count) + return line_style; + + if (canvas->cxLineStyle) + canvas->line_style = canvas->cxLineStyle(canvas->ctxcanvas, style); + else + canvas->line_style = style; + + return line_style; +} + +int cdCanvasLineJoin(cdCanvas* canvas, int join) +{ + int line_join; + + assert(canvas); + assert(join==CD_QUERY || (join>=CD_MITER && join<=CD_ROUND)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (joinCD_ROUND) return CD_ERROR; + + line_join = canvas->line_join; + + if (join == CD_QUERY || join == line_join) + return line_join; + + if (canvas->cxLineJoin) + canvas->line_join = canvas->cxLineJoin(canvas->ctxcanvas, join); + else + canvas->line_join = join; + + return line_join; +} + +int cdCanvasLineCap(cdCanvas* canvas, int cap) +{ + int line_cap; + + assert(canvas); + assert(cap==CD_QUERY || (cap>=CD_CAPFLAT && cap<=CD_CAPROUND)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (capCD_CAPROUND) return CD_ERROR; + + line_cap = canvas->line_cap; + + if (cap == CD_QUERY || cap == line_cap) + return line_cap; + + if (canvas->cxLineCap) + canvas->line_cap = canvas->cxLineCap(canvas->ctxcanvas, cap); + else + canvas->line_cap = cap; + + return line_cap; +} + +int cdCanvasRegionCombineMode(cdCanvas* canvas, int mode) +{ + int combine_mode; + + assert(canvas); + assert(mode==CD_QUERY || (mode>=CD_UNION && mode<=CD_NOTINTERSECT)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (modeCD_NOTINTERSECT) return CD_ERROR; + + combine_mode = canvas->combine_mode; + + if (mode == CD_QUERY || mode == combine_mode) + return combine_mode; + + canvas->combine_mode = mode; + + return combine_mode; +} + +void cdCanvasLineStyleDashes(cdCanvas* canvas, const int* dashes, int count) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->line_dashes) + { + free(canvas->line_dashes); + canvas->line_dashes = NULL; + } + + if (dashes) + { + canvas->line_dashes = malloc(count*sizeof(int)); + canvas->line_dashes_count = count; + memcpy(canvas->line_dashes, dashes, count*sizeof(int)); + } +} + +int cdCanvasLineWidth(cdCanvas* canvas, int width) +{ + int line_width; + + assert(canvas); + assert(width==CD_QUERY || width>0); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (width!=CD_QUERY && width<=0) return CD_ERROR; + + line_width = canvas->line_width; + + if (width == CD_QUERY || width == line_width) + return line_width; + + if (canvas->cxLineWidth) + canvas->line_width = canvas->cxLineWidth(canvas->ctxcanvas, width); + else + canvas->line_width = width; + + return line_width; +} + +int cdCanvasFillMode(cdCanvas* canvas, int mode) +{ + int fill_mode; + + assert(canvas); + assert(mode==CD_QUERY || (mode>=CD_EVENODD && mode<=CD_WINDING)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (modeCD_WINDING) return CD_ERROR; + + fill_mode = canvas->fill_mode; + + if (mode == CD_QUERY || mode == fill_mode) + return fill_mode; + + canvas->fill_mode = mode; + + return fill_mode; +} + +int cdCanvasInteriorStyle (cdCanvas* canvas, int style) +{ + int interior_style; + + assert(canvas); + assert(style==CD_QUERY || (style>=CD_SOLID && style<=CD_HOLLOW)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (styleCD_HOLLOW) return CD_ERROR; + + interior_style = canvas->interior_style; + + if ( style == CD_QUERY || style == interior_style) + return interior_style; + + if ((style == CD_PATTERN && !canvas->pattern_size) || + (style == CD_STIPPLE && !canvas->stipple_size)) + return interior_style; + + if (style == CD_HOLLOW) + { + canvas->interior_style = CD_HOLLOW; + return interior_style; + } + + if (canvas->cxInteriorStyle) + canvas->interior_style = canvas->cxInteriorStyle(canvas->ctxcanvas, style); + else + canvas->interior_style = style; + + return interior_style; +} + +int cdCanvasHatch(cdCanvas* canvas, int style) +{ + int hatch_style; + + assert(canvas); + assert(style==CD_QUERY || (style>=CD_HORIZONTAL && style<=CD_DIAGCROSS)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (styleCD_DIAGCROSS) return CD_ERROR; + + hatch_style = canvas->hatch_style; + + if (style == CD_QUERY) + return hatch_style; + + if (canvas->cxHatch) + canvas->hatch_style = canvas->cxHatch(canvas->ctxcanvas, style); + else + canvas->hatch_style = style; + + canvas->interior_style = CD_HATCH; + + return hatch_style; +} + +void cdCanvasStipple(cdCanvas* canvas, int w, int h, const unsigned char *stipple) +{ + assert(canvas); + assert(stipple); + assert(w>0); + assert(h>0); + if (!_cdCheckCanvas(canvas)) return; + if (w <= 0 || h <= 0 || !stipple) + return; + + if (canvas->cxStipple) + canvas->cxStipple(canvas->ctxcanvas, w, h, stipple); + + if (w*h > canvas->stipple_size) /* realoca array dos pontos */ + { + int newsize = w*h; + canvas->stipple = (unsigned char*)realloc(canvas->stipple, newsize); + canvas->stipple_size = newsize; + + if (!canvas->stipple) + { + canvas->stipple_size = 0; + return; + } + } + + memcpy(canvas->stipple, stipple, w*h); + + canvas->interior_style = CD_STIPPLE; + canvas->stipple_w = w; + canvas->stipple_h = h; +} + +unsigned char* cdCanvasGetStipple(cdCanvas* canvas, int* w, int* h) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + if (!canvas->stipple_size) + return NULL; + + if (w) *w = canvas->stipple_w; + if (h) *h = canvas->stipple_h; + + return canvas->stipple; +} + +void cdCanvasPattern(cdCanvas* canvas, int w, int h, const long *pattern) +{ + assert(canvas); + assert(pattern); + assert(w>0); + assert(h>0); + if (!_cdCheckCanvas(canvas)) return; + if (w <= 0 || h <= 0 || !pattern) + return; + + if (canvas->cxPattern) + canvas->cxPattern(canvas->ctxcanvas, w, h, pattern); + + if (w*h > canvas->pattern_size) /* realoca array dos pontos */ + { + int newsize = w*h; + + if (canvas->pattern) free(canvas->pattern); + canvas->pattern = (long*)malloc(newsize*sizeof(long)); + canvas->pattern_size = newsize; + + if (!canvas->pattern) + { + canvas->pattern_size = 0; + return; + } + } + + memcpy(canvas->pattern, pattern, w*h*sizeof(long)); + + canvas->interior_style = CD_PATTERN; + canvas->pattern_w = w; + canvas->pattern_h = h; +} + +long * cdCanvasGetPattern(cdCanvas* canvas, int* w, int* h) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + if (!canvas->pattern_size) + return NULL; + + if (w) *w = canvas->pattern_w; + if (h) *h = canvas->pattern_h; + + return canvas->pattern; +} + +int cdCanvasMarkType(cdCanvas* canvas, int type) +{ + int mark_type; + + assert(canvas); + assert(type==CD_QUERY || (type>=CD_PLUS && type<=CD_HOLLOW_DIAMOND)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (typeCD_HOLLOW_DIAMOND) return CD_ERROR; + + mark_type = canvas->mark_type; + + if (type == CD_QUERY || type == mark_type) + return mark_type; + + canvas->mark_type = type; + + return mark_type; +} + +int cdCanvasMarkSize(cdCanvas* canvas, int size) +{ + int mark_size; + + assert(canvas); + assert(size == CD_QUERY || size>0); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (size != CD_QUERY && size<=0) return CD_ERROR; + + mark_size = canvas->mark_size; + + if (size == CD_QUERY || size == mark_size) + return mark_size; + + canvas->mark_size = size; + + return mark_size; +} + +long cdCanvasBackground(cdCanvas* canvas, long color) +{ + long background; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + background = canvas->background; + + if (color == CD_QUERY || color == background) + return background; + + if (canvas->cxBackground) + canvas->background = canvas->cxBackground(canvas->ctxcanvas, color); + else + canvas->background = color; + + return background; +} + +long cdCanvasForeground(cdCanvas* canvas, long color) +{ + long foreground; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + foreground = canvas->foreground; + + if (color == CD_QUERY || color == foreground) + return foreground; + + if (canvas->cxForeground) + canvas->foreground = canvas->cxForeground(canvas->ctxcanvas, color); + else + canvas->foreground = color; + + return foreground; +} + +void cdCanvasSetBackground(cdCanvas* canvas, long color) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (color == canvas->background) + return; + + if (canvas->cxBackground) + canvas->background = canvas->cxBackground(canvas->ctxcanvas, color); + else + canvas->background = color; +} + +void cdCanvasSetForeground(cdCanvas* canvas, long color) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (color == canvas->foreground) + return; + + if (canvas->cxForeground) + canvas->foreground = canvas->cxForeground(canvas->ctxcanvas, color); + else + canvas->foreground = color; +} + +/****************/ +/* color coding */ +/****************/ + +long cdEncodeColor(unsigned char r, unsigned char g, unsigned char b) +{ + return (((unsigned long)r) << 16) | + (((unsigned long)g) << 8) | + (((unsigned long)b) << 0); +} + +void cdDecodeColor(long color, unsigned char *r, unsigned char *g, unsigned char *b) +{ + *r = cdRed(color); + *g = cdGreen(color); + *b = cdBlue(color); +} + +unsigned char cdDecodeAlpha(long color) +{ + unsigned char alpha = cdReserved(color); + return ~alpha; +} + +long cdEncodeAlpha(long color, unsigned char alpha) +{ + alpha = ~alpha; + return (((unsigned long)alpha) << 24) | (color & 0xFFFFFF); +} + +int cdCanvasGetColorPlanes(cdCanvas* canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + return canvas->bpp; +} + +void cdCanvasPalette(cdCanvas* canvas, int n, const long *palette, int mode) +{ + assert(canvas); + assert(n>0); + assert(palette); + assert(mode>=CD_POLITE && mode<=CD_FORCE); + if (!_cdCheckCanvas(canvas)) return; + if (!palette) return; + if (n <= 0 || canvas->bpp > 8) + return; + + if (canvas->cxPalette) + canvas->cxPalette(canvas->ctxcanvas, n, palette, mode); +} + diff --git a/cd/src/cd_bitmap.c b/cd/src/cd_bitmap.c new file mode 100755 index 0000000..234668c --- /dev/null +++ b/cd/src/cd_bitmap.c @@ -0,0 +1,293 @@ +/** \file + * \brief cdBitmap implementation + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include +#include + + +#include "cd.h" +#include "cdirgb.h" + +#include "cd_private.h" + + +typedef struct _cdBitmapData +{ + void *buffer; + + unsigned char *index; /* pointers into buffer */ + unsigned char *r; + unsigned char *g; + unsigned char *b; + unsigned char *a; + + long* colors; + + int xmin, xmax, ymin, ymax; +} cdBitmapData; + + +cdBitmap* cdCreateBitmap(int w, int h, int type) +{ + int num_channel; + int size = w * h; + cdBitmap* bitmap; + cdBitmapData* data; + + assert(w>0); + assert(h>0); + if (w <= 0) return NULL; + if (h <= 0) return NULL; + + switch (type) + { + case CD_RGB: + num_channel = 3; + break; + case CD_RGBA: + num_channel = 4; + break; + case CD_MAP: + num_channel = 1; + break; + default: + return NULL; + } + + bitmap = (cdBitmap*)malloc(sizeof(cdBitmap)); + data = (cdBitmapData*)malloc(sizeof(cdBitmapData)); + memset(data, 0, sizeof(cdBitmapData)); + + bitmap->w = w; + bitmap->h = h; + bitmap->type = type; + bitmap->data = data; + + data->buffer = malloc(size*num_channel); + if (!data->buffer) + { + free(data); + free(bitmap); + return NULL; + } + + if (type == CD_RGB) + { + data->r = data->buffer; + data->g = data->r + size; + data->b = data->g + size; + memset(data->r, 255, 3*size); /* white */ + } + + if (type == CD_RGBA) + { + data->a = data->b + size; + memset(data->a, 0, size); /* transparent */ + } + + if (type == CD_MAP) + { + data->index = data->buffer; + data->colors = (long*)calloc(256, sizeof(long)); + memset(data->index, 0, size); /* index=0 */ + } + + data->xmin = 0; + data->ymin = 0; + data->xmax = bitmap->w-1; + data->ymax = bitmap->h-1; + + return bitmap; +} + +cdBitmap* cdInitBitmap(int w, int h, int type, ...) +{ + va_list arglist; + cdBitmap* bitmap; + cdBitmapData* data; + + assert(w>0); + assert(h>0); + if (w <= 0) return NULL; + if (h <= 0) return NULL; + + if (type != CD_RGB && + type != CD_RGBA && + type != CD_MAP) + return NULL; + + bitmap = (cdBitmap*)malloc(sizeof(cdBitmap)); + data = (cdBitmapData*)malloc(sizeof(cdBitmapData)); + memset(data, 0, sizeof(cdBitmapData)); + + bitmap->w = w; + bitmap->h = h; + bitmap->type = type; + bitmap->data = data; + + va_start(arglist, type); + + if (type == CD_RGB) + { + data->r = va_arg(arglist, unsigned char*); + data->g = va_arg(arglist, unsigned char*); + data->b = va_arg(arglist, unsigned char*); + } + + if (type == CD_RGBA) + data->a = va_arg(arglist, unsigned char*); + + if (type == CD_MAP) + { + data->index = va_arg(arglist, unsigned char*); + data->colors = va_arg(arglist, long*); + } + + data->xmin = 0; + data->ymin = 0; + data->xmax = bitmap->w-1; + data->ymax = bitmap->h-1; + + return bitmap; +} + +void cdKillBitmap(cdBitmap* bitmap) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + if (data->buffer) + { + free(data->buffer); + + if (bitmap->type == CD_MAP) + free(data->colors); + } + + free(data); + free(bitmap); +} + +void cdCanvasGetBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + if (bitmap->type == CD_RGB || bitmap->type == CD_RGBA) + cdCanvasGetImageRGB(canvas, data->r, data->g, data->b, x, y, bitmap->w, bitmap->h); +} + +void cdBitmapRGB2Map(cdBitmap* bitmap_rgb, cdBitmap* bitmap_map) +{ + cdBitmapData* data_rgb; + cdBitmapData* data_map; + + assert(bitmap_rgb); + assert(bitmap_rgb->data); + assert(bitmap_map); + assert(bitmap_map->data); + if (!bitmap_rgb) return; + if (!bitmap_rgb->data) return; + if (!bitmap_map) return; + if (!bitmap_map->data) return; + + data_rgb = (cdBitmapData*)bitmap_rgb->data; + data_map = (cdBitmapData*)bitmap_map->data; + + if ((bitmap_rgb->type != CD_RGB && bitmap_rgb->type != CD_RGBA) || (bitmap_map->type != CD_MAP)) + return; + + cdRGB2Map(bitmap_rgb->w, bitmap_rgb->h, data_rgb->r, data_rgb->g, data_rgb->b, data_map->index, bitmap_map->type, data_map->colors); +} + +unsigned char* cdBitmapGetData(cdBitmap* bitmap, int dataptr) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return NULL; + if (!bitmap->data) return NULL; + + data = (cdBitmapData*)bitmap->data; + + switch(dataptr) + { + case CD_IRED: + return data->r; + case CD_IGREEN: + return data->g; + case CD_IBLUE: + return data->b; + case CD_IALPHA: + return data->a; + case CD_INDEX: + return data->index; + case CD_COLORS: + return (unsigned char*)data->colors; + } + + return NULL; +} + +void cdBitmapSetRect(cdBitmap* bitmap, int xmin, int xmax, int ymin, int ymax) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + data->xmin = xmin; + data->xmax = xmax; + data->ymin = ymin; + data->ymax = ymax; +} + +void cdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* bitmap, int x, int y, int w, int h) +{ + cdBitmapData* data; + + assert(bitmap); + assert(bitmap->data); + if (!bitmap) return; + if (!bitmap->data) return; + + data = (cdBitmapData*)bitmap->data; + + switch(bitmap->type) + { + case CD_RGB: + cdCanvasPutImageRectRGB(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + case CD_RGBA: + cdCanvasPutImageRectRGBA(canvas, bitmap->w, bitmap->h, data->r, data->g, data->b, data->a, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + case CD_MAP: + cdCanvasPutImageRectMap(canvas, bitmap->w, bitmap->h, data->index, data->colors, x, y, w, h, data->xmin, data->xmax, data->ymin, data->ymax); + break; + } +} diff --git a/cd/src/cd_image.c b/cd/src/cd_image.c new file mode 100755 index 0000000..002d288 --- /dev/null +++ b/cd/src/cd_image.c @@ -0,0 +1,441 @@ +/** \file + * \brief External API - Images + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include + + +#include "cd.h" +#include "cd_private.h" + + +void cdCanvasGetImageRGB(cdCanvas* canvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + assert(canvas); + assert(r); + assert(g); + assert(b); + assert(w>0); + assert(h>0); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (canvas->cxGetImageRGB) + canvas->cxGetImageRGB(canvas->ctxcanvas, r, g, b, x, y, w, h); +} + +void cdRGB2Gray(int width, int height, const unsigned char* red, const unsigned char* green, const unsigned char* blue, unsigned char* index, long *color) +{ + int c, i, count; + for (c = 0; c < 256; c++) + color[c] = cdEncodeColor((unsigned char)c, (unsigned char)c, (unsigned char)c); + + count = width*height; + for (i=0; i0); + assert(ih>0); + assert(r); + assert(g); + assert(b); + if (!_cdCheckCanvas(canvas)) return; + + if (w == 0) w = iw; + if (h == 0) h = ih; + if (xmax == 0) xmax = iw - 1; + if (ymax == 0) ymax = ih - 1; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax); + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (canvas->bpp <= 8) + { + int height = ymax-ymin+1; + unsigned char* map = (unsigned char*)malloc(iw * height); + int pal_size = 1L << canvas->bpp; + long colors[256]; + + if (!map) + return; + + if (pal_size == 2) /* probably a laser printer, use a gray image for better results */ + cdRGB2Gray(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, colors); + else + cdRGB2Map(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, pal_size, colors); + + canvas->cxPutImageRectMap(canvas->ctxcanvas, iw, height, map, colors, x, y, w, h, xmin, xmax, 0, height-1); + + free(map); + } + else + canvas->cxPutImageRectRGB(canvas->ctxcanvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); +} + +void cdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + assert(iw>0); + assert(ih>0); + assert(r); + assert(g); + assert(b); + if (!_cdCheckCanvas(canvas)) return; + + if (w == 0) w = iw; + if (h == 0) h = ih; + if (xmax == 0) xmax = iw - 1; + if (ymax == 0) ymax = ih - 1; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax); + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (!canvas->cxPutImageRectRGBA) + { + if (canvas->cxGetImageRGB) + cdSimPutImageRectRGBA(canvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); + else + canvas->cxPutImageRectRGB(canvas->ctxcanvas, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); + } + else + canvas->cxPutImageRectRGBA(canvas->ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); +} + +static long* cd_getgraycolormap(void) +{ + static long color_map[256] = {1}; + + if (color_map[0]) + { + int c; + for (c = 0; c < 256; c++) + color_map[c] = cdEncodeColor((unsigned char)c, (unsigned char)c, (unsigned char)c); + } + + return color_map; +} + +void cdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char *index, const long *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + assert(index); + assert(iw>0); + assert(ih>0); + if (!_cdCheckCanvas(canvas)) return; + + if (w == 0) w = iw; + if (h == 0) h = ih; + if (xmax == 0) xmax = iw - 1; + if (ymax == 0) ymax = ih - 1; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + cdNormalizeLimits(iw, ih, &xmin, &xmax, &ymin, &ymax); + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (colors == NULL) + colors = cd_getgraycolormap(); + + canvas->cxPutImageRectMap(canvas->ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); +} + +cdImage* cdCanvasCreateImage(cdCanvas* canvas, int w, int h) +{ + cdImage *image; + cdCtxImage *ctximage; + + assert(canvas); + assert(w>0); + assert(h>0); + if (!_cdCheckCanvas(canvas)) return NULL; + if (w <= 0) return NULL; + if (h <= 0) return NULL; + if (!canvas->cxCreateImage) return NULL; + + ctximage = canvas->cxCreateImage(canvas->ctxcanvas, w, h); + if (!ctximage) + return NULL; + + image = (cdImage*)malloc(sizeof(cdImage)); + + image->cxGetImage = canvas->cxGetImage; + image->cxPutImageRect = canvas->cxPutImageRect; + image->cxKillImage = canvas->cxKillImage; + image->w = w; + image->h = h; + image->ctximage = ctximage; + + return image; +} + +void cdCanvasGetImage(cdCanvas* canvas, cdImage* image, int x, int y) +{ + assert(canvas); + assert(image); + if (!_cdCheckCanvas(canvas)) return; + if (!image) return; + if (image->cxGetImage != canvas->cxGetImage) return; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + canvas->cxGetImage(canvas->ctxcanvas, image->ctximage, x, y); +} + +void cdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + assert(image); + if (!_cdCheckCanvas(canvas)) return; + if (!image) return; + if (image->cxPutImageRect != canvas->cxPutImageRect) return; + + if (xmax == 0) xmax = image->w - 1; + if (ymax == 0) ymax = image->h - 1; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + cdNormalizeLimits(image->w, image->h, &xmin, &xmax, &ymin, &ymax); + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + canvas->cxPutImageRect(canvas->ctxcanvas, image->ctximage, x, y, xmin, xmax, ymin, ymax); +} + +void cdKillImage(cdImage* image) +{ + assert(image); + if (!image) return; + + image->cxKillImage(image->ctximage); + memset(image, 0, sizeof(cdImage)); + free(image); +} + +void cdCanvasScrollArea(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + if (!canvas->cxScrollArea) return; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (dx == 0 && dy == 0) + return; + + if (canvas->use_origin) + { + xmin += canvas->origin.x; + xmax += canvas->origin.x; + ymin += canvas->origin.y; + ymax += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + dy = -dy; + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + canvas->cxScrollArea(canvas->ctxcanvas, xmin, xmax, ymin, ymax, dx, dy); +} + +unsigned char cdZeroOrderInterpolation(int width, int height, const unsigned char *map, float xl, float yl) +{ + int x0 = (int)(xl-0.5f); + int y0 = (int)(yl-0.5f); + x0 = x0<0? 0: x0>width-1? width-1: x0; + y0 = y0<0? 0: y0>height-1? height-1: y0; + return map[y0*width + x0]; +} + +unsigned char cdBilinearInterpolation(int width, int height, const unsigned char *map, float xl, float yl) +{ + unsigned char fll, fhl, flh, fhh; + int x0, y0, x1, y1; + float t, u; + + if (xl < 0.5) + { + x1 = x0 = 0; + t = 0; + } + else if (xl > width-0.5) + { + x1 = x0 = width-1; + t = 0; + } + else + { + x0 = (int)(xl-0.5f); + x1 = x0+1; + t = xl - (x0+0.5f); + } + + if (yl < 0.5) + { + y1 = y0 = 0; + u = 0; + } + else if (yl > height-0.5) + { + y1 = y0 = height-1; + u = 0; + } + else + { + y0 = (int)(yl-0.5f); + y1 = y0+1; + u = yl - (y0+0.5f); + } + + fll = map[y0*width + x0]; + fhl = map[y0*width + x1]; + flh = map[y1*width + x0]; + fhh = map[y1*width + x1]; + + return (unsigned char)((fhh - flh - fhl + fll) * u * t + + (fhl - fll) * t + + (flh - fll) * u + + fll); +} + +void cdImageRGBInitInverseTransform(int w, int h, int xmin, int xmax, int ymin, int ymax, float *xfactor, float *yfactor, const double* matrix, double* inv_matrix) +{ + *xfactor = (float)(xmax-xmin)/(float)(w-1); + *yfactor = (float)(ymax-ymin)/(float)(h-1); + cdMatrixInverse(matrix, inv_matrix); +} + +void cdImageRGBInverseTransform(int t_x, int t_y, float *i_x, float *i_y, float xfactor, float yfactor, int xmin, int ymin, int x, int y, double *inv_matrix) +{ + double rx, ry; + cdfMatrixTransformPoint(inv_matrix, t_x, t_y, &rx, &ry); + *i_x = xfactor*((float)rx - x) + xmin; + *i_y = yfactor*((float)ry - y) + ymin; +} + +void cdImageRGBCalcDstLimits(cdCanvas* canvas, int x, int y, int w, int h, int *xmin, int *xmax, int *ymin, int *ymax, int* rect) +{ + int t_xmin, t_xmax, t_ymin, t_ymax, + t_x, t_y, t_w, t_h; + + /* calculate the bounding box of the transformed rectangle */ + cdMatrixTransformPoint(canvas->matrix, x, y, &t_x, &t_y); + if (rect) { rect[0] = t_x; rect[1] = t_y; } + t_xmax = t_xmin = t_x; t_ymax = t_ymin = t_y; + cdMatrixTransformPoint(canvas->matrix, x+w-1, y, &t_x, &t_y); + if (rect) { rect[2] = t_x; rect[3] = t_y; } + if (t_x > t_xmax) t_xmax = t_x; + if (t_x < t_xmin) t_xmin = t_x; + if (t_y > t_ymax) t_ymax = t_y; + if (t_y < t_ymin) t_ymin = t_y; + cdMatrixTransformPoint(canvas->matrix, x+w-1, y+h-1, &t_x, &t_y); + if (rect) { rect[4] = t_x; rect[5] = t_y; } + if (t_x > t_xmax) t_xmax = t_x; + if (t_x < t_xmin) t_xmin = t_x; + if (t_y > t_ymax) t_ymax = t_y; + if (t_y < t_ymin) t_ymin = t_y; + cdMatrixTransformPoint(canvas->matrix, x, y+h-1, &t_x, &t_y); + if (rect) { rect[6] = t_x; rect[7] = t_y; } + if (t_x > t_xmax) t_xmax = t_x; + if (t_x < t_xmin) t_xmin = t_x; + if (t_y > t_ymax) t_ymax = t_y; + if (t_y < t_ymin) t_ymin = t_y; + + t_x = t_xmin; + t_y = t_ymin; + t_w = t_xmax-t_xmin+1; + t_h = t_ymax-t_ymin+1; + + /* check if inside the canvas */ + if (t_x > (canvas->w-1) || t_y > (canvas->h-1) || + (t_x+t_w) < 0 || (t_y+t_h) < 0) + return; + + /* fit to canvas area */ + if (t_x < 0) t_x = 0; + if (t_y < 0) t_y = 0; + if ((t_x+t_w) > (canvas->w-1)) t_w = (canvas->w-1)-t_x; + if ((t_y+t_h) > (canvas->h-1)) t_h = (canvas->h-1)-t_y; + + /* define the destiny limits */ + *xmin = t_x; + *ymin = t_y; + *xmax = t_x+t_w-1; + *ymax = t_y+t_h-1; +} diff --git a/cd/src/cd_primitives.c b/cd/src/cd_primitives.c new file mode 100755 index 0000000..b1a19ba --- /dev/null +++ b/cd/src/cd_primitives.c @@ -0,0 +1,702 @@ +/** \file + * \brief External API - Primitives + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include +#include + + +#include "cd.h" +#include "cd_private.h" + +#define _CD_POLY_BLOCK 100 + +void cdCanvasPixel(cdCanvas* canvas, int x, int y, long color) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + canvas->cxPixel(canvas->ctxcanvas, x, y, color); +} + +void cdCanvasMark(cdCanvas* canvas, int x, int y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->mark_size == 1) + { + cdCanvasPixel(canvas, x, y, canvas->foreground); + return; + } + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + cdSimMark(canvas, x, y); +} + +void cdCanvasLine(cdCanvas* canvas, int x1, int y1, int x2, int y2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (x1 == x2 && y1 == y2) + { + cdCanvasPixel(canvas, x1, y1, canvas->foreground); + return; + } + + if (canvas->use_origin) + { + x1 += canvas->origin.x; + y1 += canvas->origin.y; + x2 += canvas->origin.x; + y2 += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + y1 = _cdInvertYAxis(canvas, y1); + y2 = _cdInvertYAxis(canvas, y2); + } + + canvas->cxLine(canvas->ctxcanvas, x1, y1, x2, y2); +} + +void cdfCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (x1 == x2 && y1 == y2) + { + cdCanvasPixel(canvas, _cdRound(x1), _cdRound(y1), canvas->foreground); + return; + } + + if (canvas->use_origin) + { + x1 += canvas->forigin.x; + y1 += canvas->forigin.y; + x2 += canvas->forigin.x; + y2 += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + { + y1 = _cdInvertYAxis(canvas, y1); + y2 = _cdInvertYAxis(canvas, y2); + } + + if (canvas->cxFLine) + canvas->cxFLine(canvas->ctxcanvas, x1, y1, x2, y2); + else + canvas->cxLine(canvas->ctxcanvas, _cdRound(x1), _cdRound(y1), _cdRound(x2), _cdRound(y2)); +} + +void cdCanvasBegin(cdCanvas* canvas, int mode) +{ + assert(canvas); + assert(mode>=CD_FILL); + if (!_cdCheckCanvas(canvas)) return; + + if (mode == CD_REGION) + { + if (!canvas->cxNewRegion) return; + + canvas->new_region = 1; + canvas->poly_n = 0; + canvas->cxNewRegion(canvas->ctxcanvas); + return; + } + + canvas->sim_poly = 0; + + if (canvas->interior_style == CD_HOLLOW && mode == CD_FILL) + mode = CD_CLOSED_LINES; + + /* simulacao de linhas */ + if ((mode == CD_CLOSED_LINES || mode == CD_OPEN_LINES || mode == CD_BEZIER) && + canvas->sim_mode & CD_SIM_POLYLINE) + canvas->sim_poly = 1; + + /* simulacao de poligonos preenchidos */ + if (mode == CD_FILL && canvas->sim_mode & CD_SIM_POLYGON) + canvas->sim_poly = 1; + + canvas->use_fpoly = -1; + canvas->poly_n = 0; + canvas->poly_mode = mode; +} + +void cdCanvasVertex(cdCanvas* canvas, int x, int y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + if (canvas->use_fpoly == 1) return; /* integer vertex inside a real poligon */ + + if (!canvas->poly) + { + canvas->poly = (cdPoint*)malloc(sizeof(cdPoint)*(_CD_POLY_BLOCK+1)); /* always add 1 so we add another point at the end if necessary */ + canvas->poly_size = _CD_POLY_BLOCK; + } + + canvas->use_fpoly = 0; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (canvas->poly_n == canvas->poly_size) + { + canvas->poly_size += _CD_POLY_BLOCK; + canvas->poly = (cdPoint*)realloc(canvas->poly, sizeof(cdPoint) * (canvas->poly_size+1)); + } + + if (canvas->poly_mode != CD_BEZIER && + canvas->poly_n > 0 && + canvas->poly[canvas->poly_n-1].x == x && + canvas->poly[canvas->poly_n-1].y == y) + return; /* avoid duplicate points, if not a bezier */ + + canvas->poly[canvas->poly_n].x = x; + canvas->poly[canvas->poly_n].y = y; + canvas->poly_n++; +} + +void cdfCanvasVertex(cdCanvas* canvas, double x, double y) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!canvas->cxFPoly) + { + cdCanvasVertex(canvas, _cdRound(x), _cdRound(y)); + return; + } + + if (canvas->use_fpoly == 0) return; /* real vertex inside a integer poligon */ + + if (!canvas->fpoly) + { + canvas->fpoly = (cdfPoint*)malloc(sizeof(cdfPoint)*(_CD_POLY_BLOCK+1)); + canvas->fpoly_size = _CD_POLY_BLOCK; + } + + canvas->use_fpoly = 1; + + if (canvas->use_origin) + { + x += canvas->forigin.x; + y += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (canvas->poly_n == canvas->fpoly_size) + { + canvas->fpoly_size += _CD_POLY_BLOCK; + canvas->fpoly = (cdfPoint*)realloc(canvas->fpoly, sizeof(cdfPoint) * (canvas->fpoly_size+1)); + } + + canvas->fpoly[canvas->poly_n].x = x; + canvas->fpoly[canvas->poly_n].y = y; + canvas->poly_n++; +} + +void cdCanvasEnd(cdCanvas* canvas) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->new_region && canvas->poly_n == 0) + { + canvas->new_region = 0; + if (canvas->clip_mode == CD_CLIPREGION) cdCanvasClip(canvas, CD_CLIPREGION); + return; + } + + if (canvas->poly_mode==CD_OPEN_LINES && canvas->poly_n < 2) + { + canvas->poly_n = 0; + return; + } + + if (canvas->poly_mode==CD_BEZIER && (canvas->poly_n < 4 || ((canvas->poly_n-4)%3 != 0))) + { + canvas->poly_n = 0; + return; + } + + if ((canvas->poly_mode == CD_CLOSED_LINES || + canvas->poly_mode == CD_FILL || + canvas->poly_mode == CD_CLIP) && canvas->poly_n < 3) + { + canvas->poly_n = 0; + return; + } + + if (canvas->sim_poly) + cdpolySIM(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n); + else + { + if (canvas->use_fpoly) + canvas->cxFPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->fpoly, canvas->poly_n); + else + canvas->cxPoly(canvas->ctxcanvas, canvas->poly_mode, canvas->poly, canvas->poly_n); + } + + if (canvas->poly_mode == CD_CLIP) + { + canvas->clip_poly_n = canvas->poly_n; + + if (canvas->clip_fpoly) + { + free(canvas->clip_fpoly); + canvas->clip_fpoly = NULL; + } + + if (canvas->clip_poly) + { + free(canvas->clip_poly); + canvas->clip_poly = NULL; + } + + if (canvas->use_fpoly) + { + canvas->clip_fpoly = (cdfPoint*)malloc((canvas->poly_n+1) * sizeof(cdfPoint)); + memcpy(canvas->clip_fpoly, canvas->fpoly, canvas->poly_n * sizeof(cdfPoint)); + } + else + { + canvas->clip_poly = (cdPoint*)malloc((canvas->poly_n+1) * sizeof(cdPoint)); + memcpy(canvas->clip_poly, canvas->poly, canvas->poly_n * sizeof(cdPoint)); + } + } + + canvas->poly_n = 0; + canvas->use_fpoly = -1; +} + +void cdCanvasRect(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->origin.x; + xmax += canvas->origin.x; + ymin += canvas->origin.y; + ymax += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + canvas->cxRect(canvas->ctxcanvas, xmin, xmax, ymin, ymax); +} + +void cdfCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->origin.x; + xmax += canvas->origin.x; + ymin += canvas->origin.y; + ymax += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapDouble(ymin, ymax); + } + + if (canvas->cxFRect) + canvas->cxFRect(canvas->ctxcanvas, xmin, xmax, ymin, ymax); + else + canvas->cxRect(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax)); +} + +void cdCanvasBox(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->interior_style == CD_HOLLOW) + { + cdCanvasRect(canvas, xmin, xmax, ymin, ymax); + return; + } + + if (!cdCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->origin.x; + xmax += canvas->origin.x; + ymin += canvas->origin.y; + ymax += canvas->origin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + canvas->cxBox(canvas->ctxcanvas, xmin, xmax, ymin, ymax); +} + +void cdfCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (canvas->interior_style == CD_HOLLOW) + { + cdfCanvasRect(canvas, xmin, xmax, ymin, ymax); + return; + } + + if (!cdfCheckBoxSize(&xmin, &xmax, &ymin, &ymax)) + return; + + if (canvas->use_origin) + { + xmin += canvas->forigin.x; + xmax += canvas->forigin.x; + ymin += canvas->forigin.y; + ymax += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + { + ymin = _cdInvertYAxis(canvas, ymin); + ymax = _cdInvertYAxis(canvas, ymax); + _cdSwapDouble(ymin, ymax); + } + + if (canvas->cxFBox) + canvas->cxFBox(canvas->ctxcanvas, xmin, xmax, ymin, ymax); + else + canvas->cxBox(canvas->ctxcanvas, _cdRound(xmin), _cdRound(xmax), _cdRound(ymin), _cdRound(ymax)); +} + +static void normAngles(double *angle1, double *angle2) +{ + *angle1 = fmod(*angle1,360); + *angle2 = fmod(*angle2,360); + if (*angle2 <= *angle1) *angle2 += 360; +} + +void cdCanvasArc(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->use_origin) + { + xc += canvas->origin.x; + yc += canvas->origin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + canvas->cxArc(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); +} + +void cdfCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->use_origin) + { + xc += canvas->forigin.x; + yc += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + + if (canvas->cxFArc) + canvas->cxFArc(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); + else + canvas->cxArc(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2); +} + +void cdCanvasSector(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->interior_style == CD_HOLLOW) + { + cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + + if (fabs(angle2-angle1) < 360) + { + int xi,yi,xf,yf; + + xi = xc + cdRound(w*cos(CD_DEG2RAD*angle1)/2.0); + yi = yc + cdRound(h*sin(CD_DEG2RAD*angle1)/2.0); + + xf = xc + cdRound(w*cos(CD_DEG2RAD*angle2)/2.0); + yf = yc + cdRound(h*sin(CD_DEG2RAD*angle2)/2.0); + + cdCanvasLine(canvas, xi, yi, xc, yc); + cdCanvasLine(canvas, xc, yc, xf, yf); + } + + return; + } + + if (canvas->use_origin) + { + xc += canvas->origin.x; + yc += canvas->origin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + canvas->cxSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); +} + +void cdfCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->interior_style == CD_HOLLOW) + { + cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + + if (fabs(angle2-angle1) < 360) + { + double xi,yi,xf,yf; + + xi = xc + w*cos(CD_DEG2RAD*angle1)/2.0; + yi = yc + h*sin(CD_DEG2RAD*angle1)/2.0; + + xf = xc + w*cos(CD_DEG2RAD*angle2)/2.0; + yf = yc + h*sin(CD_DEG2RAD*angle2)/2.0; + + cdfCanvasLine(canvas, xi, yi, xc, yc); + cdfCanvasLine(canvas, xc, yc, xf, yf); + } + + return; + } + + if (canvas->use_origin) + { + xc += canvas->forigin.x; + yc += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + if (canvas->cxFSector) + canvas->cxFSector(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); + else + canvas->cxSector(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2); +} + +void cdCanvasChord(cdCanvas* canvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->interior_style == CD_HOLLOW) + { + int xi,yi,xf,yf; + + xi = xc + cdRound(w*cos(CD_DEG2RAD*angle1)/2.0); + yi = yc + cdRound(h*sin(CD_DEG2RAD*angle1)/2.0); + + xf = xc + cdRound(w*cos(CD_DEG2RAD*angle2)/2.0); + yf = yc + cdRound(h*sin(CD_DEG2RAD*angle2)/2.0); + + cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + + if (fabs(angle2-angle1) < 360) + cdCanvasLine(canvas, xi, yi, xf, yf); + + return; + } + + if (canvas->use_origin) + { + xc += canvas->origin.x; + yc += canvas->origin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + canvas->cxChord(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); +} + +void cdfCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (angle1 == angle2 || w == 0 || h == 0) + return; + + normAngles(&angle1, &angle2); + + if (canvas->interior_style == CD_HOLLOW) + { + double xi,yi,xf,yf; + + xi = xc + w*cos(CD_DEG2RAD*angle1)/2.0; + yi = yc + h*sin(CD_DEG2RAD*angle1)/2.0; + + xf = xc + w*cos(CD_DEG2RAD*angle2)/2.0; + yf = yc + h*sin(CD_DEG2RAD*angle2)/2.0; + + cdfCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + + if (fabs(angle2-angle1) < 360) + cdfCanvasLine(canvas, xi, yi, xf, yf); + + return; + } + + if (canvas->use_origin) + { + xc += canvas->forigin.x; + yc += canvas->forigin.y; + } + + if (canvas->invert_yaxis) + yc = _cdInvertYAxis(canvas, yc); + + if (canvas->cxFChord) + canvas->cxFChord(canvas->ctxcanvas, xc, yc, w, h, angle1, angle2); + else + canvas->cxChord(canvas->ctxcanvas, _cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), angle1, angle2); +} + +void cdCanvasGetEllipseBox(int xc, int yc, int w, int h, double a1, double a2, int *xmin, int *xmax, int *ymin, int *ymax) +{ +#define _BBOX() \ + if (x > *xmax) *xmax = x; \ + if (y > *ymax) *ymax = y; \ + if (x < *xmin) *xmin = x; \ + if (y < *ymin) *ymin = y; + + int x, y; + + *xmin = (int)(xc+w/2*cos(a1*CD_DEG2RAD)); + *ymin = (int)(yc+h/2*sin(a1*CD_DEG2RAD)); + *xmax = *xmin; + *ymax = *ymin; + + x = (int)(xc+w/2*cos(a2*CD_DEG2RAD)); + y = (int)(yc+h/2*sin(a2*CD_DEG2RAD)); + _BBOX() + + if (a1 > a2) + { + x = xc+w/2; + y = yc; + _BBOX() + } + if ((a1<90 && 90a2 && a2>90) || (a2a2 && a2>180) || (a2a2 && a2>270) || (a2 +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" + + +void cdCanvasText(cdCanvas* canvas, int x, int y, const char *s) +{ + int num_line; + + assert(canvas); + assert(s); + if (!_cdCheckCanvas(canvas)) return; + + if (s[0] == 0) + return; + + if (canvas->use_origin) + { + x += canvas->origin.x; + y += canvas->origin.y; + } + + num_line = cdStrLineCount(s); + if (num_line == 1) + { + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + canvas->cxText(canvas->ctxcanvas, x, y, s, strlen(s)); + } + else + { + int yr, i, line_height, len; + const char *p, *q; + double cos_theta = 0, sin_theta = 0; + + canvas->cxGetFontDim(canvas->ctxcanvas, NULL, &line_height, NULL, NULL); + + if (canvas->text_orientation) + { + int align = canvas->text_alignment; + cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + + /* position vertically at the first line */ + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST || /* it is relative to the full text */ + align == CD_BASE_LEFT || align == CD_BASE_CENTER || align == CD_BASE_RIGHT) /* it is relative to the first line already */ + { + /* Already at position */ + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) /* it is relative to the full text */ + { + cdMovePoint(&x, &y, 0, (num_line-1)*line_height, sin_theta, cos_theta); + } + else /* CD_CENTER || CD_EAST || CD_WEST */ /* it is relative to the full text */ + cdMovePoint(&x, &y, 0, (num_line-1)*line_height/2.0, sin_theta, cos_theta); + } + else + { + int align = canvas->text_alignment; + + /* position vertically at the first line */ + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST || /* it is relative to the full text */ + align == CD_BASE_LEFT || align == CD_BASE_CENTER || align == CD_BASE_RIGHT) /* it is relative to the first line already */ + { + /* Already at position */ + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) /* it is relative to the full text */ + { + y += (num_line-1)*line_height; + } + else /* CD_CENTER || CD_EAST || CD_WEST */ /* it is relative to the full text */ + y += ((num_line-1)*line_height)/2; + } + + p = s; + for(i = 0; i < num_line; i++) + { + q = strchr(p, '\n'); + if (q) len = (int)(q-p); /* Cut the string to contain only one line */ + else len = strlen(p); + + /* Draw the line */ + if (canvas->invert_yaxis) + yr = _cdInvertYAxis(canvas, y); + else + yr = y; + canvas->cxText(canvas->ctxcanvas, x, yr, p, len); + + /* Advance the string */ + if (q) p = q + 1; + + /* Advance a line */ + if (canvas->text_orientation) + cdMovePoint(&x, &y, 0, -line_height, sin_theta, cos_theta); + else + y -= line_height; + } + } +} + +void cdfCanvasText(cdCanvas* canvas, double x, double y, const char *s) +{ + int num_line; + + assert(canvas); + assert(s); + if (!_cdCheckCanvas(canvas)) return; + + if (s[0] == 0) + return; + + if (canvas->use_origin) + { + x += canvas->forigin.x; + y += canvas->forigin.y; + } + + num_line = cdStrLineCount(s); + if (num_line == 1) + { + if (canvas->invert_yaxis) + y = _cdInvertYAxis(canvas, y); + + if (canvas->cxFText) + canvas->cxFText(canvas->ctxcanvas, x, y, s, strlen(s)); + else + canvas->cxText(canvas->ctxcanvas, _cdRound(x), _cdRound(y), s, strlen(s)); + } + else + { + int i, line_height, len; + const char *p, *q; + double yr, cos_theta = 0, sin_theta = 0; + + canvas->cxGetFontDim(canvas->ctxcanvas, NULL, &line_height, NULL, NULL); + + if (canvas->text_orientation) + { + int align = canvas->text_alignment; + cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + + /* position vertically at the first line */ + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST || /* it is relative to the full text */ + align == CD_BASE_LEFT || align == CD_BASE_CENTER || align == CD_BASE_RIGHT) /* it is relative to the first line already */ + { + /* Already at position */ + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) /* it is relative to the full text */ + { + cdfMovePoint(&x, &y, 0, (num_line-1)*line_height, sin_theta, cos_theta); + } + else /* CD_CENTER || CD_EAST || CD_WEST */ /* it is relative to the full text */ + cdfMovePoint(&x, &y, 0, (num_line-1)*line_height/2.0, sin_theta, cos_theta); + } + + p = s; + for(i = 0; i < num_line; i++) + { + q = strchr(p, '\n'); + if (q) len = (int)(q-p); /* Cut the string to contain only one line */ + else len = strlen(p); + + /* Draw the line */ + if (canvas->invert_yaxis) + yr = _cdInvertYAxis(canvas, y); + else + yr = y; + if (canvas->cxFText) + canvas->cxFText(canvas->ctxcanvas, x, yr, p, len); + else + canvas->cxText(canvas->ctxcanvas, _cdRound(x), _cdRound(yr), p, len); + + /* Advance the string */ + if (q) p = q + 1; + + /* Advance a line */ + if (canvas->text_orientation) + cdfMovePoint(&x, &y, 0, -line_height, sin_theta, cos_theta); + else + y -= line_height; + } + } +} + +int cdGetFontSizePixels(cdCanvas* canvas, int size) +{ + if (size < 0) + size = -size; + else + { + double size_mm = (double)size/CD_MM2PT; + size = cdRound(size_mm*canvas->xres); + } + + if (size == 0) + size = 1; + + return size; +} + +int cdGetFontSizePoints(cdCanvas* canvas, int size) +{ + if (size < 0) + { + double size_mm = ((double)-size)/canvas->xres; + size = cdRound(size_mm * CD_MM2PT); + } + + if (size == 0) + size = 1; + + return size; +} + +int cdCanvasFont(cdCanvas* canvas, const char* type_face, int style, int size) +{ + assert(canvas); + assert(style>=-1 && style<=CD_STRIKEOUT); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + if (!type_face || type_face[0]==0) + type_face = canvas->font_type_face; + if (style==-1) + style = canvas->font_style; + if (size==0) + size = canvas->font_size; + + if (strcmp(type_face, canvas->font_type_face)==0 && + style == canvas->font_style && + size == canvas->font_size) + return 1; + + if (canvas->cxFont(canvas->ctxcanvas, type_face, style, size)) + { + strcpy(canvas->font_type_face, type_face); + canvas->font_style = style; + canvas->font_size = size; + canvas->native_font[0] = 0; + return 1; + } + + return 0; +} + +void cdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, int *size) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + if (type_face) strcpy(type_face, canvas->font_type_face); + if (style) *style = canvas->font_style; + if (size) *size = canvas->font_size; +} + +char* cdCanvasNativeFont(cdCanvas* canvas, const char* font) +{ + static char native_font[1024] = ""; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + strcpy(native_font, canvas->native_font); + + if (!font || font[0] == 0) + return native_font; + + if (font == (char*)CD_QUERY) + { + char style[200] = " "; + if (canvas->font_style&CD_BOLD) + strcat(style, "Bold "); + if (canvas->font_style&CD_ITALIC) + strcat(style, "Italic "); + if (canvas->font_style&CD_UNDERLINE) + strcat(style, "Underline "); + if (canvas->font_style&CD_STRIKEOUT) + strcat(style, "Strikeout "); + + sprintf(native_font, "%s,%s %d", canvas->font_type_face, style, canvas->font_size); + return native_font; + } + + if (canvas->cxNativeFont) + { + if (canvas->cxNativeFont(canvas->ctxcanvas, font)) + strcpy(canvas->native_font, font); + } + else + { + char type_face[1024]; + int size, style = CD_PLAIN; + + if (!cdParseIupWinFont(font, type_face, &style, &size)) + { + if (!cdParseXWinFont(font, type_face, &style, &size)) + { + if (!cdParsePangoFont(font, type_face, &style, &size)) + return native_font; + } + } + + if (cdCanvasFont(canvas, type_face, style, size)) + strcpy(canvas->native_font, font); + } + + return native_font; +} + +int cdCanvasTextAlignment(cdCanvas* canvas, int alignment) +{ + int text_alignment; + + assert(canvas); + assert(alignment==CD_QUERY || (alignment>=CD_NORTH && alignment<=CD_BASE_RIGHT)); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + if (alignmentCD_BASE_RIGHT); + + text_alignment = canvas->text_alignment; + + if (alignment == CD_QUERY || alignment == text_alignment) + return text_alignment; + + if (canvas->cxTextAlignment) + canvas->text_alignment = canvas->cxTextAlignment(canvas->ctxcanvas, alignment); + else + canvas->text_alignment = alignment; + + return text_alignment; +} + +double cdCanvasTextOrientation(cdCanvas* canvas, double angle) +{ + double text_orientation; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return CD_ERROR; + + text_orientation = canvas->text_orientation; + + if (angle == CD_QUERY || angle == text_orientation) + return text_orientation; + + if (canvas->cxTextOrientation) + canvas->text_orientation = canvas->cxTextOrientation(canvas->ctxcanvas, angle); + else + canvas->text_orientation = angle; + + return text_orientation; +} + +void cdCanvasGetFontDim(cdCanvas* canvas, int *max_width, int *height, int *ascent, int *descent) +{ + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + canvas->cxGetFontDim(canvas->ctxcanvas, max_width, height, ascent, descent); +} + +void cdCanvasGetTextSize(cdCanvas* canvas, const char *s, int *width, int *height) +{ + int num_line; + + assert(canvas); + assert(s); + if (!_cdCheckCanvas(canvas)) return; + + num_line = cdStrLineCount(s); + if (num_line == 1) + canvas->cxGetTextSize(canvas->ctxcanvas, s, strlen(s), width, height); + else + { + int i, line_height, max_w = 0, w, len; + const char *p, *q; + + p = s; + + canvas->cxGetFontDim(canvas->ctxcanvas, NULL, &line_height, NULL, NULL); + + for(i = 0; i < num_line; i++) + { + q = strchr(p, '\n'); + if (q) len = (int)(q-p); /* Cut the string to contain only one line */ + else len = strlen(p); + + /* Calculate line width */ + canvas->cxGetTextSize(canvas->ctxcanvas, p, len, &w, NULL); + if (w > max_w) max_w = w; + + /* Advance the string */ + if (q) p = q + 1; /* skip line break */ + } + + if (width) *width = max_w; + if (height) *height = num_line*line_height; + } +} + +void cdTextTranslatePoint(cdCanvas* canvas, int x, int y, int w, int h, int baseline, int *rx, int *ry) +{ + /* move to left */ + switch (canvas->text_alignment) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + *rx = x - w; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + *rx = x - w/2; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + *rx = x; + break; + } + + /* move to bottom */ + switch (canvas->text_alignment) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + if (canvas->invert_yaxis) + *ry = y + baseline; + else + *ry = y - baseline; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + *ry = y; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + if (canvas->invert_yaxis) + *ry = y + h; + else + *ry = y - h; + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + if (canvas->invert_yaxis) + *ry = y + h/2; + else + *ry = y - h/2; + break; + } +} + +void cdCanvasGetTextBounds(cdCanvas* canvas, int x, int y, const char *s, int *rect) +{ + int w, h, ascent, line_height, baseline; + int xmin, xmax, ymin, ymax; + int old_invert_yaxis, num_lin; + + assert(canvas); + assert(s); + if (!_cdCheckCanvas(canvas)) return; + + if (s[0] == 0) + return; + + cdCanvasGetTextSize(canvas, s, &w, &h); + cdCanvasGetFontDim(canvas, NULL, &line_height, &ascent, NULL); + baseline = line_height - ascent; + num_lin = h/line_height; + if (num_lin > 1) + baseline += (num_lin-1)*line_height; + + /* from here we are always upwards */ + old_invert_yaxis = canvas->invert_yaxis; + canvas->invert_yaxis = 0; + + /* move to bottom-left */ + cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin); + + xmax = xmin + w-1; + ymax = ymin + h-1; + + if (canvas->text_orientation) + { + double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + + cdRotatePoint(canvas, xmin, ymin, x, y, &rect[0], &rect[1], sin_theta, cos_theta); + cdRotatePoint(canvas, xmax, ymin, x, y, &rect[2], &rect[3], sin_theta, cos_theta); + cdRotatePoint(canvas, xmax, ymax, x, y, &rect[4], &rect[5], sin_theta, cos_theta); + cdRotatePoint(canvas, xmin, ymax, x, y, &rect[6], &rect[7], sin_theta, cos_theta); + } + else + { + rect[0] = xmin; rect[1] = ymin; + rect[2] = xmax; rect[3] = ymin; + rect[4] = xmax; rect[5] = ymax; + rect[6] = xmin; rect[7] = ymax; + } + + canvas->invert_yaxis = old_invert_yaxis; +} + +void cdCanvasGetTextBox(cdCanvas* canvas, int x, int y, const char *s, int *xmin, int *xmax, int *ymin, int *ymax) +{ + int rect[8]; + int _xmin, _xmax, _ymin, _ymax; + + cdCanvasGetTextBounds(canvas, x, y, s, rect); + + _xmin = rect[0]; + _ymin = rect[1]; + _xmax = rect[0]; + _ymax = rect[1]; + + if(rect[2] < _xmin) _xmin = rect[2]; + if(rect[4] < _xmin) _xmin = rect[4]; + if(rect[6] < _xmin) _xmin = rect[6]; + + if(rect[3] < _ymin) _ymin = rect[3]; + if(rect[5] < _ymin) _ymin = rect[5]; + if(rect[7] < _ymin) _ymin = rect[7]; + + if(rect[2] > _xmax) _xmax = rect[2]; + if(rect[4] > _xmax) _xmax = rect[4]; + if(rect[6] > _xmax) _xmax = rect[6]; + + if(rect[3] > _ymax) _ymax = rect[3]; + if(rect[5] > _ymax) _ymax = rect[5]; + if(rect[7] > _ymax) _ymax = rect[7]; + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; +} + +/**************************************************************/ +/* Native Font Format, compatible with Pango Font Description */ +/**************************************************************/ + +/* +The string contains the font name, the style and the size. +Style can be a free combination of some names separated by spaces. +Font name can be a list of font family names separated by comma. +*/ + +#define isspace(_x) (_x == ' ') + +static int cd_find_style_name(const char *name, int len, int *style) +{ +#define CD_STYLE_NUM_NAMES 21 + static struct { const char* name; int style; } cd_style_names[CD_STYLE_NUM_NAMES] = { + {"Normal", 0}, + {"Oblique", CD_ITALIC}, + {"Italic", CD_ITALIC}, + {"Small-Caps", 0}, + {"Ultra-Light", 0}, + {"Light", 0}, + {"Medium", 0}, + {"Semi-Bold", CD_BOLD}, + {"Bold", CD_BOLD}, + {"Ultra-Bold", CD_BOLD}, + {"Heavy", 0}, + {"Ultra-Condensed",0}, + {"Extra-Condensed",0}, + {"Condensed", 0}, + {"Semi-Condensed", 0}, + {"Semi-Expanded", 0}, + {"Expanded", 0}, + {"Extra-Expanded", 0}, + {"Ultra-Expanded", 0}, + {"Underline", CD_UNDERLINE}, + {"Strikeout", CD_STRIKEOUT} + }; + + int i; + for (i = 0; i < CD_STYLE_NUM_NAMES; i++) + { + if (strncmp(cd_style_names[i].name, name, len)==0) + { + *style = cd_style_names[i].style; + return 1; + } + } + + return 0; +} + +static const char * cd_getword(const char *str, const char *last, int *wordlen) +{ + const char *result; + + while (last > str && isspace(*(last - 1))) + last--; + + result = last; + while (result > str && !isspace (*(result - 1))) + result--; + + *wordlen = last - result; + + return result; +} + +int cdParsePangoFont(const char *nativefont, char *type_face, int *style, int *size) +{ + const char *p, *last; + int len, wordlen; + + len = (int)strlen(nativefont); + last = nativefont + len; + p = cd_getword(nativefont, last, &wordlen); + + /* Look for a size at the end of the string */ + if (wordlen != 0) + { + int new_size = atoi(p); + if (new_size != 0) + { + *size = new_size; + last = p; + } + } + + /* Now parse style words */ + p = cd_getword(nativefont, last, &wordlen); + while (wordlen != 0) + { + int new_style = 0; + + if (!cd_find_style_name(p, wordlen, &new_style)) + break; + else + { + *style |= new_style; + + last = p; + p = cd_getword(nativefont, last, &wordlen); + } + } + + /* Remainder is font family list. */ + + /* Trim off trailing white space */ + while (last > nativefont && isspace(*(last - 1))) + last--; + + /* Trim off trailing commas */ + if (last > nativefont && *(last - 1) == ',') + last--; + + /* Again, trim off trailing white space */ + while (last > nativefont && isspace(*(last - 1))) + last--; + + /* Trim off leading white space */ + while (last > nativefont && isspace(*nativefont)) + nativefont++; + + if (nativefont != last) + { + len = (last - nativefont); + strncpy(type_face, nativefont, len); + type_face[len] = 0; + return 1; + } + else + return 0; +} + +int cdParseIupWinFont(const char *nativefont, char *type_face, int *style, int *size) +{ + int c; + + if (strstr(nativefont, ":") == NULL) + return 0; + + c = strcspn(nativefont, ":"); /* extract type_face */ + if (c == 0) return 0; + strncpy(type_face, nativefont, c); + type_face[c]='\0'; + nativefont += c+1; + + if(nativefont[0] == ':') /* check for attributes */ + nativefont++; + else + { + *style = 0; + while(strlen(nativefont)) /* extract style (bold/italic etc) */ + { + char style_str[20]; + + c = strcspn(nativefont, ":,"); + if (c == 0) + break; + + strncpy(style_str, nativefont, c); + style_str[c] = '\0'; + + if(!strcmp(style_str, "BOLD")) + *style |= CD_BOLD; + else if(!strcmp(style_str,"ITALIC")) + *style |= CD_ITALIC; + else if(!strcmp(style_str,"UNDERLINE")) + *style |= CD_UNDERLINE; + else if(!strcmp(style_str,"STRIKEOUT")) + *style |= CD_STRIKEOUT; + + nativefont += c; + + if(nativefont[0] == ':') /* end attribute list */ + { + nativefont++; + break; + } + + nativefont++; /* skip separator */ + } + } + + /* extract size in points */ + if (sscanf(nativefont, "%d", size) != 1) + return 0; + + if (*size == 0) + return 0; + + return 1; +} + +int cdParseXWinFont(const char *nativefont, char *type_face, int *style, int *size) +{ + char style1[10], style2[10]; + char* token; + char font[1024]; + + if (nativefont[0] != '-') + return 0; + + strcpy(font, nativefont+1); /* skip first '-' */ + + *style = 0; + + /* fndry */ + token = strtok(font, "-"); + if (!token) return 0; + + /* fmly */ + token = strtok(NULL, "-"); + if (!token) return 0; + strcpy(type_face, token); + + /* wght */ + token = strtok(NULL, "-"); + if (!token) return 0; + strcpy(style1, token); + if (strstr("bold", style1)) + *style |= CD_BOLD; + + /* slant */ + token = strtok(NULL, "-"); + if (!token) return 0; + strcpy(style2, token); + if (*style2 == 'i' || *style2 == 'o') + *style |= CD_ITALIC; + + /* sWdth */ + token = strtok(NULL, "-"); + if (!token) return 0; + /* adstyl */ + token = strtok(NULL, "-"); + if (!token) return 0; + + /* pxlsz */ + token = strtok(NULL, "-"); + if (!token) return 0; + *size = -atoi(token); /* size in pixels */ + + if (*size < 0) + return 1; + + /* ptSz */ + token = strtok(NULL, "-"); + if (!token) return 0; + *size = atoi(token)/10; /* size in deci-points */ + + if (*size > 0) + return 1; + + return 0; +} diff --git a/cd/src/cd_util.c b/cd/src/cd_util.c new file mode 100755 index 0000000..1767ac4 --- /dev/null +++ b/cd/src/cd_util.c @@ -0,0 +1,351 @@ +/** \file + * \brief Utilities + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include + + +#include "cd.h" + +#include "cd_private.h" + + +int cdRound(double x) +{ + return _cdRound(x); +} + +/* Returns a table to speed up zoom in discrete zoom rotines. + Adds the min parameter and allocates the table using malloc. + The table should be used when mapping from destiny coordinates to + source coordinates (src_pos = tab[dst_pos]). + dst_len is the full destiny size range. + src_len is only the zoomed region size, usually max-min+1. +*/ +int* cdGetZoomTable(int dst_len, int src_len, int src_min) +{ + int dst_i, src_i; + double factor; + int* tab = (int*)malloc(dst_len*sizeof(int)); + + factor = (double)(src_len) / (double)(dst_len); + + for(dst_i = 0; dst_i < dst_len; dst_i++) + { + src_i = cdRound((factor*(dst_i + 0.5)) - 0.5); + tab[dst_i] = src_i + src_min; + } + + return tab; +} + +/* funcao usada para calcular os retangulos efetivos de zoom + de imagens clientes. Pode ser usada para os eixos X e Y. + + canvas_size - tamanho do canvas (canvas->w, canvas->h) + cnv_rect_pos - posicao no canvas onde a regiao sera´ desenhada (x, y) + cnv_rect_size - tamanho da regiao no canvas com zoom (w, h) + img_rect_pos - posicao na imagem da regiao a ser desenhada (min) + img_rect_size - tamanho da regiao na imagem (max-min+1) + + calcula o melhor tamanho a ser usado + retorna 0 se o retangulo resultante e´ nulo +*/ +int cdCalcZoom(int canvas_size, + int cnv_rect_pos, int cnv_rect_size, + int *new_cnv_rect_pos, int *new_cnv_rect_size, + int img_rect_pos, int img_rect_size, + int *new_img_rect_pos, int *new_img_rect_size, + int is_horizontal) +{ + int offset; + float zoom_factor = (float)img_rect_size / (float)cnv_rect_size; + + /* valores default sem otimizacao */ + *new_cnv_rect_size = cnv_rect_size, *new_cnv_rect_pos = cnv_rect_pos; + *new_img_rect_size = img_rect_size, *new_img_rect_pos = img_rect_pos; + + if (cnv_rect_size > 0) + { + /* se posicao no canvas > tamanho do canvas, fora da janela, nao desenha nada */ + if (cnv_rect_pos >= canvas_size) + return 0; + + /* se posicao no canvas + tamanho da regiao no canvas < 0, fora da janela, nao desenha nada */ + if (cnv_rect_pos+cnv_rect_size < 0) + return 0; + + /* se posicao no canvas < 0, entao comeca fora do canvas melhor posicao no canvas e' 0 + E o tamanho e' reduzido do valor negativo */ + if (cnv_rect_pos < 0) + { + /* valores ajustados para cair numa vizinhanca de um pixel da imagem */ + offset = (int)ceil(cnv_rect_pos*zoom_factor); /* offset is <0 */ + offset = (int)ceil(offset/zoom_factor); + *new_cnv_rect_pos -= offset; + *new_cnv_rect_size += offset; + } + + /* se posicao no canvas + tamanho da regiao no canvas > tamanho do canvas, + termina fora do canvas entao + o tamanho da regiao no canvas e' o tamanho do canvas reduzido da posicao */ + if (*new_cnv_rect_pos+*new_cnv_rect_size > canvas_size) + { + offset = (int)((*new_cnv_rect_pos+*new_cnv_rect_size - canvas_size)*zoom_factor); + *new_cnv_rect_size -= (int)(offset/zoom_factor); /* offset is >0 */ + } + } + else + { + /* cnv_rect_size tamanho negativo, significa imagem top down */ + /* calculos adicionados pela Paula */ + + /* se posicao no canvas + tamanho no canvas (xmin+1) >= tamanho do canvas, fora da janela, nao desenha nada */ + if (cnv_rect_pos+cnv_rect_size >= canvas_size) + return 0; + + /* se posicao da imagem com zoom (xmax) < 0, fora da janela, nao desenha nada */ + if (cnv_rect_pos < 0) + return 0; + + /* se posicao com zoom (xmax) >= tamanho do canvas, posicao da imagem com zoom e' o tamanho do canvas menos um + tambem o tamanho e' reduzido do valor negativo */ + if (cnv_rect_pos >= canvas_size) + { + *new_cnv_rect_pos = canvas_size-1; + *new_cnv_rect_size = cnv_rect_size + (cnv_rect_pos - *new_cnv_rect_pos); + } + + /* se posicao + tamanho com zoom (xmin+1) < 0, + entao o tamanho com zoom e' a posição + 1 */ + if (cnv_rect_pos+cnv_rect_size < 0) + *new_cnv_rect_size = -(*new_cnv_rect_pos + 1); + } + + /* agora ja' tenho tamanho e posicao da regiao no canvas, + tenho que obter tamanho e posicao dentro da imagem original, + baseado nos novos valores */ + + /* tamanho da regiao na imagem e' a conversao de zoom para real do tamanho no canvas */ + *new_img_rect_size = (int)(*new_cnv_rect_size * zoom_factor + 0.5); + + if (is_horizontal) + { + /* em X, o offset dentro da imagem so' existe se houver diferenca entre a posicao inicial da + imagem e a posicao otimizada (ambas da imagem com zoom) */ + if (*new_cnv_rect_pos != cnv_rect_pos) + { + offset = *new_cnv_rect_pos - cnv_rect_pos; /* offset is >0 */ + *new_img_rect_pos += (int)(offset*zoom_factor); + } + } + else + { + /* em Y, o offset dentro da imagem so' existe se houver diferenca entre a posicao + final (posição inicial + tamanho) da imagem e a posicao otimizada (ambas da + imagem com zoom) */ + if ((cnv_rect_pos + cnv_rect_size) != (*new_cnv_rect_pos + *new_cnv_rect_size)) + { + /* offset is >0, because Y axis is from top to bottom */ + offset = (cnv_rect_pos + cnv_rect_size) - (*new_cnv_rect_pos + *new_cnv_rect_size); + *new_img_rect_pos += (int)(offset*zoom_factor); + } + } + + return 1; +} + +int cdGetFileName(const char* strdata, char* filename) +{ + const char* start = strdata; + if (!strdata || strdata[0] == 0) return 0; + + if (strdata[0] == '\"') + { + strdata++; /* the first " */ + while(*strdata && *strdata != '\"') + *filename++ = *strdata++; + strdata++; /* the last " */ + } + else + { + while(*strdata && *strdata != ' ') + *filename++ = *strdata++; + } + + if (*strdata == ' ') + strdata++; + + *filename = 0; + return (int)(strdata - start); +} + +void cdNormalizeLimits(int w, int h, int *xmin, int *xmax, int *ymin, int *ymax) +{ + *xmin = *xmin < 0? 0: *xmin < w? *xmin: (w - 1); + *ymin = *ymin < 0? 0: *ymin < h? *ymin: (h - 1); + *xmax = *xmax < 0? 0: *xmax < w? *xmax: (w - 1); + *ymax = *ymax < 0? 0: *ymax < h? *ymax: (h - 1); +} + +int cdCheckBoxSize(int *xmin, int *xmax, int *ymin, int *ymax) +{ + if (*xmin > *xmax) _cdSwapInt(*xmin, *xmax); + if (*ymin > *ymax) _cdSwapInt(*ymin, *ymax); + + if ((*xmax-*xmin+1) <= 0) + return 0; + + if ((*ymax-*ymin+1) <= 0) + return 0; + + return 1; +} + +int cdfCheckBoxSize(double *xmin, double *xmax, double *ymin, double *ymax) +{ + if (*xmin > *xmax) _cdSwapDouble(*xmin, *xmax); + if (*ymin > *ymax) _cdSwapDouble(*ymin, *ymax); + + if ((*xmax-*xmin+1) <= 0) + return 0; + + if ((*ymax-*ymin+1) <= 0) + return 0; + + return 1; +} + +void cdMovePoint(int *x, int *y, double dx, double dy, double sin_theta, double cos_theta) +{ + double t; + t = cos_theta*dx - sin_theta*dy; + *x += _cdRound(t); + t = sin_theta*dx + cos_theta*dy; + *y += _cdRound(t); +} + +void cdfMovePoint(double *x, double *y, double dx, double dy, double sin_theta, double cos_theta) +{ + *x += cos_theta*dx - sin_theta*dy; + *y += sin_theta*dx + cos_theta*dy; +} + +void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int *ry, double sin_theta, double cos_theta) +{ + double t; + + /* translate to (cx,cy) */ + x = x - cx; + y = y - cy; + + /* rotate */ + if (canvas->invert_yaxis) + { + t = (x * cos_theta) + (y * sin_theta); *rx = _cdRound(t); + t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t); + } + else + { + t = (x * cos_theta) - (y * sin_theta); *rx = _cdRound(t); + t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t); + } + + /* translate back */ + *rx = *rx + cx; + *ry = *ry + cy; +} + +void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta) +{ + double t; + + /* translate to (cx,cy) */ + x = x - cx; + y = y - cy; + + /* rotate */ + if (canvas->invert_yaxis) + { + t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t); + } + else + { + t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t); + } + + /* translate back */ + *ry = *ry + cy; +} + +int cdStrEqualNoCase(const char* str1, const char* str2) +{ + int i = 0; + if (str1 == str2) return 1; + if (!str1 || !str2 || tolower(*str1) != tolower(*str2)) return 0; + + while (str1[i] && str2[i] && tolower(str1[i])==tolower(str2[i])) + i++; + if (str1[i] == str2[i]) return 1; + + return 0; +} + +/* Copied from IUP3, simply ignore line breaks other than '\n' for CD */ + +int cdStrLineCount(const char* str) +{ + int num_lin = 1; + + if (!str) + return num_lin; + + while(*str != 0) + { + while(*str!=0 && *str!='\n') + str++; + + if (*str=='\n') /* UNIX line end */ + { + num_lin++; + str++; + } + } + + return num_lin; +} + +char* cdStrDup(const char *str) +{ + if (str) + { + int size = strlen(str)+1; + char *newstr = malloc(size); + if (newstr) memcpy(newstr, str, size); + return newstr; + } + return NULL; +} + +char* cdStrDupN(const char *str, int len) +{ + if (str) + { + int size = len+1; + char *newstr = malloc(size); + if (newstr) + { + memcpy(newstr, str, len); + newstr[len]=0; + } + return newstr; + } + return NULL; +} diff --git a/cd/src/cd_vectortext.c b/cd/src/cd_vectortext.c new file mode 100755 index 0000000..4e196b6 --- /dev/null +++ b/cd/src/cd_vectortext.c @@ -0,0 +1,5189 @@ +/** \file + * \brief Vector Text + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" +#include "cd_private.h" + + +#define MULTILINE_MAXLEN 10240 + +typedef struct cdOperation +{ + char operation; + signed char x, y; +} cdOperation; + +typedef struct cdCaracter +{ + int right, center, operations; + cdOperation *op; +} cdCaracter; + +struct _cdVectorFont +{ + /* font data */ + char name[256]; /* font name */ + char file_name[10240]; /* font file name */ + cdCaracter *chars; /* array of characters */ + int top, /* from baseline to top */ + cap, /* from baseline to cap (UNUSED) */ + half, /* half between top and bottom (UNUSED) */ + bottom; /* from baseline to bottom (negative) */ + + /* attributes (independ from font) */ + double size_x, size_y; /* internal font size */ + double current_cos, current_sin; /* text direction */ + + /* general transformation matrix */ + int text_transf; + double text_matrix[6]; + + cdCanvas* canvas; +}; + +static unsigned char vf_ansi2ascii[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +/* 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, */ + 199, 252, 233, 226, 228, 224, 229, 231, 234, 235, 232, 239, 238, 236, 196, 197, 201, 230, 198, 244, 246, 242, 251, 249, 255, 214, 220, 155, 156, 157, 158, 159, +/* 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, */ + 225, 237, 243, 250, 241, 209, 170, 176, 191, 169, 166, 189, 188, 173, 174, 175, 167, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 172, 171, 190, 168, +/* 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, */ + 192, 193, 194, 195, 142, 143, 146, 128, 200, 144, 202, 203, 204, 205, 206, 207, 208, 165, 210, 211, 212, 213, 153, 215, 216, 217, 218, 219, 154, 221, 222, 223, +/* 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, */ + 133, 160, 131, 227, 132, 134, 145, 135, 138, 130, 136, 137, 141, 161, 140, 139, 240, 164, 149, 162, 147, 245, 148, 247, 248, 151, 163, 150, 129, 253, 254, 152 +}; + +/******************************************************/ +/* descricao do fonte default */ +/******************************************************/ + +static int vf_default_top = 28; +static int vf_default_cap = 28; +static int vf_default_half = 14; +static int vf_default_bottom = -7; + +static cdOperation vf_default_char_33[] = { +{'m', 1, 21}, +{'l', 1, 7}, +{'m', 1, 2}, +{'l', 0, 1}, +{'l', 1, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +}; +static cdOperation vf_default_char_34[] = { +{'m', 1, 21}, +{'l', 0, 20}, +{'l', 0, 14}, +{'m', 1, 20}, +{'l', 0, 14}, +{'m', 1, 21}, +{'l', 2, 20}, +{'l', 0, 14}, +{'m', 10, 21}, +{'l', 9, 20}, +{'l', 9, 14}, +{'m', 10, 20}, +{'l', 9, 14}, +{'m', 10, 21}, +{'l', 11, 20}, +{'l', 9, 14}, +}; +static cdOperation vf_default_char_35[] = { +{'m', 8, 21}, +{'l', 1, -7}, +{'m', 14, 21}, +{'l', 7, -7}, +{'m', 1, 10}, +{'l', 15, 10}, +{'m', 0, 4}, +{'l', 14, 4}, +}; +static cdOperation vf_default_char_36[] = { +{'m', 5, 25}, +{'l', 5, -4}, +{'m', 9, 25}, +{'l', 9, -4}, +{'m', 13, 18}, +{'l', 12, 17}, +{'l', 13, 16}, +{'l', 14, 17}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 9, 21}, +{'l', 5, 21}, +{'l', 2, 20}, +{'l', 0, 18}, +{'l', 0, 16}, +{'l', 1, 14}, +{'l', 2, 13}, +{'l', 4, 12}, +{'l', 10, 10}, +{'l', 12, 9}, +{'l', 14, 7}, +{'m', 0, 16}, +{'l', 2, 14}, +{'l', 4, 13}, +{'l', 10, 11}, +{'l', 12, 10}, +{'l', 13, 9}, +{'l', 14, 7}, +{'l', 14, 3}, +{'l', 12, 1}, +{'l', 9, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 0, 3}, +{'l', 0, 4}, +{'l', 1, 5}, +{'l', 2, 4}, +{'l', 1, 3}, +}; +static cdOperation vf_default_char_37[] = { +{'m', 18, 21}, +{'l', 0, 0}, +{'m', 5, 21}, +{'l', 7, 19}, +{'l', 7, 17}, +{'l', 6, 15}, +{'l', 4, 14}, +{'l', 2, 14}, +{'l', 0, 16}, +{'l', 0, 18}, +{'l', 1, 20}, +{'l', 3, 21}, +{'l', 5, 21}, +{'l', 7, 20}, +{'l', 10, 19}, +{'l', 13, 19}, +{'l', 16, 20}, +{'l', 18, 21}, +{'m', 14, 7}, +{'l', 12, 6}, +{'l', 11, 4}, +{'l', 11, 2}, +{'l', 13, 0}, +{'l', 15, 0}, +{'l', 17, 1}, +{'l', 18, 3}, +{'l', 18, 5}, +{'l', 16, 7}, +{'l', 14, 7}, +}; +static cdOperation vf_default_char_38[] = { +{'m', 18, 13}, +{'l', 17, 12}, +{'l', 18, 11}, +{'l', 19, 12}, +{'l', 19, 13}, +{'l', 18, 14}, +{'l', 17, 14}, +{'l', 16, 13}, +{'l', 15, 11}, +{'l', 13, 6}, +{'l', 11, 3}, +{'l', 9, 1}, +{'l', 7, 0}, +{'l', 4, 0}, +{'l', 1, 1}, +{'l', 0, 3}, +{'l', 0, 6}, +{'l', 1, 8}, +{'l', 7, 12}, +{'l', 9, 14}, +{'l', 10, 16}, +{'l', 10, 18}, +{'l', 9, 20}, +{'l', 7, 21}, +{'l', 5, 20}, +{'l', 4, 18}, +{'l', 4, 16}, +{'l', 5, 13}, +{'l', 7, 10}, +{'l', 12, 3}, +{'l', 14, 1}, +{'l', 17, 0}, +{'l', 18, 0}, +{'l', 19, 1}, +{'l', 19, 2}, +{'m', 4, 0}, +{'l', 2, 1}, +{'l', 1, 3}, +{'l', 1, 6}, +{'l', 2, 8}, +{'l', 4, 10}, +{'m', 4, 16}, +{'l', 5, 14}, +{'l', 13, 3}, +{'l', 15, 1}, +{'l', 17, 0}, +}; +static cdOperation vf_default_char_39[] = { +{'m', 1, 19}, +{'l', 0, 20}, +{'l', 1, 21}, +{'l', 2, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 15}, +}; +static cdOperation vf_default_char_40[] = { +{'m', 7, 25}, +{'l', 5, 23}, +{'l', 3, 20}, +{'l', 1, 16}, +{'l', 0, 11}, +{'l', 0, 7}, +{'l', 1, 2}, +{'l', 3, -2}, +{'l', 5, -5}, +{'l', 7, -7}, +{'m', 5, 23}, +{'l', 3, 19}, +{'l', 2, 16}, +{'l', 1, 11}, +{'l', 1, 7}, +{'l', 2, 2}, +{'l', 3, -1}, +{'l', 5, -5}, +}; +static cdOperation vf_default_char_41[] = { +{'m', 0, 25}, +{'l', 2, 23}, +{'l', 4, 20}, +{'l', 6, 16}, +{'l', 7, 11}, +{'l', 7, 7}, +{'l', 6, 2}, +{'l', 4, -2}, +{'l', 2, -5}, +{'l', 0, -7}, +{'m', 2, 23}, +{'l', 4, 19}, +{'l', 5, 16}, +{'l', 6, 11}, +{'l', 6, 7}, +{'l', 5, 2}, +{'l', 4, -1}, +{'l', 2, -5}, +}; +static cdOperation vf_default_char_42[] = { +{'m', 5, 21}, +{'l', 5, 9}, +{'m', 0, 18}, +{'l', 10, 12}, +{'m', 10, 18}, +{'l', 0, 12}, +}; +static cdOperation vf_default_char_43[] = { +{'m', 9, 18}, +{'l', 9, 0}, +{'m', 0, 9}, +{'l', 18, 9}, +}; +static cdOperation vf_default_char_44[] = { +{'m', 2, 1}, +{'l', 1, 0}, +{'l', 0, 1}, +{'l', 1, 2}, +{'l', 2, 1}, +{'l', 2, -1}, +{'l', 1, -3}, +{'l', 0, -4}, +}; +static cdOperation vf_default_char_45[] = { +{'m', 0, 9}, +{'l', 18, 9}, +}; +static cdOperation vf_default_char_46[] = { +{'m', 1, 2}, +{'l', 0, 1}, +{'l', 1, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +}; +static cdOperation vf_default_char_47[] = { +{'m', 0, -3}, +{'l', 14, 21}, +}; +static cdOperation vf_default_char_48[] = { +{'m', 6, 21}, +{'l', 3, 20}, +{'l', 1, 17}, +{'l', 0, 12}, +{'l', 0, 9}, +{'l', 1, 4}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 4}, +{'l', 14, 9}, +{'l', 14, 12}, +{'l', 13, 17}, +{'l', 11, 20}, +{'l', 8, 21}, +{'l', 6, 21}, +}; +static cdOperation vf_default_char_49[] = { +{'m', 0, 17}, +{'l', 2, 18}, +{'l', 5, 21}, +{'l', 5, 0}, +}; +static cdOperation vf_default_char_50[] = { +{'m', 1, 16}, +{'l', 1, 17}, +{'l', 2, 19}, +{'l', 3, 20}, +{'l', 5, 21}, +{'l', 9, 21}, +{'l', 11, 20}, +{'l', 12, 19}, +{'l', 13, 17}, +{'l', 13, 15}, +{'l', 12, 13}, +{'l', 10, 10}, +{'l', 0, 0}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_51[] = { +{'m', 2, 21}, +{'l', 13, 21}, +{'l', 7, 13}, +{'l', 10, 13}, +{'l', 12, 12}, +{'l', 13, 11}, +{'l', 14, 8}, +{'l', 14, 6}, +{'l', 13, 3}, +{'l', 11, 1}, +{'l', 8, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +{'l', 0, 4}, +}; +static cdOperation vf_default_char_52[] = { +{'m', 10, 21}, +{'l', 0, 7}, +{'l', 15, 7}, +{'m', 10, 21}, +{'l', 10, 0}, +}; +static cdOperation vf_default_char_53[] = { +{'m', 12, 21}, +{'l', 2, 21}, +{'l', 1, 12}, +{'l', 2, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +{'l', 11, 13}, +{'l', 13, 11}, +{'l', 14, 8}, +{'l', 14, 6}, +{'l', 13, 3}, +{'l', 11, 1}, +{'l', 8, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +{'l', 0, 4}, +}; +static cdOperation vf_default_char_54[] = { +{'m', 12, 18}, +{'l', 11, 20}, +{'l', 8, 21}, +{'l', 6, 21}, +{'l', 3, 20}, +{'l', 1, 17}, +{'l', 0, 12}, +{'l', 0, 7}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 7, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 7}, +{'l', 12, 10}, +{'l', 10, 12}, +{'l', 7, 13}, +{'l', 6, 13}, +{'l', 3, 12}, +{'l', 1, 10}, +{'l', 0, 7}, +}; +static cdOperation vf_default_char_55[] = { +{'m', 14, 21}, +{'l', 4, 0}, +{'m', 0, 21}, +{'l', 14, 21}, +}; +static cdOperation vf_default_char_56[] = { +{'m', 5, 21}, +{'l', 2, 20}, +{'l', 1, 18}, +{'l', 1, 16}, +{'l', 2, 14}, +{'l', 4, 13}, +{'l', 8, 12}, +{'l', 11, 11}, +{'l', 13, 9}, +{'l', 14, 7}, +{'l', 14, 4}, +{'l', 13, 2}, +{'l', 12, 1}, +{'l', 9, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +{'l', 0, 4}, +{'l', 0, 7}, +{'l', 1, 9}, +{'l', 3, 11}, +{'l', 6, 12}, +{'l', 10, 13}, +{'l', 12, 14}, +{'l', 13, 16}, +{'l', 13, 18}, +{'l', 12, 20}, +{'l', 9, 21}, +{'l', 5, 21}, +}; +static cdOperation vf_default_char_57[] = { +{'m', 13, 14}, +{'l', 12, 11}, +{'l', 10, 9}, +{'l', 7, 8}, +{'l', 6, 8}, +{'l', 3, 9}, +{'l', 1, 11}, +{'l', 0, 14}, +{'l', 0, 15}, +{'l', 1, 18}, +{'l', 3, 20}, +{'l', 6, 21}, +{'l', 7, 21}, +{'l', 10, 20}, +{'l', 12, 18}, +{'l', 13, 14}, +{'l', 13, 9}, +{'l', 12, 4}, +{'l', 10, 1}, +{'l', 7, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 1, 3}, +}; +static cdOperation vf_default_char_58[] = { +{'m', 1, 14}, +{'l', 0, 13}, +{'l', 1, 12}, +{'l', 2, 13}, +{'l', 1, 14}, +{'m', 1, 2}, +{'l', 0, 1}, +{'l', 1, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +}; +static cdOperation vf_default_char_59[] = { +{'m', 1, 14}, +{'l', 0, 13}, +{'l', 1, 12}, +{'l', 2, 13}, +{'l', 1, 14}, +{'m', 2, 1}, +{'l', 1, 0}, +{'l', 0, 1}, +{'l', 1, 2}, +{'l', 2, 1}, +{'l', 2, -1}, +{'l', 1, -3}, +{'l', 0, -4}, +}; +static cdOperation vf_default_char_60[] = { +{'m', 16, 18}, +{'l', 0, 9}, +{'l', 16, 0}, +}; +static cdOperation vf_default_char_61[] = { +{'m', 0, 12}, +{'l', 18, 12}, +{'m', 0, 6}, +{'l', 18, 6}, +}; +static cdOperation vf_default_char_62[] = { +{'m', 0, 18}, +{'l', 16, 9}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_63[] = { +{'m', 0, 16}, +{'l', 0, 17}, +{'l', 1, 19}, +{'l', 2, 20}, +{'l', 4, 21}, +{'l', 8, 21}, +{'l', 10, 20}, +{'l', 11, 19}, +{'l', 12, 17}, +{'l', 12, 15}, +{'l', 11, 13}, +{'l', 10, 12}, +{'l', 6, 10}, +{'l', 6, 7}, +{'m', 6, 2}, +{'l', 5, 1}, +{'l', 6, 0}, +{'l', 7, 1}, +{'l', 6, 2}, +}; +static cdOperation vf_default_char_64[] = { +{'m', 15, 13}, +{'l', 14, 15}, +{'l', 12, 16}, +{'l', 9, 16}, +{'l', 7, 15}, +{'l', 6, 14}, +{'l', 5, 11}, +{'l', 5, 8}, +{'l', 6, 6}, +{'l', 8, 5}, +{'l', 11, 5}, +{'l', 13, 6}, +{'l', 14, 8}, +{'m', 9, 16}, +{'l', 7, 14}, +{'l', 6, 11}, +{'l', 6, 8}, +{'l', 7, 6}, +{'l', 8, 5}, +{'m', 15, 16}, +{'l', 14, 8}, +{'l', 14, 6}, +{'l', 16, 5}, +{'l', 18, 5}, +{'l', 20, 7}, +{'l', 21, 10}, +{'l', 21, 12}, +{'l', 20, 15}, +{'l', 19, 17}, +{'l', 17, 19}, +{'l', 15, 20}, +{'l', 12, 21}, +{'l', 9, 21}, +{'l', 6, 20}, +{'l', 4, 19}, +{'l', 2, 17}, +{'l', 1, 15}, +{'l', 0, 12}, +{'l', 0, 9}, +{'l', 1, 6}, +{'l', 2, 4}, +{'l', 4, 2}, +{'l', 6, 1}, +{'l', 9, 0}, +{'l', 12, 0}, +{'l', 15, 1}, +{'l', 17, 2}, +{'l', 18, 3}, +{'m', 16, 16}, +{'l', 15, 8}, +{'l', 15, 6}, +{'l', 16, 5}, +}; +static cdOperation vf_default_char_65[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +}; +static cdOperation vf_default_char_66[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 9, 21}, +{'l', 12, 20}, +{'l', 13, 19}, +{'l', 14, 17}, +{'l', 14, 15}, +{'l', 13, 13}, +{'l', 12, 12}, +{'l', 9, 11}, +{'m', 0, 11}, +{'l', 9, 11}, +{'l', 12, 10}, +{'l', 13, 9}, +{'l', 14, 7}, +{'l', 14, 4}, +{'l', 13, 2}, +{'l', 12, 1}, +{'l', 9, 0}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_67[] = { +{'m', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +}; +static cdOperation vf_default_char_68[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 7, 21}, +{'l', 10, 20}, +{'l', 12, 18}, +{'l', 13, 16}, +{'l', 14, 13}, +{'l', 14, 8}, +{'l', 13, 5}, +{'l', 12, 3}, +{'l', 10, 1}, +{'l', 7, 0}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_69[] = { +{'m', 13, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'l', 13, 0}, +{'m', 0, 11}, +{'l', 8, 11}, +}; +static cdOperation vf_default_char_70[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 13, 21}, +{'m', 0, 11}, +{'l', 8, 11}, +}; +static cdOperation vf_default_char_71[] = { +{'m', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 15, 8}, +{'m', 10, 8}, +{'l', 15, 8}, +}; +static cdOperation vf_default_char_72[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 14, 21}, +{'l', 14, 0}, +{'m', 0, 11}, +{'l', 14, 11}, +}; +static cdOperation vf_default_char_73[] = { +{'m', 0, 21}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_74[] = { +{'m', 10, 21}, +{'l', 10, 5}, +{'l', 9, 2}, +{'l', 8, 1}, +{'l', 6, 0}, +{'l', 4, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +{'l', 0, 5}, +{'l', 0, 7}, +}; +static cdOperation vf_default_char_75[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 14, 21}, +{'l', 0, 7}, +{'m', 5, 12}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_76[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 0}, +{'l', 12, 0}, +}; +static cdOperation vf_default_char_77[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 16, 0}, +}; +static cdOperation vf_default_char_78[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 14, 0}, +{'m', 14, 21}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_79[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +}; +static cdOperation vf_default_char_80[] = { +{'m', 0, 10}, +{'l', 9, 10}, +{'l', 12, 11}, +{'l', 13, 12}, +{'l', 14, 14}, +{'l', 14, 17}, +{'l', 13, 19}, +{'l', 12, 20}, +{'l', 9, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_81[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 9, 4}, +{'l', 15, -2}, +}; +static cdOperation vf_default_char_82[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 9, 21}, +{'l', 12, 20}, +{'l', 13, 19}, +{'l', 14, 17}, +{'l', 14, 15}, +{'l', 13, 13}, +{'l', 12, 12}, +{'l', 9, 11}, +{'l', 0, 11}, +{'m', 7, 11}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_83[] = { +{'m', 14, 18}, +{'l', 12, 20}, +{'l', 9, 21}, +{'l', 5, 21}, +{'l', 2, 20}, +{'l', 0, 18}, +{'l', 0, 16}, +{'l', 1, 14}, +{'l', 2, 13}, +{'l', 4, 12}, +{'l', 10, 10}, +{'l', 12, 9}, +{'l', 13, 8}, +{'l', 14, 6}, +{'l', 14, 3}, +{'l', 12, 1}, +{'l', 9, 0}, +{'l', 5, 0}, +{'l', 2, 1}, +{'l', 0, 3}, +}; +static cdOperation vf_default_char_84[] = { +{'m', 7, 21}, +{'l', 7, 0}, +{'m', 0, 21}, +{'l', 14, 21}, +}; +static cdOperation vf_default_char_85[] = { +{'m', 0, 21}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 21}, +}; +static cdOperation vf_default_char_86[] = { +{'m', 0, 21}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 0}, +}; +static cdOperation vf_default_char_87[] = { +{'m', 0, 21}, +{'l', 5, 0}, +{'m', 10, 21}, +{'l', 5, 0}, +{'m', 10, 21}, +{'l', 15, 0}, +{'m', 20, 21}, +{'l', 15, 0}, +}; +static cdOperation vf_default_char_88[] = { +{'m', 0, 21}, +{'l', 14, 0}, +{'m', 14, 21}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_89[] = { +{'m', 0, 21}, +{'l', 8, 11}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 11}, +}; +static cdOperation vf_default_char_90[] = { +{'m', 14, 21}, +{'l', 0, 0}, +{'m', 0, 21}, +{'l', 14, 21}, +{'m', 0, 0}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_91[] = { +{'m', 0, 19}, +{'l', 0, -1}, +{'m', 1, 19}, +{'l', 1, -1}, +{'m', 0, 19}, +{'l', 5, 19}, +{'m', 0, -1}, +{'l', 5, -1}, +}; +static cdOperation vf_default_char_92[] = { +{'m', 0, 21}, +{'l', 14, -3}, +}; +static cdOperation vf_default_char_93[] = { +{'m', 4, 19}, +{'l', 4, -1}, +{'m', 5, 19}, +{'l', 5, -1}, +{'m', 0, 19}, +{'l', 5, 19}, +{'m', 0, -1}, +{'l', 5, -1}, +}; +static cdOperation vf_default_char_94[] = { +{'m', 8, 18}, +{'l', 3, 14}, +{'l', 8, 19}, +{'l', 13, 14}, +{'l', 8, 18}, +{'l', 8, 18}, +}; +static cdOperation vf_default_char_95[] = { +{'m', 0, -7}, +{'l', 16, -7}, +}; +static cdOperation vf_default_char_96[] = { +{'m', 2, 21}, +{'l', 1, 20}, +{'l', 0, 18}, +{'l', 0, 16}, +{'l', 1, 15}, +{'l', 2, 16}, +{'l', 1, 17}, +}; +static cdOperation vf_default_char_97[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_98[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 11}, +{'l', 2, 13}, +{'l', 4, 14}, +{'l', 7, 14}, +{'l', 9, 13}, +{'l', 11, 11}, +{'l', 12, 8}, +{'l', 12, 6}, +{'l', 11, 3}, +{'l', 9, 1}, +{'l', 7, 0}, +{'l', 4, 0}, +{'l', 2, 1}, +{'l', 0, 3}, +}; +static cdOperation vf_default_char_99[] = { +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_100[] = { +{'m', 12, 21}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_101[] = { +{'m', 0, 8}, +{'l', 12, 8}, +{'l', 12, 10}, +{'l', 11, 12}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_102[] = { +{'m', 8, 21}, +{'l', 6, 21}, +{'l', 4, 20}, +{'l', 3, 17}, +{'l', 3, 0}, +{'m', 0, 14}, +{'l', 7, 14}, +}; +static cdOperation vf_default_char_103[] = { +{'m', 12, 14}, +{'l', 12, -2}, +{'l', 11, -5}, +{'l', 10, -6}, +{'l', 8, -7}, +{'l', 5, -7}, +{'l', 3, -6}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_104[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 0, 10}, +{'l', 3, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +{'l', 10, 13}, +{'l', 11, 10}, +{'l', 11, 0}, +}; +static cdOperation vf_default_char_105[] = { +{'m', 2, 21}, +{'l', 3, 20}, +{'l', 4, 21}, +{'l', 3, 22}, +{'l', 2, 21}, +{'m', 3, 14}, +{'l', 3, 0}, +}; +static cdOperation vf_default_char_106[] = { +{'m', 4, 21}, +{'l', 5, 20}, +{'l', 6, 21}, +{'l', 5, 22}, +{'l', 4, 21}, +{'m', 5, 14}, +{'l', 5, -3}, +{'l', 4, -6}, +{'l', 2, -7}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_107[] = { +{'m', 0, 21}, +{'l', 0, 0}, +{'m', 10, 14}, +{'l', 0, 4}, +{'m', 4, 8}, +{'l', 11, 0}, +}; +static cdOperation vf_default_char_108[] = { +{'m', 0, 21}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_109[] = { +{'m', 0, 14}, +{'l', 0, 0}, +{'m', 0, 10}, +{'l', 3, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +{'l', 10, 13}, +{'l', 11, 10}, +{'l', 11, 0}, +{'m', 11, 10}, +{'l', 14, 13}, +{'l', 16, 14}, +{'l', 19, 14}, +{'l', 21, 13}, +{'l', 22, 10}, +{'l', 22, 0}, +}; +static cdOperation vf_default_char_110[] = { +{'m', 0, 14}, +{'l', 0, 0}, +{'m', 0, 10}, +{'l', 3, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +{'l', 10, 13}, +{'l', 11, 10}, +{'l', 11, 0}, +}; +static cdOperation vf_default_char_111[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +}; +static cdOperation vf_default_char_112[] = { +{'m', 0, 14}, +{'l', 0, -7}, +{'m', 0, 11}, +{'l', 2, 13}, +{'l', 4, 14}, +{'l', 7, 14}, +{'l', 9, 13}, +{'l', 11, 11}, +{'l', 12, 8}, +{'l', 12, 6}, +{'l', 11, 3}, +{'l', 9, 1}, +{'l', 7, 0}, +{'l', 4, 0}, +{'l', 2, 1}, +{'l', 0, 3}, +}; +static cdOperation vf_default_char_113[] = { +{'m', 12, 14}, +{'l', 12, -7}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +}; +static cdOperation vf_default_char_114[] = { +{'m', 0, 14}, +{'l', 0, 0}, +{'m', 0, 8}, +{'l', 1, 11}, +{'l', 3, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +}; +static cdOperation vf_default_char_115[] = { +{'m', 11, 11}, +{'l', 10, 13}, +{'l', 7, 14}, +{'l', 4, 14}, +{'l', 1, 13}, +{'l', 0, 11}, +{'l', 1, 9}, +{'l', 3, 8}, +{'l', 8, 7}, +{'l', 10, 6}, +{'l', 11, 4}, +{'l', 11, 3}, +{'l', 10, 1}, +{'l', 7, 0}, +{'l', 4, 0}, +{'l', 1, 1}, +{'l', 0, 3}, +}; +static cdOperation vf_default_char_116[] = { +{'m', 3, 21}, +{'l', 3, 4}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'m', 0, 14}, +{'l', 7, 14}, +}; +static cdOperation vf_default_char_117[] = { +{'m', 0, 14}, +{'l', 0, 4}, +{'l', 1, 1}, +{'l', 3, 0}, +{'l', 6, 0}, +{'l', 8, 1}, +{'l', 11, 4}, +{'m', 11, 14}, +{'l', 11, 0}, +}; +static cdOperation vf_default_char_118[] = { +{'m', 0, 14}, +{'l', 6, 0}, +{'m', 12, 14}, +{'l', 6, 0}, +}; +static cdOperation vf_default_char_119[] = { +{'m', 0, 14}, +{'l', 4, 0}, +{'m', 8, 14}, +{'l', 4, 0}, +{'m', 8, 14}, +{'l', 12, 0}, +{'m', 16, 14}, +{'l', 12, 0}, +}; +static cdOperation vf_default_char_120[] = { +{'m', 0, 14}, +{'l', 11, 0}, +{'m', 11, 14}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_121[] = { +{'m', 1, 14}, +{'l', 7, 0}, +{'m', 13, 14}, +{'l', 7, 0}, +{'l', 5, -4}, +{'l', 3, -6}, +{'l', 1, -7}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_122[] = { +{'m', 11, 14}, +{'l', 0, 0}, +{'m', 0, 14}, +{'l', 11, 14}, +{'m', 0, 0}, +{'l', 11, 0}, +}; +static cdOperation vf_default_char_123[] = { +{'m', 5, 25}, +{'l', 3, 24}, +{'l', 2, 23}, +{'l', 1, 21}, +{'l', 1, 19}, +{'l', 2, 17}, +{'l', 3, 16}, +{'l', 4, 14}, +{'l', 4, 12}, +{'l', 2, 10}, +{'m', 3, 24}, +{'l', 2, 22}, +{'l', 2, 20}, +{'l', 3, 18}, +{'l', 4, 17}, +{'l', 5, 15}, +{'l', 5, 13}, +{'l', 4, 11}, +{'l', 0, 9}, +{'l', 4, 7}, +{'l', 5, 5}, +{'l', 5, 3}, +{'l', 4, 1}, +{'l', 3, 0}, +{'l', 2, -2}, +{'l', 2, -4}, +{'l', 3, -6}, +{'m', 2, 8}, +{'l', 4, 6}, +{'l', 4, 4}, +{'l', 3, 2}, +{'l', 2, 1}, +{'l', 1, -1}, +{'l', 1, -3}, +{'l', 2, -5}, +{'l', 3, -6}, +{'l', 5, -7}, +}; +static cdOperation vf_default_char_124[] = { +{'m', 0, 21}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_125[] = { +{'m', 0, 25}, +{'l', 2, 24}, +{'l', 3, 23}, +{'l', 4, 21}, +{'l', 4, 19}, +{'l', 3, 17}, +{'l', 2, 16}, +{'l', 1, 14}, +{'l', 1, 12}, +{'l', 3, 10}, +{'m', 2, 24}, +{'l', 3, 22}, +{'l', 3, 20}, +{'l', 2, 18}, +{'l', 1, 17}, +{'l', 0, 15}, +{'l', 0, 13}, +{'l', 1, 11}, +{'l', 5, 9}, +{'l', 1, 7}, +{'l', 0, 5}, +{'l', 0, 3}, +{'l', 1, 1}, +{'l', 2, 0}, +{'l', 3, -2}, +{'l', 3, -4}, +{'l', 2, -6}, +{'m', 3, 8}, +{'l', 1, 6}, +{'l', 1, 4}, +{'l', 2, 2}, +{'l', 3, 1}, +{'l', 4, -1}, +{'l', 4, -3}, +{'l', 3, -5}, +{'l', 2, -6}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_126[] = { +{'m', 0, 16}, +{'l', 5, 19}, +{'l', 9, 16}, +{'l', 13, 18}, +}; +static cdOperation vf_default_char_127[] = { +{'m', 0, 7}, +{'l', 0, 0}, +{'l', 12, 0}, +{'l', 12, 7}, +{'l', 6, 16}, +{'l', 0, 7}, +{'m', 6, 6}, +{'l', 6, 6}, +}; +static cdOperation vf_default_char_128[] = { +{'m', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'m', 8, 0}, +{'l', 8, -1}, +{'l', 7, -1}, +{'l', 7, 0}, +{'m', 3, -4}, +{'l', 3, -6}, +{'l', 4, -7}, +{'l', 10, -7}, +{'l', 12, -5}, +{'l', 12, -4}, +{'l', 10, -2}, +{'l', 8, -1}, +}; +static cdOperation vf_default_char_129[] = { +{'m', 0, 14}, +{'l', 0, 4}, +{'l', 1, 1}, +{'l', 3, 0}, +{'l', 6, 0}, +{'l', 8, 1}, +{'l', 11, 4}, +{'m', 11, 14}, +{'l', 11, 0}, +{'m', 2, 19}, +{'l', 1, 18}, +{'l', 2, 17}, +{'l', 3, 18}, +{'l', 2, 19}, +{'m', 10, 19}, +{'l', 9, 18}, +{'l', 10, 17}, +{'l', 11, 18}, +{'l', 10, 19}, +}; +static cdOperation vf_default_char_130[] = { +{'m', 0, 8}, +{'l', 12, 8}, +{'l', 12, 10}, +{'l', 11, 12}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 10, 22}, +{'l', 5, 17}, +}; +static cdOperation vf_default_char_131[] = { +{'m', 13, 14}, +{'l', 13, 0}, +{'m', 13, 11}, +{'l', 11, 13}, +{'l', 9, 14}, +{'l', 6, 14}, +{'l', 4, 13}, +{'l', 2, 11}, +{'l', 1, 8}, +{'l', 1, 6}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 9, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'m', 3, 16}, +{'l', 8, 21}, +{'l', 13, 16}, +}; +static cdOperation vf_default_char_132[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 2, 19}, +{'l', 1, 18}, +{'l', 2, 17}, +{'l', 3, 18}, +{'l', 2, 19}, +{'m', 10, 19}, +{'l', 9, 18}, +{'l', 10, 17}, +{'l', 11, 18}, +{'l', 10, 19}, +}; +static cdOperation vf_default_char_133[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 3, 22}, +{'l', 8, 17}, +}; +static cdOperation vf_default_char_134[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 5, 19}, +{'l', 4, 18}, +{'l', 5, 17}, +{'l', 7, 17}, +{'l', 8, 18}, +{'l', 7, 19}, +{'l', 5, 19}, +}; +static cdOperation vf_default_char_135[] = { +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 6, 0}, +{'l', 6, -1}, +{'l', 9, -2}, +{'l', 10, -5}, +{'l', 8, -7}, +{'l', 4, -7}, +{'l', 3, -5}, +}; +static cdOperation vf_default_char_136[] = { +{'m', 2, 8}, +{'l', 14, 8}, +{'l', 14, 10}, +{'l', 13, 12}, +{'l', 12, 13}, +{'l', 10, 14}, +{'l', 7, 14}, +{'l', 5, 13}, +{'l', 3, 11}, +{'l', 2, 8}, +{'l', 2, 6}, +{'l', 3, 3}, +{'l', 5, 1}, +{'l', 7, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'m', 4, 16}, +{'l', 9, 21}, +{'l', 14, 16}, +}; +static cdOperation vf_default_char_137[] = { +{'m', 0, 8}, +{'l', 12, 8}, +{'l', 12, 10}, +{'l', 11, 12}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 3, 19}, +{'l', 2, 18}, +{'l', 3, 17}, +{'l', 4, 18}, +{'l', 3, 19}, +{'m', 11, 19}, +{'l', 10, 18}, +{'l', 11, 17}, +{'l', 12, 18}, +{'l', 11, 19}, +}; +static cdOperation vf_default_char_138[] = { +{'m', 0, 8}, +{'l', 12, 8}, +{'l', 12, 10}, +{'l', 11, 12}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 2, 22}, +{'l', 7, 17}, +}; +static cdOperation vf_default_char_139[] = { +{'m', 5, 14}, +{'l', 5, 0}, +{'m', 1, 19}, +{'l', 0, 18}, +{'l', 1, 17}, +{'l', 2, 18}, +{'l', 1, 19}, +{'m', 9, 19}, +{'l', 8, 18}, +{'l', 9, 17}, +{'l', 10, 18}, +{'l', 9, 19}, +}; +static cdOperation vf_default_char_140[] = { +{'m', 8, 14}, +{'l', 8, 0}, +{'m', 3, 16}, +{'l', 8, 21}, +{'l', 13, 16}, +}; +static cdOperation vf_default_char_141[] = { +{'m', 5, 14}, +{'l', 5, 0}, +{'m', 0, 22}, +{'l', 5, 17}, +}; +static cdOperation vf_default_char_142[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 4, 26}, +{'l', 3, 25}, +{'l', 4, 24}, +{'l', 5, 25}, +{'l', 4, 26}, +{'m', 12, 26}, +{'l', 11, 25}, +{'l', 12, 24}, +{'l', 13, 25}, +{'l', 12, 26}, +}; +static cdOperation vf_default_char_143[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 7, 26}, +{'l', 6, 25}, +{'l', 7, 24}, +{'l', 9, 24}, +{'l', 10, 25}, +{'l', 9, 26}, +{'l', 7, 26}, +}; +static cdOperation vf_default_char_144[] = { +{'m', 13, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'l', 13, 0}, +{'m', 0, 11}, +{'l', 8, 11}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_145[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 17, 14}, +{'l', 20, 14}, +{'l', 22, 13}, +{'l', 23, 12}, +{'l', 24, 10}, +{'l', 24, 8}, +{'l', 12, 8}, +{'l', 13, 11}, +{'l', 15, 13}, +{'l', 17, 14}, +{'m', 12, 6}, +{'l', 13, 3}, +{'l', 15, 1}, +{'l', 17, 0}, +{'l', 20, 0}, +{'l', 22, 1}, +{'l', 24, 3}, +}; +static cdOperation vf_default_char_146[] = { +{'m', 23, 21}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 10, 21}, +{'l', 10, 0}, +{'l', 23, 0}, +{'m', 10, 11}, +{'l', 18, 11}, +{'m', 3, 7}, +{'l', 10, 7}, +}; +static cdOperation vf_default_char_147[] = { +{'m', 6, 14}, +{'l', 4, 13}, +{'l', 2, 11}, +{'l', 1, 8}, +{'l', 1, 6}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 9, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 8}, +{'l', 13, 11}, +{'l', 11, 13}, +{'l', 9, 14}, +{'l', 6, 14}, +{'m', 3, 16}, +{'l', 8, 21}, +{'l', 13, 16}, +}; +static cdOperation vf_default_char_148[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 3, 19}, +{'l', 2, 18}, +{'l', 3, 17}, +{'l', 4, 18}, +{'l', 3, 19}, +{'m', 11, 19}, +{'l', 10, 18}, +{'l', 11, 17}, +{'l', 12, 18}, +{'l', 11, 19}, +}; +static cdOperation vf_default_char_149[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 2, 22}, +{'l', 7, 17}, +}; +static cdOperation vf_default_char_150[] = { +{'m', 2, 14}, +{'l', 2, 4}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 13, 4}, +{'m', 13, 14}, +{'l', 13, 0}, +{'m', 3, 17}, +{'l', 8, 22}, +{'l', 13, 17}, +}; +static cdOperation vf_default_char_151[] = { +{'m', 0, 14}, +{'l', 0, 4}, +{'l', 1, 1}, +{'l', 3, 0}, +{'l', 6, 0}, +{'l', 8, 1}, +{'l', 11, 4}, +{'m', 11, 14}, +{'l', 11, 0}, +{'m', 1, 22}, +{'l', 6, 17}, +}; +static cdOperation vf_default_char_152[] = { +{'m', 1, 14}, +{'l', 7, 0}, +{'l', 5, -4}, +{'l', 3, -6}, +{'l', 1, -7}, +{'l', 0, -7}, +{'m', 13, 14}, +{'l', 7, 0}, +{'m', 3, 19}, +{'l', 2, 18}, +{'l', 3, 17}, +{'l', 4, 18}, +{'l', 3, 19}, +{'m', 11, 19}, +{'l', 10, 18}, +{'l', 11, 17}, +{'l', 12, 18}, +{'l', 11, 19}, +}; +static cdOperation vf_default_char_153[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 4, 26}, +{'l', 3, 25}, +{'l', 4, 24}, +{'l', 5, 25}, +{'l', 4, 26}, +{'m', 12, 26}, +{'l', 11, 25}, +{'l', 12, 24}, +{'l', 13, 25}, +{'l', 12, 26}, +}; +static cdOperation vf_default_char_154[] = { +{'m', 0, 21}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 21}, +{'m', 3, 26}, +{'l', 2, 25}, +{'l', 3, 24}, +{'l', 4, 25}, +{'l', 3, 26}, +{'m', 11, 26}, +{'l', 10, 25}, +{'l', 11, 24}, +{'l', 12, 25}, +{'l', 11, 26}, +}; +static cdOperation vf_default_char_155[] = { +{'m', 12, 15}, +{'l', 10, 17}, +{'l', 8, 18}, +{'l', 5, 18}, +{'l', 3, 17}, +{'l', 1, 15}, +{'l', 0, 12}, +{'l', 0, 10}, +{'l', 1, 7}, +{'l', 3, 5}, +{'l', 5, 4}, +{'l', 8, 4}, +{'l', 10, 5}, +{'l', 12, 7}, +{'m', 6, 0}, +{'l', 6, 22}, +}; +static cdOperation vf_default_char_156[] = { +{'m', 13, 20}, +{'l', 10, 21}, +{'l', 8, 21}, +{'l', 5, 20}, +{'l', 4, 19}, +{'l', 3, 16}, +{'l', 3, 0}, +{'l', 12, 0}, +{'l', 15, 1}, +{'l', 15, 2}, +{'m', 0, 12}, +{'l', 7, 12}, +}; +static cdOperation vf_default_char_157[] = { +{'m', 0, 21}, +{'l', 8, 11}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 11}, +{'m', 4, 11}, +{'l', 13, 11}, +{'m', 4, 8}, +{'l', 13, 8}, +}; +static cdOperation vf_default_char_158[] = { +{'m', 0, 10}, +{'l', 9, 10}, +{'l', 12, 11}, +{'l', 13, 12}, +{'l', 14, 14}, +{'l', 14, 17}, +{'l', 13, 19}, +{'l', 12, 20}, +{'l', 9, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'m', 12, 8}, +{'l', 18, 8}, +{'m', 15, 12}, +{'l', 15, 2}, +{'l', 16, 0}, +{'l', 18, 0}, +{'l', 19, 1}, +}; +static cdOperation vf_default_char_159[] = { +{'m', 0, 21}, +{'l', 8, 11}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 11}, +{'m', 4, 25}, +{'l', 3, 24}, +{'l', 4, 23}, +{'l', 5, 24}, +{'l', 4, 25}, +{'m', 12, 25}, +{'l', 11, 24}, +{'l', 12, 23}, +{'l', 13, 24}, +{'l', 12, 25}, +}; +static cdOperation vf_default_char_160[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 10, 22}, +{'l', 5, 17}, +}; +static cdOperation vf_default_char_161[] = { +{'m', 3, 14}, +{'l', 3, 0}, +{'m', 7, 22}, +{'l', 2, 17}, +}; +static cdOperation vf_default_char_162[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 11, 22}, +{'l', 6, 17}, +}; +static cdOperation vf_default_char_163[] = { +{'m', 0, 14}, +{'l', 0, 4}, +{'l', 1, 1}, +{'l', 3, 0}, +{'l', 6, 0}, +{'l', 8, 1}, +{'l', 11, 4}, +{'m', 11, 14}, +{'l', 11, 0}, +{'m', 9, 22}, +{'l', 4, 17}, +}; +static cdOperation vf_default_char_164[] = { +{'m', 0, 14}, +{'l', 0, 0}, +{'m', 0, 10}, +{'l', 3, 13}, +{'l', 5, 14}, +{'l', 8, 14}, +{'l', 10, 13}, +{'l', 11, 10}, +{'l', 11, 0}, +{'m', 0, 17}, +{'l', 5, 20}, +{'l', 9, 17}, +{'l', 13, 19}, +}; +static cdOperation vf_default_char_165[] = { +{'m', 14, 21}, +{'l', 14, 0}, +{'l', 0, 21}, +{'l', 0, 0}, +{'m', 0, 24}, +{'l', 5, 27}, +{'l', 9, 24}, +{'l', 13, 26}, +}; +static cdOperation vf_default_char_166[] = { +{'m', 12, 21}, +{'l', 12, 7}, +{'m', 12, 18}, +{'l', 10, 20}, +{'l', 8, 21}, +{'l', 5, 21}, +{'l', 3, 20}, +{'l', 1, 18}, +{'l', 0, 15}, +{'l', 0, 13}, +{'l', 1, 10}, +{'l', 3, 8}, +{'l', 5, 7}, +{'l', 8, 7}, +{'l', 10, 8}, +{'l', 12, 10}, +{'m', 0, 0}, +{'l', 12, 0}, +}; +static cdOperation vf_default_char_167[] = { +{'m', 0, 15}, +{'l', 1, 12}, +{'l', 3, 10}, +{'l', 5, 9}, +{'l', 8, 9}, +{'l', 10, 10}, +{'l', 12, 12}, +{'l', 13, 15}, +{'l', 12, 18}, +{'l', 10, 20}, +{'l', 8, 21}, +{'l', 5, 21}, +{'l', 3, 20}, +{'l', 1, 18}, +{'l', 0, 15}, +{'m', 0, 0}, +{'l', 13, 0}, +}; +static cdOperation vf_default_char_168[] = { +{'m', 12, 5}, +{'l', 12, 4}, +{'l', 11, 2}, +{'l', 10, 1}, +{'l', 8, 0}, +{'l', 4, 0}, +{'l', 2, 1}, +{'l', 1, 2}, +{'l', 0, 4}, +{'l', 0, 6}, +{'l', 1, 8}, +{'l', 2, 9}, +{'l', 6, 11}, +{'l', 6, 14}, +{'m', 6, 19}, +{'l', 7, 20}, +{'l', 6, 21}, +{'l', 5, 20}, +{'l', 6, 19}, +}; +static cdOperation vf_default_char_169[] = { +{'m', 0, 0}, +{'l', 0, 8}, +{'l', 12, 8}, +{'l', 12, 5}, +{'l', 3, 5}, +{'l', 3, 0}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_170[] = { +{'m', 12, 0}, +{'l', 12, 8}, +{'l', 0, 8}, +{'l', 0, 5}, +{'l', 9, 5}, +{'l', 9, 0}, +{'l', 12, 0}, +}; +static cdOperation vf_default_char_171[] = { +{'m', 0, 18}, +{'l', 3, 21}, +{'l', 4, 21}, +{'l', 4, 12}, +{'m', 9, 6}, +{'l', 9, 7}, +{'l', 11, 9}, +{'l', 15, 9}, +{'l', 16, 7}, +{'l', 16, 5}, +{'l', 15, 4}, +{'l', 9, 0}, +{'l', 16, 0}, +{'m', 15, 21}, +{'l', 1, 0}, +}; +static cdOperation vf_default_char_172[] = { +{'m', 0, 18}, +{'l', 3, 21}, +{'l', 4, 21}, +{'l', 4, 12}, +{'m', 15, 21}, +{'l', 1, 0}, +{'m', 15, 3}, +{'l', 7, 3}, +{'l', 13, 9}, +{'l', 13, 0}, +}; +static cdOperation vf_default_char_173[] = { +{'m', 1, 0}, +{'l', 1, 14}, +{'m', 1, 19}, +{'l', 0, 20}, +{'l', 1, 21}, +{'l', 2, 20}, +{'l', 1, 19}, +}; +static cdOperation vf_default_char_174[] = { +{'m', 7, 17}, +{'l', 0, 11}, +{'l', 7, 5}, +{'m', 15, 17}, +{'l', 8, 11}, +{'l', 15, 5}, +}; +static cdOperation vf_default_char_175[] = { +{'m', 8, 17}, +{'l', 15, 11}, +{'l', 8, 5}, +{'m', 0, 17}, +{'l', 7, 11}, +{'l', 0, 5}, +}; +static cdOperation vf_default_char_176[] = { +{'m', 4, 21}, +{'l', 6, 21}, +{'l', 6, 19}, +{'l', 4, 19}, +{'l', 4, 21}, +{'m', 5, 21}, +{'l', 5, 19}, +{'m', 4, 15}, +{'l', 6, 15}, +{'l', 6, 13}, +{'l', 4, 13}, +{'l', 4, 15}, +{'m', 5, 15}, +{'l', 5, 13}, +{'m', 4, 9}, +{'l', 6, 9}, +{'l', 6, 7}, +{'l', 4, 7}, +{'l', 4, 9}, +{'m', 5, 9}, +{'l', 5, 7}, +{'m', 4, 3}, +{'l', 6, 3}, +{'l', 6, 1}, +{'l', 4, 1}, +{'l', 4, 3}, +{'m', 5, 3}, +{'l', 5, 1}, +{'m', 0, 18}, +{'l', 2, 18}, +{'l', 2, 16}, +{'l', 0, 16}, +{'l', 0, 18}, +{'m', 1, 18}, +{'l', 1, 16}, +{'m', 0, 12}, +{'l', 2, 12}, +{'l', 2, 10}, +{'l', 0, 10}, +{'l', 0, 12}, +{'m', 1, 12}, +{'l', 1, 10}, +{'m', 0, 6}, +{'l', 2, 6}, +{'l', 2, 4}, +{'l', 0, 4}, +{'l', 0, 6}, +{'m', 1, 6}, +{'l', 1, 4}, +{'m', 0, 0}, +{'l', 2, 0}, +{'l', 2, -2}, +{'l', 0, -2}, +{'l', 0, 0}, +{'m', 1, 0}, +{'l', 1, -2}, +{'m', 8, 18}, +{'l', 10, 18}, +{'l', 10, 16}, +{'l', 8, 16}, +{'l', 8, 18}, +{'m', 9, 18}, +{'l', 9, 16}, +{'m', 8, 12}, +{'l', 10, 12}, +{'l', 10, 10}, +{'l', 8, 10}, +{'l', 8, 12}, +{'m', 9, 12}, +{'l', 9, 10}, +{'m', 8, 6}, +{'l', 10, 6}, +{'l', 10, 4}, +{'l', 8, 4}, +{'l', 8, 6}, +{'m', 9, 6}, +{'l', 9, 4}, +{'m', 8, 0}, +{'l', 10, 0}, +{'l', 10, -2}, +{'l', 8, -2}, +{'l', 8, 0}, +{'m', 9, 0}, +{'l', 9, -2}, +{'m', 12, 21}, +{'l', 14, 21}, +{'l', 14, 19}, +{'l', 12, 19}, +{'l', 12, 21}, +{'m', 13, 21}, +{'l', 13, 19}, +{'m', 12, 15}, +{'l', 14, 15}, +{'l', 14, 13}, +{'l', 12, 13}, +{'l', 12, 15}, +{'m', 13, 15}, +{'l', 13, 13}, +{'m', 12, 9}, +{'l', 14, 9}, +{'l', 14, 7}, +{'l', 12, 7}, +{'l', 12, 9}, +{'m', 13, 9}, +{'l', 13, 7}, +{'m', 12, 3}, +{'l', 14, 3}, +{'l', 14, 1}, +{'l', 12, 1}, +{'l', 12, 3}, +{'m', 13, 3}, +{'l', 13, 1}, +{'m', 3, -3}, +{'l', 3, -5}, +{'l', 5, -5}, +{'l', 5, -3}, +{'l', 3, -3}, +{'m', 4, -3}, +{'l', 4, -5}, +{'m', 12, -3}, +{'l', 12, -5}, +{'l', 14, -5}, +{'l', 14, -3}, +{'l', 12, -3}, +{'m', 13, -3}, +{'l', 13, -5}, +}; +static cdOperation vf_default_char_177[] = { +{'m', 0, 18}, +{'l', 2, 18}, +{'l', 2, 16}, +{'l', 0, 16}, +{'l', 0, 18}, +{'m', 1, 18}, +{'l', 1, 16}, +{'m', 0, 12}, +{'l', 2, 12}, +{'l', 2, 10}, +{'l', 0, 10}, +{'l', 0, 12}, +{'m', 1, 12}, +{'l', 1, 10}, +{'m', 0, 6}, +{'l', 2, 6}, +{'l', 2, 4}, +{'l', 0, 4}, +{'l', 0, 6}, +{'m', 1, 6}, +{'l', 1, 4}, +{'m', 0, 0}, +{'l', 2, 0}, +{'l', 2, -2}, +{'l', 0, -2}, +{'l', 0, 0}, +{'m', 1, 0}, +{'l', 1, -2}, +{'m', 2, 21}, +{'l', 4, 21}, +{'l', 4, 19}, +{'l', 2, 19}, +{'l', 2, 21}, +{'m', 3, 21}, +{'l', 3, 19}, +{'m', 2, 15}, +{'l', 4, 15}, +{'l', 4, 13}, +{'l', 2, 13}, +{'l', 2, 15}, +{'m', 3, 15}, +{'l', 3, 13}, +{'m', 2, 9}, +{'l', 4, 9}, +{'l', 4, 7}, +{'l', 2, 7}, +{'l', 2, 9}, +{'m', 3, 9}, +{'l', 3, 7}, +{'m', 2, 3}, +{'l', 4, 3}, +{'l', 4, 1}, +{'l', 2, 1}, +{'l', 2, 3}, +{'m', 3, 3}, +{'l', 3, 1}, +{'m', 4, 18}, +{'l', 6, 18}, +{'l', 6, 16}, +{'l', 4, 16}, +{'l', 4, 18}, +{'m', 5, 18}, +{'l', 5, 16}, +{'m', 4, 12}, +{'l', 6, 12}, +{'l', 6, 10}, +{'l', 4, 10}, +{'l', 4, 12}, +{'m', 5, 12}, +{'l', 5, 10}, +{'m', 4, 6}, +{'l', 6, 6}, +{'l', 6, 4}, +{'l', 4, 4}, +{'l', 4, 6}, +{'m', 5, 6}, +{'l', 5, 4}, +{'m', 4, 0}, +{'l', 6, 0}, +{'l', 6, -2}, +{'l', 4, -2}, +{'l', 4, 0}, +{'m', 5, 0}, +{'l', 5, -2}, +{'m', 6, 21}, +{'l', 8, 21}, +{'l', 8, 19}, +{'l', 6, 19}, +{'l', 6, 21}, +{'m', 7, 21}, +{'l', 7, 19}, +{'m', 6, 15}, +{'l', 8, 15}, +{'l', 8, 13}, +{'l', 6, 13}, +{'l', 6, 15}, +{'m', 7, 15}, +{'l', 7, 13}, +{'m', 6, 9}, +{'l', 8, 9}, +{'l', 8, 7}, +{'l', 6, 7}, +{'l', 6, 9}, +{'m', 7, 9}, +{'l', 7, 7}, +{'m', 6, 3}, +{'l', 8, 3}, +{'l', 8, 1}, +{'l', 6, 1}, +{'l', 6, 3}, +{'m', 7, 3}, +{'l', 7, 1}, +{'m', 8, 18}, +{'l', 10, 18}, +{'l', 10, 16}, +{'l', 8, 16}, +{'l', 8, 18}, +{'m', 9, 18}, +{'l', 9, 16}, +{'m', 8, 12}, +{'l', 10, 12}, +{'l', 10, 10}, +{'l', 8, 10}, +{'l', 8, 12}, +{'m', 9, 12}, +{'l', 9, 10}, +{'m', 8, 6}, +{'l', 10, 6}, +{'l', 10, 4}, +{'l', 8, 4}, +{'l', 8, 6}, +{'m', 9, 6}, +{'l', 9, 4}, +{'m', 8, 0}, +{'l', 10, 0}, +{'l', 10, -2}, +{'l', 8, -2}, +{'l', 8, 0}, +{'m', 9, 0}, +{'l', 9, -2}, +{'m', 10, 21}, +{'l', 12, 21}, +{'l', 12, 19}, +{'l', 10, 19}, +{'l', 10, 21}, +{'m', 11, 21}, +{'l', 11, 19}, +{'m', 10, 15}, +{'l', 12, 15}, +{'l', 12, 13}, +{'l', 10, 13}, +{'l', 10, 15}, +{'m', 11, 15}, +{'l', 11, 13}, +{'m', 10, 9}, +{'l', 12, 9}, +{'l', 12, 7}, +{'l', 10, 7}, +{'l', 10, 9}, +{'m', 11, 9}, +{'l', 11, 7}, +{'m', 10, 3}, +{'l', 12, 3}, +{'l', 12, 1}, +{'l', 10, 1}, +{'l', 10, 3}, +{'m', 11, 3}, +{'l', 11, 1}, +{'m', 12, 18}, +{'l', 14, 18}, +{'l', 14, 16}, +{'l', 12, 16}, +{'l', 12, 18}, +{'m', 13, 18}, +{'l', 13, 16}, +{'m', 12, 12}, +{'l', 14, 12}, +{'l', 14, 10}, +{'l', 12, 10}, +{'l', 12, 12}, +{'m', 13, 12}, +{'l', 13, 10}, +{'m', 12, 6}, +{'l', 14, 6}, +{'l', 14, 4}, +{'l', 12, 4}, +{'l', 12, 6}, +{'m', 13, 6}, +{'l', 13, 4}, +{'m', 12, 0}, +{'l', 14, 0}, +{'l', 14, -2}, +{'l', 12, -2}, +{'l', 12, 0}, +{'m', 13, 0}, +{'l', 13, -2}, +{'m', 14, 21}, +{'l', 16, 21}, +{'l', 16, 19}, +{'l', 14, 19}, +{'l', 14, 21}, +{'m', 15, 21}, +{'l', 15, 19}, +{'m', 14, 15}, +{'l', 16, 15}, +{'l', 16, 13}, +{'l', 14, 13}, +{'l', 14, 15}, +{'m', 15, 15}, +{'l', 15, 13}, +{'m', 14, 9}, +{'l', 16, 9}, +{'l', 16, 7}, +{'l', 14, 7}, +{'l', 14, 9}, +{'m', 15, 9}, +{'l', 15, 7}, +{'m', 14, 3}, +{'l', 16, 3}, +{'l', 16, 1}, +{'l', 14, 1}, +{'l', 14, 3}, +{'m', 15, 3}, +{'l', 15, 1}, +{'m', 2, -3}, +{'l', 2, -5}, +{'l', 4, -5}, +{'l', 4, -3}, +{'l', 2, -3}, +{'m', 3, -3}, +{'l', 3, -5}, +{'m', 6, -3}, +{'l', 6, -5}, +{'l', 8, -5}, +{'l', 8, -3}, +{'l', 6, -3}, +{'m', 7, -3}, +{'l', 7, -5}, +{'m', 10, -3}, +{'l', 10, -5}, +{'l', 12, -5}, +{'l', 12, -3}, +{'l', 10, -3}, +{'m', 11, -3}, +{'l', 11, -5}, +{'m', 14, -3}, +{'l', 14, -5}, +{'l', 16, -5}, +{'l', 16, -3}, +{'l', 14, -3}, +{'m', 15, -3}, +{'l', 15, -5}, +}; +static cdOperation vf_default_char_178[] = { +{'m', 0, 21}, +{'l', 2, 21}, +{'l', 2, 19}, +{'l', 0, 19}, +{'l', 0, 21}, +{'m', 1, 21}, +{'l', 1, 19}, +{'m', 2, 21}, +{'l', 4, 21}, +{'l', 4, 19}, +{'l', 2, 19}, +{'l', 2, 21}, +{'m', 3, 21}, +{'l', 3, 19}, +{'m', 10, 21}, +{'l', 12, 21}, +{'l', 12, 19}, +{'l', 10, 19}, +{'l', 10, 21}, +{'m', 11, 21}, +{'l', 11, 19}, +{'m', 12, 21}, +{'l', 14, 21}, +{'l', 14, 19}, +{'l', 12, 19}, +{'l', 12, 21}, +{'m', 13, 21}, +{'l', 13, 19}, +{'m', 20, 21}, +{'l', 22, 21}, +{'l', 22, 19}, +{'l', 20, 19}, +{'l', 20, 21}, +{'m', 21, 21}, +{'l', 21, 19}, +{'m', 22, 21}, +{'l', 24, 21}, +{'l', 24, 19}, +{'l', 22, 19}, +{'l', 22, 21}, +{'m', 23, 21}, +{'l', 23, 19}, +{'m', 4, 17}, +{'l', 6, 17}, +{'l', 6, 15}, +{'l', 4, 15}, +{'l', 4, 17}, +{'m', 5, 17}, +{'l', 5, 15}, +{'m', 6, 17}, +{'l', 8, 17}, +{'l', 8, 15}, +{'l', 6, 15}, +{'l', 6, 17}, +{'m', 7, 17}, +{'l', 7, 15}, +{'m', 8, 17}, +{'l', 10, 17}, +{'l', 10, 15}, +{'l', 8, 15}, +{'l', 8, 17}, +{'m', 9, 17}, +{'l', 9, 15}, +{'m', 0, 13}, +{'l', 2, 13}, +{'l', 2, 11}, +{'l', 0, 11}, +{'l', 0, 13}, +{'m', 1, 13}, +{'l', 1, 11}, +{'m', 2, 13}, +{'l', 4, 13}, +{'l', 4, 11}, +{'l', 2, 11}, +{'l', 2, 13}, +{'m', 3, 13}, +{'l', 3, 11}, +{'m', 10, 13}, +{'l', 12, 13}, +{'l', 12, 11}, +{'l', 10, 11}, +{'l', 10, 13}, +{'m', 11, 13}, +{'l', 11, 11}, +{'m', 12, 13}, +{'l', 14, 13}, +{'l', 14, 11}, +{'l', 12, 11}, +{'l', 12, 13}, +{'m', 13, 13}, +{'l', 13, 11}, +{'m', 20, 13}, +{'l', 22, 13}, +{'l', 22, 11}, +{'l', 20, 11}, +{'l', 20, 13}, +{'m', 21, 13}, +{'l', 21, 11}, +{'m', 22, 13}, +{'l', 24, 13}, +{'l', 24, 11}, +{'l', 22, 11}, +{'l', 22, 13}, +{'m', 23, 13}, +{'l', 23, 11}, +{'m', 14, 9}, +{'l', 16, 9}, +{'l', 16, 7}, +{'l', 14, 7}, +{'l', 14, 9}, +{'m', 15, 9}, +{'l', 15, 7}, +{'m', 16, 9}, +{'l', 18, 9}, +{'l', 18, 7}, +{'l', 16, 7}, +{'l', 16, 9}, +{'m', 17, 9}, +{'l', 17, 7}, +{'m', 18, 9}, +{'l', 20, 9}, +{'l', 20, 7}, +{'l', 18, 7}, +{'l', 18, 9}, +{'m', 19, 9}, +{'l', 19, 7}, +{'m', 0, 5}, +{'l', 2, 5}, +{'l', 2, 3}, +{'l', 0, 3}, +{'l', 0, 5}, +{'m', 1, 5}, +{'l', 1, 3}, +{'m', 2, 5}, +{'l', 4, 5}, +{'l', 4, 3}, +{'l', 2, 3}, +{'l', 2, 5}, +{'m', 3, 5}, +{'l', 3, 3}, +{'m', 10, 5}, +{'l', 12, 5}, +{'l', 12, 3}, +{'l', 10, 3}, +{'l', 10, 5}, +{'m', 11, 5}, +{'l', 11, 3}, +{'m', 12, 5}, +{'l', 14, 5}, +{'l', 14, 3}, +{'l', 12, 3}, +{'l', 12, 5}, +{'m', 13, 5}, +{'l', 13, 3}, +{'m', 20, 5}, +{'l', 22, 5}, +{'l', 22, 3}, +{'l', 20, 3}, +{'l', 20, 5}, +{'m', 21, 5}, +{'l', 21, 3}, +{'m', 22, 5}, +{'l', 24, 5}, +{'l', 24, 3}, +{'l', 22, 3}, +{'l', 22, 5}, +{'m', 23, 5}, +{'l', 23, 3}, +{'m', 4, 1}, +{'l', 10, 1}, +{'l', 10, -1}, +{'l', 4, -1}, +{'l', 4, 1}, +{'m', 5, 1}, +{'l', 5, -1}, +{'m', 7, 1}, +{'l', 7, -1}, +{'m', 9, 1}, +{'l', 9, -1}, +{'m', 0, -3}, +{'l', 2, -3}, +{'l', 2, -5}, +{'l', 0, -5}, +{'l', 0, -3}, +{'m', 1, -3}, +{'l', 1, -5}, +{'m', 2, -3}, +{'l', 4, -3}, +{'l', 4, -5}, +{'l', 2, -5}, +{'l', 2, -3}, +{'m', 3, -3}, +{'l', 3, -5}, +{'m', 10, -3}, +{'l', 14, -3}, +{'l', 14, -5}, +{'l', 10, -5}, +{'l', 10, -3}, +{'m', 11, -3}, +{'l', 11, -5}, +{'m', 13, -3}, +{'l', 13, -5}, +{'m', 20, -3}, +{'l', 24, -3}, +{'l', 24, -5}, +{'l', 20, -5}, +{'l', 20, -3}, +{'m', 21, -3}, +{'l', 21, -5}, +{'m', 23, -3}, +{'l', 23, -5}, +{'m', 8, 1}, +{'l', 8, -1}, +{'m', 6, 1}, +{'l', 6, -1}, +{'m', 12, -3}, +{'l', 12, -5}, +{'m', 22, -3}, +{'l', 22, -5}, +{'m', 18, 17}, +{'l', 20, 17}, +{'l', 20, 15}, +{'l', 18, 15}, +{'l', 18, 17}, +{'m', 19, 17}, +{'l', 19, 15}, +{'m', 20, 17}, +{'l', 22, 17}, +{'l', 22, 15}, +{'l', 20, 15}, +{'l', 20, 17}, +{'m', 21, 17}, +{'l', 21, 15}, +{'m', 22, 17}, +{'l', 24, 17}, +{'l', 24, 15}, +{'l', 22, 15}, +{'l', 22, 17}, +{'m', 23, 17}, +{'l', 23, 15}, +{'m', 0, 9}, +{'l', 2, 9}, +{'l', 2, 7}, +{'l', 0, 7}, +{'l', 0, 9}, +{'m', 1, 9}, +{'l', 1, 7}, +{'m', 2, 9}, +{'l', 4, 9}, +{'l', 4, 7}, +{'l', 2, 7}, +{'l', 2, 9}, +{'m', 3, 9}, +{'l', 3, 7}, +{'m', 4, 9}, +{'l', 6, 9}, +{'l', 6, 7}, +{'l', 4, 7}, +{'l', 4, 9}, +{'m', 5, 9}, +{'l', 5, 7}, +{'m', 18, 1}, +{'l', 24, 1}, +{'l', 24, -1}, +{'l', 18, -1}, +{'l', 18, 1}, +{'m', 19, 1}, +{'l', 19, -1}, +{'m', 21, 1}, +{'l', 21, -1}, +{'m', 23, 1}, +{'l', 23, -1}, +{'m', 20, 1}, +{'l', 20, -1}, +{'m', 22, 1}, +{'l', 22, -1}, +}; +static cdOperation vf_default_char_179[] = { +{'m', 0, 21}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_180[] = { +{'m', 8, 21}, +{'l', 8, -7}, +{'m', 0, 5}, +{'l', 8, 5}, +}; +static cdOperation vf_default_char_181[] = { +{'m', 8, -7}, +{'l', 8, 21}, +{'m', 0, 9}, +{'l', 8, 9}, +{'m', 0, 5}, +{'l', 8, 5}, +}; +static cdOperation vf_default_char_182[] = { +{'m', 8, 21}, +{'l', 8, -7}, +{'m', 0, 5}, +{'l', 8, 5}, +{'m', 16, 21}, +{'l', 16, -7}, +}; +static cdOperation vf_default_char_183[] = { +{'m', 0, 5}, +{'l', 16, 5}, +{'l', 16, -7}, +{'m', 8, 5}, +{'l', 8, -7}, +}; +static cdOperation vf_default_char_184[] = { +{'m', 0, 9}, +{'l', 8, 9}, +{'l', 8, -7}, +{'m', 0, 5}, +{'l', 8, 5}, +}; +static cdOperation vf_default_char_185[] = { +{'m', 0, 5}, +{'l', 8, 5}, +{'l', 8, -7}, +{'m', 16, 21}, +{'l', 16, -7}, +{'m', 0, 9}, +{'l', 8, 9}, +{'l', 8, 21}, +{'m', 0, 1}, +{'l', 0, 1}, +}; +static cdOperation vf_default_char_186[] = { +{'m', 8, 21}, +{'l', 8, -7}, +{'m', 16, 21}, +{'l', 16, -7}, +}; +static cdOperation vf_default_char_187[] = { +{'m', 0, 9}, +{'l', 16, 9}, +{'l', 16, -7}, +{'m', 0, 5}, +{'l', 8, 5}, +{'l', 8, -7}, +}; +static cdOperation vf_default_char_188[] = { +{'m', 0, 5}, +{'l', 16, 5}, +{'l', 16, 21}, +{'m', 0, 9}, +{'l', 8, 9}, +{'l', 8, 21}, +}; +static cdOperation vf_default_char_189[] = { +{'m', 0, 9}, +{'l', 16, 9}, +{'l', 16, 21}, +{'m', 8, 9}, +{'l', 8, 21}, +}; +static cdOperation vf_default_char_190[] = { +{'m', 0, 5}, +{'l', 8, 5}, +{'l', 8, 21}, +{'m', 0, 9}, +{'l', 8, 9}, +}; +static cdOperation vf_default_char_191[] = { +{'m', 0, 5}, +{'l', 8, 5}, +{'l', 8, -7}, +}; +static cdOperation vf_default_char_192[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 4, 28}, +{'l', 9, 23}, +}; +static cdOperation vf_default_char_193[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_194[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 3, 23}, +{'l', 8, 28}, +{'l', 13, 23}, +}; +static cdOperation vf_default_char_195[] = { +{'m', 16, 0}, +{'l', 8, 21}, +{'l', 0, 0}, +{'m', 3, 7}, +{'l', 13, 7}, +{'m', 2, 24}, +{'l', 7, 27}, +{'l', 11, 24}, +{'l', 15, 26}, +}; +static cdOperation vf_default_char_196[] = { +{'m', 0, 5}, +{'l', 16, 5}, +}; +static cdOperation vf_default_char_197[] = { +{'m', 8, 21}, +{'l', 8, -7}, +{'m', 0, 5}, +{'l', 16, 5}, +}; +static cdOperation vf_default_char_198[] = { +{'m', 0, -7}, +{'l', 0, 21}, +{'m', 8, 9}, +{'l', 0, 9}, +{'m', 8, 5}, +{'l', 0, 5}, +}; +static cdOperation vf_default_char_199[] = { +{'m', 8, 21}, +{'l', 8, -7}, +{'m', 16, 5}, +{'l', 8, 5}, +{'m', 0, 21}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_200[] = { +{'m', 13, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'l', 13, 0}, +{'m', 0, 11}, +{'l', 8, 11}, +{'m', 4, 28}, +{'l', 9, 23}, +}; +static cdOperation vf_default_char_201[] = { +{'m', 16, 9}, +{'l', 0, 9}, +{'l', 0, -7}, +{'m', 16, 5}, +{'l', 8, 5}, +{'l', 8, -7}, +}; +static cdOperation vf_default_char_202[] = { +{'m', 13, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'l', 13, 0}, +{'m', 0, 11}, +{'l', 8, 11}, +{'m', 2, 24}, +{'l', 7, 29}, +{'l', 12, 24}, +{'l', 7, 29}, +{'l', 2, 24}, +}; +static cdOperation vf_default_char_203[] = { +{'m', 13, 21}, +{'l', 0, 21}, +{'l', 0, 0}, +{'l', 13, 0}, +{'m', 0, 11}, +{'l', 8, 11}, +{'m', 4, 26}, +{'l', 3, 25}, +{'l', 4, 24}, +{'l', 5, 25}, +{'l', 4, 26}, +{'m', 12, 26}, +{'l', 11, 25}, +{'l', 12, 24}, +{'l', 13, 25}, +{'l', 12, 26}, +}; +static cdOperation vf_default_char_204[] = { +{'m', 5, 21}, +{'l', 5, 0}, +{'m', 0, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_205[] = { +{'m', 5, 21}, +{'l', 5, 0}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_206[] = { +{'m', 6, 21}, +{'l', 6, 0}, +{'m', 2, 26}, +{'l', 7, 31}, +{'l', 12, 26}, +}; +static cdOperation vf_default_char_207[] = { +{'m', 8, 21}, +{'l', 8, 0}, +{'m', 4, 26}, +{'l', 3, 25}, +{'l', 4, 24}, +{'l', 5, 25}, +{'l', 4, 26}, +{'m', 12, 26}, +{'l', 11, 25}, +{'l', 12, 24}, +{'l', 13, 25}, +{'l', 12, 26}, +}; +static cdOperation vf_default_char_208[] = { +{'m', 6, 21}, +{'l', 6, 0}, +{'m', 6, 21}, +{'l', 13, 21}, +{'l', 16, 20}, +{'l', 18, 18}, +{'l', 19, 16}, +{'l', 20, 13}, +{'l', 20, 8}, +{'l', 19, 5}, +{'l', 18, 3}, +{'l', 16, 1}, +{'l', 13, 0}, +{'l', 6, 0}, +{'m', 0, 10}, +{'l', 12, 10}, +}; +static cdOperation vf_default_char_209[] = { +{'m', 0, 5}, +{'l', 8, 5}, +{'l', 8, -7}, +{'m', 16, 5}, +{'l', 8, 5}, +{'m', 0, 9}, +{'l', 16, 9}, +}; +static cdOperation vf_default_char_210[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 4, 28}, +{'l', 9, 23}, +}; +static cdOperation vf_default_char_211[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_212[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 3, 23}, +{'l', 8, 28}, +{'l', 13, 23}, +}; +static cdOperation vf_default_char_213[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 2, 24}, +{'l', 7, 27}, +{'l', 11, 24}, +{'l', 15, 26}, +}; +static cdOperation vf_default_char_214[] = { +{'m', 16, 5}, +{'l', 0, 5}, +{'l', 0, -7}, +{'m', 8, 5}, +{'l', 8, -7}, +}; +static cdOperation vf_default_char_215[] = { +{'m', 0, 0}, +{'l', 14, 14}, +{'m', 0, 13}, +{'l', 14, -1}, +}; +static cdOperation vf_default_char_216[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 1, -3}, +{'l', 2, -1}, +{'l', 16, 23}, +}; +static cdOperation vf_default_char_217[] = { +{'m', 0, 21}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 21}, +{'m', 4, 28}, +{'l', 9, 23}, +}; +static cdOperation vf_default_char_218[] = { +{'m', 0, 21}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 21}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_219[] = { +{'m', 0, 21}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 6, 0}, +{'l', 8, 0}, +{'l', 11, 1}, +{'l', 13, 3}, +{'l', 14, 6}, +{'l', 14, 21}, +{'m', 2, 24}, +{'l', 7, 29}, +{'l', 12, 24}, +{'l', 7, 29}, +{'l', 2, 24}, +}; +static cdOperation vf_default_char_220[] = { +{'m', 16, 0}, +{'l', 0, 0}, +{'l', 0, 11}, +{'l', 16, 11}, +{'l', 16, 0}, +{'l', 15, 0}, +{'l', 15, 11}, +{'m', 1, 11}, +{'l', 1, 0}, +{'m', 2, 11}, +{'l', 2, 0}, +{'m', 3, 11}, +{'l', 3, 0}, +{'m', 4, 11}, +{'l', 4, 0}, +{'m', 5, 11}, +{'l', 5, 0}, +{'m', 6, 11}, +{'l', 6, 0}, +{'m', 7, 11}, +{'l', 7, 0}, +{'m', 8, 11}, +{'l', 8, 0}, +{'m', 9, 11}, +{'l', 9, 0}, +{'m', 10, 11}, +{'l', 10, 0}, +{'m', 11, 11}, +{'l', 11, 0}, +{'m', 12, 11}, +{'l', 12, 0}, +{'m', 13, 11}, +{'l', 13, 0}, +{'m', 14, 11}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_221[] = { +{'m', 0, 21}, +{'l', 8, 11}, +{'l', 8, 0}, +{'m', 16, 21}, +{'l', 8, 11}, +{'m', 10, 28}, +{'l', 5, 23}, +}; +static cdOperation vf_default_char_222[] = { +{'m', 9, 0}, +{'l', 9, 21}, +{'m', 10, 21}, +{'l', 10, 0}, +{'m', 11, 21}, +{'l', 11, 0}, +{'m', 12, 21}, +{'l', 12, 0}, +{'m', 13, 21}, +{'l', 13, 0}, +{'m', 14, 21}, +{'l', 14, 0}, +{'m', 15, 21}, +{'l', 15, 0}, +{'m', 16, 21}, +{'l', 16, 0}, +{'m', 17, 21}, +{'l', 17, 0}, +}; +static cdOperation vf_default_char_223[] = { +{'m', 0, 1}, +{'l', 10, 1}, +{'l', 13, 3}, +{'l', 13, 7}, +{'l', 9, 9}, +{'l', 13, 11}, +{'l', 13, 14}, +{'l', 10, 16}, +{'l', 3, 16}, +{'l', 0, 14}, +{'l', 0, -3}, +{'m', 9, 9}, +{'l', 0, 9}, +}; +static cdOperation vf_default_char_224[] = { +{'m', 18, 0}, +{'l', 12, 9}, +{'l', 10, 11}, +{'l', 8, 12}, +{'l', 5, 12}, +{'l', 3, 11}, +{'l', 1, 9}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 18, 12}, +}; +static cdOperation vf_default_char_225[] = { +{'m', 0, 1}, +{'l', 10, 1}, +{'l', 13, 3}, +{'l', 13, 7}, +{'l', 9, 9}, +{'l', 13, 11}, +{'l', 13, 14}, +{'l', 10, 16}, +{'l', 3, 16}, +{'l', 0, 14}, +{'l', 0, -3}, +{'m', 9, 9}, +{'l', 0, 9}, +}; +static cdOperation vf_default_char_226[] = { +{'m', 0, 0}, +{'l', 0, 14}, +{'l', 9, 14}, +{'l', 9, 11}, +}; +static cdOperation vf_default_char_227[] = { +{'m', 12, 14}, +{'l', 12, 0}, +{'m', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'m', 0, 17}, +{'l', 5, 20}, +{'l', 9, 17}, +{'l', 13, 19}, +}; +static cdOperation vf_default_char_228[] = { +{'m', 13, 2}, +{'l', 13, 0}, +{'l', 0, 0}, +{'l', 8, 11}, +{'l', 0, 21}, +{'l', 13, 21}, +{'l', 13, 19}, +}; +static cdOperation vf_default_char_229[] = { +{'m', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 12, 9}, +{'l', 10, 11}, +{'l', 8, 12}, +{'l', 5, 12}, +{'l', 3, 11}, +{'l', 1, 9}, +{'l', 0, 6}, +{'m', 5, 12}, +{'l', 9, 14}, +{'l', 20, 14}, +}; +static cdOperation vf_default_char_230[] = { +{'m', 2, 14}, +{'l', 2, 4}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 13, 4}, +{'m', 13, 14}, +{'l', 13, 0}, +{'m', 3, 1}, +{'l', 3, -3}, +{'l', 0, -6}, +}; +static cdOperation vf_default_char_231[] = { +{'m', 0, 9}, +{'l', 0, 11}, +{'l', 1, 13}, +{'l', 3, 14}, +{'l', 6, 14}, +{'l', 8, 12}, +{'l', 8, -2}, +{'m', 8, 9}, +{'l', 11, 11}, +{'l', 14, 14}, +}; +static cdOperation vf_default_char_232[] = { +{'m', 0, 9}, +{'l', 1, 6}, +{'l', 3, 4}, +{'l', 5, 3}, +{'l', 8, 3}, +{'l', 10, 4}, +{'l', 12, 6}, +{'l', 13, 9}, +{'l', 12, 12}, +{'l', 10, 14}, +{'l', 8, 15}, +{'l', 5, 15}, +{'l', 3, 14}, +{'l', 1, 12}, +{'l', 0, 9}, +{'m', 6, 21}, +{'l', 6, 15}, +{'m', 7, 21}, +{'l', 7, 15}, +{'m', 0, 21}, +{'l', 13, 21}, +{'m', 6, -3}, +{'l', 6, 3}, +{'m', 7, -3}, +{'l', 7, 3}, +{'m', 0, -3}, +{'l', 13, -3}, +}; +static cdOperation vf_default_char_233[] = { +{'m', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 8}, +{'l', 1, 5}, +{'l', 2, 3}, +{'l', 4, 1}, +{'l', 6, 0}, +{'l', 10, 0}, +{'l', 12, 1}, +{'l', 14, 3}, +{'l', 15, 5}, +{'l', 16, 8}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'m', 0, 10}, +{'l', 16, 10}, +}; +static cdOperation vf_default_char_234[] = { +{'m', 16, 0}, +{'l', 11, 0}, +{'l', 11, 6}, +{'l', 14, 7}, +{'l', 16, 9}, +{'l', 16, 13}, +{'l', 15, 16}, +{'l', 14, 18}, +{'l', 12, 20}, +{'l', 10, 21}, +{'l', 6, 21}, +{'l', 4, 20}, +{'l', 2, 18}, +{'l', 1, 16}, +{'l', 0, 13}, +{'l', 0, 9}, +{'l', 2, 7}, +{'l', 5, 6}, +{'l', 5, 0}, +{'l', 0, 0}, +}; +static cdOperation vf_default_char_235[] = { +{'m', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 12, 9}, +{'l', 10, 11}, +{'l', 8, 12}, +{'l', 5, 12}, +{'l', 3, 11}, +{'l', 1, 9}, +{'l', 0, 6}, +{'m', 10, 11}, +{'l', 0, 21}, +{'l', 13, 21}, +{'l', 13, 18}, +}; +static cdOperation vf_default_char_236[] = { +{'m', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 12, 9}, +{'l', 10, 11}, +{'l', 8, 12}, +{'l', 5, 12}, +{'l', 3, 11}, +{'l', 1, 9}, +{'l', 0, 6}, +{'m', 12, 6}, +{'l', 13, 3}, +{'l', 15, 1}, +{'l', 17, 0}, +{'l', 20, 0}, +{'l', 22, 1}, +{'l', 24, 3}, +{'l', 25, 6}, +{'l', 24, 9}, +{'l', 22, 11}, +{'l', 20, 12}, +{'l', 17, 12}, +{'l', 15, 11}, +{'l', 13, 9}, +{'l', 12, 6}, +}; +static cdOperation vf_default_char_237[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 0, -3}, +{'l', 13, 17}, +}; +static cdOperation vf_default_char_238[] = { +{'m', 13, 21}, +{'l', 3, 21}, +{'l', 0, 19}, +{'l', 0, 11}, +{'l', 8, 11}, +{'m', 0, 11}, +{'l', 0, 2}, +{'l', 3, 0}, +{'l', 13, 0}, +}; +static cdOperation vf_default_char_239[] = { +{'m', 0, 0}, +{'l', 0, 15}, +{'l', 1, 18}, +{'l', 3, 20}, +{'l', 6, 21}, +{'l', 8, 21}, +{'l', 11, 20}, +{'l', 13, 18}, +{'l', 14, 15}, +{'l', 14, 0}, +}; +static cdOperation vf_default_char_240[] = { +{'m', 0, 9}, +{'l', 18, 9}, +{'m', 0, 5}, +{'l', 18, 5}, +{'m', 0, 13}, +{'l', 18, 13}, +}; +static cdOperation vf_default_char_241[] = { +{'m', 0, 0}, +{'l', 18, 0}, +{'m', 9, 21}, +{'l', 9, 3}, +{'m', 0, 12}, +{'l', 18, 12}, +}; +static cdOperation vf_default_char_242[] = { +{'m', 0, 0}, +{'l', 18, 0}, +{'m', 0, 21}, +{'l', 18, 12}, +{'l', 0, 3}, +}; +static cdOperation vf_default_char_243[] = { +{'m', 18, 0}, +{'l', 0, 0}, +{'m', 18, 21}, +{'l', 0, 12}, +{'l', 18, 3}, +}; +static cdOperation vf_default_char_244[] = { +{'m', 10, 20}, +{'l', 7, 21}, +{'l', 5, 21}, +{'l', 2, 20}, +{'l', 1, 19}, +{'l', 0, 16}, +{'l', 0, -7}, +}; +static cdOperation vf_default_char_245[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 0, 17}, +{'l', 5, 20}, +{'l', 9, 17}, +{'l', 13, 19}, +}; +static cdOperation vf_default_char_246[] = { +{'m', 9, 20}, +{'l', 8, 19}, +{'l', 9, 18}, +{'l', 10, 19}, +{'l', 9, 20}, +{'m', 9, 3}, +{'l', 8, 2}, +{'l', 9, 1}, +{'l', 10, 2}, +{'l', 9, 3}, +{'m', 0, 10}, +{'l', 18, 10}, +}; +static cdOperation vf_default_char_247[] = { +{'m', 9, 20}, +{'l', 8, 19}, +{'l', 9, 18}, +{'l', 10, 19}, +{'l', 9, 20}, +{'m', 9, 3}, +{'l', 8, 2}, +{'l', 9, 1}, +{'l', 10, 2}, +{'l', 9, 3}, +{'m', 0, 10}, +{'l', 18, 10}, +}; +static cdOperation vf_default_char_248[] = { +{'m', 5, 14}, +{'l', 3, 13}, +{'l', 1, 11}, +{'l', 0, 8}, +{'l', 0, 6}, +{'l', 1, 3}, +{'l', 3, 1}, +{'l', 5, 0}, +{'l', 8, 0}, +{'l', 10, 1}, +{'l', 12, 3}, +{'l', 13, 6}, +{'l', 13, 8}, +{'l', 12, 11}, +{'l', 10, 13}, +{'l', 8, 14}, +{'l', 5, 14}, +{'m', 0, -3}, +{'l', 13, 17}, +}; +static cdOperation vf_default_char_249[] = { +{'m', 0, 4}, +{'l', 3, 4}, +{'l', 3, 0}, +{'l', 0, 0}, +{'l', 0, 4}, +{'m', 1, 4}, +{'l', 1, 0}, +{'m', 2, 4}, +{'l', 2, 0}, +}; +static cdOperation vf_default_char_250[] = { +{'m', 0, 2}, +{'l', 3, 2}, +{'l', 3, 0}, +{'l', 0, 0}, +{'l', 0, 2}, +{'l', 3, 1}, +{'m', 1, 2}, +{'l', 1, 0}, +{'m', 2, 2}, +{'l', 2, 0}, +}; +static cdOperation vf_default_char_251[] = { +{'m', 16, 18}, +{'l', 16, 21}, +{'l', 8, 21}, +{'l', 8, 0}, +{'l', 0, 10}, +}; +static cdOperation vf_default_char_252[] = { +{'m', 0, 21}, +{'l', 0, 10}, +{'m', 0, 17}, +{'l', 3, 20}, +{'l', 5, 21}, +{'l', 8, 21}, +{'l', 10, 20}, +{'l', 11, 17}, +{'l', 11, 10}, +}; +static cdOperation vf_default_char_253[] = { +{'m', 1, 14}, +{'l', 7, 0}, +{'m', 13, 14}, +{'l', 7, 0}, +{'l', 5, -4}, +{'l', 3, -6}, +{'l', 1, -7}, +{'l', 0, -7}, +{'m', 10, 22}, +{'l', 5, 17}, +}; +static cdOperation vf_default_char_254[] = { +{'m', 0, 0}, +{'l', 0, 11}, +{'l', 8, 11}, +{'l', 8, 0}, +{'l', 0, 0}, +{'m', 1, 11}, +{'l', 1, 0}, +{'m', 2, 11}, +{'l', 2, 0}, +{'m', 3, 11}, +{'l', 3, 0}, +{'m', 4, 11}, +{'l', 4, 0}, +{'m', 5, 11}, +{'l', 5, 0}, +{'m', 6, 11}, +{'l', 6, 0}, +{'m', 7, 11}, +{'l', 7, 0}, +}; +static cdCaracter vf_default_chars[256] = { +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{ 0, 0, 0, 0}, +{12, 6, 0, 0}, +{6, 3, 7, vf_default_char_33}, +{14, 7, 16, vf_default_char_34}, +{18, 9, 8, vf_default_char_35}, +{17, 8, 38, vf_default_char_36}, +{21, 10, 29, vf_default_char_37}, +{22, 11, 46, vf_default_char_38}, +{6, 3, 7, vf_default_char_39}, +{10, 5, 18, vf_default_char_40}, +{11, 5, 18, vf_default_char_41}, +{13, 6, 6, vf_default_char_42}, +{22, 11, 4, vf_default_char_43}, +{6, 3, 8, vf_default_char_44}, +{22, 11, 2, vf_default_char_45}, +{6, 3, 5, vf_default_char_46}, +{14, 7, 2, vf_default_char_47}, +{17, 8, 17, vf_default_char_48}, +{14, 7, 4, vf_default_char_49}, +{17, 8, 14, vf_default_char_50}, +{17, 8, 15, vf_default_char_51}, +{17, 8, 5, vf_default_char_52}, +{17, 8, 17, vf_default_char_53}, +{16, 8, 23, vf_default_char_54}, +{17, 8, 4, vf_default_char_55}, +{17, 8, 29, vf_default_char_56}, +{17, 8, 23, vf_default_char_57}, +{6, 3, 10, vf_default_char_58}, +{6, 3, 13, vf_default_char_59}, +{20, 10, 3, vf_default_char_60}, +{22, 11, 4, vf_default_char_61}, +{20, 10, 3, vf_default_char_62}, +{15, 7, 19, vf_default_char_63}, +{24, 12, 52, vf_default_char_64}, +{19, 9, 5, vf_default_char_65}, +{17, 8, 21, vf_default_char_66}, +{19, 9, 18, vf_default_char_67}, +{17, 8, 14, vf_default_char_68}, +{15, 7, 6, vf_default_char_69}, +{14, 7, 6, vf_default_char_70}, +{18, 9, 21, vf_default_char_71}, +{18, 9, 6, vf_default_char_72}, +{4, 2, 2, vf_default_char_73}, +{14, 7, 10, vf_default_char_74}, +{17, 8, 6, vf_default_char_75}, +{13, 6, 4, vf_default_char_76}, +{20, 10, 8, vf_default_char_77}, +{18, 9, 6, vf_default_char_78}, +{19, 9, 21, vf_default_char_79}, +{17, 8, 11, vf_default_char_80}, +{19, 9, 23, vf_default_char_81}, +{17, 8, 14, vf_default_char_82}, +{17, 8, 20, vf_default_char_83}, +{15, 7, 4, vf_default_char_84}, +{18, 9, 10, vf_default_char_85}, +{17, 8, 4, vf_default_char_86}, +{22, 11, 8, vf_default_char_87}, +{17, 8, 4, vf_default_char_88}, +{17, 8, 5, vf_default_char_89}, +{17, 8, 6, vf_default_char_90}, +{7, 3, 8, vf_default_char_91}, +{14, 7, 2, vf_default_char_92}, +{8, 4, 8, vf_default_char_93}, +{19, 9, 6, vf_default_char_94}, +{17, 8, 2, vf_default_char_95}, +{6, 3, 7, vf_default_char_96}, +{16, 8, 16, vf_default_char_97}, +{15, 7, 16, vf_default_char_98}, +{15, 7, 14, vf_default_char_99}, +{16, 8, 16, vf_default_char_100}, +{15, 7, 17, vf_default_char_101}, +{10, 5, 7, vf_default_char_102}, +{16, 8, 21, vf_default_char_103}, +{15, 7, 9, vf_default_char_104}, +{7, 3, 7, vf_default_char_105}, +{9, 4, 10, vf_default_char_106}, +{13, 6, 6, vf_default_char_107}, +{4, 2, 2, vf_default_char_108}, +{26, 13, 16, vf_default_char_109}, +{15, 7, 9, vf_default_char_110}, +{16, 8, 17, vf_default_char_111}, +{15, 7, 16, vf_default_char_112}, +{16, 8, 16, vf_default_char_113}, +{9, 4, 7, vf_default_char_114}, +{14, 7, 17, vf_default_char_115}, +{10, 5, 7, vf_default_char_116}, +{15, 7, 9, vf_default_char_117}, +{14, 7, 4, vf_default_char_118}, +{19, 9, 8, vf_default_char_119}, +{14, 7, 4, vf_default_char_120}, +{15, 7, 8, vf_default_char_121}, +{14, 7, 6, vf_default_char_122}, +{10, 5, 37, vf_default_char_123}, +{4, 2, 2, vf_default_char_124}, +{9, 4, 37, vf_default_char_125}, +{14, 7, 4, vf_default_char_126}, +{16, 8, 8, vf_default_char_127}, +{18, 9, 30, vf_default_char_128}, +{15, 7, 19, vf_default_char_129}, +{15, 7, 19, vf_default_char_130}, +{18, 9, 19, vf_default_char_131}, +{16, 8, 26, vf_default_char_132}, +{16, 8, 18, vf_default_char_133}, +{16, 8, 23, vf_default_char_134}, +{15, 7, 21, vf_default_char_135}, +{18, 9, 20, vf_default_char_136}, +{15, 7, 27, vf_default_char_137}, +{15, 7, 19, vf_default_char_138}, +{12, 6, 12, vf_default_char_139}, +{16, 8, 5, vf_default_char_140}, +{7, 3, 4, vf_default_char_141}, +{17, 8, 15, vf_default_char_142}, +{17, 8, 12, vf_default_char_143}, +{15, 7, 8, vf_default_char_144}, +{28, 14, 33, vf_default_char_145}, +{26, 13, 10, vf_default_char_146}, +{16, 8, 20, vf_default_char_147}, +{16, 8, 27, vf_default_char_148}, +{16, 8, 19, vf_default_char_149}, +{17, 8, 12, vf_default_char_150}, +{15, 7, 11, vf_default_char_151}, +{15, 7, 18, vf_default_char_152}, +{19, 9, 31, vf_default_char_153}, +{18, 9, 20, vf_default_char_154}, +{15, 7, 16, vf_default_char_155}, +{21, 10, 12, vf_default_char_156}, +{17, 8, 9, vf_default_char_157}, +{21, 10, 18, vf_default_char_158}, +{17, 8, 15, vf_default_char_159}, +{16, 8, 18, vf_default_char_160}, +{7, 3, 4, vf_default_char_161}, +{16, 8, 19, vf_default_char_162}, +{15, 7, 11, vf_default_char_163}, +{17, 8, 13, vf_default_char_164}, +{18, 9, 8, vf_default_char_165}, +{16, 8, 18, vf_default_char_166}, +{16, 8, 17, vf_default_char_167}, +{15, 7, 19, vf_default_char_168}, +{16, 8, 7, vf_default_char_169}, +{16, 8, 7, vf_default_char_170}, +{19, 9, 15, vf_default_char_171}, +{19, 9, 10, vf_default_char_172}, +{6, 3, 7, vf_default_char_173}, +{19, 9, 6, vf_default_char_174}, +{19, 9, 6, vf_default_char_175}, +{14, 7, 126, vf_default_char_176}, +{16, 8, 252, vf_default_char_177}, +{24, 12, 276, vf_default_char_178}, +{5, 2, 2, vf_default_char_179}, +{13, 6, 4, vf_default_char_180}, +{13, 6, 6, vf_default_char_181}, +{21, 10, 6, vf_default_char_182}, +{21, 10, 5, vf_default_char_183}, +{13, 6, 5, vf_default_char_184}, +{21, 10, 10, vf_default_char_185}, +{20, 10, 4, vf_default_char_186}, +{21, 10, 6, vf_default_char_187}, +{21, 10, 6, vf_default_char_188}, +{21, 10, 5, vf_default_char_189}, +{13, 6, 5, vf_default_char_190}, +{0, 0, 3, vf_default_char_191}, +{19, 9, 7, vf_default_char_192}, +{19, 9, 7, vf_default_char_193}, +{19, 9, 8, vf_default_char_194}, +{19, 9, 9, vf_default_char_195}, +{16, 8, 2, vf_default_char_196}, +{16, 8, 4, vf_default_char_197}, +{8, 4, 6, vf_default_char_198}, +{16, 8, 6, vf_default_char_199}, +{15, 7, 8, vf_default_char_200}, +{16, 8, 6, vf_default_char_201}, +{15, 7, 11, vf_default_char_202}, +{15, 7, 16, vf_default_char_203}, +{9, 2, 4, vf_default_char_204}, +{9, 2, 4, vf_default_char_205}, +{12, 2, 5, vf_default_char_206}, +{12, 2, 12, vf_default_char_207}, +{23, 8, 16, vf_default_char_208}, +{16, 8, 7, vf_default_char_209}, +{19, 9, 23, vf_default_char_210}, +{19, 9, 23, vf_default_char_211}, +{19, 9, 24, vf_default_char_212}, +{19, 9, 25, vf_default_char_213}, +{16, 8, 5, vf_default_char_214}, +{18, 11, 4, vf_default_char_215}, +{19, 9, 24, vf_default_char_216}, +{18, 9, 12, vf_default_char_217}, +{18, 9, 12, vf_default_char_218}, +{18, 9, 15, vf_default_char_219}, +{16, 8, 35, vf_default_char_220}, +{17, 8, 7, vf_default_char_221}, +{17, 8, 18, vf_default_char_222}, +{18, 9, 13, vf_default_char_223}, +{22, 11, 15, vf_default_char_224}, +{18, 9, 13, vf_default_char_225}, +{14, 7, 4, vf_default_char_226}, +{16, 8, 20, vf_default_char_227}, +{18, 9, 7, vf_default_char_228}, +{24, 12, 18, vf_default_char_229}, +{18, 9, 12, vf_default_char_230}, +{18, 9, 10, vf_default_char_231}, +{18, 9, 27, vf_default_char_232}, +{21, 10, 23, vf_default_char_233}, +{21, 10, 20, vf_default_char_234}, +{18, 9, 19, vf_default_char_235}, +{29, 14, 30, vf_default_char_236}, +{16, 8, 19, vf_default_char_237}, +{17, 8, 9, vf_default_char_238}, +{19, 9, 10, vf_default_char_239}, +{23, 11, 6, vf_default_char_240}, +{23, 11, 6, vf_default_char_241}, +{23, 11, 5, vf_default_char_242}, +{24, 12, 5, vf_default_char_243}, +{13, 6, 7, vf_default_char_244}, +{16, 8, 21, vf_default_char_245}, +{23, 11, 12, vf_default_char_246}, +{23, 11, 12, vf_default_char_247}, +{16, 8, 19, vf_default_char_248}, +{7, 3, 9, vf_default_char_249}, +{7, 3, 10, vf_default_char_250}, +{18, 9, 5, vf_default_char_251}, +{15, 7, 9, vf_default_char_252}, +{15, 7, 10, vf_default_char_253}, +{13, 6, 19, vf_default_char_254}, +{ 0, 0, 0, 0} +}; + +/******************************************************/ +/* inicializacao & controle */ +/******************************************************/ + +static void vf_releasefontchars(cdVectorFont *vector_font) +{ + int c; + + for (c=0; c<256; c++) + { + if (vector_font->chars[c].op) + free(vector_font->chars[c].op); + } + + free(vector_font->chars); +} + +static void vf_setdefaultfont(cdVectorFont *vector_font) +{ + if (vector_font->chars && vector_font->chars != vf_default_chars) + vf_releasefontchars(vector_font); + + strcpy(vector_font->name, "Simplex II"); + vector_font->file_name[0] = 0; + vector_font->chars = vf_default_chars; + vector_font->top = vf_default_top; + vector_font->cap = vf_default_cap; + vector_font->half = vf_default_half; + vector_font->bottom = vf_default_bottom; +} + +static int vf_readfontfile(FILE *file, cdVectorFont *vector_font) +{ + int c, right, center, operations; + + if (vector_font->chars && vector_font->chars != vf_default_chars) + vf_releasefontchars(vector_font); + + vector_font->chars = (cdCaracter *)calloc(256, sizeof(cdCaracter)); + if (!vector_font->chars) + return 0; + + if (fscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom) != 4) + { + if (fscanf(file, "%[^\n]", vector_font->name) != 1) + return 0; + if (fscanf(file,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom)!=4) + return 0; + } + else + sprintf(vector_font->name, "Unknown"); + + while (fscanf(file, "%d%d%d%d", &c, &right, ¢er, &operations) == 4) + { + vector_font->chars[c].right = right; + vector_font->chars[c].center = center; + vector_font->chars[c].operations = operations; + if (operations) + { + int i; + vector_font->chars[c].op = (cdOperation *)calloc(operations, sizeof(cdOperation)); + if (!vector_font->chars[c].op) return 0; + for (i=0; ichars[c].op[i].operation = operation; + vector_font->chars[c].op[i].x = (signed char)x; + vector_font->chars[c].op[i].y = (signed char)y; + } + } + } + + return 1; +} + +static int vf_readfontstring(const char* strdata, cdVectorFont *vector_font) +{ + int c, right, center, operations; + + if (vector_font->chars && vector_font->chars != vf_default_chars) + vf_releasefontchars(vector_font); + + vector_font->chars = (cdCaracter *)calloc(256, sizeof(cdCaracter)); + if (!vector_font->chars) + return 0; + + /* try to read without a name */ + if (sscanf(strdata,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom) != 4) + { + if (sscanf(strdata, "%[^\n]", vector_font->name) != 1) + return 0; + strdata = strstr(strdata, "\n")+1; /* goto next line */ + if (strdata == (void*)1) return 0; + + if (sscanf(strdata,"%d%d%d%d",&vector_font->top,&vector_font->cap,&vector_font->half,&vector_font->bottom)!=4) + return 0; + strdata = strstr(strdata, "\n"); /* goto next line */ + if (strdata == (void*)1) return 0; + } + else + { + strdata = strstr(strdata, "\n")+1; /* goto next line */ + sprintf(vector_font->name, "Unknown"); + } + + /* skip 2 blank lines */ + strdata = strstr(strdata, "\n")+1; /* goto next line */ + strdata = strstr(strdata, "\n")+1; /* goto next line */ + + /* for each font character */ + while (sscanf(strdata, "%d%d%d%d", &c, &right, ¢er, &operations) == 4) + { + strdata = strstr(strdata, "\n")+1; /* goto next line */ + if (strdata == (void*)1) return 0; + + vector_font->chars[c].right = right; + vector_font->chars[c].center = center; + vector_font->chars[c].operations = operations; + if (operations) + { + int i; + vector_font->chars[c].op = (cdOperation *)calloc(operations, sizeof(cdOperation)); + if (!vector_font->chars[c].op) return 0; + for (i=0; ichars[c].op[i].operation = operation; + vector_font->chars[c].op[i].x = (signed char)x; + vector_font->chars[c].op[i].y = (signed char)y; + } + } + + /* skip 1 blank line */ + strdata = strstr(strdata, "\n")+1; /* goto next line */ + if (strdata == (void*)1) return 1; + } + + return 1; +} + +static int vf_textwidth(cdVectorFont *vector_font, const char* str) +{ + int width = 0; + while (*str && *str!='\n') + width += vector_font->chars[(unsigned char)(*(str++))].right; + if (width==0) width = 1; + return width; +} + +static void vf_move_dir(cdVectorFont *vector_font, int *x, int *y, double dx, double dy) +{ + *x += cdRound(vector_font->current_cos*dx - vector_font->current_sin*dy); + *y += cdRound(vector_font->current_sin*dx + vector_font->current_cos*dy); +} + +static void vf_wmove_dir(cdVectorFont *vector_font, double *x, double *y, double dx, double dy) +{ + *x += vector_font->current_cos*dx - vector_font->current_sin*dy; + *y += vector_font->current_sin*dx + vector_font->current_cos*dy; +} + +static void vf_draw_char(cdVectorFont *vector_font, char c, int *x, int *y) +{ + unsigned char ac = vf_ansi2ascii[(unsigned char)c]; + cdOperation *current = vector_font->chars[ac].op; + int m, op = vector_font->chars[ac].operations; + + for(m = 0; m < op; m++) + { + int px = *x; + int py = *y; + + if (current->operation == 'm') + { + if (m) cdCanvasEnd(vector_font->canvas); + cdCanvasBegin(vector_font->canvas, CD_OPEN_LINES); + } + + vf_move_dir(vector_font, &px, &py, current->x*vector_font->size_x, current->y*vector_font->size_y); + + if (vector_font->text_transf) + { + double aux = px*vector_font->text_matrix[3] + py*vector_font->text_matrix[4] + vector_font->text_matrix[5]; + py = cdRound(px*vector_font->text_matrix[0] + py*vector_font->text_matrix[1] + vector_font->text_matrix[2]); + px = _cdRound(aux); + } + + cdCanvasVertex(vector_font->canvas, px, py); + current++; + } + + if (m) cdCanvasEnd(vector_font->canvas); +} + +static void vf_wdraw_char(cdVectorFont *vector_font, char c, double *x, double *y) +{ + unsigned char ac = vf_ansi2ascii[(unsigned char)c]; + cdOperation *current = vector_font->chars[ac].op; + int m, op = vector_font->chars[ac].operations; + + for(m = 0; m < op; m++) + { + double px = *x; + double py = *y; + + if (current->operation == 'm') + { + if (m) cdCanvasEnd(vector_font->canvas); + cdCanvasBegin(vector_font->canvas, CD_OPEN_LINES); + } + + vf_wmove_dir(vector_font, &px, &py, current->x*vector_font->size_x, current->y*vector_font->size_y); + + if (vector_font->text_transf) + { + double aux = px*vector_font->text_matrix[3] + py*vector_font->text_matrix[4] + vector_font->text_matrix[5]; + py = px*vector_font->text_matrix[0] + py*vector_font->text_matrix[1] + vector_font->text_matrix[2]; + px = aux; + } + + wdCanvasVertex(vector_font->canvas, px, py); + current++; + } + + if (m) cdCanvasEnd(vector_font->canvas); +} + +static void vf_move_to_base(cdVectorFont *vector_font, int *x, int *y, const char* str, int width) +{ + /* move point to baseline/left according to alignment */ + int align = vector_font->canvas->text_alignment; + + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST) + { + vf_move_dir(vector_font, x, y, 0, -vector_font->top*vector_font->size_y); + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) + { + vf_move_dir(vector_font, x, y, 0, -vector_font->bottom*vector_font->size_y); /* bottom is < 0 */ + } + else if (align == CD_BASE_CENTER || align == CD_BASE_LEFT || align == CD_BASE_RIGHT) + { + /* y = y; */ + } + else /* CD_CENTER || CD_EAST || CD_WEST */ + vf_move_dir(vector_font, x, y, 0, -((double)(vector_font->top+vector_font->bottom)/2.0)*vector_font->size_y); + + if (align == CD_EAST || align == CD_NORTH_EAST || align == CD_SOUTH_EAST || align == CD_BASE_RIGHT) + { + if (str) width = vf_textwidth(vector_font, str); + vf_move_dir(vector_font, x, y, -width*vector_font->size_x, 0); + } + else if (align == CD_WEST || align == CD_NORTH_WEST || align == CD_SOUTH_WEST || align == CD_BASE_LEFT) + { + /* x = x; */ + } + else /* CD_CENTER || CD_NORTH || CD_SOUTH */ + { + if (str) width = vf_textwidth(vector_font, str); + vf_move_dir(vector_font, x, y, -(width*vector_font->size_x)/2.0, 0); + } +} + +static void vf_wmove_to_base(cdVectorFont *vector_font, double *x, double *y, const char* str, int width) +{ + /* move point to baseline/left according to alignment */ + int align = vector_font->canvas->text_alignment; + + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST) + { + vf_wmove_dir(vector_font, x, y, 0, -vector_font->top*vector_font->size_y); + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) + { + vf_wmove_dir(vector_font, x, y, 0, -vector_font->bottom*vector_font->size_y); /* bottom is < 0 */ + } + else if (align == CD_BASE_CENTER || align == CD_BASE_LEFT || align == CD_BASE_RIGHT) + { + /* y = y; */ + } + else /* CD_CENTER || CD_EAST || CD_WEST */ + vf_wmove_dir(vector_font, x, y, 0, -((double)(vector_font->top+vector_font->bottom)/2.0)*vector_font->size_y); + + if (align == CD_EAST || align == CD_NORTH_EAST || align == CD_SOUTH_EAST || align == CD_BASE_RIGHT) + { + if (str) width = vf_textwidth(vector_font, str); + vf_wmove_dir(vector_font, x, y, -width*vector_font->size_x, 0); + } + else if (align == CD_WEST || align == CD_NORTH_WEST || align == CD_SOUTH_WEST || align == CD_BASE_LEFT) + { + /* x = x; */ + } + else /* CD_CENTER || CD_NORTH || CD_SOUTH */ + { + if (str) width = vf_textwidth(vector_font, str); + vf_wmove_dir(vector_font, x, y, -(width*vector_font->size_x)/2.0, 0); + } +} + +static void vf_draw_text(cdVectorFont* vector_font, int x, int y, const char* str) +{ + vf_move_to_base(vector_font, &x, &y, str, 0); + + while (*str && *str!='\n') + { + vf_draw_char(vector_font, *str, &x, &y); + vf_move_dir(vector_font, &x, &y, (vector_font->chars[(unsigned char)*str].right)*vector_font->size_x, 0); + str++; + } +} + +static void vf_wdraw_text(cdVectorFont* vector_font, double x, double y, const char* str) +{ + vf_wmove_to_base(vector_font, &x, &y, str, 0); + + while (*str && *str!='\n') + { + vf_wdraw_char(vector_font, *str, &x, &y); + vf_wmove_dir(vector_font, &x, &y, (vector_font->chars[(unsigned char)*str].right)*vector_font->size_x, 0); + str++; + } +} + +static void vf_calc_point(cdVectorFont *vector_font, int start_x, int start_y, int *x, int *y, int dx, int dy) +{ + *x = start_x; + *y = start_y; + + vf_move_dir(vector_font, x, y, dx, dy); + + if (vector_font->text_transf) + { + double aux = *x * vector_font->text_matrix[3] + *y * vector_font->text_matrix[4] + vector_font->text_matrix[5]; + *y = cdRound(*x * vector_font->text_matrix[0] + *y * vector_font->text_matrix[1] + vector_font->text_matrix[2]); + *x = _cdRound(aux); + } +} + +static void vf_wcalc_point(cdVectorFont *vector_font, double start_x, double start_y, double *x, double *y, double dx, double dy) +{ + *x = start_x; + *y = start_y; + + vf_wmove_dir(vector_font, x, y, dx, dy); + + if (vector_font->text_transf) + { + double aux = *x * vector_font->text_matrix[3] + *y * vector_font->text_matrix[4] + vector_font->text_matrix[5]; + *y = *x * vector_font->text_matrix[0] + *y * vector_font->text_matrix[1] + vector_font->text_matrix[2]; + *x = aux; + } +} + +static int vf_gettextmaxwidth(cdVectorFont* vector_font, const char* str, int num_lin) +{ + int i, max_w = 0, w; + const char *p_str, *q; + + p_str = str; + + for(i = 0; i < num_lin; i++) + { + /* Calculate line width */ + w = vf_textwidth(vector_font, p_str); + if (w > max_w) max_w = w; + + /* Advance the string */ + q = strchr(p_str, '\n'); + if (q) p_str = q + 1; /* skip line break */ + } + + return max_w; +} + +static void vf_gettextsize(cdVectorFont* vector_font, const char* str, int *width, int *height) +{ + int num_lin = cdStrLineCount(str); + if (num_lin == 1) + { + *width = vf_textwidth(vector_font, str); + *height = vector_font->top - vector_font->bottom; + } + else + { + *width = vf_gettextmaxwidth(vector_font, str, num_lin); + *height = num_lin*(vector_font->top - vector_font->bottom); + } +} + +static void vf_move_to_first(cdVectorFont* vector_font, int align, int *x, int *y, int num_lin, double line_height) +{ + /* position vertically at the first line */ + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST || /* it is relative to the full text */ + align == CD_BASE_LEFT || align == CD_BASE_CENTER || align == CD_BASE_RIGHT) /* it is relative to the first line already */ + { + /* Already at position */ + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) /* it is relative to the full text */ + { + vf_move_dir(vector_font, x, y, 0, (num_lin-1)*line_height); + } + else /* CD_CENTER || CD_EAST || CD_WEST */ /* it is relative to the full text */ + vf_move_dir(vector_font, x, y, 0, (num_lin-1)*line_height/2.0); +} + +static void vf_wmove_to_first(cdVectorFont* vector_font, int align, double *x, double *y, int num_lin, double line_height) +{ + /* position vertically at the first line */ + if (align == CD_NORTH || align == CD_NORTH_EAST || align == CD_NORTH_WEST || /* it is relative to the full text */ + align == CD_BASE_LEFT || align == CD_BASE_CENTER || align == CD_BASE_RIGHT) /* it is relative to the first line already */ + { + /* Already at position */ + } + else if (align == CD_SOUTH || align == CD_SOUTH_EAST || align == CD_SOUTH_WEST) /* it is relative to the full text */ + { + vf_wmove_dir(vector_font, x, y, 0, (num_lin-1)*line_height); + } + else /* CD_CENTER || CD_EAST || CD_WEST */ /* it is relative to the full text */ + vf_wmove_dir(vector_font, x, y, 0, (num_lin-1)*line_height/2.0); +} + +/******************************************************/ +/* vector text */ +/******************************************************/ + +cdVectorFont* cdCreateVectorFont(cdCanvas* canvas) +{ + cdVectorFont* vector_font; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return NULL; + + vector_font = calloc(1, sizeof(cdVectorFont)); + + vector_font->canvas = canvas; + + vf_setdefaultfont(vector_font); + + vector_font->size_x = 1.0; + vector_font->size_y = 1.0; + + vector_font->current_cos = 1.0; + vector_font->current_sin = 0.0; + + vector_font->text_transf = 0; + + return vector_font; +} + +void cdKillVectorFont(cdVectorFont* vector_font) +{ + assert(vector_font); + if (!vector_font) return; + + if (vector_font->chars && vector_font->chars != vf_default_chars) + vf_releasefontchars(vector_font); /* not the default font */ + + free(vector_font); +} + +char *cdCanvasVectorFont(cdCanvas* canvas, const char *file) +{ + cdVectorFont* vector_font; + + assert(canvas); + assert(file); + if (!_cdCheckCanvas(canvas)) return NULL; + + if (file[0] == 0) + return NULL; + + vector_font = canvas->vector_font; + if (!file) + { + vf_setdefaultfont(vector_font); + vector_font->file_name[0] = 0; + } + else + { + FILE *font = NULL; + int read_ok; + char *env; + + /* se arquivo foi o mesmo que o arq. corrente, entao retorna */ + if (strcmp (file, vector_font->file_name) == 0) + return vector_font->name; + + /* abre arq. no dir. corrente */ + font = fopen(file, "r"); + + /* se nao conseguiu, abre arq. no dir. do cd, */ + env = getenv("CDDIR"); + if (!font && env && strlen(file)<10240) + { + char filename[10240]; + sprintf(filename, "%str/%str", env, file); + font = fopen(filename, "r"); + } + + if (font) + read_ok = vf_readfontfile(font, vector_font); + else + read_ok = vf_readfontstring(file, vector_font); + + if (!read_ok) + { + if (font) fclose(font); + vf_setdefaultfont(vector_font); + vector_font->file_name[0] = 0; + return NULL; + } + + /* guarda nome do arquivo que esta' carregado */ + if (font) + { + strcpy(vector_font->file_name, file); + fclose(font); + } + else + strcpy(vector_font->file_name, vector_font->name); + } + + return vector_font->name; +} + +double* cdCanvasVectorTextTransform(cdCanvas* canvas, const double* matrix) +{ + cdVectorFont* vector_font; + int i; + static double old_matrix[6]; + + assert(canvas); + assert(matrix); + if (!_cdCheckCanvas(canvas)) return NULL; + + vector_font = canvas->vector_font; + if (vector_font->text_transf) + { + for (i=0; i<6; i++) + old_matrix[i] = vector_font->text_matrix[i]; + } + else + { + old_matrix[0] = 1; old_matrix[1] = 0; old_matrix[2] = 0; + old_matrix[3] = 0; old_matrix[4] = 1; old_matrix[5] = 0; + } + + if (matrix) + { + for (i=0; i<6; i++) + vector_font->text_matrix[i] = matrix[i]; + + vector_font->text_transf = 1; + } + else + vector_font->text_transf = 0; + + return old_matrix; +} + +/******************************************************/ +/* vector text em Raster */ +/******************************************************/ + +void cdCanvasVectorTextDirection(cdCanvas* canvas, int x1, int y1, int x2, int y2) +{ + cdVectorFont* vector_font; + int dx, dy; + double len; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + vector_font = canvas->vector_font; + + dx=x2-x1; + dy=y2-y1; + len = sqrt(dx*dx +dy*dy); + if (len == 0) len = 1; + vector_font->current_sin = dy/len; + vector_font->current_cos = dx/len; +} + +void cdCanvasVectorFontSize(cdCanvas* canvas, double size_x, double size_y) +{ + cdVectorFont* vector_font; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + vector_font = canvas->vector_font; + + vector_font->size_x = size_x; + vector_font->size_y = size_y; +} + +void cdCanvasGetVectorFontSize(cdCanvas* canvas, double *size_x, double *size_y) +{ + cdVectorFont* vector_font; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + vector_font = canvas->vector_font; + + if (size_x) *size_x = vector_font->size_x; + if (size_y) *size_y = vector_font->size_y; +} + +int cdCanvasVectorCharSize(cdCanvas* canvas, int size) +{ + cdVectorFont* vector_font; + int old_size; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return 0; + + vector_font = canvas->vector_font; + old_size = cdRound(vector_font->size_y*vector_font->top); + if (size == CD_QUERY) + return old_size; + + vector_font->size_y = size/(double)vector_font->top; + vector_font->size_x = vector_font->size_y; + + return old_size; +} + +void cdCanvasVectorTextSize(cdCanvas* canvas, int s_width, int s_height, const char* str) +{ + int width, height; + cdVectorFont* vector_font; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + vf_gettextsize(vector_font, str, &width, &height); + + vector_font->size_x = (double)s_width/(double)width; + vector_font->size_y = (double)s_height/(double)height; +} + +void cdCanvasGetVectorTextSize(cdCanvas* canvas, const char *str, int *x, int *y) +{ + int width, height; + cdVectorFont* vector_font; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + vf_gettextsize(vector_font, str, &width, &height); + + if (x) *x = cdRound(width*vector_font->size_x); + if (y) *y = cdRound(height*vector_font->size_y); +} + +void cdCanvasGetVectorTextBounds(cdCanvas* canvas, const char *str, int x, int y, int *rect) +{ + cdVectorFont* vector_font; + int sx, sy; + int width, height, num_lin; + double line_height; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + vf_gettextsize(vector_font, str, &width, &height); + num_lin = height/(vector_font->top - vector_font->bottom); + + sx = cdRound(width*vector_font->size_x); + sy = cdRound(height*vector_font->size_y); + + line_height = (vector_font->top - vector_font->bottom) * vector_font->size_y; + + if (num_lin > 1) + { + /* position vertically at the first line */ + int align = canvas->text_alignment; + vf_move_to_first(vector_font, align, &x, &y, num_lin, line_height); + } + + /* move to bottom/left corner */ + vf_move_to_base(vector_font, &x, &y, NULL, width); + vf_move_dir(vector_font, &x, &y, 0, vector_font->bottom*vector_font->size_y); /* from base/left to bottom/left of the first line */ + if (num_lin > 1) + vf_move_dir(vector_font, &x, &y, 0, -(height*vector_font->size_y - line_height)); /* from bottom/left to the bottom of the last line */ + + vf_calc_point(vector_font, x, y, &rect[0], &rect[1], 0, 0); + vf_calc_point(vector_font, x, y, &rect[2], &rect[3], sx, 0); + vf_calc_point(vector_font, x, y, &rect[4], &rect[5], sx, sy); + vf_calc_point(vector_font, x, y, &rect[6], &rect[7], 0, sy); +} + +void cdCanvasGetVectorTextBox(cdCanvas* canvas, int x, int y, const char *str, int *xmin, int *xmax, int *ymin, int *ymax) +{ + int rect[8]; + int _xmin, _xmax, _ymin, _ymax; + + cdCanvasGetVectorTextBounds(canvas, str, x, y, rect); + + _xmin = rect[0]; + _ymin = rect[1]; + _xmax = rect[0]; + _ymax = rect[1]; + + if(rect[2] < _xmin) _xmin = rect[2]; + if(rect[4] < _xmin) _xmin = rect[4]; + if(rect[6] < _xmin) _xmin = rect[6]; + + if(rect[3] < _ymin) _ymin = rect[3]; + if(rect[5] < _ymin) _ymin = rect[5]; + if(rect[7] < _ymin) _ymin = rect[7]; + + if(rect[2] > _xmax) _xmax = rect[2]; + if(rect[4] > _xmax) _xmax = rect[4]; + if(rect[6] > _xmax) _xmax = rect[6]; + + if(rect[3] > _ymax) _ymax = rect[3]; + if(rect[5] > _ymax) _ymax = rect[5]; + if(rect[7] > _ymax) _ymax = rect[7]; + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; +} + +void cdCanvasVectorText(cdCanvas* canvas, int x, int y, const char* str) +{ + cdVectorFont* vector_font; + int num_lin; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + num_lin = cdStrLineCount(str); + if (num_lin == 1) + vf_draw_text(vector_font, x, y, str); + else + { + const char *p_str, *q; + double line_height = (vector_font->top - vector_font->bottom) * vector_font->size_y; + int i; + + /* position vertically at the first line */ + vf_move_to_first(vector_font, canvas->text_alignment, &x, &y, num_lin, line_height); + + p_str = str; + + for(i = 0; i < num_lin; i++) + { + /* Draw the line */ + vf_draw_text(vector_font, x, y, p_str); + + /* Advance the string */ + q = strchr(p_str, '\n'); + if (q) p_str = q + 1; /* skip line break */ + + /* Advance a line */ + vf_move_dir(vector_font, &x, &y, 0, -line_height); + } + } +} + +void cdCanvasMultiLineVectorText(cdCanvas* canvas, int x, int y, const char* str) +{ + cdCanvasVectorText(canvas, x, y, str); +} + +/******************************************************/ +/* vector text em WC */ +/******************************************************/ + +void wdCanvasVectorTextDirection(cdCanvas* canvas, double x1, double y1, double x2, double y2) +{ + cdVectorFont* vector_font; + double dx, dy, len; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return; + + vector_font = canvas->vector_font; + + dx=x2-x1; + dy=y2-y1; + len = sqrt(dx*dx +dy*dy); + if (len == 0) len = 1; + vector_font->current_sin = dy/len; + vector_font->current_cos = dx/len; +} + +double wdCanvasVectorCharSize(cdCanvas* canvas, double size) +{ + cdVectorFont* vector_font; + double old_size; + + assert(canvas); + if (!_cdCheckCanvas(canvas)) return 0; + + vector_font = canvas->vector_font; + old_size = vector_font->size_y*vector_font->top; + if (size == CD_QUERY) + return old_size; + + vector_font->size_y = size/(double)vector_font->top; + vector_font->size_x = vector_font->size_y; + + return old_size; +} + +void wdCanvasVectorTextSize(cdCanvas* canvas, double s_width, double s_height, const char* str) +{ + int width, height; + cdVectorFont* vector_font; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + vf_gettextsize(vector_font, str, &width, &height); + + vector_font->size_x = s_width/(double)width; + vector_font->size_y = s_height/(double)height; +} + +void wdCanvasGetVectorTextSize(cdCanvas* canvas, const char *str, double *x, double *y) +{ + int width, height; + cdVectorFont* vector_font; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + vf_gettextsize(vector_font, str, &width, &height); + + if (x) *x = width*vector_font->size_x; + if (y) *y = height*vector_font->size_y; +} + +void wdCanvasGetVectorTextBounds(cdCanvas* canvas, const char *str, double x, double y, double *rect) +{ + cdVectorFont* vector_font; + double sx, sy, line_height; + int width, height, num_lin; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + vf_gettextsize(vector_font, str, &width, &height); + num_lin = height/(vector_font->top - vector_font->bottom); + + sx = width*vector_font->size_x; + sy = height*vector_font->size_y; + + line_height = (vector_font->top - vector_font->bottom) * vector_font->size_y; + + if (num_lin > 1) + { + /* position vertically at the first line */ + int align = canvas->text_alignment; + vf_wmove_to_first(vector_font, align, &x, &y, num_lin, line_height); + } + + /* move to bottom/left corner */ + vf_wmove_to_base(vector_font, &x, &y, NULL, width); + vf_wmove_dir(vector_font, &x, &y, 0, vector_font->bottom*vector_font->size_y); /* from base/left to bottom/left of the first line */ + if (num_lin > 1) + vf_wmove_dir(vector_font, &x, &y, 0, -(height*vector_font->size_y - line_height)); /* from bottom/left to the bottom of the last line */ + + vf_wcalc_point(vector_font, x, y, &rect[0], &rect[1], 0, 0); + vf_wcalc_point(vector_font, x, y, &rect[2], &rect[3], sx, 0); + vf_wcalc_point(vector_font, x, y, &rect[4], &rect[5], sx, sy); + vf_wcalc_point(vector_font, x, y, &rect[6], &rect[7], 0, sy); +} + +void wdCanvasGetVectorTextBox(cdCanvas* canvas, double x, double y, const char *str, double *xmin, double *xmax, double *ymin, double *ymax) +{ + double rect[8]; + double _xmin, _xmax, _ymin, _ymax; + + wdCanvasGetVectorTextBounds(canvas, str, x, y, rect); + + _xmin = rect[0]; + _ymin = rect[1]; + _xmax = rect[0]; + _ymax = rect[1]; + + if(rect[2] < _xmin) _xmin = rect[2]; + if(rect[4] < _xmin) _xmin = rect[4]; + if(rect[6] < _xmin) _xmin = rect[6]; + + if(rect[3] < _ymin) _ymin = rect[3]; + if(rect[5] < _ymin) _ymin = rect[5]; + if(rect[7] < _ymin) _ymin = rect[7]; + + if(rect[2] > _xmax) _xmax = rect[2]; + if(rect[4] > _xmax) _xmax = rect[4]; + if(rect[6] > _xmax) _xmax = rect[6]; + + if(rect[3] > _ymax) _ymax = rect[3]; + if(rect[5] > _ymax) _ymax = rect[5]; + if(rect[7] > _ymax) _ymax = rect[7]; + + if (xmin) *xmin = _xmin; + if (xmax) *xmax = _xmax; + if (ymin) *ymin = _ymin; + if (ymax) *ymax = _ymax; +} + +void wdCanvasVectorText(cdCanvas* canvas, double x, double y, const char* str) +{ + cdVectorFont* vector_font; + int num_lin; + + assert(canvas); + assert(str); + if (!_cdCheckCanvas(canvas)) return; + + if (str[0] == 0) + return; + + vector_font = canvas->vector_font; + + num_lin = cdStrLineCount(str); + if (num_lin == 1) + vf_wdraw_text(vector_font, x, y, str); + else + { + const char *p_str, *q; + double line_height = (vector_font->top - vector_font->bottom) * vector_font->size_y; + int i; + + /* position vertically at the first line */ + vf_wmove_to_first(vector_font, canvas->text_alignment, &x, &y, num_lin, line_height); + + p_str = str; + + for(i = 0; i < num_lin; i++) + { + /* Draw the line */ + vf_wdraw_text(vector_font, x, y, p_str); + + /* Advance the string */ + q = strchr(p_str, '\n'); + if (q) p_str = q + 1; /* skip line break */ + + /* Advance a line */ + vf_wmove_dir(vector_font, &x, &y, 0, -line_height); + } + } +} + +void wdCanvasMultiLineVectorText(cdCanvas* canvas, double x, double y, const char* str) +{ + wdCanvasVectorText(canvas, x, y, str); +} + diff --git a/cd/src/cdcontextplus.dep b/cd/src/cdcontextplus.dep new file mode 100644 index 0000000..2cdfc5f --- /dev/null +++ b/cd/src/cdcontextplus.dep @@ -0,0 +1,4 @@ +$(OBJDIR)/cdxrender.o: xrender/cdxrender.c x11/cdx11.h ../include/cd.h \ + ../include/cd_private.h ../include/cddbuf.h ../include/cdimage.h \ + ../include/cdnative.h sim/truetype.h sim/sim.h +$(OBJDIR)/cdxrplus.o: xrender/cdxrplus.c ../include/cd.h ../include/cd_private.h diff --git a/cd/src/cdcontextplus.mak b/cd/src/cdcontextplus.mak new file mode 100755 index 0000000..f8314cc --- /dev/null +++ b/cd/src/cdcontextplus.mak @@ -0,0 +1,25 @@ +PROJNAME = cd +LIBNAME = cdcontextplus +OPT = YES + +DEFINES = CD_NO_OLD_INTERFACE + + +ifneq ($(findstring Win, $(TEC_SYSNAME)), ) + SRCDIR = gdiplus + SRC = cdwemfp.cpp cdwimgp.cpp cdwinp.cpp cdwnativep.cpp cdwprnp.cpp cdwdbufp.cpp cdwclpp.cpp cdwgdiplus.c + + INCLUDES = . gdiplus drv + LIBS = gdiplus +else + SRC = xrender/cdxrender.c xrender/cdxrplus.c + + LIBS = Xrender Xft + USE_X11 = Yes + + INCLUDES = . sim drv /usr/include/freetype2 x11 +endif + + +USE_CD = YES +CD = .. diff --git a/cd/src/cdlua3.mak b/cd/src/cdlua3.mak new file mode 100755 index 0000000..cb809de --- /dev/null +++ b/cd/src/cdlua3.mak @@ -0,0 +1,12 @@ +PROJNAME = cd +LIBNAME = cdlua3 + +OPT = YES + +DEF_FILE = cdlua.def +SRCDIR = lua3 +SRC = cdlua.c toluacd.c toluawd.c cdvoid.c cdluactx.c + +USE_LUA = YES +USE_CD = YES +CD = .. diff --git a/cd/src/cdlua5.mak b/cd/src/cdlua5.mak new file mode 100755 index 0000000..9f862f8 --- /dev/null +++ b/cd/src/cdlua5.mak @@ -0,0 +1,14 @@ +PROJNAME = cd +LIBNAME = cdlua51 + +OPT = YES + +DEFINES = CD_NO_OLD_INTERFACE +SRCDIR = lua5 +SRC = cdlua5.c cdvoid5.c cdlua5ctx.c cdlua5_active.c cdlua5_canvas.c +DEF_FILE = cdlua5.def + +USE_LUA51 = Yes +NO_LUALINK = Yes +USE_CD = YES +CD = .. diff --git a/cd/src/cdlua51.dep b/cd/src/cdlua51.dep new file mode 100644 index 0000000..40c4e86 --- /dev/null +++ b/cd/src/cdlua51.dep @@ -0,0 +1,28 @@ +$(OBJDIR)/cdlua5.o: lua5/cdlua5.c ../include/cd.h ../include/cdgdiplus.h \ + ../include/cdnative.h ../include/cdps.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/cdlua.h \ + ../include/cdlua5_private.h +$(OBJDIR)/cdvoid5.o: lua5/cdvoid5.c ../include/cd.h ../include/cd_private.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/cdlua5_private.h +$(OBJDIR)/cdlua5ctx.o: lua5/cdlua5ctx.c ../include/cd.h ../include/wd.h \ + ../include/cdimage.h ../include/cdirgb.h ../include/cddxf.h \ + ../include/cddgn.h ../include/cdcgm.h ../include/cdwmf.h \ + ../include/cdemf.h ../include/cdnative.h ../include/cdprint.h \ + ../include/cdclipbd.h ../include/cdmf.h ../include/cdps.h \ + ../include/cddbuf.h ../include/cdgdiplus.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/cdlua.h \ + ../include/cdlua5_private.h +$(OBJDIR)/cdlua5_active.o: lua5/cdlua5_active.c ../include/cd.h ../include/cd_old.h \ + ../include/wd.h ../include/wd_old.h ../include/cdirgb.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h \ + ../include/cdlua.h ../include/cdlua5_private.h lua5/cdvoid5.h +$(OBJDIR)/cdlua5_canvas.o: lua5/cdlua5_canvas.c ../include/cd.h ../include/wd.h \ + ../include/cdirgb.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../include/cdlua.h \ + ../include/cdlua5_private.h diff --git a/cd/src/cdluacontextplus5.mak b/cd/src/cdluacontextplus5.mak new file mode 100755 index 0000000..c00fe0d --- /dev/null +++ b/cd/src/cdluacontextplus5.mak @@ -0,0 +1,17 @@ +PROJNAME = cd +LIBNAME = cdluacontextplus51 + +OPT = YES + +DEFINES = CD_NO_OLD_INTERFACE +SRCDIR = lua5 +SRC = cdluacontextplus5.c +DEF_FILE = cdluacontextplus5.def + +LIBS = cdcontextplus + +USE_LUA51 = Yes +NO_LUALINK = Yes +USE_CD = YES +USE_CDLUA = YES +CD = .. diff --git a/cd/src/cdluacontextplus51.dep b/cd/src/cdluacontextplus51.dep new file mode 100644 index 0000000..e9ed75f --- /dev/null +++ b/cd/src/cdluacontextplus51.dep @@ -0,0 +1,3 @@ +$(OBJDIR)/cdluacontextplus5.o: lua5/cdluacontextplus5.c ../include/cd.h \ + ../../lua5.1/include/lua.h ../../lua5.1/include/luaconf.h \ + ../../lua5.1/include/lauxlib.h ../../lua5.1/include/lua.h diff --git a/cd/src/cdluaim5.mak b/cd/src/cdluaim5.mak new file mode 100755 index 0000000..a9f50e0 --- /dev/null +++ b/cd/src/cdluaim5.mak @@ -0,0 +1,16 @@ +PROJNAME = cd +LIBNAME = cdluaim51 + +OPT = YES + +DEF_FILE = cdluaim5.def +SRCDIR = lua5 +SRC = cdluaim5.c + +USE_CD = YES +USE_CDLUA = YES +USE_IM = YES +USE_IMLUA = YES +USE_LUA51 = YES +NO_LUALINK = Yes +CD = .. diff --git a/cd/src/cdluaim51.dep b/cd/src/cdluaim51.dep new file mode 100644 index 0000000..881afa3 --- /dev/null +++ b/cd/src/cdluaim51.dep @@ -0,0 +1,6 @@ +$(OBJDIR)/cdluaim5.o: lua5/cdluaim5.c ../../im/include/im.h \ + ../../im/include/old_im.h ../../im/include/im_image.h ../include/cd.h \ + ../include/cdirgb.h ../include/wd.h ../../lua5.1/include/lua.h \ + ../../lua5.1/include/luaconf.h ../../lua5.1/include/lauxlib.h \ + ../../lua5.1/include/lua.h ../../im/include/imlua.h ../include/cdlua.h \ + ../include/cdlua5_private.h diff --git a/cd/src/config.mak b/cd/src/config.mak new file mode 100755 index 0000000..93c45de --- /dev/null +++ b/cd/src/config.mak @@ -0,0 +1,47 @@ +PROJNAME = cd +LIBNAME = cd +OPT = YES + +DEFINES = CD_NO_OLD_INTERFACE + +SRCINTCGM = circle.c ellipse.c intcgm1.c \ + intcgm2.c intcgm4.c intcgm6.c list.c \ + sism.c tparse.c bparse.c +SRCINTCGM := $(addprefix intcgm/, $(SRCINTCGM)) + +SRCWIN32 = cdwclp.c cdwemf.c cdwimg.c cdwin.c cdwnative.c cdwprn.c cdwwmf.c wmf_emf.c cdwdbuf.c cdwdib.c +SRCWIN32 := $(addprefix win32/, $(SRCWIN32)) + +SRCSIM := cdfontex.c sim.c cd_truetype.c sim_other.c sim_primitives.c sim_linepolyfill.c +SRCSIM := $(addprefix sim/, $(SRCSIM)) + +SRCX11 = cdx11.c cdxclp.c cdximg.c cdxnative.c cdxdbuf.c xvertex.c +SRCX11 := $(addprefix x11/, $(SRCX11)) + +SRCDRV = cddgn.c cdcgm.c cgm.c cddxf.c cdirgb.c cdmf.c cdps.c cdpicture.c cddebug.c +SRCDRV := $(addprefix drv/, $(SRCDRV)) + +SRCNULL = cd0prn.c cd0emf.c cd0wmf.c +SRCNULL := $(addprefix drv/, $(SRCNULL)) + +SRCCOMM = cd.c wd.c wdhdcpy.c rgb2map.c cd_vectortext.c cd_active.c \ + cd_attributes.c cd_bitmap.c cd_image.c cd_primitives.c cd_text.c cd_util.c + +SRC = $(SRCCOMM) $(SRCINTCGM) $(SRCDRV) $(SRCSIM) + +ifneq ($(findstring Win, $(TEC_SYSNAME)), ) + SRC += $(SRCWIN32) + LIBS = freetype6 +else + SRC += $(SRCNULL) $(SRCX11) + USE_X11 = Yes + LIBS = freetype +endif + +ifneq ($(findstring dll, $(TEC_UNAME)), ) + SRC += cd.rc +endif + +LDIR = ../lib/$(TEC_UNAME) + +INCLUDES = . drv x11 win32 intcgm /usr/include/freetype2 sim ../include diff --git a/cd/src/drv/cd0emf.c b/cd/src/drv/cd0emf.c new file mode 100755 index 0000000..13beb4c --- /dev/null +++ b/cd/src/drv/cd0emf.c @@ -0,0 +1,17 @@ +/** \file + * \brief Dummy EMF + * + * See Copyright Notice in cd.h + */ + +#include +#include "cd.h" +#include "cdemf.h" + + +cdContext* cdContextEMF(void) +{ + return NULL; +} + + diff --git a/cd/src/drv/cd0prn.c b/cd/src/drv/cd0prn.c new file mode 100755 index 0000000..429a392 --- /dev/null +++ b/cd/src/drv/cd0prn.c @@ -0,0 +1,17 @@ +/** \file + * \brief Dummy Printer + * + * See Copyright Notice in cd.h + */ + +#include +#include "cd.h" +#include "cdprint.h" + + + +cdContext* cdContextPrinter(void) +{ + return NULL; +} + diff --git a/cd/src/drv/cd0wmf.c b/cd/src/drv/cd0wmf.c new file mode 100755 index 0000000..a96761a --- /dev/null +++ b/cd/src/drv/cd0wmf.c @@ -0,0 +1,16 @@ +/** \file + * \brief Dummy WMF + * + * See Copyright Notice in cd.h + */ + +#include +#include "cd.h" +#include "cdwmf.h" + + +cdContext* cdContextWMF(void) +{ + return NULL; +} + diff --git a/cd/src/drv/cdcgm.c b/cd/src/drv/cdcgm.c new file mode 100755 index 0000000..3049818 --- /dev/null +++ b/cd/src/drv/cdcgm.c @@ -0,0 +1,1135 @@ +/** \file + * \brief CGM driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cdcgm.h" +#include "cgm.h" + +#define get_red(_) (((double)cdRed(_))/255.) +#define get_green(_) (((double)cdGreen(_))/255.) +#define get_blue(_) (((double)cdBlue(_))/255.) + + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + CGM *cgm; + + char filename[256]; /* Arquivo CGM */ + + int codificacao; /* Codificacao */ + int vdc_int_prec; + int first; /* Primeira primitiva a ser desenhada */ + long point; + int hassize; + int patindex; + + struct + { + cdfRect bbox; + int first; + } clip; + + cdfRect b_box; +}; + +static double cve_black[] = { 0.0, 0.0, 0.0 }; +static double cve_white[] = { 1.0, 1.0, 1.0 }; + +/* From INTCGM */ +int cdplayCGM(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data); +int cdRegisterCallbackCGM(int cb, cdCallback func); + + +/* +%F Atualiza os valores do bounding box +*/ +static void setbbox (cdCtxCanvas *ctxcanvas, double x, double y ) +{ + if ( ctxcanvas->first ) + { + ctxcanvas->b_box.xmin = x; + ctxcanvas->b_box.xmax = x; + ctxcanvas->b_box.ymin = y; + ctxcanvas->b_box.ymax = y; + ctxcanvas->first = 0; + } + + if ( xb_box.xmin ) ctxcanvas->b_box.xmin = x; + if ( x>ctxcanvas->b_box.xmax ) ctxcanvas->b_box.xmax = x; + if ( yb_box.ymin ) ctxcanvas->b_box.ymin = y; + if ( y>ctxcanvas->b_box.ymax ) ctxcanvas->b_box.ymax = y; +} + + +/* +%F metafile descriptor elements +*/ +static void metafile_descriptor (cdCtxCanvas *ctxcanvas) +{ + const char *font_list[] = { "SYSTEM", "COURIER", "TIMES_ROMAN", "HELVETICA", + "SYSTEM_BOLD", "COURIER_BOLD", "TIMES_ROMAN_BOLD", "HELVETICA_BOLD", + "SYSTEM_ITALIC", "COURIER_ITALIC", "TIMES_ROMAN_ITALIC", + "HELVETICA_ITALIC", "SYSTEM_BOLDITALIC", "COURIER_BOLDITALIC", + "TIMES_ROMAN_BOLDITALIC", "HELVETICA_BOLDITALIC", NULL }; + + cgm_metafile_version ( ctxcanvas->cgm, 1); + cgm_metafile_description ( ctxcanvas->cgm, "CD generated" ); + cgm_vdc_type ( ctxcanvas->cgm, 0 /* integer */ ); + cgm_integer_precision ( ctxcanvas->cgm, 16 ); + cgm_real_precision ( ctxcanvas->cgm, 3 /* fixed 32 */ ); + cgm_index_precision ( ctxcanvas->cgm, 16 ); + cgm_colour_precision ( ctxcanvas->cgm, 8 ); + cgm_colour_index_precision ( ctxcanvas->cgm, 8 ); + cgm_maximum_colour_index ( ctxcanvas->cgm, 255ul ); + cgm_colour_value_extent ( ctxcanvas->cgm, cve_black, cve_white ); + + { + static int classes[] = { -1 /* drawing set */ }; + static int ids [] = { 1 /* plus control set */ }; + cgm_metafile_element_list ( ctxcanvas->cgm, 1, classes, ids ); + } + + cgm_begin_metafile_defaults ( ctxcanvas->cgm ); + + cgm_vdc_integer_precision ( ctxcanvas->cgm, ctxcanvas->vdc_int_prec ); + cgm_interior_style ( ctxcanvas->cgm, 1 ); /* SOLID */ + cgm_edge_visibility ( ctxcanvas->cgm, 0 ); /* OFF */ + + cgm_end_metafile_defaults ( ctxcanvas->cgm ); + + cgm_font_list ( ctxcanvas->cgm, font_list ); +} + +/* +%F Pictire descriptor elements +*/ +static void picture_descriptor (cdCtxCanvas *ctxcanvas) +{ + cgm_scaling_mode ( ctxcanvas->cgm, 1 /* metric */, 1.0f ); + cgm_colour_selection_mode ( ctxcanvas->cgm, 1 /* direct */ ); + cgm_line_width_specify_mode ( ctxcanvas->cgm, 0 /* absolute=0, scaled=1 */ ); + cgm_marker_size_specify_mode ( ctxcanvas->cgm, 0 /* absolute=0, scaled=1 */ ); + + ctxcanvas->point = ftell ( ctxcanvas->cgm->file ); + if ( ctxcanvas->codificacao == CD_CLEAR_TEXT ) + { + fprintf ( ctxcanvas->cgm->file, "%80s\n", "" ); + fprintf ( ctxcanvas->cgm->file, "%80s\n", "" ); + } + else + { + cgm_vdc_extent( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h); + } +} + +/* +%F Control descriptor elements +*/ +static void control_elements (cdCtxCanvas *ctxcanvas) +{ + double c[3] = {1.0,1.0,1.0}; + + cgm_vdc_integer_precision ( ctxcanvas->cgm, ctxcanvas->vdc_int_prec ); + cgm_vdc_real_precision ( ctxcanvas->cgm, 2 /* fixed 32 */ ); + cgm_auxiliary_colour ( ctxcanvas->cgm, c ); +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + long pt; + + pt = ftell ( ctxcanvas->cgm->file ); + fseek ( ctxcanvas->cgm->file, ctxcanvas->point, SEEK_SET ); + + if (ctxcanvas->hassize) + cgm_vdc_extent ( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h); + else + { + if ( ctxcanvas->clip.first ) + cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->b_box.xmin, ctxcanvas->b_box.ymin, ctxcanvas->b_box.xmax, ctxcanvas->b_box.ymax ); + else + cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->clip.bbox.xmin, ctxcanvas->clip.bbox.ymin, ctxcanvas->clip.bbox.xmax, ctxcanvas->clip.bbox.ymax ); + } + + fseek ( ctxcanvas->cgm->file, pt, SEEK_SET ); + + cgm_end_picture ( ctxcanvas->cgm ); + cgm_end_metafile ( ctxcanvas->cgm ); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cddeactivate(cdCtxCanvas *ctxcanvas) +{ + fflush(ctxcanvas->cgm->file); +} + +/* +%F Comeca uma nova pagina. +*/ +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + long pt; + + pt = ftell ( ctxcanvas->cgm->file ); + fseek ( ctxcanvas->cgm->file, ctxcanvas->point, SEEK_SET ); + + if (ctxcanvas->hassize) + cgm_vdc_extent ( ctxcanvas->cgm, 0, 0, (double)ctxcanvas->canvas->w, (double)ctxcanvas->canvas->h); + else + { + if ( ctxcanvas->clip.first ) + cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->b_box.xmin, ctxcanvas->b_box.ymin, + ctxcanvas->b_box.xmax, ctxcanvas->b_box.ymax ); + else + cgm_vdc_extent ( ctxcanvas->cgm, ctxcanvas->clip.bbox.xmin, ctxcanvas->clip.bbox.ymin, + ctxcanvas->clip.bbox.xmax, ctxcanvas->clip.bbox.ymax ); + } + + fseek ( ctxcanvas->cgm->file, pt, SEEK_SET ); + + cgm_end_picture ( ctxcanvas->cgm ); + + cgm_begin_picture ( ctxcanvas->cgm, "Picture x" ); + picture_descriptor ( ctxcanvas); + cgm_begin_picture_body ( ctxcanvas->cgm ); +} + + +/******************************************************/ +/* coordinate transformation */ +/******************************************************/ + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + if (mode == CD_CLIPPOLYGON) + return ctxcanvas->canvas->clip_mode; + + cgm_clip_indicator ( ctxcanvas->cgm, mode ); + + if (mode == CD_CLIPAREA) + cgm_clip_rectangle ( ctxcanvas->cgm, (double) ctxcanvas->canvas->clip_rect.xmin, (double) ctxcanvas->canvas->clip_rect.ymin, + (double) ctxcanvas->canvas->clip_rect.xmax, (double) ctxcanvas->canvas->clip_rect.ymax ); + + return mode; +} + +static void clip_bbox (cdCtxCanvas *ctxcanvas, double xmin, double ymin, double xmax, double ymax) +{ + if ( ctxcanvas->clip.first ) + { + ctxcanvas->clip.bbox.xmin = xmin; + ctxcanvas->clip.bbox.xmax = xmax; + ctxcanvas->clip.bbox.ymin = ymin; + ctxcanvas->clip.bbox.ymax = ymax; + ctxcanvas->clip.first = 0; + } + + if ( xmin < ctxcanvas->clip.bbox.xmin ) ctxcanvas->clip.bbox.xmin = xmin; + if ( ymin < ctxcanvas->clip.bbox.ymin ) ctxcanvas->clip.bbox.ymin = ymin; + if ( xmax > ctxcanvas->clip.bbox.xmax ) ctxcanvas->clip.bbox.xmax = xmax; + if ( ymax > ctxcanvas->clip.bbox.ymax ) ctxcanvas->clip.bbox.ymax = ymax; +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + cgm_clip_rectangle ( ctxcanvas->cgm, (double) xmin, (double) ymin, + (double) xmax, (double) ymax ); + + clip_bbox (ctxcanvas, (double)xmin, (double)ymin, (double)xmax, (double)ymax ); +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + cgm_clip_rectangle ( ctxcanvas->cgm, xmin, ymin, xmax, ymax ); + + clip_bbox (ctxcanvas, xmin, ymin, xmax, ymax ); +} + +/******************************************************/ +/* primitives */ +/******************************************************/ + +static int cdinteriorstyle (cdCtxCanvas *ctxcanvas, int style); + +static void cdline(cdCtxCanvas *ctxcanvas, int px1, int py1, int px2, int py2) +{ + double points[4]; + + points[0] = (double)px1; + points[1] = (double)py1; + points[2] = (double)px2; + points[3] = (double)py2; + + cgm_polyline( ctxcanvas->cgm, 2, points); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double px1, double py1, double px2, double py2) +{ + double points[4]; + + points[0] = px1; + points[1] = py1; + points[2] = px2; + points[3] = py2; + + cgm_polyline( ctxcanvas->cgm, 2, points); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + double points[4]; + + points[0] = (double)xmin; + points[1] = (double)ymin; + points[2] = (double)xmax; + points[3] = (double)ymax; + + cgm_interior_style ( ctxcanvas->cgm, HOLLOW); + cgm_rectangle( ctxcanvas->cgm, points); + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); + setbbox (ctxcanvas, points[0], points[3] ); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + double points[4]; + + points[0] = xmin; + points[1] = ymin; + points[2] = xmax; + points[3] = ymax; + + cgm_interior_style ( ctxcanvas->cgm, HOLLOW); + cgm_rectangle( ctxcanvas->cgm, points); + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); + setbbox (ctxcanvas, points[0], points[3] ); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + double points[4]; + + points[0] = (double)xmin; + points[1] = (double)ymin; + points[2] = (double)xmax; + points[3] = (double)ymax; + + cgm_rectangle( ctxcanvas->cgm, points); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); + setbbox (ctxcanvas, points[0], points[3] ); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + double points[4]; + + points[0] = xmin; + points[1] = ymin; + points[2] = xmax; + points[3] = ymax; + + cgm_rectangle( ctxcanvas->cgm, points); + + setbbox (ctxcanvas, points[0], points[1] ); + setbbox (ctxcanvas, points[2], points[1] ); + setbbox (ctxcanvas, points[2], points[3] ); + setbbox (ctxcanvas, points[0], points[3] ); +} + +static void arc (cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2, + double *center, double *first_end_point, + double *second_end_point, double *dx_start, double *dy_start, + double *dx_end, double *dy_end ) +{ + double width, height; + + center[0] = xc; + center[1] = yc; + + width = w/2; + height = h/2; + + first_end_point[0] = center[0] + width; + first_end_point[1] = center[1]; + + second_end_point[0] = center[0]; + second_end_point[1] = center[1] + height; + + *dx_start = width*cos(a1*CD_DEG2RAD); + *dy_start = height*sin(a1*CD_DEG2RAD); + + *dx_end = width*cos(a2*CD_DEG2RAD); + *dy_end = height*sin(a2*CD_DEG2RAD); + + setbbox (ctxcanvas, center[0]-width, center[1]-height ); + setbbox (ctxcanvas, center[0]+width, center[1]-height ); + setbbox (ctxcanvas, center[0]+width, center[1]+height ); + setbbox (ctxcanvas, center[0]-width, center[1]+height ); +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + double center[2], first_end_point[2], second_end_point[2]; + double dx_start, dy_start, dx_end, dy_end; + + arc (ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, center, first_end_point, second_end_point, + &dx_start, &dy_start, &dx_end, &dy_end ); + + cgm_elliptical_arc ( ctxcanvas->cgm, center, first_end_point, second_end_point, dx_start, dy_start, dx_end, dy_end ); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + double center[2], first_end_point[2], second_end_point[2]; + double dx_start, dy_start, dx_end, dy_end; + + arc (ctxcanvas, xc, yc, w, h, a1, a2, center, first_end_point, second_end_point, + &dx_start, &dy_start, &dx_end, &dy_end ); + + cgm_elliptical_arc ( ctxcanvas->cgm, center, first_end_point, second_end_point, dx_start, dy_start, dx_end, dy_end ); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + double center[2], first_end_point[2], second_end_point[2]; + double dx_start, dy_start, dx_end, dy_end; + + arc (ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, center, first_end_point, second_end_point, + &dx_start, &dy_start, &dx_end, &dy_end ); + + + cgm_elliptical_arc_close ( ctxcanvas->cgm, center, first_end_point, second_end_point, + dx_start, dy_start, dx_end, dy_end, 0 ); + + setbbox (ctxcanvas, (double)xc-w/2., (double)yc-h/2. ); + setbbox (ctxcanvas, (double)xc+w/2., (double)yc-h/2. ); + setbbox (ctxcanvas, (double)xc+w/2., (double)yc+h/2. ); + setbbox (ctxcanvas, (double)xc-w/2., (double)yc+h/2. ); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + double center[2], first_end_point[2], second_end_point[2]; + double dx_start, dy_start, dx_end, dy_end; + + arc (ctxcanvas, xc, yc, w, h, a1, a2, center, first_end_point, second_end_point, + &dx_start, &dy_start, &dx_end, &dy_end ); + + + cgm_elliptical_arc_close ( ctxcanvas->cgm, center, first_end_point, second_end_point, + dx_start, dy_start, dx_end, dy_end, 0 ); + + setbbox (ctxcanvas, xc-w/2., yc-h/2. ); + setbbox (ctxcanvas, xc+w/2., yc-h/2. ); + setbbox (ctxcanvas, xc+w/2., yc+h/2. ); + setbbox (ctxcanvas, xc-w/2., yc+h/2. ); +} + +static void settextbbox (cdCtxCanvas *ctxcanvas, double x, double y, int width, int height ) +{ + switch ( ctxcanvas->canvas->text_alignment ) + { + case CD_NORTH: + setbbox (ctxcanvas, x-(width/2.), y-height ); + setbbox (ctxcanvas, x+(width/2.), y ); + break; + case CD_SOUTH: + setbbox (ctxcanvas, x-(width/2.), y+height ); + setbbox (ctxcanvas, x+(width/2.), y ); + break; + case CD_EAST: + setbbox (ctxcanvas, x-width, y-(height/2.) ); + setbbox (ctxcanvas, x, y+(height/2.) ); + break; + case CD_WEST: + setbbox (ctxcanvas, x, y-(height/2.) ); + setbbox (ctxcanvas, x+width, y+(height/2.) ); + break; + case CD_NORTH_EAST: + setbbox (ctxcanvas, x-width, y-height ); + setbbox (ctxcanvas, x, y ); + break; + case CD_NORTH_WEST: + setbbox (ctxcanvas, x, y-height ); + setbbox (ctxcanvas, x+width, y ); + break; + case CD_SOUTH_EAST: + setbbox (ctxcanvas, x-width, y ); + setbbox (ctxcanvas, x, y+height ); + break; + case CD_SOUTH_WEST: + setbbox (ctxcanvas, x, y ); + setbbox (ctxcanvas, x+width, y+height ); + break; + case CD_CENTER: + setbbox (ctxcanvas, x-(width/2.), y-(height/2.) ); + setbbox (ctxcanvas, x+(width/2.), y+(height/2.) ); + break; + case CD_BASE_LEFT: + setbbox (ctxcanvas, x, y ); + setbbox (ctxcanvas, x+width, y+height ); + break; + case CD_BASE_CENTER: + setbbox (ctxcanvas, x-(width/2.), y ); + setbbox (ctxcanvas, x+(width/2.), y+height ); + break; + case CD_BASE_RIGHT: + setbbox (ctxcanvas, x-width, y ); + setbbox (ctxcanvas, x, y+height ); + break; + } +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + int width, height; + + cgm_text( ctxcanvas->cgm, 1 /* final */ , (double)x, (double)y, s, len ); + + cdgettextsizeEX(ctxcanvas, s, len, &width, &height); + + settextbbox (ctxcanvas, (double) x, (double) y, width, height ); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) +{ + int width, height; + + cgm_text( ctxcanvas->cgm, 1 /* final */ , x, y, s, len); + + cdgettextsizeEX(ctxcanvas, s, len, &width, &height); + + settextbbox (ctxcanvas, x, y, width, height ); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + double *fpoly; + + fpoly = (double *)malloc(2 * (n+1) * sizeof(double)); + + for (i = 0; i < n; i++) + { + fpoly[2*i] = (double) poly[i].x; + fpoly[2*i+1] = (double) poly[i].y; + + setbbox (ctxcanvas, fpoly[2*i] , fpoly[2*i+1] ); + } + + switch ( mode ) + { + case CD_OPEN_LINES: + cgm_polyline( ctxcanvas->cgm, n, fpoly ); + break; + case CD_CLOSED_LINES: + fpoly[2*n] = fpoly[0]; + fpoly[2*n+1] = fpoly[1]; + n++; + cgm_polyline( ctxcanvas->cgm, n, fpoly ); + break; + case CD_FILL: + cgm_polygon( ctxcanvas->cgm, n, fpoly); + break; + } + + free(fpoly); +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + double *fpoly = (double*)poly; + + for (i = 0; i < n; i++) + { + setbbox (ctxcanvas, fpoly[2*i] , fpoly[2*i+1] ); + } + + switch ( mode ) + { + case CD_OPEN_LINES: + cgm_polyline( ctxcanvas->cgm, n, fpoly ); + break; + case CD_CLOSED_LINES: + fpoly[2*n] = fpoly[0]; + fpoly[2*n+1] = fpoly[1]; + n++; + cgm_polyline( ctxcanvas->cgm, n, fpoly ); + break; + case CD_FILL: + cgm_polygon( ctxcanvas->cgm, n, fpoly); + break; + } +} + + +/******************************************************/ +/* attributes */ +/******************************************************/ + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + cgm_line_type( ctxcanvas->cgm, (long)(style + 1)); + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + cgm_line_width( ctxcanvas->cgm, (double)width ); + return width; +} + +static int cdinteriorstyle (cdCtxCanvas *ctxcanvas, int style ) +{ + switch ( style ) + { + case CD_SOLID: + style = 1; + break; + case CD_STIPPLE: + case CD_PATTERN: + style = 2; + break; + case CD_HATCH: + style = 3; + break; + } + + cgm_interior_style ( ctxcanvas->cgm, style ); + + return style; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + int cgm_style = style; + + if ( cgm_style==2 ) + cgm_style = 3; + else if ( cgm_style==3 ) + cgm_style = 2; + + cgm_hatch_index ( ctxcanvas->cgm, (long)cgm_style+1 ); + + cgm_interior_style ( ctxcanvas->cgm, 3 ); + + return style; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ + double *pattab; + int i, j=0; + + pattab = (double *) malloc ( n*m*3*sizeof(double)); + + for ( i=0; icanvas->foreground) : get_red(ctxcanvas->canvas->background); + pattab[j+1] = ( stipple[i] ) ? get_green(ctxcanvas->canvas->foreground) : get_green(ctxcanvas->canvas->background); + pattab[j+2] = ( stipple[i] ) ? get_blue(ctxcanvas->canvas->foreground) : get_blue(ctxcanvas->canvas->background); + j+=3; + } + + cgm_pattern_table ( ctxcanvas->cgm, (long) ctxcanvas->patindex, (long) n, (long) m, (int) 8, pattab ); + cgm_pattern_index ( ctxcanvas->cgm, (long) ctxcanvas->patindex++ ); + free(pattab); + + cgm_interior_style ( ctxcanvas->cgm, 2 ); /* PATTERN */ +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ + double *pattab; + int i, j=0; + + pattab = (double *) malloc ( n*m*3*sizeof(double) ); + + for ( i=0; icgm, (long) ctxcanvas->patindex, (long) n, (long) m, (int) 8, pattab ); + cgm_pattern_index ( ctxcanvas->cgm, (long) ctxcanvas->patindex++ ); + free(pattab); + + cgm_interior_style ( ctxcanvas->cgm, 2 ); /* PATTERN */ +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + long index = 0; + + if (cdStrEqualNoCase(type_face, "System")) + switch (style&3) + { + case CD_PLAIN: + index = 1; + break; + case CD_BOLD: + index = 5; + break; + case CD_ITALIC: + index = 9; + break; + case CD_BOLD_ITALIC: + index = 13; + break; + } + else if (cdStrEqualNoCase(type_face, "Courier")) + switch (style&3) + { + case CD_PLAIN: + index = 2; + break; + case CD_BOLD: + index = 6; + break; + case CD_ITALIC: + index = 10; + break; + case CD_BOLD_ITALIC: + index = 14; + break; + } + else if (cdStrEqualNoCase(type_face, "Times")) + switch (style&3) + { + case CD_PLAIN: + index = 3; + break; + case CD_BOLD: + index = 7; + break; + case CD_ITALIC: + index = 11; + break; + case CD_BOLD_ITALIC: + index = 15; + break; + } + else if (cdStrEqualNoCase(type_face, "Helvetica")) + switch (style&3) + { + case CD_PLAIN: + index = 4; + break; + case CD_BOLD: + index = 8; + break; + case CD_ITALIC: + index = 12; + break; + case CD_BOLD_ITALIC: + index = 16; + break; + } + + if (index == 0) return 0; + + cgm_char_height ( ctxcanvas->cgm, cdGetFontSizePixels(ctxcanvas->canvas, size)); + cgm_text_font_index( ctxcanvas->cgm, index ); + + return 1; +} + +static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment) +{ + int hor = 0, ver = 0; + enum { NORMHORIZ, LEFT, CTR, RIGHT }; + enum { NORMVERT, TOP, CAP, HALF, BASE, BOTTOM }; + + switch ( alignment ) + { + case CD_NORTH: + hor = CTR; + ver = TOP; + break; + case CD_SOUTH: + hor = CTR; + ver = BOTTOM; + break; + case CD_EAST: + hor = RIGHT; + ver = HALF; + break; + case CD_WEST: + hor = LEFT; + ver = HALF; + break; + case CD_NORTH_EAST: + hor = RIGHT; + ver = TOP; + break; + case CD_NORTH_WEST: + hor = LEFT; + ver = TOP; + break; + case CD_SOUTH_EAST: + hor = RIGHT; + ver = BOTTOM; + break; + case CD_SOUTH_WEST: + hor = LEFT; + ver = BOTTOM; + break; + case CD_CENTER: + hor = CTR; + ver = HALF; + break; + case CD_BASE_LEFT: + hor = LEFT; + ver = BASE; + break; + case CD_BASE_CENTER: + hor = CTR; + ver = BASE; + break; + case CD_BASE_RIGHT: + hor = RIGHT; + ver = BASE; + break; + } + + cgm_text_alignment ( ctxcanvas->cgm, hor, ver , (double)0.0, (double)0.0 ); + + return alignment; +} + +/******************************************************/ +/* color */ +/******************************************************/ + +static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + double cor[3]; + + cor[0] = get_red(color); + cor[1] = get_green(color); + cor[2] = get_blue(color); + + cgm_text_colour( ctxcanvas->cgm, cor ); + cgm_fill_colour( ctxcanvas->cgm, cor ); + cgm_line_colour( ctxcanvas->cgm, cor ); + + return color; +} + +static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color) +{ + double bc[3]; + + bc[0] = get_red(color); + bc[1] = get_green(color); + bc[2] = get_blue(color); + + ctxcanvas->canvas->background = color; + cgm_backgound_colour ( ctxcanvas->cgm, bc ); + + return color; +} + +static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opaque) +{ + if (opaque == CD_TRANSPARENT) + cgm_transparency(ctxcanvas->cgm, 1); + else + cgm_transparency(ctxcanvas->cgm, 0); + return opaque; +} + +/******************************************************/ +/* client images */ +/******************************************************/ + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + double p[6]; + double *color_array; + int i,j,index,c; + int rw, rh; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + color_array = (double *) malloc ( rw*rh*3*sizeof(double) ); + if (!color_array) + return; + + p[0] = (double) x; p[1] = (double) (y+h); + p[2] = (double) (x+w); p[3] = (double) y; + p[4] = (double) (x+w); p[5] = (double) (y+h); + + for ( i=0; icgm, p, (long)rw, (long)rh, 8, color_array ); + + free(color_array); + + setbbox (ctxcanvas, p[0], p[1] ); + setbbox (ctxcanvas, p[2], p[3] ); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + double p[6]; + double *color_array; + int i,j,c; + unsigned char r, g, b; + int rw, rh; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + color_array = (double *) malloc ( rw*rh*3*sizeof(double) ); + if (!color_array) + return; + + p[0] = (double) x; p[1] = (double) y; + p[2] = (double) (x+w); p[3] = (double) (y+h); + p[4] = (double) (x+w); p[5] = (double) y; + + for ( i=0; icgm, p, (long)rw, (long)rh, 8, color_array ); + + free(color_array); + + setbbox (ctxcanvas, p[0], p[1] ); + setbbox (ctxcanvas, p[2], p[3] ); +} + +/******************************************************/ +/* server images */ +/******************************************************/ + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + double cor[3]; + double pts[2]; + + pts[0] = (double) x; + pts[1] = (double) y; + + cor[0] = get_red(color); + cor[1] = get_green(color); + cor[2] = get_blue(color); + + cgm_marker_colour( ctxcanvas->cgm, cor); + cgm_polymarker ( ctxcanvas->cgm, 1, pts ); +} + +/* +%F Cria um canvas CGM. +Parametros passados em data: +[nome] nome do arquivo de saida <= 255 caracteres +[size] tamanho do papel +-t codificacao clear text se nao binaria +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas *ctxcanvas; + char *line = (char *)data; + char c; + char words[4][256]; + char filename[10240] = ""; + double w=0, h=0, r=0; + int p=0; + int i, n; + + line += cdGetFileName(line, filename); + if (filename[0] == 0) + return; + + n = sscanf(line, "%s %s %s %s", words[0], words[1], words[2], words[3]); + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + + canvas->ctxcanvas = ctxcanvas; + ctxcanvas->canvas = canvas; + + strcpy(ctxcanvas->filename, filename); + + canvas->w_mm = (double)INT_MAX*3.78; + canvas->h_mm = (double)INT_MAX*3.78; + canvas->xres = 3.78; + canvas->yres = 3.78; + canvas->bpp = 24; + + ctxcanvas->vdc_int_prec = 16; + ctxcanvas->codificacao = CD_BIN; + ctxcanvas->first = 1; + ctxcanvas->clip.first = 1; + ctxcanvas->patindex = 1; + + ctxcanvas->hassize = 0; /* Indica se foi passado um tamanho para o canvas */ + + for (i = 0; i < n; i++) + { + if (sscanf ( words[i], "%lgx%lg", &w, &h )== 2) + { + canvas->w_mm = w; + canvas->h_mm = h; + ctxcanvas->hassize = 1; + } + else if (sscanf ( words[i], "%lg", &r ) == 1) + canvas->yres = canvas->xres = r; + else if (sscanf ( words[i], "-%c%d", &c, &p )>0) + { + if ( c=='t' ) + ctxcanvas->codificacao = CD_CLEAR_TEXT; + else if ( c=='p' ) + ctxcanvas->vdc_int_prec = p; + } + } + + if ( ctxcanvas->vdc_int_prec != 16 && w == 0.0 && h == 0.0 ) + { + canvas->w_mm = (double) (pow(2,p)/2)-1; + canvas->h_mm = (double) (pow(2,p)/2)-1; + } + + /* update canvas context */ + canvas->w = (int)(canvas->w_mm * canvas->xres); + canvas->h = (int)(canvas->h_mm * canvas->yres); + + ctxcanvas->cgm = cgm_begin_metafile ( ctxcanvas->filename, ctxcanvas->codificacao, "CD - CanvasDraw, Tecgraf/PUC-RIO" ); + + metafile_descriptor(ctxcanvas); + + cgm_begin_picture ( ctxcanvas->cgm, "Picture x" ); + + picture_descriptor (ctxcanvas); + + cgm_clip_rectangle ( ctxcanvas->cgm, 0, 0, (double)canvas->w, (double)canvas->h); + cgm_clip_indicator (ctxcanvas->cgm, 0); + + cgm_begin_picture_body ( ctxcanvas->cgm ); + + control_elements (ctxcanvas); + + cgm_marker_type( ctxcanvas->cgm, MARKER_DOT); + cgm_marker_size( ctxcanvas->cgm, 1.0); +} + +static void cdinittable(cdCanvas* canvas) +{ + /* initialize function table*/ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxText = cdtext; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFText = cdftext; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxFClipArea = cdfcliparea; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxBackOpacity = cdbackopacity; + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxDeactivate = cddeactivate; +} + +/******************************************************/ + +static cdContext cdCGMContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PALETTE | + CD_CAP_CLIPPOLY | CD_CAP_WRITEMODE | CD_CAP_IMAGESRV | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | + CD_CAP_FONTDIM | CD_CAP_TEXTSIZE | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | + CD_CAP_TEXTORIENTATION), + 0, + cdcreatecanvas, + cdinittable, + cdplayCGM, + cdRegisterCallbackCGM, +}; + +cdContext* cdContextCGM(void) +{ + return &cdCGMContext; +} + diff --git a/cd/src/drv/cddebug.c b/cd/src/drv/cddebug.c new file mode 100755 index 0000000..23d8446 --- /dev/null +++ b/cd/src/drv/cddebug.c @@ -0,0 +1,733 @@ +/** \file + * \brief CD DEBUG driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" +#include "cd_private.h" +#include "cddebug.h" + + +#define CDDBG_FLUSH "Flush" +#define CDDBG_CLEAR "Clear" +#define CDDBG_CLIP "Clip" +#define CDDBG_CLIPAREA "Cliparea" +#define CDDBG_LINE "Line" +#define CDDBG_BOX "Box" +#define CDDBG_ARC "Arc" +#define CDDBG_SECTOR "Sector" +#define CDDBG_TEXT "Text" +#define CDDBG_BEGIN "Begin" +#define CDDBG_VERTEX "Vertex" +#define CDDBG_END "End" +#define CDDBG_MARK "Mark" +#define CDDBG_BACKOPACITY "BackOpacity" +#define CDDBG_WRITEMODE "WriteMode" +#define CDDBG_LINESTYLE "LineStyle" +#define CDDBG_LINEWIDTH "LineWidth" +#define CDDBG_INTERIORSTYLE "InteriorStyle" +#define CDDBG_HATCH "Hatch" +#define CDDBG_STIPPLE "Stipple" +#define CDDBG_PATTERN "Pattern" +#define CDDBG_NATIVEFONT "NativeFont" +#define CDDBG_TEXTALIGNMENT "TextAlignment" +#define CDDBG_PALETTE "Palette" +#define CDDBG_BACKGROUND "Background" +#define CDDBG_FOREGROUND "Foreground" +#define CDDBG_PIXEL "Pixel" +#define CDDBG_SCROLLAREA "ScrollArea" +#define CDDBG_TEXTORIENTATION "TextOrientation" +#define CDDBG_RECT "Rect" +#define CDDBG_FILLMODE "FillMode" +#define CDDBG_LINESTYLEDASHES "LineStyleDashes" +#define CDDBG_LINECAP "LineCap" +#define CDDBG_LINEJOIN "LineJoin" +#define CDDBG_CHORD "Chord" +#define CDDBG_FLINE "fLine" +#define CDDBG_FRECT "fRect" +#define CDDBG_FBOX "fBox" +#define CDDBG_FARC "fArc" +#define CDDBG_FSECTOR "fSector" +#define CDDBG_FTEXT "fText" +#define CDDBG_FVERTEX "fVertex" +#define CDDBG_MATRIX "Matrix" +#define CDDBG_FCHORD "fChord" +#define CDDBG_FCLIPAREA "fClipArea" +#define CDDBG_FONT "Font" +#define CDDBG_PUTIMAGERGB "PutImageRGB" +#define CDDBG_PUTIMAGERGBA "PutImageRGBA" +#define CDDBG_PUTIMAGEMAP "PutImageMap" + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + char* filename; + FILE* file; + int last_line_style; + int last_fill_mode; +}; + +struct _cdCtxImage { + cdCtxCanvas *ctxcanvas; +}; + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + fflush(ctxcanvas->file); + fprintf(ctxcanvas->file, "%s()\n", CDDBG_FLUSH); +} + +static void cdclear(cdCtxCanvas *ctxcanvas) +{ + fprintf(ctxcanvas->file, "%s()\n", CDDBG_CLEAR); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + const char* enum2str[] = { + "CD_CLIPOFF", + "CD_CLIPAREA", + "CD_CLIPPOLYGON", + "CD_CLIPREGION" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_CLIP, enum2str[mode]); + return mode; +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_CLIPAREA, xmin, xmax, ymin, ymax); +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FCLIPAREA, xmin, xmax, ymin, ymax); +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_MATRIX, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + else + fprintf(ctxcanvas->file, "%s(NULL)\n", CDDBG_MATRIX); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_LINE, x1, y1, x2, y2); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FLINE, x1, y1, x2, y2); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_RECT, xmin, xmax, ymin, ymax); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FRECT, xmin, xmax, ymin, ymax); +} + +static const char* get_region_mode(int combine_mode) +{ + const char* enum2str[] = { + "CD_UNION", + "CD_INTERSECT", + "CD_DIFFERENCE", + "CD_NOTINTERSECT" + }; + return enum2str[combine_mode]; +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %s)\n", CDDBG_BOX, xmin, xmax, ymin, ymax, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d)\n", CDDBG_BOX, xmin, xmax, ymin, ymax); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %s)\n", CDDBG_FBOX, xmin, xmax, ymin, ymax, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g)\n", CDDBG_FBOX, xmin, xmax, ymin, ymax); +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_ARC, xc, yc, w, h, a1, a2); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FARC, xc, yc, w, h, a1, a2); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %g, %g, %s)\n", CDDBG_SECTOR, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_SECTOR, xc, yc, w, h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %g, %g, %s)\n", CDDBG_FSECTOR, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FSECTOR, xc, yc, w, h, a1, a2); +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%d, %d, %d, %d, %g, %g, %s)\n", CDDBG_CHORD, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %g, %g)\n", CDDBG_CHORD, xc, yc, w, h, a1, a2); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%g, %g, %g, %g, %g, %g, %s)\n", CDDBG_FCHORD, xc, yc, w, h, a1, a2, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%g, %g, %g, %g, %g, %g)\n", CDDBG_FCHORD, xc, yc, w, h, a1, a2); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int len) +{ + text = cdStrDupN(text, len); + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%d, %d, \"%s\", %s)\n", CDDBG_TEXT, x, y, text, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%d, %d, \"%s\")\n", CDDBG_TEXT, x, y, text); + free((char*)text); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text, int len) +{ + text = cdStrDupN(text, len); + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%g, %g, \"%s\", %s)\n", CDDBG_FTEXT, x, y, text, get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%g, %g, \"%s\")\n", CDDBG_FTEXT, x, y, text); + free((char*)text); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + const char* enum2str[] = { + "CD_FILL", + "CD_OPEN_LINES", + "CD_CLOSED_LINES", + "CD_CLIP", + "CD_BEZIER", + "CD_REGION" + }; + + if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode) + { + const char* enum2str[] = { + "CD_EVENODD", + "CD_WINDING" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_FILLMODE, enum2str[ctxcanvas->canvas->fill_mode]); + ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode; + } + + if (ctxcanvas->canvas->new_region) + fprintf(ctxcanvas->file, "%sRegion(%s, %s)\n", CDDBG_BEGIN, enum2str[mode], get_region_mode(ctxcanvas->canvas->combine_mode)); + else + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]); + + for(i = 0; ifile, "%s(%d, %d)\n", CDDBG_VERTEX, poly[i].x, poly[i].y); + + fprintf(ctxcanvas->file, "%s()\n", CDDBG_END); +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + const char* enum2str[] = { + "CD_FILL", + "CD_OPEN_LINES", + "CD_CLOSED_LINES", + "CD_CLIP", + "CD_BEZIER", + "CD_REGION" + }; + + if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode) + { + const char* enum2str[] = { + "CD_EVENODD", + "CD_WINDING" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_FILLMODE, enum2str[ctxcanvas->canvas->fill_mode]); + ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode; + } + + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BEGIN, enum2str[mode]); + + for(i = 0; ifile, "%s(%g, %g)\n", CDDBG_FVERTEX, poly[i].x, poly[i].y); + + fprintf(ctxcanvas->file, "%s()\n", CDDBG_END); +} + +static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opacity) +{ + const char* enum2str[] = { + "CD_OPAQUE", + "CD_TRANSPARENT" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_BACKOPACITY, enum2str[opacity]); + return opacity; +} + +static int cdwritemode(cdCtxCanvas *ctxcanvas, int mode) +{ + const char* enum2str[] = { + "CD_REPLACE", + "CD_XOR", + "CD_NOT_XOR" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_WRITEMODE, enum2str[mode]); + return mode; +} + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + const char* enum2str[] = { + "CD_CONTINUOUS", + "CD_DASHED", + "CD_DOTTED", + "CD_DASH_DOT", + "CD_DASH_DOT_DOT", + "CD_CUSTOM" + }; + + if (style == CD_CUSTOM && ctxcanvas->canvas->line_style != ctxcanvas->last_line_style) + { + int i; + + fprintf(ctxcanvas->file, "%s(%d", CDDBG_LINESTYLEDASHES, ctxcanvas->canvas->line_dashes_count); + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + fprintf(ctxcanvas->file, ", %d", ctxcanvas->canvas->line_dashes[i]); + fprintf(ctxcanvas->file, ")\n"); + + ctxcanvas->last_line_style = ctxcanvas->canvas->line_style; + } + + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINESTYLE, enum2str[style]); + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + fprintf(ctxcanvas->file, "%s(%d)\n", CDDBG_LINEWIDTH, width); + return width; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + const char* enum2str[] = { + "CD_CAPFLAT", + "CD_CAPSQUARE", + "CD_CAPROUND" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINECAP, enum2str[cap]); + return cap; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + const char* enum2str[] = { + "CD_MITER", + "CD_BEVEL", + "CD_ROUND" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_LINEJOIN, enum2str[join]); + return join; +} + +static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style) +{ + const char* enum2str[] = { + "CD_SOLID", + "CD_HATCH", + "CD_STIPPLE", + "CD_PATTERN", + "CD_HOLLOW" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_INTERIORSTYLE, enum2str[style]); + return style; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + const char* enum2str[] = { + "CD_HORIZONTAL", + "CD_VERTICAL", + "CD_FDIAGONAL", + "CD_BDIAGONAL", + "CD_CROSS", + "CD_DIAGCROSS" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_HATCH, enum2str[style]); + return style; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *stipple) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %p)\n", CDDBG_STIPPLE, w, h, stipple); +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *pattern) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %p)\n", CDDBG_PATTERN, w, h, pattern); +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char* type_face, int style, int size) +{ + char style_str[50] = ""; + if (style & CD_BOLD) + strcat(style_str, "CD_BOLD"); + if (style & CD_ITALIC) + { + if (style_str[0]!=0) strcat(style_str, "|"); + strcat(style_str, "CD_ITALIC"); + } + if (style & CD_UNDERLINE) + { + if (style_str[0]!=0) strcat(style_str, "|"); + strcat(style_str, "CD_UNDERLINE"); + } + if (style & CD_STRIKEOUT) + { + if (style_str[0]!=0) strcat(style_str, "|"); + strcat(style_str, "CD_STRIKEOUT"); + } + if (style_str[0]==0) strcat(style_str, "CD_PLAIN"); + fprintf(ctxcanvas->file, "%s(\"%s\", %s, %d)\n", CDDBG_FONT, type_face, style_str, size); + return 1; +} + +static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* font) +{ + fprintf(ctxcanvas->file, "%s(\"%s\")\n", CDDBG_NATIVEFONT, font); + return 1; +} + +static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment) +{ + const char* enum2str[] = { + "CD_NORTH", + "CD_SOUTH", + "CD_EAST", + "CD_WEST", + "CD_NORTH_EAST", + "CD_NORTH_WEST", + "CD_SOUTH_EAST", + "CD_SOUTH_WEST", + "CD_CENTER", + "CD_BASE_LEFT", + "CD_BASE_CENTER", + "CD_BASE_RIGHT" + }; + fprintf(ctxcanvas->file, "%s(%s)\n", CDDBG_TEXTALIGNMENT, enum2str[alignment]); + return alignment; +} + +static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle) +{ + fprintf(ctxcanvas->file, "%s(%g)\n", CDDBG_TEXTORIENTATION, angle); + return angle; +} + +static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode) +{ + const char* enum2str[] = { + "CD_POLITE", + "CD_FORCE" + }; + fprintf(ctxcanvas->file, "%s(%d, %p, %s)\n", CDDBG_PALETTE, n, palette, enum2str[mode]); +} + +static long cdbackground(cdCtxCanvas *ctxcanvas, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%s(%d, %d, %d)\n", CDDBG_BACKGROUND, (int)r, (int)g, (int)b); + return color; +} + +static long cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%s(%d, %d, %d)\n", CDDBG_FOREGROUND, (int)r, (int)g, (int)b); + return color; +} + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGERGB, iw, ih, r, g, b, x, y, w, h, xmin, xmax, ymin, ymax); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGERGBA, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %p, %p, %d, %d, %d, %d, %d, %d, %d, %d)\n", CDDBG_PUTIMAGEMAP, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %d)\n", CDDBG_PIXEL, x, y, (int)r, (int)g, (int)b); +} + +static void cdscrollarea(cdCtxCanvas *ctxcanvas, int xmin,int xmax, int ymin,int ymax, int dx,int dy) +{ + fprintf(ctxcanvas->file, "%s(%d, %d, %d, %d, %d, %d)\n", CDDBG_SCROLLAREA, xmin, xmax, ymin, ymax, dx, dy); +} + +static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + fprintf(ctxcanvas->file, "%p, %p, %p = GetImageRGB(%d, %d, %d, %d)\n", r, g, b, x, y, w, h); +} + +static cdCtxImage* cdcreateimage(cdCtxCanvas* ctxcanvas, int w, int h) +{ + cdCtxImage* ctximage = malloc(sizeof(cdCtxImage)); + ctximage->ctxcanvas = ctxcanvas; + fprintf(ctxcanvas->file, "%p = GetImage(%d, %d)\n", ctximage, w, h); + return ctximage; +} + +static void cdkillimage(cdCtxImage* ctximage) +{ + fprintf(ctximage->ctxcanvas->file, "KillImage(%p)\n", ctximage); + free(ctximage); +} + +static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y) +{ + fprintf(ctxcanvas->file, "GetImage(%p, %d, %d)\n", ctximage, x, y); +} + +static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "PutImage(%p, %d, %d, %d, %d, %d, %d)\n", ctximage, x, y, xmin, xmax, ymin, ymax); +} + +static void cdnewregion(cdCtxCanvas* ctxcanvas) +{ + fprintf(ctxcanvas->file, "NewRegion()\n"); +} + +static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + fprintf(ctxcanvas->file, "IsPointInRegion(%d, %d)\n", x, y); + return 0; +} + +static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + fprintf(ctxcanvas->file, "OffsetRegion(%d, %d)\n", x, y); +} + +static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + (void)xmin; + (void)ymin; + (void)xmax; + (void)ymax; + fprintf(ctxcanvas->file, "GetRegionBox()\n"); +} + +static int cdactivate(cdCtxCanvas* ctxcanvas) +{ + fprintf(ctxcanvas->file, "Activate()\n"); + return CD_OK; +} + +static void cddeactivate(cdCtxCanvas* ctxcanvas) +{ + fprintf(ctxcanvas->file, "Deactivate()\n"); +} + +static void cdgetfontdim(cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + int tmp_max_width, tmp_height, tmp_ascent, tmp_descent; + if (!max_width) max_width = &tmp_max_width; + if (!height) height = &tmp_height; + if (!ascent) ascent = &tmp_ascent; + if (!descent) descent = &tmp_descent; + cdgetfontdimEX(ctxcanvas, max_width, height, ascent, descent); + fprintf(ctxcanvas->file, "%d, %d, %d, %d = GetFontDim()\n", *max_width, *height, *ascent, *descent); +} + +static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height) +{ + int tmp_width, tmp_height; + if (!width) width = &tmp_width; + if (!height) height = &tmp_height; + cdgettextsizeEX(ctxcanvas, s, len, width, height); + fprintf(ctxcanvas->file, "%d, %d = GetTextSize(\"%s\")\n", *width, *height, s); +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + fprintf(ctxcanvas->file, "KillCanvas()\n"); + free(ctxcanvas->filename); + fclose(ctxcanvas->file); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas *canvas, void *data) +{ + char filename[10240] = ""; + char* strdata = (char*)data; + double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78; + cdCtxCanvas* ctxcanvas; + int size; + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata, "%lgx%lg %lg", &w_mm, &h_mm, &res); + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + ctxcanvas->file = fopen(filename, "w"); + if (!ctxcanvas->file) + { + free(ctxcanvas); + return; + } + + size = strlen(filename); + ctxcanvas->filename = malloc(size+1); + memcpy(ctxcanvas->filename, filename, size+1); + + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->w = (int)(w_mm * res); + canvas->h = (int)(h_mm * res); + canvas->w_mm = w_mm; + canvas->h_mm = h_mm; + canvas->bpp = 24; + canvas->xres = res; + canvas->yres = res; + canvas->ctxcanvas = ctxcanvas; + + ctxcanvas->last_line_style = -1; + ctxcanvas->last_fill_mode = -1; + + fprintf(ctxcanvas->file, "CreateCanvas(CD_DEBUG, \"%s\")\n", (char*)data); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxClear = cdclear; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxScrollArea = cdscrollarea; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFChord = cdfchord; + canvas->cxFText = cdftext; + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxWriteMode = cdwritemode; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxTextOrientation = cdtextorientation; + canvas->cxPalette = cdpalette; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxFClipArea = cdfcliparea; + canvas->cxTransform = cdtransform; + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxGetImageRGB = cdgetimagergb; + canvas->cxScrollArea = cdscrollarea; + canvas->cxCreateImage = cdcreateimage; + canvas->cxKillImage = cdkillimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxNewRegion = cdnewregion; + canvas->cxIsPointInRegion = cdispointinregion; + canvas->cxOffsetRegion = cdoffsetregion; + canvas->cxGetRegionBox = cdgetregionbox; + canvas->cxActivate = cdactivate; + canvas->cxDeactivate = cddeactivate; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; +} + +static cdContext cdDebugContext = +{ + CD_CAP_ALL, + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextDebug(void) +{ + return &cdDebugContext; +} + diff --git a/cd/src/drv/cddgn.c b/cd/src/drv/cddgn.c new file mode 100755 index 0000000..d7dd5f9 --- /dev/null +++ b/cd/src/drv/cddgn.c @@ -0,0 +1,1691 @@ +/** \file + * \brief DGN driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cddgn.h" + +/* defines */ + +#define MAX_NUM_VERTEX 101 +#define MAX_NUM_VERTEX_PER_POLYLINE 15000 + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#define END_OF_DGN_FILE 0xffff +#define DGN_FILE_BLOCK 512 + +#define NOFILL 0 /* tipos de fill que o driver faz */ +#define CONVEX 1 +#define NORMAL 2 + +/* macros */ + +#define SIZE_LINE_STRING(x) (19+4*(x)) +#define SIZE_FILLED_SHAPE(x) (27+4*(x)) +#define SIZE_ARC 40 +#define SIZE_LINE 26 + +#define IGNORE(x) ((void) x) + + +/* estruturas similares as que o MicroStation usa */ + +typedef struct +{ + union + { + struct + { + unsigned level:6; + unsigned :1; + unsigned complex:1; + unsigned type:7; + unsigned :1; + } flags; + short type_as_word; + } type; + + unsigned short words; + unsigned long xmin; + unsigned long ymin; + unsigned long xmax; + unsigned long ymax; +} Elm_hdr; + +typedef struct +{ + short attindx; + union + { + short s; + struct + { + unsigned /*class*/ :4; + unsigned /*res*/ :4; + unsigned /*l*/ :1; + unsigned /*n*/ :1; + unsigned /*m*/ :1; + unsigned attributes:1; + unsigned /*r*/ :1; + unsigned /*p*/ :1; + unsigned /*s*/ :1; + unsigned /*hole*/ :1; + } flags; + } props; + + union + { + short s; + struct + { + unsigned style:3; + unsigned weight:5; + unsigned color:8; + } b; + } symb; + +} Disp_hdr; + +/* tipo de poligono/setor */ +enum +{ + FILLED, + OPEN +}; + +/* grupos de tamanhos de caracter + (usado por gettextwidth e cdgetfontdim) */ + +static long fontsizes[4][8]= +{ + {1,2,4,5,6,7,0}, + {5,3,2,1,0}, + {8,6,4,3,2,1,0}, + {5,3,2,1,0} +}; + + +/********************** + * contexto do driver * + **********************/ + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + FILE *file; /* arquivo dgn */ + long int bytes; /* tamanho do arquivo */ + char level; + + short color, style; + + short alignment; + short typeface_index; + short symbology; + long tl; + short is_base; /* setado se texto e' do tipo CD_BASE_... */ + + short fill_type; /* como o driver faz fill: + NOFILL -> nao faz fill + CONVEX -> so faz fill de poligonos convexos + NORMAL -> faz fill normalmente */ + + long colortable[256]; /* palette */ + short num_colors; + + short is_complex; +}; + +/* prototipos de funcao */ +static void startComplexShape(cdCtxCanvas*, unsigned short,short,unsigned short, + unsigned long,unsigned long, + unsigned long,unsigned long); +static void endComplexElement(cdCtxCanvas*); + +/****************************** + * * + * funcoes internas do driver * + * * + ******************************/ + +/********************************************************* + * Obtem o descent do texto (para letras como q,p,g etc) * + *********************************************************/ + +static long get_descent(const char *text, int len, int size_pixel) +{ + char *descent="jgyqp"; + long a=0; + + while(a < len) + { + if(strchr(descent, text[a])) + return size_pixel/2; + + a++; + } + return 0; +} + +/*********************************************** + * Calcula a largura da string no MicroStation * + ***********************************************/ + +static long gettextwidth(cdCtxCanvas* ctxcanvas, const char *s, int len, int size_pixel) +{ + long a=0, + width=0; + + short default_size=0; + + static char *fontchars[4][8] = + { + { /* CD_SYSTEM */ + "Ww", + "jshyut#*-=<>", + "iIl[]", + ";:.,'|!()`{}", + "","","","" + }, + + { /* CD_COURIER */ + "Iflrit!();.'", + "1|[]\"/`", + "BCDEKPRSUVXYbdgkpq&-_", + "w#%", + "Wm^+=<>~", + "@","","" + }, + + { /* CD_TIMES_ROMAN */ + "m", + "HMUWw", + "CSTZLbhknpuvxy23567890e", + "fstz1#$-=<>", + "Iijl*[]", + ";:.,'|!()`{}", + "","" + }, + + { /* CD_HELVETICA */ + "Ww", + "jshyut#*-=<>", + "iIl[]", + ";:.,'|!()`{}", + "","","","" + } + }; + + if (ctxcanvas->typeface_index == 1) + default_size=2; + else if (ctxcanvas->typeface_index == 2) + default_size=5; + else if (ctxcanvas->typeface_index == 3) + default_size=4; + else + default_size=4; + + for(a=0,width=0;a < len; a++) + { + static short size_number; + static char letter; + + if(s[a] == ' ') + letter = s[a-1]; + else + letter = s[a]; + + for(size_number=0;size_number < 8;size_number++) + { + if(strchr(fontchars[ctxcanvas->typeface_index][size_number], letter)) + { + width+=(ctxcanvas->tl*fontsizes[ctxcanvas->typeface_index][size_number])/6; + break; + } + } + + if(size_number == 8) + width+=(ctxcanvas->tl*default_size)/6; + + width+=ctxcanvas->tl/3; + } + + width-=ctxcanvas->tl/3; + + if (ctxcanvas->canvas->font_style & CD_ITALIC) + width+= (long) ((double)size_pixel*tan(4*atan(1)/8)); /* angulo de 15 graus */ + + return width; +} + +/**************************** + * Salva um byte no arquivo * + ****************************/ + +static void put_byte(cdCtxCanvas* ctxcanvas, unsigned char byte) +{ + fputc(byte, ctxcanvas->file); +} + +/************************************ + * Salva um sequencia de caracteres * + ************************************/ + +static void writec (cdCtxCanvas* ctxcanvas, const char *t, short tam ) +{ + short i; + + ctxcanvas->bytes += tam; + for ( i = 0; i < tam; i++ ) + fputc ( t[i], ctxcanvas->file ); +} + +/****************** + * Salva uma word * + ******************/ + +static void put_word(cdCtxCanvas* ctxcanvas, unsigned short w) +{ + char c; + + c = (char) (w & 0xff); + fputc (c, ctxcanvas->file); + c = (char) ((w >> 8) & 0xff); + fputc (c, ctxcanvas->file); + ctxcanvas->bytes += 2; +} + +/**************************** + * Salva um long no arquivo * + ****************************/ + +static void put_long (cdCtxCanvas* ctxcanvas, unsigned long i) +{ + put_word(ctxcanvas, (short) (i >> 16)); + put_word(ctxcanvas, (short) i); +} + +/******************* + * Salva um double * + *******************/ + +static void put_as_double(cdCtxCanvas* ctxcanvas, long i) +{ + float dfloat=(float) 4*i; + + put_long(ctxcanvas, *((long *) &dfloat)); + put_long(ctxcanvas, 0); + + ctxcanvas->bytes+=sizeof(float); +} + +/**************************** + * Salva uma UOR no arquivo * + ****************************/ + +static void put_uor(cdCtxCanvas* ctxcanvas, long i) +{ + put_word(ctxcanvas, (unsigned short)((i >> 16) ^ (1 << 15))); /* troca o bit 31 + para transformar em uor */ + put_word(ctxcanvas, (unsigned short)i); +} + +/*************************************** + * Salva a bounding box de um elemento * + ***************************************/ + +static void put_bound(cdCtxCanvas* ctxcanvas, long xmin, long xmax, long ymin, long ymax) +{ + put_uor(ctxcanvas, xmin); + put_uor(ctxcanvas, ymin); + put_uor(ctxcanvas, 0L); + put_uor(ctxcanvas, xmax); + put_uor(ctxcanvas, ymax); + put_uor(ctxcanvas, 0L); +} + +/****************************************** + * Calcula a bounding box de uma polyline * + ******************************************/ + +static void line_string_bound(cdPoint *buffer, short num_vertex, + unsigned long *xmin, unsigned long *ymin, + unsigned long *xmax, unsigned long *ymax) +{ + short i; + unsigned long v; + + *xmin = *xmax = buffer[0].x; + *ymin = *ymax = buffer[0].y; + + for (i = 1; i < num_vertex; i++) + { + v = buffer[i].x; + if (v < *xmin) + *xmin = v; + else if (v > *xmax) + *xmax = v; + + v = (long) buffer[i].y; + if (v < *ymin) + *ymin = v; + else if (v > *ymax) + *ymax = v; + } +} + +/************************************ + * Retorna symbology de um elemento * + ************************************/ + +static short symbology(cdCtxCanvas* ctxcanvas) +{ + return (short)((ctxcanvas->color << 8) | (ctxcanvas->canvas->line_width << 3) | ctxcanvas->style); +} + +/***************************************** + * Salva um Element Header no arquivo * + *****************************************/ + +static void putElementHeader(cdCtxCanvas* ctxcanvas, Elm_hdr *ehdr) +{ + ehdr->type.flags.complex = ctxcanvas->is_complex; + + put_word(ctxcanvas, (short)(ehdr->type.flags.type << 8 | + ehdr->type.flags.complex << 7 | ehdr->type.flags.level)); + + + put_word(ctxcanvas, ehdr->words); + put_bound(ctxcanvas, ehdr->xmin, ehdr->xmax, ehdr->ymin, ehdr->ymax); +} + +/************************************** + * Salva um display header no arquivo * + **************************************/ + +static void putDisplayHeader(cdCtxCanvas* ctxcanvas, Disp_hdr *dhdr) +{ + put_word(ctxcanvas, 0); /* graphics group */ + put_word(ctxcanvas, dhdr->attindx); /* index to attributes */ + put_word(ctxcanvas, dhdr->props.flags.attributes << 11); /* properties */ + put_word(ctxcanvas, dhdr->symb.s); /* display symbology */ +} + + +/*************************************** + * completa o arquivo com zeros para * + * que o numero de bytes seja multiplo * + * de 512 * + ***************************************/ + +static void complete_file(cdCtxCanvas* ctxcanvas) +{ + long resto, i; + + put_word(ctxcanvas, END_OF_DGN_FILE); + + resto = DGN_FILE_BLOCK - ctxcanvas->bytes % DGN_FILE_BLOCK; + + /* checa validade do tamanho do arquivo */ + if (resto%2 != 0) return; + + for (i = 0; i < resto; i+=2) + put_word(ctxcanvas, 0); +} + +/************************************* + * Salva um elemento arco no arquivo * + *************************************/ + +static void arc (cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, double a1, double a2) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=16; + ehdr.words=SIZE_ARC-2; + ehdr.xmin=xc - w/2; + ehdr.xmax=xc + w/2; + ehdr.ymin=yc - h/2; + ehdr.ymax=yc + h/2; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx = ehdr.words - 14; + dhdr.props.flags.attributes = 0; + dhdr.symb.s = symbology(ctxcanvas); + putDisplayHeader(ctxcanvas, &dhdr); + + put_long(ctxcanvas, (long) a1*360000); /* start angle */ + put_long(ctxcanvas, (long) (a2-a1)*360000); /* sweep angle */ + put_as_double(ctxcanvas, w/2); /* primary axis */ + put_as_double(ctxcanvas, h/2); /* secondary axis */ + put_long(ctxcanvas, 0); /* rotation angle (sempre 0) */ + put_as_double(ctxcanvas, xc); /* x origin */ + put_as_double(ctxcanvas, yc); /* y origin */ +} + +/*************************************** + * Salva um elemento elipse no arquivo * + ***************************************/ + +static void ellipse(cdCtxCanvas* ctxcanvas, long xc, long yc, long w, long h, short type) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=15; + ehdr.words=34+((type==FILLED) ? 8 : 0); + ehdr.xmin=xc - w/2; + ehdr.xmax=xc + w/2; + ehdr.ymin=yc - h/2; + ehdr.ymax=yc + h/2; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=20; + dhdr.props.flags.attributes=(type == FILLED) ? 1 : 0; + dhdr.symb.s=symbology(ctxcanvas); + putDisplayHeader(ctxcanvas, &dhdr); + + put_as_double(ctxcanvas, w/2); /* primary axis */ + put_as_double(ctxcanvas, h/2); /* secondary axis */ + put_long(ctxcanvas, 50); /* rotation angle (sempre 0) */ + put_as_double(ctxcanvas, xc); /* x origin */ + put_as_double(ctxcanvas, yc); /* y origin */ + + /* salva atributo de fill */ + if(type == FILLED) + { + put_word(ctxcanvas, 0x1007); + put_word(ctxcanvas, 65); + put_word(ctxcanvas, 0x802); + put_word(ctxcanvas, 0x0001); + put_word(ctxcanvas, ctxcanvas->color); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + } +} + +static short getclosestColor(cdCtxCanvas* ctxcanvas, long color) +{ + short count=0, closest=0; + long diff=0; + unsigned char r = cdRed(color), + g = cdGreen(color), + b = cdBlue(color); + short rd, gd, bd; + long newdiff; + + /* procura a cor mais proxima */ + + diff = 3*65536; /* inicializa com maior diferenca possivel */ + + for(count=0; count < ctxcanvas->num_colors; count++) + { + rd = r - cdRed(ctxcanvas->colortable[count]); + gd = g - cdGreen(ctxcanvas->colortable[count]); + bd = b - cdBlue(ctxcanvas->colortable[count]); + + newdiff = rd*rd + gd*gd + bd*bd; + + if(newdiff <= diff) + { + /* verifica se encontrou a cor */ + if(newdiff == 0) + return count-1; + + diff = newdiff; + closest=count-1; + } + } + + /* nao encontrou a cor, tenta adicionar na palette, ou retorna a mais proxima */ + if(ctxcanvas->num_colors < 254) + { + ctxcanvas->colortable[ctxcanvas->num_colors+1] = color; + return ctxcanvas->num_colors++; + } + else + return closest; +} + +static void saveColorTable(cdCtxCanvas* ctxcanvas) +{ + unsigned char r,g,b; + short i; + + put_word(ctxcanvas, (0x05 << 8) | 1); /* colortable */ + put_word(ctxcanvas, 434); + + put_long(ctxcanvas, 0); + put_long(ctxcanvas, 0); + put_long(ctxcanvas, 0); + put_long(ctxcanvas, 0xffffffff); + put_long(ctxcanvas, 0xffffffff); + put_long(ctxcanvas, 0xffffffff); + + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 420); + put_word(ctxcanvas, 0x0400); + put_word(ctxcanvas, 0x100); + put_word(ctxcanvas, 0); + + for(i=0;i<256;i++) + { + cdDecodeColor(ctxcanvas->colortable[i], &r, &g, &b); + put_byte(ctxcanvas, r); + put_byte(ctxcanvas, g); + put_byte(ctxcanvas, b); + } + + put_word(ctxcanvas, 25); + for(i=0;i<32;i++) + put_word(ctxcanvas, 0x2020); +} + + +/***************************** + * Le uma word de um arquivo * + *****************************/ + +static short file_get_word(FILE *fp) +{ + short word=0; + + word = (short)fgetc(fp); + word |= ((short)fgetc(fp) << 8) & 0xff00; + + return word; +} + +/******************************** + * Salva uma word em um arquivo * + ********************************/ + +static void file_put_word (short word, FILE *fp) +{ + fputc ((char) (word & 0xff), fp); + fputc ((char) ((word >> 8) & 0xff), fp); +} + +/******************************************* + * Le elementos de um arquivo DGN e os * + * coloca no inicio do arquivo aberto pelo * + * driver * + *******************************************/ + +static void dgn_copy (FILE *file, cdCtxCanvas *ctxcanvas) +{ + short word=0; + + while ((word = file_get_word(file)) != END_OF_DGN_FILE) + { + file_put_word(word, ctxcanvas->file); /* type e level do elemento */ + ctxcanvas->bytes+=2; + + word = file_get_word(file); /* words to follow */ + file_put_word(word, ctxcanvas->file); + ctxcanvas->bytes+=2; + + while (word) /* copia resto do elemento */ + { + file_put_word(file_get_word(file), ctxcanvas->file); + word--; + ctxcanvas->bytes+=2; + } + } +} + + +/* + * Funcoes do driver + */ + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + saveColorTable(ctxcanvas); + complete_file(ctxcanvas); + fclose (ctxcanvas->file); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cddeactivate (cdCtxCanvas* ctxcanvas) +{ + fflush(ctxcanvas->file); +} + +static void cdflush (cdCtxCanvas* ctxcanvas) +{ + fflush(ctxcanvas->file); +} + + +/******************************************************/ +/* primitives */ +/******************************************************/ + +static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + cdPoint buffer[2]; + + buffer[0].x=x1; + buffer[0].y=y1; + buffer[1].x=x2; + buffer[1].y=y2; + + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=3; + + ehdr.words=SIZE_LINE-2; + + line_string_bound(buffer, 2, &ehdr.xmin, + &ehdr.ymin,&ehdr.xmax,&ehdr.ymax); + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx = ehdr.words - 14; + dhdr.props.flags.attributes = 0; + dhdr.symb.s=symbology(ctxcanvas); + + putDisplayHeader(ctxcanvas, &dhdr); + + /* pontos inicial e final da linha */ + + put_long(ctxcanvas, (long) x1); + put_long(ctxcanvas, (long) y1); + put_long(ctxcanvas, (long) x2); + put_long(ctxcanvas, (long) y2); +} + +static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=6; + ehdr.words=17+4*5+8; + ehdr.xmin=xmin; + ehdr.xmax=xmax; + ehdr.ymin=ymin; + ehdr.ymax=ymax; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=3+4*5; + dhdr.props.flags.attributes=1; + dhdr.symb.s=symbology(ctxcanvas); + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, 5); /* numero de vertices */ + + /* vertices */ + put_long(ctxcanvas, (long) xmin); + put_long(ctxcanvas, (long) ymin); + + put_long(ctxcanvas, (long) xmax); + put_long(ctxcanvas, (long) ymin); + + put_long(ctxcanvas, (long) xmax); + put_long(ctxcanvas, (long) ymax); + + put_long(ctxcanvas, (long) xmin); + put_long(ctxcanvas, (long) ymax); + + put_long(ctxcanvas, (long) xmin); + put_long(ctxcanvas, (long) ymin); + + /* atributos de fill */ + + put_word(ctxcanvas, 0x1007); + put_word(ctxcanvas, 65); + put_word(ctxcanvas, 0x802); + put_word(ctxcanvas, 0x0001); + put_word(ctxcanvas, ctxcanvas->color); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); +} + +static void cdarc (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (a2 == a1 + 360) + ellipse(ctxcanvas, xc,yc,w,h,OPEN); + else + arc(ctxcanvas, xc, yc, w, h, a1, a2); +} + +static void cdsector (cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (a2 == a1 + 360) + { + ellipse(ctxcanvas, xc,yc,w,h,FILLED); + return; + } + + startComplexShape(ctxcanvas, 3, 1, SIZE_ARC+SIZE_LINE*2, + (unsigned long) xc-w/2, (unsigned long) yc-h/2, + (unsigned long) xc+h/2, (unsigned long) yc+h/2); + + arc(ctxcanvas, xc, yc, w, h, a1, a2); + + cdline(ctxcanvas, xc, yc, (int) + (((double)w*cos(a1*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a1*CD_DEG2RAD))/2.+.5)); + cdline(ctxcanvas, xc, yc, (int) + (((double)w*cos(a2*CD_DEG2RAD)/2.+.5)), (int) (((double)h*sin(a2*CD_DEG2RAD))/2.+.5)); + + endComplexElement(ctxcanvas); +} + +static void cdtext (cdCtxCanvas* ctxcanvas, int x, int y, const char *s, int len) +{ + long descent=0; + short w=0; + long hc=0,wc=0; + int size_pixel; + short italic = (ctxcanvas->canvas->font_style&CD_ITALIC); + + Elm_hdr ehdr; + Disp_hdr dhdr; + + if(len > 255) + len=255; + + w = (short)((len/2)+(len%2)); + size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size); + descent=get_descent(s, len, size_pixel); + hc = size_pixel+descent; + wc = gettextwidth(ctxcanvas, s, len, size_pixel); + + y+=descent; + + switch (ctxcanvas->alignment) + { + case 12: x = x; y = y; break; + case 13: x = x; y = y - (int) (hc/2.0); break; + case 14: x = x; y = y - (int) hc; break; + case 6: x = x - (int) (wc/2.0); y = y; break; + case 7: x = x - (int) (wc/2.0); y = y - (int) (hc/2.0); break; + case 8: x = x - (int) (wc/2.0); y = y - (int) hc; break; + case 0: x = x - (int) wc; y = y; break; + case 1: x = x - (int) wc; y = y - (int) (hc/2.0); break; + case 2: x = x - (int) wc; y = y - (int) hc; break; + } + + if(ctxcanvas->is_base) + y -= (int) (hc/4.0); + + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=17; + ehdr.words=28+w+((italic) ? 8 : 0); + ehdr.xmin=x; + ehdr.xmax=x+wc; + ehdr.ymin=y-descent; + ehdr.ymax=y+hc; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=14+w; + dhdr.props.flags.attributes=(italic) ? 1 : 0; + + if (ctxcanvas->canvas->font_style&CD_BOLD) + dhdr.symb.s=ctxcanvas->color << 8 | (3 << 3); + else + dhdr.symb.s=ctxcanvas->color << 8; + + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, (ctxcanvas->alignment << 8) | ctxcanvas->typeface_index); + + put_long(ctxcanvas, (long)((1000 * ctxcanvas->tl) / 6) | (1 << 7)); + put_long(ctxcanvas, (long)((1000 * size_pixel) / 6) | (1 << 7)); + + put_long(ctxcanvas, 0); + put_long(ctxcanvas, x); + put_long(ctxcanvas, y); + put_word(ctxcanvas, (unsigned short)len); + writec(ctxcanvas, s, (short)(len+(len%2))); /* deve escrever sempre um numero par de caracteres */ + + if(italic) + { + put_word(ctxcanvas, 0x1007); /* atributos e words to follow */ + put_word(ctxcanvas, 0x80d4); /* tipo de atributo */ + put_long(ctxcanvas, 0x000865c0); + put_long(ctxcanvas, 0x00520000); + put_long(ctxcanvas, 0x00000000); + } +} + +static void startComplexShape(cdCtxCanvas* ctxcanvas, + unsigned short num_elements, + short is_fill, + unsigned short size, + unsigned long xmin, + unsigned long ymin, + unsigned long xmax, + unsigned long ymax) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=14; + ehdr.words=22 + ((is_fill) ? 8 : 0); + ehdr.xmax = xmax; + ehdr.xmin = xmin; + ehdr.ymax = ymax; + ehdr.ymin = ymin; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=4; + dhdr.props.flags.attributes = (is_fill) ? 1 : 0; + dhdr.symb.s=symbology(ctxcanvas); + + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, size + 5 + ((is_fill) ? 8 : 0)); + put_word(ctxcanvas, num_elements); + + put_long(ctxcanvas, 0); /* atributo nulo */ + put_long(ctxcanvas, 0); + + /* salva atributo de fill */ + if(is_fill) + { + put_word(ctxcanvas, 0x1007); + put_word(ctxcanvas, 65); + put_word(ctxcanvas, 0x802); + put_word(ctxcanvas, 0x0001); + put_word(ctxcanvas, ctxcanvas->color); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + } + + /* marca inicio de elemento complexo */ + + ctxcanvas->is_complex = 1; +} + + +static void startComplexChain(cdCtxCanvas* ctxcanvas, + unsigned short num_elements, + unsigned short size, + unsigned long xmin, + unsigned long ymin, + unsigned long xmax, + unsigned long ymax) + +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=12; + + ehdr.words=22; + ehdr.xmax = xmax; + ehdr.xmin = xmin; + ehdr.ymax = ymax; + ehdr.ymin = ymin; + + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=4; + dhdr.props.flags.attributes = 1; + dhdr.symb.s=symbology(ctxcanvas); + + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, size+5); + put_word(ctxcanvas, num_elements); + + put_long(ctxcanvas, 0); /* atributo nulo */ + put_long(ctxcanvas, 0); + + + /* marca inicio de elemento complexo */ + + ctxcanvas->is_complex = 1; +} + +static void endComplexElement(cdCtxCanvas* ctxcanvas) +{ + ctxcanvas->is_complex = 0; +} + +static void putLineString(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + short i=0; + + ehdr.type.flags.level=ctxcanvas->level; + + ehdr.type.flags.type=4; + + ehdr.words=SIZE_LINE_STRING(num_vertex)-2; + + line_string_bound(buffer, num_vertex, &ehdr.xmin, + &ehdr.ymin,&ehdr.xmax,&ehdr.ymax); + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=ehdr.words-14; + dhdr.props.flags.attributes = 0; + dhdr.symb.s=symbology(ctxcanvas); + + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, num_vertex); + + for (i = 0; i < num_vertex; i++) + { + put_long(ctxcanvas, (long) buffer[i].x); + put_long(ctxcanvas, (long) buffer[i].y); + } +} + +static void putShape(cdCtxCanvas* ctxcanvas, cdPoint *buffer, short num_vertex) +{ + Elm_hdr ehdr; + Disp_hdr dhdr; + short i=0; + + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=6; + + ehdr.words=SIZE_FILLED_SHAPE(num_vertex)-2; + + line_string_bound(buffer, num_vertex, &ehdr.xmin, + &ehdr.ymin,&ehdr.xmax,&ehdr.ymax); + + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=ehdr.words - 14 - 8; /* 8 -> size of attributes */ + dhdr.props.flags.attributes = 1; + dhdr.symb.s=symbology(ctxcanvas); + + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, num_vertex); + + for (i = 0; i < num_vertex; i++) + { + put_long(ctxcanvas, (long) buffer[i].x); + put_long(ctxcanvas, (long) buffer[i].y); + } + + put_word(ctxcanvas, 0x1007); + put_word(ctxcanvas, 65); + put_word(ctxcanvas, 0x802); + put_word(ctxcanvas, 0x0001); + put_word(ctxcanvas, ctxcanvas->color); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); + put_word(ctxcanvas, 0); +} + +static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + short is_fill=0; + + if(mode == CD_FILL && ctxcanvas->fill_type == NOFILL) + mode = CD_CLOSED_LINES; + + if(n > MAX_NUM_VERTEX_PER_POLYLINE) + n = MAX_NUM_VERTEX_PER_POLYLINE; + + /* acerta buffer de pontos */ + if(mode == CD_FILL || mode == CD_CLOSED_LINES) + { + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + } + + /* se fill_type for CONVEX, testa se poligono e' convexo ou concavo */ + if((ctxcanvas->fill_type == CONVEX) && (n > 3) && (mode == CD_FILL)) + { + short signal=0; + short count=0; + long vect=0; + + /* calcula sinal do vetorial entre o primeiro lado e o segundo */ + vect = (poly[1].x - poly[0].x) * + (poly[2].y - poly[1].y) - + (poly[1].y - poly[0].y) * + (poly[2].x - poly[1].x); + + if(vect == 0) + mode = CD_CLOSED_LINES; /* ver se precisa mudar */ + else + { + signal = (short)(vect/abs(vect)); + + for(count=1 ; count< (n-2); count++) + { + vect = (poly[count+1].x - poly[count].x) * + (poly[count+2].y - poly[count+1].y) - + (poly[count+1].y - poly[count].y) * + (poly[count+2].x - poly[count+1].x); + + if(vect == 0) + { + mode=CD_CLOSED_LINES; + break; + } + + if((vect/abs(vect)) != signal) + { + mode=CD_CLOSED_LINES; + break; + } + } + } + } + + /* se tiver fill */ + + if(mode == CD_FILL) + is_fill=1; + + if(n > MAX_NUM_VERTEX) /* tem que usar complex shape ou chain */ + { + short count=0; + short num_whole_elements = n / MAX_NUM_VERTEX; + short num_whole_vertex = num_whole_elements * MAX_NUM_VERTEX; + short rest = n % MAX_NUM_VERTEX; + short is_there_rest = (rest > 0) ? 1 : 0; + unsigned long xmax, xmin, ymax, ymin; + unsigned short size = + SIZE_LINE_STRING(MAX_NUM_VERTEX)*num_whole_elements+ + SIZE_LINE_STRING(rest)*is_there_rest; + + line_string_bound(poly, n, &xmin, &ymin, &xmax, &ymax); + + if(mode == CD_OPEN_LINES) + startComplexChain(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)), + size, xmin, ymin, xmax, ymax); + else + startComplexShape(ctxcanvas, (unsigned short) (num_whole_elements+((rest > 0) ? 1 : 0)), + is_fill, size, xmin, ymin, xmax, ymax); + + for(count=0;count < num_whole_vertex; count+=MAX_NUM_VERTEX, n-=MAX_NUM_VERTEX) + putLineString(ctxcanvas, &poly[count], MAX_NUM_VERTEX); + + if(rest) + putLineString(ctxcanvas, &poly[num_whole_vertex],n); + + endComplexElement(ctxcanvas); + } + else + { + if(is_fill) + putShape(ctxcanvas, poly, n); + else + putLineString(ctxcanvas, poly, n); + } +} + +/************** + * attributes * + **************/ + +static int cdlinestyle (cdCtxCanvas* ctxcanvas, int style) +{ + switch(style) + { + case CD_CONTINUOUS: + ctxcanvas->style = 0; + break; + + case CD_DASHED: + ctxcanvas->style = 3; + break; + + case CD_DOTTED: + ctxcanvas->style = 1; + break; + + case CD_DASH_DOT: + ctxcanvas->style = 4; + break; + + case CD_DASH_DOT_DOT: + ctxcanvas->style = 6; + break; + } + + return style; +} + +static int cdlinewidth (cdCtxCanvas* ctxcanvas, int width) +{ + (void)ctxcanvas; + width = width & 31; + return width; +} + +static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size) +{ + (void)style; + ctxcanvas->tl = (long)(cdGetFontSizePoints(ctxcanvas->canvas, size)/4)*3; + + if (cdStrEqualNoCase(type_face, "Courier")) + ctxcanvas->typeface_index=1; + else if (cdStrEqualNoCase(type_face, "Times")) + ctxcanvas->typeface_index=2; + else if (cdStrEqualNoCase(type_face, "Helvetica")) + ctxcanvas->typeface_index=3; + else if (cdStrEqualNoCase(type_face, "System")) + ctxcanvas->typeface_index=0; + else + return 0; + + return 1; +} + +static void cdgetfontdim (cdCtxCanvas* ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + int size_pixel; + + if(max_width) + { + int a=0; + *max_width=0; + + while(fontsizes[ctxcanvas->typeface_index][a]) + { + if(fontsizes[ctxcanvas->typeface_index][a] > *max_width) + *max_width = fontsizes[ctxcanvas->typeface_index][a]; + a++; + } + } + + size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size); + + if(height) *height = (size_pixel*3)/2; + if(ascent) *ascent = size_pixel; + if(descent) *descent = size_pixel/2; +} + +static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height) +{ + int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size); + if(height) *height = size_pixel + get_descent(s, len, size_pixel); + if(width) *width = gettextwidth(ctxcanvas, s, len, size_pixel); +} + +static int cdtextalignment (cdCtxCanvas* ctxcanvas, int alignment) +{ + ctxcanvas->is_base = 0; + + /* DGN guarda posicao do texto em relacao ao ponto */ + + switch(alignment) + { + case CD_NORTH: + ctxcanvas->alignment = 8; /* center-bottom */ + break; + + case CD_SOUTH: + ctxcanvas->alignment = 6; /* center-top */ + break; + + case CD_EAST: + ctxcanvas->alignment = 1; /* left-center */ + break; + + case CD_WEST: + ctxcanvas->alignment = 13; /* right-center */ + break; + + case CD_NORTH_EAST: + ctxcanvas->alignment = 2; /* left-bottom */ + break; + + case CD_NORTH_WEST: + ctxcanvas->alignment = 14; /* right-bottom */ + break; + + case CD_SOUTH_EAST: + ctxcanvas->alignment = 0; /* left-top */ + break; + + case CD_SOUTH_WEST: + ctxcanvas->alignment = 12; /* right-top */ + break; + + case CD_CENTER: + ctxcanvas->alignment = 7; /* center-center */ + break; + + case CD_BASE_LEFT: + ctxcanvas->alignment = 13; /* right-center */ + ctxcanvas->is_base=1; + break; + + case CD_BASE_CENTER: + ctxcanvas->alignment = 7; /* center-center */ + ctxcanvas->is_base=1; + break; + + case CD_BASE_RIGHT: + ctxcanvas->alignment = 1; /* left-center */ + ctxcanvas->is_base=1; + break; + } + + return alignment; +} + +/******************************************************/ +/* color */ +/******************************************************/ + +static void cdpalette (cdCtxCanvas* ctxcanvas, int n, const long int *palette, int mode) +{ + int c=0; + + IGNORE(mode); + + for(c=0; c < n; c++) + ctxcanvas->colortable[c] = *palette++; + + ctxcanvas->num_colors = n; +} + +static long int cdforeground (cdCtxCanvas* ctxcanvas, long int color) +{ + ctxcanvas->color = getclosestColor(ctxcanvas, color); + return color; +} + +/******************************************************/ +/* client images */ +/******************************************************/ + +static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, + const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i=0,j=0, remainder=iw%2, total_colors; + int *ix=NULL,*iy=NULL; + Elm_hdr ehdr; + Disp_hdr dhdr; + unsigned char map_colors[256]; + + + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=87; + ehdr.words=39; + ehdr.xmin=x; + ehdr.xmax=x+w; + ehdr.ymin=y; + ehdr.ymax=y+h; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=25; + dhdr.symb.s=0; + + putDisplayHeader(ctxcanvas, &dhdr); + + /* description of the element */ + put_long(ctxcanvas, 21+(23+w/2+w%2)*h); /* total length of cell */ + put_word(ctxcanvas, 0x0714); /* raster flags */ + put_word(ctxcanvas, 0x0100); /* background e foreground colors + (nao usados) */ + put_word(ctxcanvas, w); /* largura da imagem em pixels */ + put_word(ctxcanvas, h); /* altura da imagem em pixel */ + put_long(ctxcanvas, 0); /* resevado */ + put_as_double(ctxcanvas, 0); /* resolution (nao usado) */ + + put_word(ctxcanvas, 0x4080); /* scale */ + put_long(ctxcanvas, 0); + put_word(ctxcanvas, 0); + + put_long(ctxcanvas, x); /* origem */ + put_long(ctxcanvas, y+h); + put_long(ctxcanvas, 0); + + put_word(ctxcanvas, 0); /* no de vertices */ + + ctxcanvas->is_complex = 1; /* elemento complexo */ + + /* obtem o maior indice usado na imagem */ + + total_colors = 0; + for (i = 0; i < iw*ih; i++) + { + if (index[i] > total_colors) + total_colors = index[i]; + } + total_colors++; + + /* cria tabela para acelerar match de cor na palette */ + + for (i = 0; i < total_colors; i++) + { + map_colors[i] = (unsigned char)getclosestColor(ctxcanvas, colors[i]); + } + + /** salva dados da imagem **/ + + /* calcula stretch */ + + ix = cdGetZoomTable(w, xmax-xmin+1, xmin); + iy = cdGetZoomTable(h, ymax-ymin+1, ymin); + + for(i=h-1; i >= 0; i--) + { + /* raster header element */ + ehdr.type.flags.level=ctxcanvas->level; + ehdr.type.flags.type=88; + ehdr.words=21+w/2+remainder; + + putElementHeader(ctxcanvas, &ehdr); + + /* Display Header */ + dhdr.attindx=7+w/2+remainder; + dhdr.symb.s=0; + putDisplayHeader(ctxcanvas, &dhdr); + + put_word(ctxcanvas, 0x0714); /* raster flags */ + put_word(ctxcanvas, 0x0100); /* background e foreground + colors (nao usados) */ + + put_word(ctxcanvas, 0); /* x offset da origem */ + put_word(ctxcanvas, i); /* y offset */ + put_word(ctxcanvas, w); /* numero de pixels neste elemento */ + + for(j=0; j < w; j++) + put_byte(ctxcanvas, map_colors[index[(iy[i])*iw + ix[j]]]); + + if(remainder) put_byte(ctxcanvas, 0); + } + + ctxcanvas->is_complex = 0; + + free(ix); /* libera memoria alocada */ + free(iy); +} + +/******************************************************/ +/* server images */ +/******************************************************/ + +static void cdpixel (cdCtxCanvas* ctxcanvas, int x, int y, long int color) +{ + long old_color = cdforeground(ctxcanvas, color); + int old_linestyle = cdlinestyle(ctxcanvas, CD_CONTINUOUS); + int old_linewidth = cdlinewidth(ctxcanvas, 1); + + cdline(ctxcanvas, x,y,x,y); + + cdforeground(ctxcanvas, old_color); + cdlinestyle(ctxcanvas, old_linestyle); + cdlinewidth(ctxcanvas, old_linewidth); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas *ctxcanvas; + char* strdata = (char*)data; + char words[4][256]; + char filename[10240] = ""; + char seedfile[10240] = ""; + int count = 0; + double res = 0; + + if (!data) return; + + /* separa palavras da expressao, que e' na forma + "filename [mm_wxmm_h] [res] [-f] [-sseedfile]" */ + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata, "%s %s %s %s", words[0], words[1], words[2], words[3]); + + if(!strlen(filename)) /* se nao pegou filename */ + return; + + ctxcanvas = (cdCtxCanvas *) malloc(sizeof(cdCtxCanvas)); + + /* tenta criar arquivo DGN */ + + if((ctxcanvas->file = fopen (filename, "wb"))==NULL) + { + free(ctxcanvas); + return; + } + + /* verifica se foi passado tamanho do canvas em mm. Se foi, + extrai-o da string */ + + if(sscanf(words[0], "%lgx%lg", + &canvas->w_mm, &canvas->h_mm) == 2) + { + count++; /* incrementa contador de palavras */ + + if(canvas->w_mm == 0 || canvas->h_mm == 0) + { + fclose(ctxcanvas->file); + free(ctxcanvas); + return; + } + } + else + canvas->w_mm = canvas->h_mm = 0; + + /* Verifica se foi passada resolucao */ + + if(sscanf(words[count], "%lg", &res) == 1) + { + count++; /* incrementa contador de palavras */ + + if(res <= 0) /* verifica validade da resolucao */ + { + fclose(ctxcanvas->file); + free(ctxcanvas); + return; + } + } + else + res = 3.78; + + /* se tamanho em milimetros nao tiver sido inicializado, + usa como default o tamanho maximo em pixels para fazer as + contas + */ + + if (canvas->w_mm == 0 || canvas->h_mm == 0) + { + canvas->w = INT_MAX; + canvas->h = INT_MAX; + + canvas->w_mm = canvas->w / res; + canvas->h_mm = canvas->h / res; + } + else + { + canvas->w = (long) (canvas->w_mm * res); + canvas->h = (long) (canvas->h_mm * res); + } + + canvas->xres = res; + canvas->yres = res; + canvas->bpp = 8; + + /* verifica se usuario que alterar metodo de fill */ + + if (strcmp(words[count], "-f")==0) + { + ctxcanvas->fill_type = CONVEX; + count++; + } + else + ctxcanvas->fill_type = NORMAL; + + /* se tiver passado seedfile como argumento */ + if(sscanf(words[count], "-s%s", seedfile) == 1) + { + FILE *seed=NULL; + char *cd_dir = getenv("CDDIR"); + static char newfilename[512]; + + if(cd_dir == NULL) + cd_dir = "."; + + sprintf(newfilename, "%s/%s", cd_dir, seedfile); + + count++; + + /* testa concatenando com variavel de ambiente */ + + if((seed = fopen (newfilename, "rb"))==NULL) + { + /* tenta abrir usando string passada pelo usuario + diretamente */ + + if((seed = fopen (seedfile, "rb"))==NULL) + { + fclose(ctxcanvas->file); + free(ctxcanvas); + return; + } + } + + /* concatena seed */ + + fseek(seed, 0, SEEK_SET); + fseek(ctxcanvas->file, 0, SEEK_SET); + + ctxcanvas->bytes=0; + dgn_copy(seed, ctxcanvas); + fclose(seed); + } + + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + /* config */ + + ctxcanvas->level = 1; + + /** valores default do contexto sao setados **/ + + /* texto */ + + ctxcanvas->alignment = 12; + ctxcanvas->is_base = 1; + ctxcanvas->typeface_index = 0; + ctxcanvas->tl=12; + + /* cores */ + + memset(ctxcanvas->colortable, 0, 1024); + ctxcanvas->colortable[0] = CD_BLACK; + ctxcanvas->num_colors = 1; + + /* atributos */ + + ctxcanvas->color = 1; + ctxcanvas->style = 0; + + /* DGN */ + + ctxcanvas->is_complex=0; +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxText = cdtext; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPutImageRectMap = cdputimagerectmap; + + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxFont = cdfont; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxPalette = cdpalette; + canvas->cxForeground = cdforeground; + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxDeactivate = cddeactivate; +} + +/******************************************************/ + +static cdContext cdDGNContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | + CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_RECT | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | + CD_CAP_IMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | + CD_CAP_HATCH | CD_CAP_STIPPLE | CD_CAP_PATTERN | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | + CD_CAP_FPRIMTIVES | CD_CAP_TEXTORIENTATION), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextDGN(void) +{ + return &cdDGNContext; +} + + diff --git a/cd/src/drv/cddxf.c b/cd/src/drv/cddxf.c new file mode 100755 index 0000000..b4dc875 --- /dev/null +++ b/cd/src/drv/cddxf.c @@ -0,0 +1,1188 @@ +/** \file + * \brief DXF driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include "cd.h" +#include "cd_private.h" +#include "cddxf.h" + + +#ifndef ignore +#define ignore(x) (void)x +#endif + +#ifndef max +#define max(x, y) ((x > y)? x : y) +#endif + +#ifndef min +#define min(x, y) ((x < y)? x : y) +#endif + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + FILE *file; /* pointer to file */ + int layer; /* layer */ + + int tf; /* text font */ + double th; /* text height (in points) */ + int toa; /* text oblique angle (for italics) */ + int tha, tva; /* text horizontal and vertical alignment */ + + int fgcolor; /* foreground AutoCAD palette color */ + + int lt; /* line type */ + double lw; /* line width (in milimeters) */ +}; + + +static void wnamline (cdCtxCanvas* ctxcanvas, int t) /* write name of a line */ +{ + + static char *line[] = + {"CONTINUOUS", + "DASHED", + "HIDDEN", + "CENTER", + "PHANTOM", + "DOT", + "DASHDOT", + "BORDER", + "DIVIDE"}; + +/* + AutoCAD line styles ( see acad.lin ): + + 0 CONTINUOUS ____________________________________________ + 1 DASHED __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ + 2 HIDDEN _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + 3 CENTER ____ _ ____ _ ____ _ ____ _ ____ _ ____ _ __ + 4 PHANTOM _____ _ _ _____ _ _ _____ _ _ _____ _ _ ____ + 5 DOT ............................................ + 6 DASHDOT __ . __ . __ . __ . __ . __ . __ . __ . __ . + 7 BORDER __ __ . __ __ . __ __ . __ __ . __ __ . __ _ + 8 DIVIDE __ . . __ . . __ . . __ . . __ . . __ . . __ + +*/ + + fprintf (ctxcanvas->file, "%s\n", line[t]); +} + + +static void wnamfont (cdCtxCanvas *ctxcanvas, int t) /* write name of a font */ +{ + static char *font[] = + { + "STANDARD", + "ROMAN", + "ROMAN_BOLD", + "ROMANTIC", + "ROMANTIC_BOLD", + "SANSSERIF", + "SANSSERIF_BOLD", + }; +/* + CD Fonts / Style AutoCAD Fonts + ------------------------------------------------------------------- + CD_SYSTEM 0 STANDARD + CD_COURIER / CD_PLAIN 1 ROMAN + CD_COURIER / CD_BOLD 2 ROMAN_BOLD + CD_COURIER / CD_ITALIC 1 ROMAN (ctxcanvas->toa = 15) + CD_COURIER / CD_BOLD_ITALIC 2 ROMAN_BOLD (ctxcanvas->toa = 15) + CD_TIMES_ROMAN / CD_PLAIN 3 ROMANTIC + CD_TIMES_ROMAN / CD_BOLD 4 ROMANTIC_BOLD + CD_TIMES_ROMAN / CD_ITALIC 3 ROMANTIC (ctxcanvas->toa = 15) + CD_TIMES_ROMAN / CD_BOLD_ITALIC 4 ROMANTIC_BOLD (ctxcanvas->toa = 15) + CD_HELVETICA / CD_PLAIN 5 SANSSERIF + CD_HELVETICA / CD_BOLD 6 SANSSERIF_BOLD + CD_HELVETICA / CD_ITALIC 5 SANSSERIF (ctxcanvas->toa = 15) + CD_HELVETICA / CD_BOLD_ITALIC 6 SANSSERIF_BOLD(ctxcanvas->toa = 15) +*/ + + fprintf (ctxcanvas->file, "%s\n", font[t]); +} + + +static void writepoly (cdCtxCanvas *ctxcanvas, cdPoint *poly, int nv) /* write polygon */ +{ + int i; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "POLYLINE\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + + fprintf ( ctxcanvas->file, "6\n" ); + wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */ + + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); + fprintf ( ctxcanvas->file, "66\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "40\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "41\n" ); /* entire polygon line width */ + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres ); + for ( i=0; ifile, "0\n" ); + fprintf ( ctxcanvas->file, "VERTEX\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres ); + } + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "SEQEND\n" ); +} + +static void writepolyf (cdCtxCanvas *ctxcanvas, cdfPoint *poly, int nv) /* write polygon */ +{ + int i; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "POLYLINE\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + + fprintf ( ctxcanvas->file, "6\n" ); + wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */ + + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); + fprintf ( ctxcanvas->file, "66\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "40\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "41\n" ); /* entire polygon line width */ + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw/ctxcanvas->canvas->xres ); + for ( i=0; ifile, "0\n" ); + fprintf ( ctxcanvas->file, "VERTEX\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].x/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "%f\n", poly[i].y/ctxcanvas->canvas->xres ); + } + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "SEQEND\n" ); +} + +static void deflines (cdCtxCanvas *ctxcanvas) /* define lines */ +{ + int i, j; + static char *line[] = + {"Solid line", + "Dashed line", + "Hidden line", + "Center line", + "Phantom line", + "Dot line", + "Dashdot line", + "Border line", + "Divide Line"}; + +#define TABSIZE (sizeof(tab)/sizeof(tab[0])) + + static int tab[][8] = + { + { 0, 0, 0 , 0, 0, 0, 0, 0 }, + { 2, 15, 10, -5, 0, 0, 0, 0 }, + { 2, 10, 5 , -5, 0, 0, 0, 0 }, + { 4, 35, 20, -5, 5, -5, 0, 0 }, + { 6, 50, 25, -5, 5, -5, 5, -5 }, + { 2, 5, 0 , -5, 0, 0, 0, 0 }, + { 4, 20, 10, -5, 0, -5, 0, 0 }, + { 6, 35, 10, -5, 10, -5, 0, -5 }, + { 6, 25, 10, -5, 0, -5, 0, -5 } + }; + + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "TABLE\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "LTYPE\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "5\n"); + for (j = 0; j < TABSIZE; j++) + { + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "LTYPE\n"); + fprintf (ctxcanvas->file, "2\n"); + + wnamline (ctxcanvas, j); /* line style */ + + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "64\n"); + fprintf (ctxcanvas->file, "3\n"); + fprintf (ctxcanvas->file, "%s\n", line[j]); /* line style */ + fprintf (ctxcanvas->file, "72\n"); + fprintf (ctxcanvas->file, "65\n"); + fprintf (ctxcanvas->file, "73\n"); + fprintf (ctxcanvas->file, "%d\n", tab[j][0]); /* number of parameters */ + fprintf (ctxcanvas->file, "40\n"); + fprintf (ctxcanvas->file, "%d\n", tab[j][1]); + for (i = 2; i < 2 + tab[j][0]; i++) + { + fprintf (ctxcanvas->file, "49\n"); + fprintf (ctxcanvas->file, "%d\n", tab[j][i]); /* parameters */ + } + } + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "ENDTAB\n"); +} + + +static void deffonts (cdCtxCanvas *ctxcanvas) /* define fonts */ +{ + int i; + static char *font[] = + { + "romanc.shx" , + "romant.shx" , + "rom_____.pfb", + "romb____.pfb", + "sas_____.pfb", + "sasb____.pfb" + }; + + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "TABLE\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "STYLE\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "5\n"); + for (i = 1; i < 7; i++) + { + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "STYLE\n"); + fprintf (ctxcanvas->file, "2\n"); + + wnamfont (ctxcanvas, i); /* font style name */ + + fprintf (ctxcanvas->file, "3\n"); + fprintf (ctxcanvas->file, "%s\n", font[i-1]); /* font style file */ + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "64\n"); + fprintf (ctxcanvas->file, "71\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "40\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "41\n"); + fprintf (ctxcanvas->file, "1\n"); + fprintf (ctxcanvas->file, "42\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "50\n"); + fprintf (ctxcanvas->file, "0\n"); + } + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "ENDTAB\n"); +} + +static void cddeactivate (cdCtxCanvas *ctxcanvas) +{ + fflush (ctxcanvas->file); /* flush file */ +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "ENDSEC\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "EOF\n"); /* fputs eof */ + fprintf (ctxcanvas->file, " \n"); + + fflush (ctxcanvas->file); /* flush file */ + fclose (ctxcanvas->file); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free (ctxcanvas); +} + +static void cdflush (cdCtxCanvas *ctxcanvas) +{ + ctxcanvas->layer++; +} + +/*==========================================================================*/ +/* Primitives */ +/*==========================================================================*/ +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + if (mode == CD_CLOSED_LINES || mode == CD_FILL) + { + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + } + + writepoly (ctxcanvas, poly, n); /* write polygon */ +} + +static void cdline (cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + cdPoint line[2]; /* uses new array of points to avoid */ + + line[0].x = x1; /* starting point */ + line[0].y = y1; + line[1].x = x2; /* ending point */ + line[1].y = y2; + writepoly (ctxcanvas, line, 2); /* draw line as a polygon */ +} + +static void cdboxrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdPoint rect[5]; /* uses new array of points to avoid */ + + rect[0].x = xmin; + rect[0].y = ymin; + rect[1].x = xmin; + rect[1].y = ymax; + rect[2].x = xmax; /* box edges */ + rect[2].y = ymax; + rect[3].x = xmax; + rect[3].y = ymin; + rect[4].x = xmin; + rect[4].y = ymin; + writepoly (ctxcanvas, rect, 5); /* draw box as a polygon */ +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + if (mode == CD_CLOSED_LINES || mode == CD_FILL) + { + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + } + + writepolyf (ctxcanvas, poly, n); /* write polygon */ +} + +static void cdfline (cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + cdfPoint line[2]; /* uses new array of points to avoid */ + + line[0].x = x1; /* starting point */ + line[0].y = y1; + line[1].x = x2; /* ending point */ + line[1].y = y2; + writepolyf (ctxcanvas, line, 2); /* draw line as a polygon */ +} + +static void cdfboxrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + cdfPoint rect[5]; /* uses new array of points to avoid */ + + rect[0].x = xmin; + rect[0].y = ymin; + rect[1].x = xmin; + rect[1].y = ymax; + rect[2].x = xmax; /* box edges */ + rect[2].y = ymax; + rect[3].x = xmax; + rect[3].y = ymin; + rect[4].x = xmin; + rect[4].y = ymin; + writepolyf (ctxcanvas, rect, 5); /* draw box as a polygon */ +} + +/*--------------------------------------------------------------------------*/ +/* gives radius of the circle most resembling elliptic arc at angle t */ +/*--------------------------------------------------------------------------*/ +static double calc_radius (double a, double b, double t) +{ + return (pow ((a*a*sin(t)*sin(t) + b*b*cos(t)*cos(t)), 1.5))/(a*b); +} + +/*--------------------------------------------------------------------------*/ +/* calculates bulge for a given circular arc segment (between points p1 and */ +/* p2, with radius r). Bulge is the tangent of 1/4 the angle theta of the */ +/* arc segment(a bulge of 1 is a semicircle, which has an angle of 180 deg) */ +/*--------------------------------------------------------------------------*/ +static double calc_bulge (double a, double b, double t1, double t2) +{ + cdfPoint p1, p2; /* initial and ending arc points */ + double r; /* radius most resembling arc at angle (t1+t2)/2 */ + double theta; /* angle of circular arc segment */ + double sin_theta; /* sine of theta */ + double dist_x; /* distance between two points along the x axis */ + double dist_y; /* distance between two points along the y axis */ + double halfdist; /* half distance between two points */ + + p1.x = a*cos(t1); + p1.y = b*sin(t1); + p2.x = a*cos(t2); + p2.y = b*sin(t2); + r = calc_radius (a, b, (t1+t2)/2); + + dist_x = p2.x - p1.x; + dist_y = p2.y - p1.y; + halfdist = (sqrt (dist_x*dist_x + dist_y*dist_y))/2; + sin_theta = halfdist/r; + if (sin_theta > 1) sin_theta = 1; + theta = 2*asin(sin_theta); + + return tan(theta/4); +} + +static void writevertex (cdCtxCanvas *ctxcanvas, int xc, int yc, double a, double b, double t, double bulge) +{ + cdfPoint p; + p.x = (xc + a*cos(t))/ctxcanvas->canvas->xres; + p.y = (yc + b*sin(t))/ctxcanvas->canvas->xres; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "VERTEX\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", p.x ); + fprintf ( ctxcanvas->file, "20\n" ); /* vertex coordinates */ + fprintf ( ctxcanvas->file, "%f\n", p.y ); + fprintf ( ctxcanvas->file, "42\n" ); /* bulge from this vertex */ + fprintf ( ctxcanvas->file, "%f\n", bulge ); /* to the next one */ +} + +static void cdarc (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + double bulge; /* bulge is the tangent of 1/4 the angle for a given */ + /* circle arc segment (a bulge of 1 is a semicircle) */ + double t; /* current arc angle being calculated */ + double t1; /* a1 in radians */ + double t2; /* a2 in radians */ + double a; /* half horizontal axis */ + double b; /* half vertical axis */ + double seg_angle; /* angle of every arc segment */ + double diff; /* angle between a1 and a2 */ + int nseg; /* number of arc segments */ + int i; + + a = w/2; + b = h/2; + t1 = a1*CD_DEG2RAD; /* a1 in radians */ + t2 = a2*CD_DEG2RAD; /* a2 in radians */ + diff = fabs(a2 - a1); + nseg = cdRound(diff)/(360/32); /* 32 segments in closed ellipse */ + nseg = max(nseg, 1); + seg_angle = (t2-t1)/nseg; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "POLYLINE\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "6\n" ); + wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->fgcolor ); /* color */ + fprintf ( ctxcanvas->file, "66\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "70\n" ); + fprintf ( ctxcanvas->file, "128\n" ); + fprintf ( ctxcanvas->file, "40\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw ); + fprintf ( ctxcanvas->file, "41\n" ); /* entire arc line width */ + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw ); + + for (i=0, t=t1; ifile, "0\n" ); + fprintf ( ctxcanvas->file, "SEQEND\n" ); +} + +static void cdsector (cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + double bulge; /* bulge is the tangent of 1/4 the angle for a given */ + /* circle arc segment (a bulge of 1 is a semicircle) */ + double t; /* current arc angle being calculated */ + double t1; /* a1 in radians */ + double t2; /* a2 in radians */ + double a; /* half horizontal axis */ + double b; /* half vertical axis */ + double seg_angle; /* angle of every arc segment */ + double diff; /* angle between a1 and a2 */ + int nseg; /* number of arc segments */ + int i; + + a = w/2; + b = h/2; + t1 = a1*CD_DEG2RAD; /* a1 in radians */ + t2 = a2*CD_DEG2RAD; /* a2 in radians */ + diff = fabs(a2 - a1); + nseg = cdRound(diff)/(360/32); /* 32 segments in closed ellipse */ + nseg = max(nseg, 1); + seg_angle = (t2-t1)/nseg; + + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "POLYLINE\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "6\n" ); + wnamline( ctxcanvas, ctxcanvas->lt ); /* line type */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->fgcolor ); /* color */ + fprintf ( ctxcanvas->file, "66\n" ); + fprintf ( ctxcanvas->file, "1\n" ); + fprintf ( ctxcanvas->file, "70\n" ); + fprintf ( ctxcanvas->file, "128\n" ); + fprintf ( ctxcanvas->file, "40\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw ); + fprintf ( ctxcanvas->file, "41\n" ); /* entire arc line width */ + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->lw ); + + if ((a2-a1) != 360) + writevertex (ctxcanvas, xc, yc, 0, 0, 0, 0); /* center */ + for (i=0, t=t1; ifile, " 0\n" ); + fprintf ( ctxcanvas->file, "SEQEND\n" ); +} + +static void cdtext (cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "TEXT\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "7\n" ); + wnamfont( ctxcanvas, ctxcanvas->tf ); /* current font */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); /* color */ + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* current position */ + fprintf ( ctxcanvas->file, "20\n" ); + fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "11\n" ); + fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* alignment point */ + fprintf ( ctxcanvas->file, "21\n" ); + fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres ); + fprintf ( ctxcanvas->file, "40\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->th ); /* text height */ + fprintf ( ctxcanvas->file, "50\n" ); + fprintf ( ctxcanvas->file, "%f\n", ctxcanvas->canvas->text_orientation ); /* text orientation angle */ + fprintf ( ctxcanvas->file, "51\n" ); + fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->toa ); /* text oblique angle */ + fprintf ( ctxcanvas->file, "72\n" ); + fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->tha ); /* text horizontal alignment */ + fprintf ( ctxcanvas->file, "73\n" ); + fprintf ( ctxcanvas->file, "%3d\n", ctxcanvas->tva ); /* text vertical alignment */ + fprintf ( ctxcanvas->file, "1\n" ); + + s = cdStrDupN(s, len); + fprintf ( ctxcanvas->file, "%s\n", s ); /* text */ + free((char*)s); +} + + +/*==========================================================================*/ +/* Attributes */ +/*==========================================================================*/ + +static int cdlinestyle (cdCtxCanvas *ctxcanvas, int style) +{ + switch (style) + { + case CD_CONTINUOUS: + ctxcanvas->lt = 0; + break; + case CD_DASHED: + ctxcanvas->lt = 1; + break; + case CD_DOTTED: + ctxcanvas->lt = 5; + break; + case CD_DASH_DOT: + ctxcanvas->lt = 6; + break; + case CD_DASH_DOT_DOT: + ctxcanvas->lt = 8; + break; + } + + return style; +} + +static int cdlinewidth (cdCtxCanvas *ctxcanvas, int width) +{ + ctxcanvas->lw = width/ctxcanvas->canvas->xres; + return width; +} + +static int cdfont (cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + /* obs: DXF's text height (ctxcanvas->th) corresponds to CD ascent */ + + if (cdStrEqualNoCase(type_face, "System")) + { + ctxcanvas->tf = 0; + ctxcanvas->toa = 0; + ctxcanvas->th = 0.75; + } + else if (cdStrEqualNoCase(type_face, "Courier")) + { + switch (style&3) + { + case CD_PLAIN: + ctxcanvas->tf = 1; + ctxcanvas->toa = 0; + break; + + case CD_BOLD: + ctxcanvas->tf = 2; + ctxcanvas->toa = 0; + break; + + case CD_ITALIC: + ctxcanvas->tf = 1; + ctxcanvas->toa = 15; + break; + + case CD_BOLD_ITALIC: + ctxcanvas->tf = 2; + ctxcanvas->toa = 15; + break; + } + ctxcanvas->th = 0.75; + } + else if (cdStrEqualNoCase(type_face, "Times")) + { + switch (style&3) + { + case CD_PLAIN: + ctxcanvas->tf = 3; + ctxcanvas->toa = 0; + break; + + case CD_BOLD: + ctxcanvas->tf = 4; + ctxcanvas->toa = 0; + break; + + case CD_ITALIC: + ctxcanvas->tf = 3; + ctxcanvas->toa = 15; + break; + + case CD_BOLD_ITALIC: + ctxcanvas->tf = 4; + ctxcanvas->toa = 15; + break; + } + ctxcanvas->th = 1.125; + } + else if (cdStrEqualNoCase(type_face, "Helvetica")) + { + switch (style&3) + { + case CD_PLAIN: + ctxcanvas->tf = 5; + ctxcanvas->toa = 0; + break; + + case CD_BOLD: + ctxcanvas->tf = 6; + ctxcanvas->toa = 0; + break; + + case CD_ITALIC: + ctxcanvas->tf = 5; + ctxcanvas->toa = 15; + break; + + case CD_BOLD_ITALIC: + ctxcanvas->tf = 6; + ctxcanvas->toa = 15; + break; + } + ctxcanvas->th = 1.; + } + else + return 0; + + ctxcanvas->th = ctxcanvas->th * cdGetFontSizePoints(ctxcanvas->canvas, size); + + return 1; +} + +static void cdgetfontdim (cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + double tangent_ta; + double pixel_th; + + tangent_ta = tan(ctxcanvas->toa*CD_DEG2RAD); + pixel_th = (ctxcanvas->th*ctxcanvas->canvas->xres)/CD_MM2PT; /* points to pixels */ + switch (ctxcanvas->tf) + { + case 0: /* STANDARD font (CD_SYSTEM) */ + if (height) *height = cdRound(pixel_th*4/3); + if (ascent) *ascent = _cdRound(pixel_th); + if (descent) *descent = cdRound(pixel_th/3); + if (max_width) *max_width = _cdRound(pixel_th); + break; + + case 1: /* ROMAN fonts (CD_COURIER) */ + case 2: + if (height) *height = cdRound(pixel_th*4/3); + if (ascent) *ascent = _cdRound(pixel_th); + if (descent) *descent = cdRound(pixel_th/3); + if (max_width) *max_width = cdRound((pixel_th*21/20) + tangent_ta*(*ascent)); + break; + + case 3: /* ROMANTIC fonts (CD_TIMES_ROMAN) */ + if (height) *height = cdRound(pixel_th*8/9); + if (ascent) *ascent = cdRound(pixel_th*2/3); + if (descent) *descent = cdRound(pixel_th*2/9); + if (max_width) *max_width = cdRound((pixel_th*14/15) + tangent_ta*(*ascent)); + break; + + case 4: + if (height) *height = cdRound(pixel_th*8/9); + if (ascent) *ascent = cdRound(pixel_th*2/3); + if (descent) *descent = cdRound(pixel_th*2/9); + if (max_width) *max_width = cdRound((pixel_th*29/30) + tangent_ta*(*ascent)); + break; + + case 5: /* SANSSERIF fonts (CD_HELVETICA) */ + case 6: + if (height) *height = _cdRound(pixel_th); + if (ascent) *ascent = cdRound(pixel_th*3/4); + if (descent) *descent = cdRound(pixel_th/4); + if (max_width) *max_width = cdRound((pixel_th*15/16) + tangent_ta*(*ascent)); + break; + } +} + +static void cdgettextsize (cdCtxCanvas *ctxcanvas, const char *s, int len, int *width, int *height) +{ + int i; + double tangent_ta; + double pixel_th; + (void)s; + + i = len; + tangent_ta = tan(ctxcanvas->toa*CD_DEG2RAD); + pixel_th = (ctxcanvas->th*ctxcanvas->canvas->xres)/CD_MM2PT; /* points to pixels */ + + switch (ctxcanvas->tf) /* width return value based on maximum character width */ + { + case 0: /* STANDARD font (CD_SYSTEM) */ + if (height) *height = cdRound(pixel_th*4/3); + if (width) *width = cdRound(pixel_th*i + (pixel_th/3)*(i-1)); + break; + + case 1: /* ROMAN fonts (CD_COURIER) */ + case 2: + if (height) *height = cdRound(pixel_th*4/3); + if (width) *width = cdRound((pixel_th*21/20)*i + (pixel_th/10)*(i-1) + tangent_ta*pixel_th); + break; + + case 3: /* ROMANTIC fonts (CD_TIMES_ROMAN) */ + if (height) *height = cdRound(pixel_th*2/3 + pixel_th*2/9); + if (width) *width = cdRound((pixel_th*14/15)*i + (pixel_th/45)*(i-1) + tangent_ta*pixel_th*2/3); + break; + + case 4: + if (height) *height = cdRound(pixel_th*2/3 + pixel_th*2/9); + if (width) *width = cdRound((pixel_th*29/30)*i + (pixel_th*2/45)*(i-1) + tangent_ta*pixel_th*2/3); + break; + + case 5: /* SANSSERIF fonts (CD_HELVETICA) */ + case 6: + if (height) *height = _cdRound(pixel_th); + if (width) *width = cdRound((pixel_th*15/16)*i + (pixel_th/45)*(i-1) + tangent_ta*pixel_th*3/4); + break; + } +} + +static int cdtextalignment (cdCtxCanvas *ctxcanvas, int alignment) +{ + switch (alignment) /* convert alignment to DXF format */ + { + case CD_BASE_LEFT: + ctxcanvas->tva = 0; + ctxcanvas->tha = 0; + break; + + case CD_BASE_CENTER: + ctxcanvas->tva = 0; + ctxcanvas->tha = 1; + break; + + case CD_BASE_RIGHT: + ctxcanvas->tva = 0; + ctxcanvas->tha = 2; + break; + + case CD_SOUTH_WEST: + ctxcanvas->tva = 1; + ctxcanvas->tha = 0; + break; + + case CD_SOUTH: + ctxcanvas->tva = 1; + ctxcanvas->tha = 1; + break; + + case CD_SOUTH_EAST: + ctxcanvas->tva = 1; + ctxcanvas->tha = 2; + break; + + case CD_WEST: + ctxcanvas->tva = 2; + ctxcanvas->tha = 0; + break; + + case CD_CENTER: + ctxcanvas->tva = 2; + ctxcanvas->tha = 1; + break; + + case CD_EAST: + ctxcanvas->tva = 2; + ctxcanvas->tha = 2; + break; + + case CD_NORTH_WEST: + ctxcanvas->tva = 3; + ctxcanvas->tha = 0; + break; + + case CD_NORTH: + ctxcanvas->tva = 3; + ctxcanvas->tha = 1; + break; + + case CD_NORTH_EAST: + ctxcanvas->tva = 3; + ctxcanvas->tha = 2; + break; + } + + return alignment; +} + +/*==========================================================================*/ +/* Color */ +/*==========================================================================*/ + +static void RGB_to_HSB (unsigned char r, unsigned char g, unsigned char b, + double *hue, double *sat, double *bright) +{ + double maximum; + double minimum; + double delta; + double red = r/255.; /* red, green and blue range from 0 to 1 */ + double green = g/255.; + double blue = b/255.; + + maximum = max(max(red, green), blue); /* stores higher index */ + minimum = min(min(red, green), blue); /* stores lower index */ + delta = maximum - minimum; + + *bright = maximum*100; + *sat = 0; + + if (maximum != 0) /* sat from 0 to 100 */ + *sat = (delta*100)/maximum; + + if (*sat != 0) /* hue from 0 to 359 */ + { + if (red == maximum) *hue = (green - blue)/delta; + if (green == maximum) *hue = 2 + (blue - red)/delta; + if (blue == maximum) *hue = 4 + (red - green)/delta; + *hue *= 60; + if (*hue < 0) *hue += 360; + } + else + *hue = 0; /* color is greyscale (hue is meaningless) */ +} + +static int HSB_to_AutoCAD_Palette (double hue, double sat, double bright) +{ + int index; + int h, s, b; + + if (bright < 17) /* 5 levels of brightness in AutoCAD palette, 6 with */ + { /* black. If bright < 17, index is black (7). */ + index = 7; /* 17 is 100/6 (rounded up) */ + } + else if (sat < 10) /* low saturation makes color tend to */ + { /* grey/white. 6 levels of grey/white in */ + b = (int)floor(bright/14.3)-1;/* palette WITHOUT black. 14.3 is 100/7 */ + index = 250 + b; /* index is grey to white(255 in palette) */ + } + else + { + h = cdRound(hue/15.) + 1; + if (h > 24) h -= 24; /* 15 is 360/24 */ + h *= 10; /* h ranges from 10 to 240 in palette */ + s = (sat < 55) ? 1 : 0; /* s is 'high'(0) or 'low'(1) in palette */ + b = (int)floor(bright/16.7)-1;/* b is 0, 2, 4, 6 or 8 in palette */ + b = 2*(4 - b); /* (from brightest to dimmest) */ + index = h + s + b; /* index is simple sum of h, s and b */ + } + return index; +} + +static int get_palette_index (long int color) /* gives closest palette */ +{ /* index to RGB color */ + unsigned char red, green, blue; + double hue, sat, bright; + + cdDecodeColor (color, &red, &green, &blue); /* AutoCAD palette is */ + RGB_to_HSB (red, green, blue, &hue, &sat, &bright); /* based on HSB model */ + + return HSB_to_AutoCAD_Palette (hue, sat, bright); +} + +static long int cdforeground (cdCtxCanvas *ctxcanvas, long int color) +{ + ctxcanvas->fgcolor = get_palette_index (color); + return color; +} + + +/*==========================================================================*/ +/* Server Images */ +/*==========================================================================*/ + +static void cdpixel (cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + int oldcolor = ctxcanvas->fgcolor; /* put 'color' as current */ + cdforeground (ctxcanvas, color); /* foreground color */ + fprintf ( ctxcanvas->file, "0\n" ); + fprintf ( ctxcanvas->file, "POINT\n" ); + fprintf ( ctxcanvas->file, "8\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->layer); /* current layer */ + fprintf ( ctxcanvas->file, "62\n" ); + fprintf ( ctxcanvas->file, "%d\n", ctxcanvas->fgcolor ); /* color */ + fprintf ( ctxcanvas->file, "10\n" ); + fprintf ( ctxcanvas->file, "%f\n", x/ctxcanvas->canvas->xres ); /* position */ + fprintf ( ctxcanvas->file, " 20\n" ); + fprintf ( ctxcanvas->file, "%f\n", y/ctxcanvas->canvas->xres ); + ctxcanvas->fgcolor = oldcolor; /* retrieve old fgcolor */ +} + +/******************************************************/ + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char filename[10240] = ""; + char* strdata = (char*)data; + cdCtxCanvas *ctxcanvas; + double param1, param2, param3; + + ctxcanvas = (cdCtxCanvas *) malloc (sizeof (cdCtxCanvas)); + + param1 = 0; + param2 = 0; + param3 = 0; + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata, "%lfx%lf %lf", ¶m1, ¶m2, ¶m3); + + ctxcanvas->file = fopen (filename, "w"); + if (ctxcanvas->file == NULL) + { + free(ctxcanvas); + return; + } + + if (!param1) + { + canvas->w_mm = INT_MAX*3.78; + canvas->h_mm = INT_MAX*3.78; + canvas->xres = 3.78; + } + else if (!param2) + { + canvas->w_mm = INT_MAX*param1; + canvas->h_mm = INT_MAX*param1; + canvas->xres = param1; + } + else if (!param3) + { + canvas->w_mm = param1; + canvas->h_mm = param2; + canvas->xres = 3.78; + } + else + { + canvas->w_mm = param1; + canvas->h_mm = param2; + canvas->xres = param3; + } + + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + canvas->bpp = 8; + + canvas->yres = canvas->xres; + + canvas->w = (int)(canvas->w_mm * canvas->xres); + canvas->h = (int)(canvas->h_mm * canvas->yres); + + ctxcanvas->layer = 0; /* reset layer */ + + ctxcanvas->tf = 0; /* text font (0 is STANDARD) */ + ctxcanvas->th = 9; /* text height */ + ctxcanvas->toa = 0; /* text oblique angle */ + ctxcanvas->tva = 0; /* text vertical alignment (0 is baseline) */ + ctxcanvas->tha = 0; /* text horizontal alignment (0 is left) */ + ctxcanvas->fgcolor = 7; /* foreground AutoCAD palette color */ + + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "SECTION\n"); /* header maker */ + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "HEADER\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$LIMCHECK\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "1\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$LIMMIN\n"); + fprintf (ctxcanvas->file, "10\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "20\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$LIMMAX\n"); + fprintf (ctxcanvas->file, "10\n"); + fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->w_mm); + fprintf (ctxcanvas->file, "20\n"); + fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->h_mm); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$EXTMIN\n"); + fprintf (ctxcanvas->file, "10\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "20\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$EXTMAX\n"); + fprintf (ctxcanvas->file, "10\n"); + fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->w_mm); + fprintf (ctxcanvas->file, "20\n"); + fprintf (ctxcanvas->file, "%f\n", ctxcanvas->canvas->h_mm); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$CLAYER\n"); + fprintf (ctxcanvas->file, "8\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$LUNITS\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$LUPREC\n"); + fprintf (ctxcanvas->file, "70\n"); /* precision (resolution dependant) */ + fprintf (ctxcanvas->file, "%d\n", (int)ceil(log10(ctxcanvas->canvas->xres))); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$AUNITS\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$AUPREC\n"); + fprintf (ctxcanvas->file, "70\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "9\n"); + fprintf (ctxcanvas->file, "$TEXTSTYLE\n"); + fprintf (ctxcanvas->file, "7\n"); + fprintf (ctxcanvas->file, "STANDARD\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "ENDSEC\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "SECTION\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "TABLES\n"); + + deflines (ctxcanvas); /* define lines */ + deffonts (ctxcanvas); /* define fonts */ + + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "ENDSEC\n"); + fprintf (ctxcanvas->file, "0\n"); + fprintf (ctxcanvas->file, "SECTION\n"); + fprintf (ctxcanvas->file, "2\n"); + fprintf (ctxcanvas->file, "ENTITIES\n"); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdboxrect; + canvas->cxBox = cdboxrect; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfboxrect; + canvas->cxFBox = cdfboxrect; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxText = cdtext; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxFont = cdfont; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxForeground = cdforeground; + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxDeactivate = cddeactivate; +} + +/******************************************************/ + +static cdContext cdDXFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE | + CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | CD_CAP_CHORD | + CD_CAP_IMAGERGB | CD_CAP_IMAGEMAP | CD_CAP_IMAGESRV | + CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | + CD_CAP_HATCH | CD_CAP_STIPPLE | CD_CAP_PATTERN | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextDXF(void) +{ + return &cdDXFContext; +} + diff --git a/cd/src/drv/cdirgb.c b/cd/src/drv/cdirgb.c new file mode 100755 index 0000000..7e4720c --- /dev/null +++ b/cd/src/drv/cdirgb.c @@ -0,0 +1,2051 @@ +/** \file + * \brief Image RGB Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "sim.h" +#include "cdirgb.h" + + +struct _cdCtxImage +{ + int w, h; + unsigned char* red; /* red color buffer */ + unsigned char* green; /* green color buffer */ + unsigned char* blue; /* blue color buffer */ + unsigned char* alpha; /* alpha color buffer */ +}; + + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + int user_image; /* can not free an user image */ + + unsigned char* red; /* red color buffer */ + unsigned char* green; /* green color buffer */ + unsigned char* blue; /* blue color buffer */ + unsigned char* alpha; /* alpha color buffer */ + unsigned char* clip; /* clipping buffer */ + + unsigned char* clip_region; /* clipping region used during NewRegion */ + + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + cdCanvas* canvas_dbuffer; /* used by the CD_DBUFFERRGB driver */ +}; + +/*******************/ +/* Local functions */ +/*******************/ + +#define _sNormX(_ctxcanvas, _x) (_x < 0? 0: _x < _ctxcanvas->canvas->w? _x: _ctxcanvas->canvas->w-1) +#define _sNormY(_ctxcanvas, _y) (_y < 0? 0: _y < _ctxcanvas->canvas->h? _y: _ctxcanvas->canvas->h-1) + +#define RGB_COMPOSE(_SRC, _SRC_ALPHA, _DST, _TMP_MULTI, _TMP_ALPHA) (unsigned char)(((_SRC_ALPHA)*(_SRC) + (_TMP_MULTI)*(_DST)) / (_TMP_ALPHA)) + +#define RGBA_COLOR_COMBINE(_ctxcanvas, _pdst_red, _pdst_green, _pdst_blue, _pdst_alpha, _src_red, _src_green, _src_blue, _src_alpha) \ +{ \ + unsigned char _tmp_red = 0, _tmp_green = 0, _tmp_blue = 0; \ + \ + if (_pdst_alpha) /* (_pdst_alpha != NULL) */ \ + { \ + if (_src_alpha != 255) /* some transparency */ \ + { \ + if (_src_alpha != 0) /* source not full transparent */ \ + { \ + if (*_pdst_alpha == 0) /* destiny full transparent */ \ + { \ + _tmp_red = _src_red; \ + _tmp_green = _src_green; \ + _tmp_blue = _src_blue; \ + *_pdst_alpha = _src_alpha; \ + } \ + else if (*_pdst_alpha == 255) /* destiny opaque */ \ + { \ + _tmp_red = CD_ALPHA_BLEND(_src_red, *_pdst_red, _src_alpha); \ + _tmp_green = CD_ALPHA_BLEND(_src_green, *_pdst_green, _src_alpha); \ + _tmp_blue = CD_ALPHA_BLEND(_src_blue, *_pdst_blue, _src_alpha); \ + /* *_pdst_alpha is not changed */ \ + } \ + else /* (0<*_pdst_alpha<255 && 0<_src_alpha<255) destiny and source are semi-transparent */ \ + { \ + /* Closed Compositing Formulas for SRC over DST, Colors Not Premultiplied by Alpha: */ \ + int _tmp_multi = *_pdst_alpha * (255 - _src_alpha); \ + int _tmp_alpha = _src_alpha + _tmp_multi; \ + _tmp_red = RGB_COMPOSE(_src_red, _src_alpha, *_pdst_red, _tmp_multi, _tmp_alpha); \ + _tmp_green = RGB_COMPOSE(_src_green, _src_alpha, *_pdst_green, _tmp_multi, _tmp_alpha); \ + _tmp_blue = RGB_COMPOSE(_src_blue, _src_alpha, *_pdst_blue, _tmp_multi, _tmp_alpha); \ + *_pdst_alpha = (unsigned char)(_tmp_alpha / 255); \ + } \ + } \ + else /* (_src_alpha == 0) source full transparent */ \ + { \ + _tmp_red = *_pdst_red; \ + _tmp_green = *_pdst_green; \ + _tmp_blue = *_pdst_blue; \ + /* *_pdst_alpha is not changed */ \ + } \ + } \ + else /* (_src_alpha == 255) source has no alpha = opaque */ \ + { \ + _tmp_red = _src_red; \ + _tmp_green = _src_green; \ + _tmp_blue = _src_blue; \ + *_pdst_alpha = (unsigned char)255; /* set destiny as opaque */ \ + } \ + } \ + else /* (_pdst_alpha == NULL) */ \ + { \ + if (_src_alpha != 255) /* source has some transparency */ \ + { \ + if (_src_alpha != 0) /* source semi-transparent */ \ + { \ + _tmp_red = CD_ALPHA_BLEND(_src_red, *_pdst_red, _src_alpha); \ + _tmp_green = CD_ALPHA_BLEND(_src_green, *_pdst_green, _src_alpha); \ + _tmp_blue = CD_ALPHA_BLEND(_src_blue, *_pdst_blue, _src_alpha); \ + } \ + else /* (_src_alpha == 0) source full transparent */ \ + { \ + _tmp_red = *_pdst_red; \ + _tmp_green = *_pdst_green; \ + _tmp_blue = *_pdst_blue; \ + } \ + } \ + else /* (_src_alpha == 255) source has no alpha = opaque */ \ + { \ + _tmp_red = _src_red; \ + _tmp_green = _src_green; \ + _tmp_blue = _src_blue; \ + } \ + } \ + \ + switch (_ctxcanvas->canvas->write_mode) \ + { \ + case CD_REPLACE: \ + *_pdst_red = _tmp_red; \ + *_pdst_green = _tmp_green; \ + *_pdst_blue = _tmp_blue; \ + break; \ + case CD_XOR: \ + *_pdst_red ^= _tmp_red; \ + *_pdst_green ^= _tmp_green; \ + *_pdst_blue ^= _tmp_blue; \ + break; \ + case CD_NOT_XOR: \ + *_pdst_red = (unsigned char)~(_tmp_red ^ *_pdst_red); \ + *_pdst_green = (unsigned char)~(_tmp_green ^ *_pdst_green); \ + *_pdst_blue = (unsigned char)~(_tmp_blue ^ *_pdst_blue); \ + break; \ + } \ +} + +static void sCombineRGBColor(cdCtxCanvas* ctxcanvas, int offset, long color) +{ + unsigned char *dr = ctxcanvas->red + offset; + unsigned char *dg = ctxcanvas->green + offset; + unsigned char *db = ctxcanvas->blue + offset; + unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL; + unsigned char *clip = ctxcanvas->clip + offset; + + unsigned char sr = cdRed(color); + unsigned char sg = cdGreen(color); + unsigned char sb = cdBlue(color); + unsigned char sa = cdAlpha(color); + + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, sr, sg, sb, sa); +} + +static void sCombineRGB(cdCtxCanvas* ctxcanvas, int offset, unsigned char sr, unsigned char sg, unsigned char sb, unsigned char sa) +{ + unsigned char *dr = ctxcanvas->red + offset; + unsigned char *dg = ctxcanvas->green + offset; + unsigned char *db = ctxcanvas->blue + offset; + unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL; + unsigned char *clip = ctxcanvas->clip + offset; + + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, sr, sg, sb, sa); +} + +static void sCombineRGBLine(cdCtxCanvas* ctxcanvas, int offset, const unsigned char *sr, const unsigned char *sg, const unsigned char *sb, int size) +{ + int c; + unsigned char *dr = ctxcanvas->red + offset; + unsigned char *dg = ctxcanvas->green + offset; + unsigned char *db = ctxcanvas->blue + offset; + unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL; + unsigned char *clip = ctxcanvas->clip + offset; + unsigned char src_a = 255; + + if (size > 0) + { + for (c = 0; c < size; c++) + { + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, src_a); + dr++; dg++; db++; clip++; + sr++; sg++; sb++; + if (da) da++; + } + } + else + { + size *= -1; + for (c = 0; c < size; c++) + { + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, src_a); + dr--; dg--; db--; clip--; + sr--; sg--; sb--; + if (da) da--; + } + } +} + +static void sCombineRGBALine(cdCtxCanvas* ctxcanvas, int offset, const unsigned char *sr, const unsigned char *sg, const unsigned char *sb, const unsigned char *sa, int size) +{ + int c; + unsigned char *dr = ctxcanvas->red + offset; + unsigned char *dg = ctxcanvas->green + offset; + unsigned char *db = ctxcanvas->blue + offset; + unsigned char *da = ctxcanvas->alpha? ctxcanvas->alpha + offset: NULL; + unsigned char *clip = ctxcanvas->clip + offset; + + if (size > 0) + { + for (c = 0; c < size; c++) + { + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, *sa); + dr++; dg++; db++; clip++; + sr++; sg++; sb++; sa++; + if (da) da++; + } + } + else + { + size *= -1; + for (c = 0; c < size; c++) + { + if (*clip) + RGBA_COLOR_COMBINE(ctxcanvas, dr, dg, db, da, *sr, *sg, *sb, *sa); + dr--; dg--; db--; clip--; + sr--; sg--; sb--; sa--; + if (da) da--; + } + } +} + +static void irgbSolidLine(cdCanvas* canvas, int xmin, int y, int xmax) +{ + int x; + unsigned long offset = y * canvas->w; + + if (y < 0) + return; + + if (y > (canvas->h-1)) + return; + + if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */ + xmin = 0; /* so clipa em x */ + if (xmax > (canvas->w-1)) + xmax = (canvas->w-1); + + for (x = xmin; x <= xmax; x++) + sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground); +} + +static void irgbPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern) +{ + int x, i; + unsigned long offset = y * canvas->w; + + if (y < 0 || y > (canvas->h-1)) + return; + + if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */ + xmin = 0; /* so clipa em x */ + if (xmax > (canvas->w-1)) + xmax = (canvas->w-1); + + i = xmin % pw; + + for (x = xmin; x <= xmax; x++,i++) + { + if (i == pw) + i = 0; + + sCombineRGBColor(canvas->ctxcanvas, offset + x, pattern[i]); + } +} + +static void irgbStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple) +{ + int x,i; + unsigned long offset = y * canvas->w; + + if (y < 0 || y > (canvas->h-1)) + return; + + if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */ + xmin = 0; /* so clipa em x */ + if (xmax > (canvas->w-1)) + xmax = (canvas->w-1); + + i = xmin % pw; + + for (x = xmin; x <= xmax; x++,i++) + { + if (i == pw) + i = 0; + if(stipple[i]) + sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground); + else if (canvas->back_opacity == CD_OPAQUE) + sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->background); + } +} + +static void irgbHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch) +{ + int x; + unsigned long offset = y * canvas->w; + unsigned char n; + + if (y < 0 || y > (canvas->h-1)) + return; + + if (xmin < 0) /* Arruma limites de acordo com o retangulo de clip */ + xmin = 0; /* so clipa em x */ + if (xmax > (canvas->w-1)) + xmax = (canvas->w-1); + + n = (unsigned char)(xmin&7); + simRotateHatchN(hatch, n); + + for (x = xmin; x <= xmax; x++) + { + if (hatch & 0x80) + sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->foreground); + else if (canvas->back_opacity == CD_OPAQUE) + sCombineRGBColor(canvas->ctxcanvas, offset + x, canvas->background); + + _cdRotateHatch(hatch); + } +} + +/********************/ +/* driver functions */ +/********************/ + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + if (!ctxcanvas->user_image) + free(ctxcanvas->red); + + if (ctxcanvas->clip_region) + free(ctxcanvas->clip_region); + + free(ctxcanvas->clip); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +unsigned char* cdAlphaImage(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas; + assert(canvas); + ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas; + return ctxcanvas->alpha; +} + +unsigned char* cdRedImage(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas; + assert(canvas); + ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas; + return ctxcanvas->red; +} + +unsigned char* cdGreenImage(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas; + assert(canvas); + ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas; + return ctxcanvas->green; +} + +unsigned char* cdBlueImage(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas; + assert(canvas); + ctxcanvas = (cdCtxCanvas*)canvas->ctxcanvas; + return ctxcanvas->blue; +} + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + int size = ctxcanvas->canvas->w * ctxcanvas->canvas->h; + memset(ctxcanvas->red, cdRed(ctxcanvas->canvas->background), size); + memset(ctxcanvas->green, cdGreen(ctxcanvas->canvas->background), size); + memset(ctxcanvas->blue, cdBlue(ctxcanvas->canvas->background), size); + if (ctxcanvas->alpha) memset(ctxcanvas->alpha, cdAlpha(ctxcanvas->canvas->background), size); +} + +static void irgPostProcessIntersect(unsigned char* clip, int size) +{ + int i; + for(i = 0; i < size; i++) + { + if (*clip == 2) + *clip = 1; + else + *clip = 0; + + clip++; + } +} + +#define _irgSetClipPixel(_clip, _combine_mode) \ +{ \ + switch (_combine_mode) \ + { \ + case CD_INTERSECT: \ + if (_clip) \ + _clip = 2; /* fills the intersection \ + with a value to be post-processed */ \ + break; \ + case CD_DIFFERENCE: \ + if (_clip) \ + _clip = 0; /* clears the intersection */ \ + break; \ + case CD_NOTINTERSECT: /* XOR */ \ + if (_clip) \ + _clip = 0; /* clears the intersection */ \ + else \ + _clip = 1; /* fills the region */ \ + break; \ + default: /* CD_UNION */ \ + _clip = 1; /* fills the region */ \ + break; \ + } \ +} + +static void irgbClipFillLine(unsigned char* clip_line, int combine_mode, int x1, int x2, int width) +{ + int x; + if (x1 < 0) x1 = 0; + if (x2 > width-1) x2 = width-1; + for (x = x1; x <= x2; x++) + { + _irgSetClipPixel(clip_line[x], combine_mode); + } +} + +static int compare_int(const int* xx1, const int* xx2) +{ + return *xx1 - *xx2; +} + +static void irgbClipPoly(cdCtxCanvas* ctxcanvas, unsigned char* clip_region, cdPoint* poly, int n, int combine_mode) +{ + cdCanvas* canvas = ctxcanvas->canvas; + unsigned char* clip_line; + simLineSegment *seg_i; + cdPoint* t_poly = NULL; + int y_max, y_min, i, y, i1, fill_mode, num_lines, + inter_count, width, height; + + int *xx = (int*)malloc((n+1)*sizeof(int)); + simLineSegment *segment = (simLineSegment *)malloc(n*sizeof(simLineSegment)); + + if (canvas->use_matrix) + { + t_poly = malloc(sizeof(cdPoint)*n); + memcpy(t_poly, poly, sizeof(cdPoint)*n); + poly = t_poly; + + for(i = 0; i < n; i++) + cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y); + } + + width = canvas->w; + height = canvas->h; + fill_mode = canvas->fill_mode; + + y_max = poly[0].y; + y_min = poly[0].y; + for(i = 0; i < n; i++) + { + i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */ + simAddSegment(segment+i, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y, &y_max, &y_min); + } + + if (y_min < 0) + y_min = 0; + + if (y_max > height-1) + num_lines = height-y_min; + else + num_lines = y_max-y_min+1; + + /* for all horizontal lines between y_max and y_min */ + for(y = y_max; y >= y_min; y--) + { + inter_count = 0; + + /* for all segments, calculates the intervals to be filled. */ + for(i = 0; i < n; i++) + { + seg_i = segment + i; + + /* if the minimum Y coordinate of the segment is greater than the current y, then ignore the segment. */ + /* if it is an horizontal line, then ignore the segment. */ + if (seg_i->y1 > y || + seg_i->y1 == seg_i->y2) + continue; + + if (y == seg_i->y1) /* intersection at the start point (x1,y1) */ + { + int i_next = (i==n-1)? 0: i+1; + int i_prev = (i==0)? n-1: i-1; + simLineSegment *seg_i_next = segment + i_next; + simLineSegment *seg_i_prev = segment + i_prev; + + /* always save at least one intersection point for (y1) */ + + xx[inter_count++] = seg_i->x1; /* save the intersection point */ + + /* check for missing bottom-corner points (|_|), must duplicate the intersection */ + if ((seg_i_next->y1 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */ + (seg_i_prev->y1 == y && seg_i_prev->y2 == seg_i_prev->y1)) /* previous is an horizontal line */ + { + xx[inter_count++] = seg_i->x1; /* save the intersection point */ + } + } + else if ((y > seg_i->y1) && (y < seg_i->y2)) /* intersection inside the segment, do not include y2 */ + { + xx[inter_count++] = simSegmentInc(seg_i, canvas, y); /* save the intersection point */ + } + else if (y == seg_i->y2) /* intersection at the end point (x2,y2) */ + { + int i_next = (i==n-1)? 0: i+1; + int i_prev = (i==0)? n-1: i-1; + simLineSegment *seg_i_next = segment + i_next; + simLineSegment *seg_i_prev = segment + i_prev; + + /* only save the intersection point for (y2) if not handled by (y1) of another segment */ + + /* check for missing top-corner points (^) or (|¯¯|) */ + if ((seg_i_next->y2 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */ + (seg_i_prev->y2 == y && seg_i_prev->y2 == seg_i_prev->y1) || /* previous is an horizontal line */ + (seg_i_next->y2 == y && seg_i_next->x2 == seg_i->x2 && seg_i_next->x1 != seg_i->x1) || + (seg_i_prev->y2 == y && seg_i_prev->x2 == seg_i->x2 && seg_i_prev->x1 != seg_i->x1)) + { + xx[inter_count++] = seg_i->x2; /* save the intersection point */ + } + } + } + + /* if outside the canvas, ignore the intervals and */ + /* continue since the segments where updated. */ + if (y > height-1 || inter_count == 0) + continue; + + /* sort the intervals */ + qsort(xx, inter_count, sizeof(int), (int (*)(const void*,const void*))compare_int); + + clip_line = clip_region + y*width; + + /* for all intervals, fill the interval */ + for(i = 0; i < inter_count; i += 2) + { + if (fill_mode == CD_EVENODD) + { + /* since it fills only pairs of intervals, */ + /* it is the EVENODD fill rule. */ + irgbClipFillLine(clip_line, combine_mode, xx[i], xx[i+1], width); + } + else + { + irgbClipFillLine(clip_line, combine_mode, xx[i], xx[i+1], width); + if ((i+2 < inter_count) && (xx[i+1] < xx[i+2])) /* avoid point intervals */ + if (simIsPointInPolyWind(poly, n, (xx[i+1]+xx[i+2])/2, y)) /* if the next interval is inside the polygon then fill it */ + irgbClipFillLine(clip_line, combine_mode, xx[i+1], xx[i+2], width); + } + } + } + + if (t_poly) free(t_poly); + free(xx); + free(segment); + + if (combine_mode == CD_INTERSECT) + irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h); +} + +static void irgbClipElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector) +{ + float c, s, sx, sy, x, y, prev_x, prev_y; + double da; + int i, p; + cdPoint* poly; + + /* number of segments of equivalent poligonal for a full ellipse */ + int n = simCalcEllipseNumSegments(ctxcanvas->canvas, xc, yc, width, height); + + /* number of segments for the arc */ + n = cdRound((fabs(angle2-angle1)*n)/360); + if (n < 1) n = 1; + + poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */ + + /* converts degrees into radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + + /* generates arc points at origin with axis x and y */ + + da = (angle2-angle1)/n; + c = (float)cos(da); + s = (float)sin(da); + sx = -(width*s)/height; + sy = (height*s)/width; + + x = xc + (width/2.0f)*(float)cos(angle1); + y = yc + (height/2.0f)*(float)sin(angle1); + poly[0].x = _cdRound(x); + poly[0].y = _cdRound(y); + prev_x = x; + prev_y = y; + p = 1; + + for (i = 1; i < n+1; i++) /* n+1 points */ + { + x = xc + c*(prev_x-xc) + sx*(prev_y-yc); + y = yc + sy*(prev_x-xc) + c*(prev_y-yc); + + poly[p].x = _cdRound(x); + poly[p].y = _cdRound(y); + + if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) + p++; + + prev_x = x; + prev_y = y; + } + + if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y) + { + if (sector) /* cdSector */ + { + /* add center */ + poly[p].x = xc; + poly[p].y = yc; + } + else /* cdChord */ + { + /* add initial point */ + poly[p].x = poly[0].x; + poly[p].y = poly[0].y; + } + p++; + } + + irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, p, ctxcanvas->canvas->combine_mode); + + free(poly); +} + +static void irgbClipBox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + int combine_mode = ctxcanvas->canvas->combine_mode; + unsigned char* clip_line; + int x, y, width; + + if (ctxcanvas->canvas->use_matrix) + { + cdPoint poly[4]; + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, 4, ctxcanvas->canvas->combine_mode); + return; + } + + xmin = _sNormX(ctxcanvas, xmin); + ymin = _sNormY(ctxcanvas, ymin); + xmax = _sNormX(ctxcanvas, xmax); + ymax = _sNormY(ctxcanvas, ymax); + width = ctxcanvas->canvas->w; + + for(y = ymin; y <= ymax; y++) + { + clip_line = ctxcanvas->clip_region + y*width; + for(x = xmin; x <= xmax; x++) + { + _irgSetClipPixel(clip_line[x], combine_mode); + } + } + + if (combine_mode == CD_INTERSECT) + irgPostProcessIntersect(ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h); +} + +static void irgbClipArea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + unsigned char* clip_line = ctxcanvas->clip; /* set directly to clip */ + int y, xsize, ysize, height, width, xrigth; + + if (ctxcanvas->canvas->use_matrix) + { + cdPoint poly[4]; + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + memset(ctxcanvas->clip, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h); + irgbClipPoly(ctxcanvas, ctxcanvas->clip, poly, 4, CD_UNION); + return; + } + + xmin = _sNormX(ctxcanvas, xmin); + ymin = _sNormY(ctxcanvas, ymin); + xmax = _sNormX(ctxcanvas, xmax); + ymax = _sNormY(ctxcanvas, ymax); + xsize = xmax-xmin+1; + ysize = ymax-ymin+1; + height = ctxcanvas->canvas->h; + width = ctxcanvas->canvas->w; + xrigth = width-(xmax+1); + + for(y = 0; y < ymin; y++) + { + memset(clip_line, 0, width); + clip_line += width; + } + + for(y = ymin; y <= ymax; y++) + { + if (xmin) + memset(clip_line, 0, xmin); + + memset(clip_line+xmin, 1, xsize); + + if (xrigth) + memset(clip_line+xmax+1, 0, xrigth); + + clip_line += width; + } + + for(y = ymax+1; y < height; y++) + { + memset(clip_line, 0, width); + clip_line += width; + } +} + +static int cdclip(cdCtxCanvas* ctxcanvas, int mode) +{ + switch(mode) + { + case CD_CLIPAREA: + irgbClipArea(ctxcanvas, ctxcanvas->canvas->clip_rect.xmin, + ctxcanvas->canvas->clip_rect.xmax, + ctxcanvas->canvas->clip_rect.ymin, + ctxcanvas->canvas->clip_rect.ymax); + break; + case CD_CLIPPOLYGON: + memset(ctxcanvas->clip, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h); + irgbClipPoly(ctxcanvas, ctxcanvas->clip, ctxcanvas->canvas->clip_poly, ctxcanvas->canvas->clip_poly_n, CD_UNION); + break; + case CD_CLIPREGION: + if (ctxcanvas->clip_region) + memcpy(ctxcanvas->clip, ctxcanvas->clip_region, ctxcanvas->canvas->w * ctxcanvas->canvas->h); + break; + default: + memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); /* CD_CLIPOFF */ + break; + } + + return mode; +} + +static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + irgbClipArea(ctxcanvas, xmin, xmax, ymin, ymax); +} + +static void cdnewregion(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->clip_region) + free(ctxcanvas->clip_region); + ctxcanvas->clip_region = malloc(ctxcanvas->canvas->w * ctxcanvas->canvas->h); + memset(ctxcanvas->clip_region, 0, ctxcanvas->canvas->w * ctxcanvas->canvas->h); +} + +static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + if (!ctxcanvas->clip_region) + return 0; + + if (x >= 0 && y >= 0 && x < ctxcanvas->canvas->w && y < ctxcanvas->canvas->h) + { + if (ctxcanvas->clip_region[y*ctxcanvas->canvas->w + x]) + return 1; + } + + return 0; +} + +static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int dx, int dy) +{ + unsigned char* clip_region = ctxcanvas->clip_region; + int x, y, X, Y, old_X, old_Y, width, height; + + if (!ctxcanvas->clip_region) + return; + + height = ctxcanvas->canvas->h; + width = ctxcanvas->canvas->w; + + for (y = 0; y < height; y++) + { + if (dy > 0) + Y = height-1 - y; + else + Y = y; + old_Y = Y - dy; + for(x = 0; x < width; x++) + { + if (dx > 0) + X = width-1 - x; + else + X = x; + old_X = X - dx; + + if (old_X >= 0 && old_Y >= 0 && old_Y < height && old_X < width) + clip_region[Y*width + X] = clip_region[old_Y*width + old_X]; + else + clip_region[Y*width + X] = 0; + } + } +} + +static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + unsigned char* clip_line = ctxcanvas->clip_region; + int x, y, width, height; + + if (!ctxcanvas->clip_region) + return; + + *xmin = ctxcanvas->canvas->w-1; + *xmax = 0; + *ymin = ctxcanvas->canvas->h-1; + *ymax = 0; + height = ctxcanvas->canvas->h; + width = ctxcanvas->canvas->w; + + for (y = 0; y < height; y++) + { + for(x = 0; x < width; x++) + { + if (*clip_line) + { + if (x < *xmin) + *xmin = x; + if (y < *ymin) + *ymin = y; + if (x > *xmax) + *xmax = x; + if (y > *ymax) + *ymax = y; + } + + clip_line++; + } + } +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->new_region) + { + irgbClipBox(ctxcanvas, xmin, xmax, ymin, ymax); + return; + } + + cdboxSIM(ctxcanvas, xmin, xmax, ymin, ymax); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + { + irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1); + return; + } + + cdsectorSIM(ctxcanvas, xc, yc, w, h, a1, a2); +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->new_region) + { + irgbClipElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0); + return; + } + + cdchordSIM(ctxcanvas, xc, yc, w, h, a1, a2); +} + +static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + if (ctxcanvas->canvas->new_region) + { + irgbClipPoly(ctxcanvas, ctxcanvas->clip_region, poly, n, ctxcanvas->canvas->combine_mode); + return; + } + + if (mode == CD_CLIP) + { + /* set directly to clip */ + memset(ctxcanvas->clip, 1, ctxcanvas->canvas->w * ctxcanvas->canvas->h); /* CD_CLIPOFF */ + irgbClipPoly(ctxcanvas, ctxcanvas->clip, poly, n, CD_UNION); + } + else + cdpolySIM(ctxcanvas, mode, poly, n); +} + +static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + int dst_offset, src_offset, l, xsize, ysize, xpos, ypos; + unsigned char *src_red, *src_green, *src_blue; + + if (x >= ctxcanvas->canvas->w || y >= ctxcanvas->canvas->h || + x + w < 0 || y + h < 0) + return; + + /* ajusta parametros de entrada */ + xpos = _sNormX(ctxcanvas, x); + ypos = _sNormY(ctxcanvas, y); + + xsize = w < (ctxcanvas->canvas->w - xpos)? w: ctxcanvas->canvas->w - xpos; + ysize = h < (ctxcanvas->canvas->h - ypos)? h: ctxcanvas->canvas->h - ypos; + + /* ajusta posicao inicial em source */ + src_offset = xpos + ypos * ctxcanvas->canvas->w; + src_red = ctxcanvas->red + src_offset; + src_green = ctxcanvas->green + src_offset; + src_blue = ctxcanvas->blue + src_offset; + + /* offset para source */ + src_offset = ctxcanvas->canvas->w; + + /* ajusta posicao inicial em destine */ + dst_offset = (xpos - x) + (ypos - y) * w; + r += dst_offset; + g += dst_offset; + b += dst_offset; + + for (l = 0; l < ysize; l++) + { + memcpy(r, src_red, xsize); + memcpy(g, src_green, xsize); + memcpy(b, src_blue, xsize); + + src_red += src_offset; + src_green += src_offset; + src_blue += src_offset; + + r += w; + g += w; + b += w; + } +} + +static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int t_xmin, t_xmax, t_ymin, t_ymax, + t_x, t_y, img_topdown = 0, dst_offset; + float i_x, i_y, xfactor, yfactor; + unsigned char sr, sg, sb, sa = 255; + double inv_matrix[6]; + + if (h < 0) + { + h = -h; + y -= (h - 1); /* y is at top-left, move it to bottom-left */ + img_topdown = 1; /* image pointer will start at top-left */ + } + + /* calculate the destination limits */ + cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL); + + /* Setup inverse transform */ + cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix); + + /* for all pixels in the destiny area */ + for(t_y = t_ymin; t_y <= t_ymax; t_y++) + { + dst_offset = t_y * ctxcanvas->canvas->w; + + for(t_x = t_xmin; t_x <= t_xmax; t_x++) + { + cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix); + + if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) + { + if (img_topdown) /* image is top-bottom */ + i_y = ih-1 - i_y; + + if (t_x == 350 && t_y == 383) + t_x = 350; + + sr = cdBilinearInterpolation(iw, ih, r, i_x, i_y); + sg = cdBilinearInterpolation(iw, ih, g, i_x, i_y); + sb = cdBilinearInterpolation(iw, ih, b, i_x, i_y); + if (a) sa = cdBilinearInterpolation(iw, ih, a, i_x, i_y); + + if (sr > 210 && sg > 210 && sb > 210) + sr = sr; + + sCombineRGB(ctxcanvas, t_x + dst_offset, sr, sg, sb, sa); + } + } + } +} + +static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int t_xmin, t_xmax, t_ymin, t_ymax, + t_x, t_y, img_topdown = 0, dst_offset; + float i_x, i_y, xfactor, yfactor; + unsigned char si; + double inv_matrix[6]; + + if (h < 0) + { + h = -h; + y -= (h - 1); /* y is at top-left, move it to bottom-left */ + img_topdown = 1; /* image pointer will start at top-left (undocumented feature) */ + } + + /* calculate the destination limits */ + cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, NULL); + + /* Setup inverse transform */ + cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix); + + /* for all pixels in the destiny area */ + for(t_y = t_ymin; t_y <= t_ymax; t_y++) + { + dst_offset = t_y * ctxcanvas->canvas->w; + + for(t_x = t_xmin; t_x <= t_xmax; t_x++) + { + cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix); + + if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) + { + if (img_topdown) /* image is top-bottom */ + i_y = ih-1 - i_y; + + si = cdZeroOrderInterpolation(iw, ih, index, i_x, i_y); + sCombineRGBColor(ctxcanvas, t_x + dst_offset, colors[si]); + } + } + } +} + +static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rh, rw, img_topdown = 0; + const unsigned char *src_red, *src_green, *src_blue; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, NULL, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + if (h < 0) + { + h = -h; + y -= (h - 1); /* y is at top-left, move it to bottom-left */ + img_topdown = 1; /* image pointer will start at top-left */ + } + + /* verifica se esta dentro da area de desenho */ + if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || + (x+w) < 0 || (y+h) < 0) + return; + + xpos = x < 0? 0: x; + ypos = y < 0? 0: y; + + xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1; + ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + /* testa se tem que fazer zoom */ + if (rw != w || rh != h) + { + int* XTab = cdGetZoomTable(w, rw, xmin); + int* YTab = cdGetZoomTable(h, rh, ymin); + + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + for(l = 0; l < ysize; l++) + { + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; + else + src_offset = YTab[l + (ypos - y)] * iw; + + src_red = r + src_offset; + src_green = g + src_offset; + src_blue = b + src_offset; + + for(c = 0; c < xsize; c++) + { + src_offset = XTab[c + (xpos - x)]; + sCombineRGB(ctxcanvas, c + dst_offset, src_red[src_offset], src_green[src_offset], src_blue[src_offset], 255); + } + + dst_offset += ctxcanvas->canvas->w; + } + + free(XTab); + free(YTab); + } + else + { + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; + else + src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; + + r += src_offset; + g += src_offset; + b += src_offset; + + for (l = 0; l < ysize; l++) + { + sCombineRGBLine(ctxcanvas, dst_offset, r, g, b, xsize); + + dst_offset += ctxcanvas->canvas->w; + + if (img_topdown) + { + r -= iw; + g -= iw; + b -= iw; + } + else + { + r += iw; + g += iw; + b += iw; + } + } + } +} + +static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, img_topdown = 0; + const unsigned char *src_red, *src_green, *src_blue, *src_alpha; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + if (h < 0) + { + h = -h; + y -= (h - 1); /* y is at top-left, move it to bottom-left */ + img_topdown = 1; /* image pointer will start at top-left */ + } + + /* verifica se esta dentro da area de desenho */ + if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || + (x+w) < 0 || (y+h) < 0) + return; + + xpos = x < 0? 0: x; + ypos = y < 0? 0: y; + + xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1; + ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + /* testa se tem que fazer zoom */ + if (rw != w || rh != h) + { + int* XTab = cdGetZoomTable(w, rw, xmin); + int* YTab = cdGetZoomTable(h, rh, ymin); + + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + for(l = 0; l < ysize; l++) + { + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; + else + src_offset = YTab[l + (ypos - y)] * iw; + + src_red = r + src_offset; + src_green = g + src_offset; + src_blue = b + src_offset; + src_alpha = a + src_offset; + + for(c = 0; c < xsize; c++) + { + src_offset = XTab[c + (xpos - x)]; + sCombineRGB(ctxcanvas, c + dst_offset, src_red[src_offset], src_green[src_offset], src_blue[src_offset], src_alpha[src_offset]); + } + + dst_offset += ctxcanvas->canvas->w; + } + + free(XTab); + free(YTab); + } + else + { + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; + else + src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; + + r += src_offset; + g += src_offset; + b += src_offset; + a += src_offset; + + for (l = 0; l < ysize; l++) + { + sCombineRGBALine(ctxcanvas, dst_offset, r, g, b, a, xsize); + + dst_offset += ctxcanvas->canvas->w; + + if (img_topdown) + { + r -= iw; + g -= iw; + b -= iw; + a -= iw; + } + else + { + r += iw; + g += iw; + b += iw; + a += iw; + } + } + } +} + +static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int l, c, xsize, ysize, xpos, ypos, src_offset, dst_offset, rw, rh, pal_size, idx, img_topdown = 0; + const unsigned char *src_index; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectmap_matrix(ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + if (h < 0) + { + h = -h; + y -= (h - 1); /* y is at top-left, move it to bottom-left */ + img_topdown = 1; /* image pointer will start at top-left */ + } + + /* verifica se esta dentro da area de desenho */ + if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || + (x+w) < 0 || (y+h) < 0) + return; + + xpos = x < 0? 0: x; + ypos = y < 0? 0: y; + + xsize = (x+w) < (ctxcanvas->canvas->w-1)+1? (x+w) - xpos: (ctxcanvas->canvas->w-1) - xpos + 1; + ysize = (y+h) < (ctxcanvas->canvas->h-1)+1? (y+h) - ypos: (ctxcanvas->canvas->h-1) - ypos + 1; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + /* Como nao sabemos o tamanho da palette a priori, + teremos que ver qual o maior indice usado na imagem. */ + pal_size = 0; + + for (l=0; l pal_size) + pal_size = idx; + } + } + + pal_size++; + + /* testa se tem que fazer zoom */ + if (rw != w || rh != h) + { + int* XTab = cdGetZoomTable(w, rw, xmin); + int* YTab = cdGetZoomTable(h, rh, ymin); + + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + for(l = 0; l < ysize; l++) + { + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = YTab[(ih - 1) - (l + (ypos - y))] * iw; + else + src_offset = YTab[l + (ypos - y)] * iw; + + src_index = index + src_offset; + + for(c = 0; c < xsize; c++) + { + src_offset = XTab[c + (xpos - x)]; + idx = src_index[src_offset]; + sCombineRGBColor(ctxcanvas, c + dst_offset, colors[idx]); + } + + dst_offset += ctxcanvas->canvas->w; + } + + free(XTab); + free(YTab); + } + else + { + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + /* ajusta posicao inicial em source */ + if (img_topdown) + src_offset = (xpos - x + xmin) + ((ih - 1) - (ypos - y + ymin)) * iw; + else + src_offset = (xpos - x + xmin) + (ypos - y + ymin) * iw; + + index += src_offset; + + for (l = 0; l < ysize; l++) + { + for(c = 0; c < xsize; c++) + { + idx = index[c]; + sCombineRGBColor(ctxcanvas, c + dst_offset, colors[idx]); + } + + dst_offset += ctxcanvas->canvas->w; + + if (img_topdown) + index -= iw; + else + index += iw; + } + } +} + +static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int color) +{ + int offset; + + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->canvas->matrix, x, y, &x, &y); + + offset = ctxcanvas->canvas->w * y + x; + + /* verifica se esta dentro da area de desenho */ + if (x < 0 || + x > (ctxcanvas->canvas->w-1) || + y < 0 || + y > (ctxcanvas->canvas->h-1)) + return; + + sCombineRGBColor(ctxcanvas, offset, color); +} + +static cdCtxImage* cdcreateimage(cdCtxCanvas* ctxcanvas, int w, int h) +{ + cdCtxImage* ctximage; + int size = w * h; + int num_c = ctxcanvas->alpha? 4: 3; + + ctximage = (cdCtxImage*)malloc(sizeof(cdCtxImage)); + memset(ctximage, 0, sizeof(cdCtxImage)); + + ctximage->w = w; + ctximage->h = h; + + ctximage->red = (unsigned char*) malloc(num_c*size); + if (!ctximage->red) + { + free(ctximage); + return NULL; + } + + ctximage->green = ctximage->red + size; + ctximage->blue = ctximage->red + 2*size; + if (ctxcanvas->alpha) + ctximage->alpha = ctximage->red + 3*size; + + memset(ctximage->red, 0xFF, 3*size); + if (ctximage->alpha) memset(ctximage->alpha, 0, size); /* transparent */ + + return ctximage; +} + +static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y) +{ + unsigned char *r, *g, *b, *a = NULL; + int w, h, dst_offset, src_offset, l, xsize, ysize, xpos, ypos, do_alpha = 0; + unsigned char *src_red, *src_green, *src_blue, *src_alpha = NULL; + + w = ctximage->w; + h = ctximage->h; + + if (x >= ctxcanvas->canvas->w || y >= ctxcanvas->canvas->h || + x + w < 0 || y + h < 0) + return; + + if (ctximage->alpha && ctxcanvas->alpha) + do_alpha = 1; + + r = ctximage->red; + g = ctximage->green; + b = ctximage->blue; + if (do_alpha) a = ctximage->alpha; + + /* ajusta parametros de entrada */ + xpos = _sNormX(ctxcanvas, x); + ypos = _sNormY(ctxcanvas, y); + + xsize = w < (ctxcanvas->canvas->w - xpos)? w: ctxcanvas->canvas->w - xpos; + ysize = h < (ctxcanvas->canvas->h - ypos)? h: ctxcanvas->canvas->h - ypos; + + /* ajusta posicao inicial em source */ + src_offset = xpos + ypos * ctxcanvas->canvas->w; + src_red = ctxcanvas->red + src_offset; + src_green = ctxcanvas->green + src_offset; + src_blue = ctxcanvas->blue + src_offset; + if (do_alpha) src_alpha = ctxcanvas->alpha + src_offset; + + /* offset para source */ + src_offset = ctxcanvas->canvas->w; + + /* ajusta posicao inicial em destine */ + dst_offset = (xpos - x) + (ypos - y) * w; + r += dst_offset; + g += dst_offset; + b += dst_offset; + if (do_alpha) a += dst_offset; + + for (l = 0; l < ysize; l++) + { + memcpy(r, src_red, xsize); + memcpy(g, src_green, xsize); + memcpy(b, src_blue, xsize); + if (do_alpha) memcpy(a, src_alpha, xsize); + + src_red += src_offset; + src_green += src_offset; + src_blue += src_offset; + if (do_alpha) src_alpha += src_offset; + + r += w; + g += w; + b += w; + if (do_alpha) a += w; + } +} + +static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage* ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + int iw, ih, w, h; + unsigned char *r, *g, *b, *a; + int l, xsize, ysize, xpos, ypos, src_offset, dst_offset; + + iw = ctximage->w; + ih = ctximage->h; + + r = ctximage->red; + g = ctximage->green; + b = ctximage->blue; + a = ctximage->alpha; + + w = xmax-xmin+1; + h = ymax-ymin+1; + + /* verifica se esta dentro da area de desenho */ + if (x > (ctxcanvas->canvas->w-1) || y > (ctxcanvas->canvas->h-1) || + x + w < 0 || y + h < 0) + return; + + xpos = x; + ypos = y; + + if (ypos < 0) ypos = 0; + if (xpos < 0) xpos = 0; + + xsize = w < ((ctxcanvas->canvas->w-1)+1 - xpos)? w: ((ctxcanvas->canvas->w-1)+1 - xpos); + ysize = h < ((ctxcanvas->canvas->h-1)+1 - ypos)? h: ((ctxcanvas->canvas->h-1)+1 - ypos); + + /* ajusta posicao inicial em destine */ + dst_offset = xpos + ypos * ctxcanvas->canvas->w; + + /* ajusta posicao inicial em source */ + src_offset = ((xpos - x) + xmin) + ((ypos - y) + ymin) * iw; + r += src_offset; + g += src_offset; + b += src_offset; + if (a) a += src_offset; + + for (l = 0; l < ysize; l++) + { + if (a) + sCombineRGBALine(ctxcanvas, dst_offset, r, g, b, a, xsize); + else + sCombineRGBLine(ctxcanvas, dst_offset, r, g, b, xsize); + + dst_offset += ctxcanvas->canvas->w; + + r += iw; + g += iw; + b += iw; + if (a) a += iw; + } +} + +static void cdkillimage(cdCtxImage* ctximage) +{ + free(ctximage->red); + memset(ctximage, 0, sizeof(cdCtxImage)); + free(ctximage); +} + +static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + int l; + long src_offset, dst_offset; + int incx,incy, xsize, ysize; + int dst_xmin, dst_xmax, dst_ymin, dst_ymax; + + /* corrige valores de entrada */ + + xmin = _sNormX(ctxcanvas, xmin); + ymin = _sNormY(ctxcanvas, ymin); + xmax = _sNormX(ctxcanvas, xmax); + ymax = _sNormY(ctxcanvas, ymax); + + dst_xmin = xmin + dx; + dst_ymin = ymin + dy; + dst_xmax = xmax + dx; + dst_ymax = ymax + dy; + + /* verifica se esta dentro da area de desenho */ + if (dst_xmin > (ctxcanvas->canvas->w-1) || dst_ymin > (ctxcanvas->canvas->h-1) || + dst_xmax < 0 || dst_ymax < 0) + return; + + if (dst_ymin < 0) dst_ymin = 0; + if (dst_xmin < 0) dst_xmin = 0; + + if (dst_ymax > (ctxcanvas->canvas->h-1)) dst_ymax = (ctxcanvas->canvas->h-1); + if (dst_xmax > (ctxcanvas->canvas->w-1)) dst_xmax = (ctxcanvas->canvas->w-1); + + if (dst_xmin > dst_xmax || dst_ymin > dst_ymax) + return; + + /* Decide de onde vai comecar a copiar, isto e' necessario pois pode haver + uma intersecao entre a imagem original e a nova imagem, assim devo + garantir que nao estou colocando um ponto, em cima de um ponto ainda nao + lido da imagem antiga. */ + + xsize = dst_xmax - dst_xmin + 1; + ysize = dst_ymax - dst_ymin + 1; + + /* sentido de copia da direita para a esquerda ou ao contrario. */ + if (dx < 0) + { + incx = 1; + dst_offset = dst_xmin; + src_offset = xmin; + } + else + { + incx = -1; + dst_offset = dst_xmax; + src_offset = xmax; + } + + /* sentido de copia de cima para baixo ou ao contrario. */ + if (dy < 0) + { + incy = ctxcanvas->canvas->w; + dst_offset += dst_ymin * ctxcanvas->canvas->w; + src_offset += ymin * ctxcanvas->canvas->w; + } + else + { + incy = -(ctxcanvas->canvas->w); + dst_offset += dst_ymax * ctxcanvas->canvas->w; + src_offset += ymax * ctxcanvas->canvas->w; + } + + xsize *= incx; + + for (l = 0; l < ysize; l++) + { + sCombineRGBLine(ctxcanvas, dst_offset, ctxcanvas->red + src_offset, ctxcanvas->green + src_offset, ctxcanvas->blue + src_offset, xsize); + dst_offset += incy; + src_offset += incy; + } +} + +static char* get_green_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->green; +} + +static cdAttribute green_attrib = +{ + "GREENIMAGE", + NULL, + get_green_attrib +}; + +static char* get_blue_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->blue; +} + +static cdAttribute blue_attrib = +{ + "BLUEIMAGE", + NULL, + get_blue_attrib +}; + +static char* get_red_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->red; +} + +static cdAttribute red_attrib = +{ + "REDIMAGE", + NULL, + get_red_attrib +}; + +static char* get_alpha_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->alpha; +} + +static cdAttribute alpha_attrib = +{ + "ALPHAIMAGE", + NULL, + get_alpha_attrib +}; + +static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data || data[0] == '0') + ctxcanvas->canvas->simulation->antialias = 0; + else + ctxcanvas->canvas->simulation->antialias = 1; +} + +static char* get_aa_attrib(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->canvas->simulation->antialias) + return "0"; + else + return "1"; +} + +static cdAttribute aa_attrib = +{ + "ANTIALIAS", + set_aa_attrib, + get_aa_attrib +}; + +static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + + cdCanvasTransformTranslate(ctxcanvas->canvas, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + cdCanvasTransformRotate(ctxcanvas->canvas, ctxcanvas->rotate_angle); + cdCanvasTransformTranslate(ctxcanvas->canvas, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + + cdCanvasTransform(ctxcanvas->canvas, NULL); + } +} + +static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas* ctxcanvas; + int w = 0, h = 0, use_alpha = 0; + float res = (float)3.78; + unsigned char *r = NULL, *g = NULL, *b = NULL, *a = NULL; + char* str_data = (char*)data; + char* res_ptr = NULL; + + if (strstr(str_data, "-a")) + use_alpha = 1; + + res_ptr = strstr(str_data, "-r"); + if (res_ptr) + sscanf(res_ptr+2, "%g", &res); + + /* size and rgb */ +#ifdef SunOS_OLD + if (use_alpha) + sscanf(str_data, "%dx%d %d %d %d %d", &w, &h, &r, &g, &b, &a); + else + sscanf(str_data, "%dx%d %d %d %d", &w, &h, &r, &g, &b); +#else + if (use_alpha) + sscanf(str_data, "%dx%d %p %p %p %p", &w, &h, &r, &g, &b, &a); + else + sscanf(str_data, "%dx%d %p %p %p", &w, &h, &r, &g, &b); +#endif + + if (w == 0 || h == 0) + return; + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + canvas->w = w; + canvas->h = h; + canvas->yres = res; + canvas->xres = res; + canvas->w_mm = ((double)w) / res; + canvas->h_mm = ((double)h) / res; + if (use_alpha) + canvas->bpp = 32; + else + canvas->bpp = 24; + + if (r && g && b) + { + ctxcanvas->user_image = 1; + + ctxcanvas->red = r; + ctxcanvas->green = g; + ctxcanvas->blue = b; + ctxcanvas->alpha = a; + } + else + { + int size = w * h; + int num_c = use_alpha? 4: 3; + + ctxcanvas->user_image = 0; + + ctxcanvas->red = (unsigned char*)malloc(num_c*size); + if (!ctxcanvas->red) + { + free(ctxcanvas); + return; + } + + ctxcanvas->green = ctxcanvas->red + size; + ctxcanvas->blue = ctxcanvas->red + 2*size; + if (use_alpha) + ctxcanvas->alpha = ctxcanvas->red + 3*size; + + memset(ctxcanvas->red, 0xFF, 3*size); /* white */ + if (ctxcanvas->alpha) memset(ctxcanvas->alpha, 0, size); /* transparent */ + } + + ctxcanvas->clip = (unsigned char*)malloc(w*h); + memset(ctxcanvas->clip, 1, w*h); /* CD_CLIPOFF */ + + canvas->ctxcanvas = ctxcanvas; + ctxcanvas->canvas = canvas; + +// cdSimInitText(canvas->simulation); + /* nao preciso inicializar a fonte, + pois isso sera' feito na inicializacao dos atributos default do driver */ + + canvas->simulation->antialias = 1; + + cdRegisterAttribute(canvas, &red_attrib); + cdRegisterAttribute(canvas, &green_attrib); + cdRegisterAttribute(canvas, &blue_attrib); + cdRegisterAttribute(canvas, &alpha_attrib); + cdRegisterAttribute(canvas, &aa_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdSimulation* sim; + + /* initialize function table*/ + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxNewRegion = cdnewregion; + canvas->cxIsPointInRegion = cdispointinregion; + canvas->cxOffsetRegion = cdoffsetregion; + canvas->cxGetRegionBox = cdgetregionbox; + + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxGetImageRGB = cdgetimagergb; + + canvas->cxCreateImage = cdcreateimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxKillImage = cdkillimage; + canvas->cxScrollArea = cdscrollarea; + + canvas->cxClear = cdclear; + canvas->cxPixel = cdpixel; + + canvas->cxLine = cdlineSIM; + canvas->cxRect = cdrectSIM; + canvas->cxBox = cdbox; + canvas->cxArc = cdarcSIM; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxPoly = cdpoly; + canvas->cxText = NULL; + + canvas->cxKillCanvas = cdkillcanvas; + + /* use simulation */ + canvas->cxFont = NULL; + canvas->cxGetFontDim = NULL; + canvas->cxGetTextSize = NULL; + + sim = canvas->simulation; + + sim->SolidLine = irgbSolidLine; + sim->PatternLine = irgbPatternLine; + sim->StippleLine = irgbStippleLine; + sim->HatchLine = irgbHatchLine; +} + +static cdContext cdImageRGBContext = +{ + CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_FPRIMTIVES | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | + CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextImageRGB(void) +{ + return &cdImageRGBContext; +} + +static void cdflushDB(cdCtxCanvas *ctxcanvas) +{ + int old_writemode; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* this is done in the canvas_dbuffer context */ + + /* Flush can be affected by Origin and Clipping, but not WriteMode */ + + old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE); + cdCanvasPutImageRectRGB(canvas_dbuffer, ctxcanvas->canvas->w, ctxcanvas->canvas->h, ctxcanvas->red, ctxcanvas->green, ctxcanvas->blue, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0, 0, 0); + cdCanvasWriteMode(canvas_dbuffer, old_writemode); +} + +static void cdcreatecanvasDB(cdCanvas* canvas, cdCanvas* canvas_dbuffer) +{ + char rgbdata[100]; + sprintf(rgbdata, "%dx%d -r%g", canvas_dbuffer->w, canvas_dbuffer->h, canvas_dbuffer->xres); + cdcreatecanvas(canvas, rgbdata); + if (canvas->ctxcanvas) + canvas->ctxcanvas->canvas_dbuffer = canvas_dbuffer; +} + +static int cdactivateDB(cdCtxCanvas *ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* this is done in the canvas_dbuffer context */ + /* this will update canvas size */ + cdCanvasActivate(canvas_dbuffer); + + /* check if the size changed */ + if (canvas_dbuffer->w != ctxcanvas->canvas->w || + canvas_dbuffer->h != ctxcanvas->canvas->h) + { + cdCanvas* canvas = ctxcanvas->canvas; + /* save the current, if the rebuild fail */ + cdCtxCanvas* old_ctxcanvas = ctxcanvas; + + /* if the image is rebuild, the canvas that uses the image must be also rebuild */ + + /* rebuild the image and the canvas */ + canvas->ctxcanvas = NULL; + cdcreatecanvasDB(canvas, canvas_dbuffer); + if (!canvas->ctxcanvas) + { + canvas->ctxcanvas = old_ctxcanvas; + return CD_ERROR; + } + + /* remove the old image and canvas */ + cdkillcanvas(old_ctxcanvas); + + ctxcanvas = canvas->ctxcanvas; + + /* update canvas attributes */ + if (canvas->cxBackground) canvas->cxBackground(ctxcanvas, canvas->background); + if (canvas->cxForeground) canvas->cxForeground(ctxcanvas, canvas->foreground); + if (canvas->cxBackOpacity) canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity); + if (canvas->cxWriteMode) canvas->cxWriteMode(ctxcanvas, canvas->write_mode); + if (canvas->cxLineStyle) canvas->cxLineStyle(ctxcanvas, canvas->line_style); + if (canvas->cxLineWidth) canvas->cxLineWidth(ctxcanvas, canvas->line_width); + if (canvas->cxLineCap) canvas->cxLineCap(ctxcanvas, canvas->line_cap); + if (canvas->cxLineJoin) canvas->cxLineJoin(ctxcanvas, canvas->line_join); + if (canvas->cxHatch) canvas->cxHatch(ctxcanvas, canvas->hatch_style); + if (canvas->stipple && canvas->cxStipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple); + if (canvas->pattern && canvas->cxPattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern); + if (canvas->cxInteriorStyle) canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style); + if (canvas->native_font[0] && canvas->cxNativeFont) + canvas->cxNativeFont(ctxcanvas, canvas->native_font); + else if (canvas->cxFont) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + if (canvas->cxTextAlignment) canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment); + if (canvas->cxTextOrientation) canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation); + if (canvas->use_matrix && canvas->cxTransform) canvas->cxTransform(ctxcanvas, canvas->matrix); + if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax); + if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); + if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n); + if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); + if (canvas->clip_mode != CD_CLIPOFF && canvas->cxClip) canvas->cxClip(ctxcanvas, canvas->clip_mode); + } + + return CD_OK; +} + +static void cddeactivateDB(cdCtxCanvas *ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + /* this is done in the canvas_dbuffer context */ + cdCanvasDeactivate(canvas_dbuffer); +} + +static void cdinittableDB(cdCanvas* canvas) +{ + cdinittable(canvas); + + canvas->cxActivate = cdactivateDB; + canvas->cxDeactivate = cddeactivateDB; + + canvas->cxFlush = cdflushDB; +} + +static cdContext cdDBufferRGBContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_FPRIMTIVES | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | CD_CAP_REGION | + CD_CAP_PALETTE | CD_CAP_TEXTORIENTATION), + 0, + cdcreatecanvasDB, + cdinittableDB, + NULL, + NULL, +}; + +cdContext* cdContextDBufferRGB(void) +{ + return &cdDBufferRGBContext; +} diff --git a/cd/src/drv/cdmf.c b/cd/src/drv/cdmf.c new file mode 100755 index 0000000..d44bb5e --- /dev/null +++ b/cd/src/drv/cdmf.c @@ -0,0 +1,1192 @@ +/** \file + * \brief CD Metafile driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" +#include "cd_private.h" +#include "cdmf.h" +#include "cdmf_private.h" + + +/* codes for the primitives and attributes in the metafile + Can NOT be changed, only added for backward compatibility. +*/ +enum +{ + CDMF_FLUSH, /* 0 */ + CDMF_CLEAR, /* 1 */ + CDMF_CLIP, /* 2 */ + CDMF_CLIPAREA, /* 3 */ + CDMF_LINE, /* 4 */ + CDMF_BOX, /* 5 */ + CDMF_ARC, /* 6 */ + CDMF_SECTOR, /* 7 */ + CDMF_TEXT, /* 8 */ + CDMF_BEGIN, /* 9 */ + CDMF_VERTEX, /* 10 */ + CDMF_END, /* 11 */ + CDMF_MARK, /* 12 */ + CDMF_BACKOPACITY, /* 13 */ + CDMF_WRITEMODE, /* 14 */ + CDMF_LINESTYLE, /* 15 */ + CDMF_LINEWIDTH, /* 16 */ + CDMF_INTERIORSTYLE, /* 17 */ + CDMF_HATCH, /* 18 */ + CDMF_STIPPLE, /* 19 */ + CDMF_PATTERN, /* 20 */ + CDMF_OLDFONT, /* 21 */ + CDMF_NATIVEFONT, /* 22 */ + CDMF_TEXTALIGNMENT, /* 23 */ + CDMF_MARKTYPE, /* 24 */ + CDMF_MARKSIZE, /* 25 */ + CDMF_PALETTE, /* 26 */ + CDMF_BACKGROUND, /* 27 */ + CDMF_FOREGROUND, /* 28 */ + CDMF_PUTIMAGERGB, /* 29 */ + CDMF_PUTIMAGEMAP, /* 30 */ + CDMF_PIXEL, /* 31 */ + CDMF_SCROLLAREA, /* 32 */ + CDMF_TEXTORIENTATION, /* 33 */ + CDMF_RECT, /* 34 */ + CDMF_PUTIMAGERGBA, /* 35 */ + CDMF_WLINE, /* 36 */ + CDMF_WRECT, /* 37 */ + CDMF_WBOX, /* 38 */ + CDMF_WARC, /* 39 */ + CDMF_WSECTOR, /* 40 */ + CDMF_WTEXT, /* 41 */ + CDMF_WVERTEX, /* 42 */ + CDMF_WMARK, /* 43 */ + CDMF_VECTORTEXT, /* 44 */ + CDMF_MULTILINEVECTORTEXT, /* 45 */ + CDMF_WVECTORTEXT, /* 46 */ + CDMF_WMULTILINEVECTORTEXT, /* 47 */ + CDMF_WINDOW, /* 48 */ + CDMF_WCLIPAREA, /* 49 */ + CDMF_VECTORFONT, /* 50 */ + CDMF_VECTORTEXTDIRECTION, /* 51 */ + CDMF_VECTORTEXTTRANSFORM, /* 52 */ + CDMF_VECTORTEXTSIZE, /* 53 */ + CDMF_VECTORCHARSIZE, /* 54 */ + CDMF_WVECTORTEXTDIRECTION, /* 55 */ + CDMF_WVECTORTEXTSIZE, /* 56 */ + CDMF_WVECTORCHARSIZE, /* 57 */ + CDMF_FILLMODE, /* 58 */ + CDMF_LINESTYLEDASHES, /* 59 */ + CDMF_LINECAP, /* 60 */ + CDMF_LINEJOIN, /* 61 */ + CDMF_CHORD, /* 62 */ + CDMF_WCHORD, /* 63 */ + CDMF_FLINE, /* 64 */ + CDMF_FRECT, /* 65 */ + CDMF_FBOX, /* 66 */ + CDMF_FARC, /* 67 */ + CDMF_FSECTOR, /* 68 */ + CDMF_FTEXT, /* 69 */ + CDMF_FVERTEX, /* 70 */ + CDMF_MATRIX, /* 71 */ + CDMF_FCHORD, /* 72 */ + CDMF_FCLIPAREA, /* 73 */ + CDMF_FONT, /* 74 */ + CDMF_RESETMATRIX /* 75 */ +}; + +struct _cdCtxCanvas +{ + /* public */ + cdCanvas* canvas; + char* filename; + void* data; /* used by other drivers */ + + /* private */ + int last_line_style; + int last_fill_mode; + FILE* file; +}; + +void cdkillcanvasMF(cdCanvasMF *mfcanvas) +{ + cdCtxCanvas *ctxcanvas = (cdCtxCanvas*)mfcanvas; + free(ctxcanvas->filename); + fclose(ctxcanvas->file); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + fflush(ctxcanvas->file); + fprintf(ctxcanvas->file, "%d\n", CDMF_FLUSH); +} + +static void cdclear(cdCtxCanvas *ctxcanvas) +{ + fprintf(ctxcanvas->file, "%d\n", CDMF_CLEAR); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_CLIP, mode); + return mode; +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_CLIPAREA, xmin, xmax, ymin, ymax); +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FCLIPAREA, xmin, xmax, ymin, ymax); +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_MATRIX, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + else + fprintf(ctxcanvas->file, "%d\n", CDMF_RESETMATRIX); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_LINE, x1, y1, x2, y2); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FLINE, x1, y1, x2, y2); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_RECT, xmin, xmax, ymin, ymax); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FRECT, xmin, xmax, ymin, ymax); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d\n", CDMF_BOX, xmin, xmax, ymin, ymax); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g\n", CDMF_FBOX, xmin, xmax, ymin, ymax); +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_ARC, xc, yc, w, h, a1, a2); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FARC, xc, yc, w, h, a1, a2); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_SECTOR, xc, yc, w, h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FSECTOR, xc, yc, w, h, a1, a2); +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d %g %g\n", CDMF_CHORD, xc, yc, w, h, a1, a2); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + fprintf(ctxcanvas->file, "%d %g %g %g %g %g %g\n", CDMF_FCHORD, xc, yc, w, h, a1, a2); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int len) +{ + text = cdStrDupN(text, len); + fprintf(ctxcanvas->file, "%d %d %d %s\n", CDMF_TEXT, x, y, text); + free((char*)text); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text, int len) +{ + text = cdStrDupN(text, len); + fprintf(ctxcanvas->file, "%d %g %g %s\n", CDMF_FTEXT, x, y, text); + free((char*)text); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode) + { + fprintf(ctxcanvas->file, "%d %d\n", CDMF_FILLMODE, ctxcanvas->canvas->fill_mode); + ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode; + } + + fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode); + + for(i = 0; ifile, "%d %d %d\n", CDMF_VERTEX, poly[i].x, poly[i].y); + + fprintf(ctxcanvas->file, "%d\n", CDMF_END); +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + + if (mode == CD_FILL && ctxcanvas->canvas->fill_mode != ctxcanvas->last_fill_mode) + { + fprintf(ctxcanvas->file, "%d %d\n", CDMF_FILLMODE, ctxcanvas->canvas->fill_mode); + ctxcanvas->last_fill_mode = ctxcanvas->canvas->fill_mode; + } + + fprintf(ctxcanvas->file, "%d %d\n", CDMF_BEGIN, mode); + + for(i = 0; ifile, "%d %g %g\n", CDMF_FVERTEX, poly[i].x, poly[i].y); + + fprintf(ctxcanvas->file, "%d\n", CDMF_END); +} + +static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opacity) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_BACKOPACITY, opacity); + return opacity; +} + +static int cdwritemode(cdCtxCanvas *ctxcanvas, int mode) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_WRITEMODE, mode); + return mode; +} + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + if (style == CD_CUSTOM && ctxcanvas->canvas->line_style != ctxcanvas->last_line_style) + { + int i; + fprintf(ctxcanvas->file, "%d %d", CDMF_LINESTYLEDASHES, ctxcanvas->canvas->line_dashes_count); + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + fprintf(ctxcanvas->file, " %d", ctxcanvas->canvas->line_dashes[i]); + fprintf(ctxcanvas->file, "\n"); + ctxcanvas->last_line_style = ctxcanvas->canvas->line_style; + } + + fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINESTYLE, style); + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINEWIDTH, width); + return width; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINECAP, cap); + return cap; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_LINEJOIN, join); + return join; +} + +static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_INTERIORSTYLE, style); + return style; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_HATCH, style); + return style; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *stipple) +{ + int c, t; + + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_STIPPLE, w, h); + + t = w * h; + + for (c = 0; c < t; c++) + { + fprintf(ctxcanvas->file, "%d ", (int)*stipple++); + if ((c + 1) % w == 0) + fprintf(ctxcanvas->file, "\n"); + } +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *pattern) +{ + int c, t; + unsigned char r, g, b; + + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_PATTERN, w, h); + + t = w * h; + + /* stores the pattern with separeted RGB values */ + for (c = 0; c < t; c++) + { + cdDecodeColor(*pattern++, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d ", (int)r, (int)g, (int)b); + if (c % w == 0) + fprintf(ctxcanvas->file, "\n"); + } +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char* type_face, int style, int size) +{ + fprintf(ctxcanvas->file, "%d %d %d %s\n", CDMF_FONT, style, size, type_face); + return 1; +} + +static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* font) +{ + fprintf(ctxcanvas->file, "%d %s\n", CDMF_NATIVEFONT, font); + return 1; +} + +static int cdtextalignment(cdCtxCanvas *ctxcanvas, int alignment) +{ + fprintf(ctxcanvas->file, "%d %d\n", CDMF_TEXTALIGNMENT, alignment); + return alignment; +} + +static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle) +{ + fprintf(ctxcanvas->file, "%d %g\n", CDMF_TEXTORIENTATION, angle); + return angle; +} + +static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode) +{ + int c; + unsigned char r, g, b; + + fprintf(ctxcanvas->file, "%d %d %d\n", CDMF_PALETTE, n, mode); + + for (c = 0; c < n; c++) + { + cdDecodeColor(*palette++, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d\n", (int)r, (int)g, (int)b); + } +} + +static long cdbackground(cdCtxCanvas *ctxcanvas, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d %d\n", CDMF_BACKGROUND, (int)r, (int)g, (int)b); + return color; +} + +static long cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d %d\n", CDMF_FOREGROUND, (int)r, (int)g, (int)b); + return color; +} + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int c, l, offset; + + fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGERGB, iw, ih, x, y, w, h); + + offset = ymin*iw + xmin; + r += offset; + g += offset; + b += offset; + + offset = iw - (xmax-xmin+1); + + for (l = ymin; l <= ymax; l++) + { + for (c = xmin; c <= xmax; c++) + { + fprintf(ctxcanvas->file, "%d %d %d ", (int)*r++, (int)*g++, (int)*b++); + } + + r += offset; + g += offset; + b += offset; + + fprintf(ctxcanvas->file, "\n"); + } +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int c, l, offset; + + fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGERGBA, iw, ih, x, y, w, h); + + offset = ymin*iw + xmin; + r += offset; + g += offset; + b += offset; + a += offset; + + offset = iw - (xmax-xmin+1); + + for (l = ymin; l <= ymax; l++) + { + for (c = xmin; c <= xmax; c++) + { + fprintf(ctxcanvas->file, "%d %d %d %d ", (int)*r++, (int)*g++, (int)*b++, (int)*a++); + } + + r += offset; + g += offset; + b += offset; + a += offset; + + fprintf(ctxcanvas->file, "\n"); + } +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int c, l, n = 0, offset; + unsigned char r, g, b; + + fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_PUTIMAGEMAP, iw, ih, x, y, w, h); + + index += ymin*iw + xmin; + offset = iw - (xmax-xmin+1); + + for (l = ymin; l <= ymax; l++) + { + for (c = xmin; c <= xmax; c++) + { + if (*index > n) + n = *index; + + fprintf(ctxcanvas->file, "%d ", (int)*index++); + } + + index += offset; + + fprintf(ctxcanvas->file, "\n"); + } + + n++; + + for (c = 0; c < n; c++) + { + cdDecodeColor(*colors++, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d\n", (int)r, (int)g, (int)b); + } +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + unsigned char r, g, b; + cdDecodeColor(color, &r, &g, &b); + fprintf(ctxcanvas->file, "%d %d %d %d %d %d\n", CDMF_PIXEL, x, y, (int)r, (int)g, (int)b); +} + +static void cdscrollarea(cdCtxCanvas *ctxcanvas, int xmin,int xmax, int ymin,int ymax, int dx,int dy) +{ + fprintf(ctxcanvas->file, "%d %d %d %d %d %d %d\n", CDMF_SCROLLAREA, xmin, xmax, ymin, ymax, dx, dy); +} + + +/**********/ +/* cdPlay */ +/**********/ + + +static double factorX = 1; +static double factorY = 1; +static int offsetX = 0; +static int offsetY = 0; +static double factorS = 1; + +static int sScaleX(int x) +{ + return cdRound(x * factorX + offsetX); +} + +static int sScaleY(int y) +{ + return cdRound(y * factorY + offsetY); +} + +static double sfScaleX(double x) +{ + return x * factorX + offsetX; +} + +static double sfScaleY(double y) +{ + return y * factorY + offsetY; +} + +static int sScaleW(int w) +{ + w = (int)(w * factorX + 0.5); /* always positive */ + return w == 0? 1: w; +} + +static double sfScaleH(double h) +{ + h = h * factorY; + return h == 0? 1: h; +} + +static double sfScaleW(double w) +{ + w = w * factorX; /* always positive */ + return w == 0? 1: w; +} + +static int sScaleH(int h) +{ + h = (int)(h * factorY + 0.5); + return h == 0? 1: h; +} + +static int sScaleS(int s) +{ + s = (int)(s * factorS + 0.5); + return s == 0? 1: s; +} + +typedef int(*_cdsizecb)(cdCanvas* canvas, int w, int h, double w_mm, double h_mm); +static _cdsizecb cdsizecb = NULL; + +static int cdregistercallback(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdsizecb = (_cdsizecb)func; + return CD_OK; + } + + return CD_ERROR; +} + +static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + char* filename = (char*)data; + FILE* file; + char TextBuffer[512]; + int iparam1, iparam2, iparam3, iparam4, iparam5, iparam6, iparam7, iparam8, iparam9, iparam10; + int c, t, n, w, h, func; + double dparam1, dparam2, dparam3, dparam4, dparam5, dparam6; + unsigned char* stipple, * _stipple, *red, *green, *blue, *_red, *_green, *_blue, *index, *_index, *_alpha, *alpha; + long int *pattern, *palette, *_pattern, *_palette, *colors, *_colors; + int* dashes; + double matrix[6]; + const char * font_family[] = + { + "System", /* CD_SYSTEM */ + "Courier", /* CD_COURIER */ + "Times", /* CD_TIMES_ROMAN */ + "Helvetica" /* CD_HELVETICA */ + }; + + file = fopen(filename, "r"); + if (!file) + return CD_ERROR; + + func = -1; + w = 0; + h = 0; + + factorX = 1; + factorY = 1; + offsetX = 0; + offsetY = 0; + factorS = 1; + + fscanf(file, "%s %d %d", TextBuffer, &w, &h); + + if (strcmp(TextBuffer, "CDMF") != 0) + { + fclose(file); + return CD_ERROR; + } + + if (w>1 && h>1 && xmax!=0 && ymax!=0) + { + offsetX = xmin; + offsetY = ymin; + factorX = ((double)(xmax-xmin)) / (w-1); + factorY = ((double)(ymax-ymin)) / (h-1); + + if (factorX < factorY) + factorS = factorX; + else + factorS = factorY; + } + + if (cdsizecb) + { + int err; + err = cdsizecb(canvas, w, h, w, h); + if (err) + return CD_ERROR; + } + + while (!feof(file)) + { + fscanf(file, "%d", &func); + if (feof(file)) + break; + + switch (func) + { + case CDMF_FLUSH: + cdCanvasFlush(canvas); + break; + case CDMF_CLEAR: + cdCanvasClear(canvas); + break; + case CDMF_CLIP: + fscanf(file, "%d", &iparam1); + cdCanvasClip(canvas, iparam1); + break; + case CDMF_CLIPAREA: + fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4); + cdCanvasClipArea(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4)); + break; + case CDMF_FCLIPAREA: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + cdfCanvasClipArea(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4)); + break; + case CDMF_MATRIX: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5]); + cdCanvasTransform(canvas, matrix); + break; + case CDMF_RESETMATRIX: + cdCanvasTransform(canvas, NULL); + break; + case CDMF_WCLIPAREA: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasClipArea(canvas, dparam1, dparam2, dparam3, dparam4); + break; + case CDMF_LINE: + fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4); + cdCanvasLine(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleX(iparam3), sScaleY(iparam4)); + break; + case CDMF_FLINE: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + cdfCanvasLine(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleX(dparam3), sfScaleY(dparam4)); + break; + case CDMF_WLINE: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasLine(canvas, dparam1, dparam2, dparam3, dparam4); + break; + case CDMF_RECT: + fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4); + cdCanvasRect(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4)); + break; + case CDMF_FRECT: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + cdfCanvasRect(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4)); + break; + case CDMF_WRECT: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasRect(canvas, dparam1, dparam2, dparam3, dparam4); + break; + case CDMF_BOX: + fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4); + cdCanvasBox(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4)); + break; + case CDMF_WBOX: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasBox(canvas, dparam1, dparam2, dparam3, dparam4); + break; + case CDMF_FBOX: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + cdfCanvasBox(canvas, sfScaleX(dparam1), sfScaleX(dparam2), sfScaleY(dparam3), sfScaleY(dparam4)); + break; + case CDMF_ARC: + fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2); + cdCanvasArc(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2); + break; + case CDMF_FARC: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + cdfCanvasArc(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6); + break; + case CDMF_WARC: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + wdCanvasArc(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6); + break; + case CDMF_SECTOR: + fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2); + cdCanvasSector(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2); + break; + case CDMF_FSECTOR: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + cdfCanvasSector(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6); + break; + case CDMF_WSECTOR: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + wdCanvasSector(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6); + break; + case CDMF_CHORD: + fscanf(file, "%d %d %d %d %lg %lg", &iparam1, &iparam2, &iparam3, &iparam4, &dparam1, &dparam2); + cdCanvasChord(canvas, sScaleX(iparam1), sScaleY(iparam2), sScaleW(iparam3), sScaleH(iparam4), dparam1, dparam2); + break; + case CDMF_FCHORD: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + cdfCanvasChord(canvas, sfScaleX(dparam1), sfScaleY(dparam2), sfScaleW(dparam3), sfScaleH(dparam4), dparam5, dparam6); + break; + case CDMF_WCHORD: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4, &dparam5, &dparam6); + wdCanvasChord(canvas, dparam1, dparam2, dparam3, dparam4, dparam5, dparam6); + break; + case CDMF_TEXT: + fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer); + cdCanvasText(canvas, sScaleX(iparam1), sScaleY(iparam2), TextBuffer); + break; + case CDMF_FTEXT: + fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer); + cdfCanvasText(canvas, sfScaleX(dparam1), sfScaleY(dparam2), TextBuffer); + break; + case CDMF_WTEXT: + fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer); + wdCanvasText(canvas, dparam1, dparam2, TextBuffer); + break; + case CDMF_BEGIN: + fscanf(file, "%d", &iparam1); + cdCanvasBegin(canvas, iparam1); + break; + case CDMF_VERTEX: + fscanf(file, "%d %d", &iparam1, &iparam2); + cdCanvasVertex(canvas, sScaleX(iparam1), sScaleY(iparam2)); + break; + case CDMF_FVERTEX: + fscanf(file, "%lg %lg", &dparam1, &dparam2); + cdfCanvasVertex(canvas, sfScaleX(dparam1), sfScaleY(dparam2)); + break; + case CDMF_WVERTEX: + fscanf(file, "%lg %lg", &dparam1, &dparam2); + wdCanvasVertex(canvas, dparam1, dparam2); + break; + case CDMF_END: + cdCanvasEnd(canvas); + break; + case CDMF_MARK: + fscanf(file, "%d %d", &iparam1, &iparam2); + cdCanvasMark(canvas, sScaleX(iparam1), sScaleY(iparam2)); + break; + case CDMF_WMARK: + fscanf(file, "%lg %lg", &dparam1, &dparam2); + wdCanvasMark(canvas, dparam1, dparam2); + break; + case CDMF_BACKOPACITY: + fscanf(file, "%d", &iparam1); + cdCanvasBackOpacity(canvas, iparam1); + break; + case CDMF_WRITEMODE: + fscanf(file, "%d", &iparam1); + cdCanvasWriteMode(canvas, iparam1); + break; + case CDMF_LINESTYLE: + fscanf(file, "%d", &iparam1); + cdCanvasLineStyle(canvas, iparam1); + break; + case CDMF_LINEWIDTH: + fscanf(file, "%d", &iparam1); + cdCanvasLineWidth(canvas, sScaleS(iparam1)); + break; + case CDMF_LINECAP: + fscanf(file, "%d", &iparam1); + cdCanvasLineCap(canvas, iparam1); + break; + case CDMF_LINEJOIN: + fscanf(file, "%d", &iparam1); + cdCanvasLineJoin(canvas, iparam1); + break; + case CDMF_LINESTYLEDASHES: + fscanf(file, "%d", &iparam1); + dashes = (int*)malloc(iparam1*sizeof(int)); + for (c = 0; c < iparam1; c++) + fscanf(file, "%d", &dashes[c]); + cdCanvasLineStyleDashes(canvas, dashes, iparam1); + free(dashes); + break; + case CDMF_FILLMODE: + fscanf(file, "%d", &iparam1); + cdCanvasFillMode(canvas, iparam1); + break; + case CDMF_INTERIORSTYLE: + fscanf(file, "%d", &iparam1); + cdCanvasInteriorStyle(canvas, iparam1); + break; + case CDMF_HATCH: + fscanf(file, "%d", &iparam1); + cdCanvasHatch(canvas, iparam1); + break; + case CDMF_STIPPLE: + fscanf(file, "%d %d", &iparam1, &iparam2); + t = iparam1 * iparam2; + stipple = (unsigned char*)malloc(t); + _stipple = stipple; + for (c = 0; c < t; c++) + { + fscanf(file, "%d", &iparam3); + *_stipple++ = (unsigned char)iparam3; + } + cdCanvasStipple(canvas, iparam1, iparam2, stipple); + free(stipple); + break; + case CDMF_PATTERN: + fscanf(file, "%d %d", &iparam1, &iparam2); + t = iparam1 * iparam2; + pattern = (long int*)malloc(t * sizeof(long)); + _pattern = pattern; + for (c = 0; c < t; c++) + { + fscanf(file, "%d %d %d", &iparam3, &iparam4, &iparam5); + *_pattern++ = cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5); + } + cdCanvasPattern(canvas, iparam1, iparam2, pattern); + free(pattern); + break; + case CDMF_OLDFONT: + fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3); + if (iparam1 < 0 || iparam1 > 3) break; + if (iparam3 < 0) + { + iparam3 = -sScaleH(abs(iparam3)); + if (iparam3 > -5) iparam3 = -5; + } + else + { + iparam3 = sScaleH(abs(iparam3)); + if (iparam3 < 5) iparam3 = 5; + } + cdCanvasFont(canvas, font_family[iparam1], iparam2, iparam3); + break; + case CDMF_FONT: + fscanf(file, "%d %d %[^\n]", &iparam2, &iparam3, TextBuffer); + if (iparam3 < 0) + { + iparam3 = -sScaleH(abs(iparam3)); + if (iparam3 > -5) iparam3 = -5; + } + else + { + iparam3 = sScaleH(abs(iparam3)); + if (iparam3 < 5) iparam3 = 5; + } + cdCanvasFont(canvas, TextBuffer, iparam2, iparam3); + break; + case CDMF_NATIVEFONT: + fscanf(file, "%[^\n]", TextBuffer); + cdCanvasNativeFont(canvas, TextBuffer); + break; + case CDMF_TEXTALIGNMENT: + fscanf(file, "%d", &iparam1); + cdCanvasTextAlignment(canvas, iparam1); + break; + case CDMF_TEXTORIENTATION: + fscanf(file, "%lg", &dparam1); + cdCanvasTextOrientation(canvas, dparam1); + break; + case CDMF_MARKTYPE: + fscanf(file, "%d", &iparam1); + cdCanvasMarkType(canvas, iparam1); + break; + case CDMF_MARKSIZE: + fscanf(file, "%d", &iparam1); + cdCanvasMarkSize(canvas, sScaleS(iparam1)); + break; + case CDMF_PALETTE: + fscanf(file, "%d %d", &iparam1, &iparam2); + _palette = palette = (long int*)malloc(iparam1); + for (c = 0; c < iparam1; c++) + { + fscanf(file, "%d %d %d", &iparam3, &iparam4, &iparam5); + *_palette++ = cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5); + } + cdCanvasPalette(canvas, iparam1, palette, iparam2); + free(palette); + break; + case CDMF_BACKGROUND: + fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3); + cdCanvasSetBackground(canvas, cdEncodeColor((unsigned char)iparam1, (unsigned char)iparam2, (unsigned char)iparam3)); + break; + case CDMF_FOREGROUND: + fscanf(file, "%d %d %d", &iparam1, &iparam2, &iparam3); + cdCanvasSetForeground(canvas, cdEncodeColor((unsigned char)iparam1, (unsigned char)iparam2, (unsigned char)iparam3)); + break; + case CDMF_PUTIMAGERGB: + fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6); + t = iparam1 * iparam2; + _red = red = (unsigned char*) malloc(t); + _green = green = (unsigned char*) malloc(t); + _blue = blue = (unsigned char*) malloc(t); + for (c = 0; c < t; c++) + { + fscanf(file, "%d %d %d", &iparam7, &iparam8, &iparam9); + *_red++ = (unsigned char)iparam7; + *_green++ = (unsigned char)iparam8; + *_blue++ = (unsigned char)iparam9; + } + cdCanvasPutImageRectRGB(canvas, iparam1, iparam2, red, green, blue, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0); + free(red); + free(green); + free(blue); + break; + case CDMF_PUTIMAGERGBA: + fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6); + t = iparam1 * iparam2; + _red = red = (unsigned char*) malloc(t); + _green = green = (unsigned char*) malloc(t); + _blue = blue = (unsigned char*) malloc(t); + _alpha = alpha = (unsigned char*) malloc(t); + for (c = 0; c < t; c++) + { + fscanf(file, "%d %d %d %d", &iparam7, &iparam8, &iparam9, &iparam10); + *_red++ = (unsigned char)iparam7; + *_green++ = (unsigned char)iparam8; + *_blue++ = (unsigned char)iparam9; + *_alpha++ = (unsigned char)iparam10; + } + cdCanvasPutImageRectRGBA(canvas, iparam1, iparam2, red, green, blue, alpha, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0); + free(red); + free(green); + free(blue); + free(alpha); + break; + case CDMF_PUTIMAGEMAP: + fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6); + t = iparam1 * iparam2; + n = 0; + _index = index = (unsigned char*) malloc(t); + for (c = 0; c < t; c++) + { + fscanf(file, "%d", &iparam7); + *_index++ = (unsigned char)iparam7; + if (iparam7 > n) + n = iparam7; + } + _colors = colors = (long int*)malloc(n); + for (c = 0; c < n; c++) + { + fscanf(file, "%d %d %d", &iparam7, &iparam8, &iparam9); + *_colors++ = cdEncodeColor((unsigned char)iparam7, (unsigned char)iparam8, (unsigned char)iparam9); + } + cdCanvasPutImageRectMap(canvas, iparam1, iparam2, index, colors, sScaleX(iparam3), sScaleY(iparam4), sScaleW(iparam5), sScaleH(iparam6), 0, 0, 0, 0); + free(index); + free(colors); + break; + case CDMF_PIXEL: + fscanf(file, "%d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5); + cdCanvasPixel(canvas, sScaleX(iparam1), sScaleY(iparam2), cdEncodeColor((unsigned char)iparam3, (unsigned char)iparam4, (unsigned char)iparam5)); + break; + case CDMF_SCROLLAREA: + fscanf(file, "%d %d %d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4, &iparam5, &iparam6); + cdCanvasScrollArea(canvas, sScaleX(iparam1), sScaleX(iparam2), sScaleY(iparam3), sScaleY(iparam4), sScaleX(iparam5), sScaleY(iparam6)); + break; + case CDMF_WVECTORTEXT: + fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer); + wdCanvasVectorText(canvas, dparam1, dparam2, TextBuffer); + break; + case CDMF_WMULTILINEVECTORTEXT: + fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer); + wdCanvasVectorText(canvas, dparam1, dparam2, TextBuffer); + break; + case CDMF_VECTORTEXT: + fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer); + cdCanvasVectorText(canvas, iparam1, iparam2, TextBuffer); + break; + case CDMF_MULTILINEVECTORTEXT: + fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer); + cdCanvasVectorText(canvas, iparam1, iparam2, TextBuffer); + break; + case CDMF_WVECTORCHARSIZE: + fscanf(file, "%lg", &dparam1); + wdCanvasVectorCharSize(canvas, dparam1); + break; + case CDMF_WVECTORTEXTSIZE: + fscanf(file, "%lg %lg %[^\n]", &dparam1, &dparam2, TextBuffer); + wdCanvasVectorTextSize(canvas, dparam1, dparam2, TextBuffer); + break; + case CDMF_WVECTORTEXTDIRECTION: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasVectorTextDirection(canvas, dparam1, dparam2, dparam3, dparam4); + break; + case CDMF_VECTORCHARSIZE: + fscanf(file, "%d", &iparam1); + cdCanvasVectorCharSize(canvas, iparam1); + break; + case CDMF_VECTORTEXTSIZE: + fscanf(file, "%d %d %[^\n]", &iparam1, &iparam2, TextBuffer); + cdCanvasVectorTextSize(canvas, iparam1, iparam2, TextBuffer); + break; + case CDMF_VECTORTEXTDIRECTION: + fscanf(file, "%d %d %d %d", &iparam1, &iparam2, &iparam3, &iparam4); + cdCanvasVectorTextDirection(canvas, iparam1, iparam2, iparam3, iparam4); + break; + case CDMF_VECTORFONT: + fscanf(file, "%[^\n]", TextBuffer); + cdCanvasVectorFont(canvas, TextBuffer); + break; + case CDMF_VECTORTEXTTRANSFORM: + fscanf(file, "%lg %lg %lg %lg %lg %lg", &matrix[0], &matrix[1], &matrix[2], &matrix[3], &matrix[4], &matrix[5]); + cdCanvasVectorTextTransform(canvas, matrix); + break; + case CDMF_WINDOW: + fscanf(file, "%lg %lg %lg %lg", &dparam1, &dparam2, &dparam3, &dparam4); + wdCanvasWindow(canvas, dparam1, dparam2, dparam3, dparam4); + break; + default: + fclose(file); + return CD_ERROR; + } + } + + fclose(file); + + return CD_OK; +} + +/*******************/ +/* Canvas Creation */ +/*******************/ + +void cdcreatecanvasMF(cdCanvas *canvas, void *data) +{ + char filename[10240] = ""; + char* strdata = (char*)data; + double w_mm = INT_MAX*3.78, h_mm = INT_MAX*3.78, res = 3.78; + cdCtxCanvas* ctxcanvas; + int size; + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata, "%lgx%lg %lg", &w_mm, &h_mm, &res); + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + ctxcanvas->file = fopen(filename, "w"); + if (!ctxcanvas->file) + { + free(ctxcanvas); + return; + } + + size = strlen(filename); + ctxcanvas->filename = malloc(size+1); + memcpy(ctxcanvas->filename, filename, size+1); + + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->w = (int)(w_mm * res); + canvas->h = (int)(h_mm * res); + canvas->w_mm = w_mm; + canvas->h_mm = h_mm; + canvas->bpp = 24; + canvas->xres = res; + canvas->yres = res; + canvas->ctxcanvas = ctxcanvas; + + ctxcanvas->last_line_style = -1; + ctxcanvas->last_fill_mode = -1; + + fprintf(ctxcanvas->file, "CDMF %d %d\n", canvas->w, canvas->h); +} + +void cdinittableMF(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxClear = cdclear; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxScrollArea = cdscrollarea; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFChord = cdfchord; + canvas->cxFText = cdftext; + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxWriteMode = cdwritemode; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxTextOrientation = cdtextorientation; + canvas->cxPalette = cdpalette; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxFClipArea = cdfcliparea; + canvas->cxTransform = cdtransform; + + canvas->cxKillCanvas = (void (*)(cdCtxCanvas*))cdkillcanvasMF; +} + +static cdContext cdMetafileContext = +{ + CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_REGION | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE), + 0, + cdcreatecanvasMF, + cdinittableMF, + cdplay, + cdregistercallback, +}; + +cdContext* cdContextMetafile(void) +{ + return &cdMetafileContext; +} diff --git a/cd/src/drv/cdpdf.c b/cd/src/drv/cdpdf.c new file mode 100755 index 0000000..79ce28f --- /dev/null +++ b/cd/src/drv/cdpdf.c @@ -0,0 +1,1491 @@ +/** \file + * \brief PDF Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cdpdf.h" + +#include "pdflib.h" + + +/* +** dada uma cor do CD, obtem uma de suas componentes, na faixa 0-1. +*/ +#define get_red(_) (((double)cdRed(_))/255.) +#define get_green(_) (((double)cdGreen(_))/255.) +#define get_blue(_) (((double)cdBlue(_))/255.) + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + PDF *pdf; /* Arquivo PDF */ + int res; /* Resolucao - DPI */ + int pages; /* Numero total de paginas */ + double width_pt; /* Largura do papel (points) */ + double height_pt; /* Altura do papel (points) */ + double width_mm; /* Largura do papel (mm) */ + double height_mm; /* Altura do papel (mm) */ + double scale; /* Fator de conversao de coordenadas (pixel2points) */ + int landscape; /* page orientation */ + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + int font; + int underline; + int strikeover; + + int hatchboxsize; + int pattern; + int opacity; + int opacity_states[256]; + + int poly_holes[500]; + int holes; +}; + + +/* +%F Ajusta o tamanho do papel em points. +*/ +static void setpdfpapersize(cdCtxCanvas* ctxcanvas, int size) +{ + static struct + { + int width; + int height; + } paper[] = + { + { 2393, 3391 }, /* A0 */ + { 1689, 2393 }, /* A1 */ + { 1192, 1689 }, /* A2 */ + { 842, 1192 }, /* A3 */ + { 595, 842 }, /* A4 */ + { 420, 595 }, /* A5 */ + { 612, 792 }, /* LETTER */ + { 612, 1008 } /* LEGAL */ + }; + + if (sizeCD_LEGAL) + return; + + ctxcanvas->width_pt = paper[size].width; + ctxcanvas->height_pt = paper[size].height; + ctxcanvas->width_mm = ctxcanvas->width_pt/CD_MM2PT; + ctxcanvas->height_mm = ctxcanvas->height_pt/CD_MM2PT; +} + +/* +%F Registra os valores default para impressao. +*/ +static void setpdfdefaultvalues(cdCtxCanvas* ctxcanvas) +{ + int i; + + /* all the other values are set to 0 */ + setpdfpapersize(ctxcanvas, CD_A4); + ctxcanvas->res = 300; + ctxcanvas->hatchboxsize = 8; + ctxcanvas->opacity = 255; /* full opaque */ + + for (i=0; i<256; i++) + ctxcanvas->opacity_states[i] = -1; +} + +static void update_state(cdCtxCanvas *ctxcanvas) +{ + cdCanvas* canvas = ctxcanvas->canvas; + + if (!canvas->cxFont) /* just check if the first time */ + return; + + /* must set the current transform and line style if different from the default */ + + if (canvas->line_style != CD_CONTINUOUS) + canvas->cxLineStyle(ctxcanvas, canvas->line_style); + if (canvas->line_width != 1) + canvas->cxLineWidth(ctxcanvas, canvas->line_width); + if (canvas->line_cap != CD_CAPFLAT) + canvas->cxLineCap(ctxcanvas, canvas->line_cap); + if (canvas->line_join != CD_MITER) + canvas->cxLineJoin(ctxcanvas, canvas->line_join); + if (canvas->use_matrix) + canvas->cxTransform(ctxcanvas, canvas->matrix); + canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); +} + +static void begin_page(cdCtxCanvas *ctxcanvas) +{ + PDF_begin_page_ext(ctxcanvas->pdf, ctxcanvas->width_pt, ctxcanvas->height_pt, ""); + + /* default coordinate system is in points, change it to pixels. */ + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + PDF_save(ctxcanvas->pdf); /* save the initial configuration, to be used when clipping is reset. */ + + update_state(ctxcanvas); +} + +static void init_pdf(cdCtxCanvas *ctxcanvas) +{ + ctxcanvas->scale = 72.0/ctxcanvas->res; + + /* Converte p/ unidades do usuario */ + ctxcanvas->canvas->w = (int)(ctxcanvas->width_pt/ctxcanvas->scale + 0.5); + ctxcanvas->canvas->h = (int)(ctxcanvas->height_pt/ctxcanvas->scale + 0.5); + + /* Passa o valor em milimetros para o canvas CD */ + ctxcanvas->canvas->w_mm = ctxcanvas->width_mm; + ctxcanvas->canvas->h_mm = ctxcanvas->height_mm; + + ctxcanvas->canvas->bpp = 24; + ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm; + ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm; + + begin_page(ctxcanvas); +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration. */ + PDF_end_page_ext(ctxcanvas->pdf, ""); + PDF_end_document(ctxcanvas->pdf, ""); + PDF_delete(ctxcanvas->pdf); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void update_fill(cdCtxCanvas *ctxcanvas, int fill) +{ + if (fill == 0) + { + /* called before a NON filled primitive */ + PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + + } + else + { + /* called before a filled primitive */ + if (ctxcanvas->canvas->interior_style == CD_SOLID) + { + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + } + else + PDF_setcolor(ctxcanvas->pdf, "fill", "pattern", (float)ctxcanvas->pattern, 0, 0, 0); + } +} + +/* +%F Comeca uma nova pagina. +*/ +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + PDF_restore(ctxcanvas->pdf); /* restore to match the save of the initial configuration */ + + PDF_end_page_ext(ctxcanvas->pdf, ""); + + begin_page(ctxcanvas); +} + + +/******************************************************/ +/* coordinate transformation */ +/******************************************************/ + +static void resetcliprect(cdCtxCanvas* ctxcanvas) +{ + /* clipping is reset, by restoring the initial state */ + /* this will also reset the current transformation and line style */ + PDF_restore(ctxcanvas->pdf); + PDF_save(ctxcanvas->pdf); + + update_state(ctxcanvas); +} + +static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax) +{ + resetcliprect(ctxcanvas); + + PDF_moveto(ctxcanvas->pdf, xmin, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymax); + PDF_lineto(ctxcanvas->pdf, xmin, ymax); + + PDF_clip(ctxcanvas->pdf); +} + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA) + return; + + setcliprect(ctxcanvas, xmin, ymin, xmax, ymax); +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfcliparea(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + if (mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_mode = CD_CLIPAREA; + + setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin, + (double)ctxcanvas->canvas->clip_rect.ymin, + (double)ctxcanvas->canvas->clip_rect.xmax, + (double)ctxcanvas->canvas->clip_rect.ymax); + } + else if (mode == CD_CLIPPOLYGON) + { + int hole_index = 0; + int i; + + resetcliprect(ctxcanvas); + + if (ctxcanvas->canvas->clip_poly) + { + cdPoint *poly = ctxcanvas->canvas->clip_poly; + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + for (i=1; icanvas->clip_poly_n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + else if (ctxcanvas->canvas->clip_fpoly) + { + cdfPoint *poly = ctxcanvas->canvas->clip_fpoly; + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + for (i=1; icanvas->clip_poly_n; i++) + { + if (ctxcanvas->holes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + PDF_clip(ctxcanvas->pdf); + } + else if (mode == CD_CLIPOFF) + { + resetcliprect(ctxcanvas); + } + + return mode; +} + +/******************************************************/ +/* primitives */ +/******************************************************/ + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + update_fill(ctxcanvas, 0); + + PDF_moveto(ctxcanvas->pdf, x1, y1); + PDF_lineto(ctxcanvas->pdf, x2, y2); + PDF_stroke(ctxcanvas->pdf); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 0); + + PDF_rect(ctxcanvas->pdf, xmin, ymin, xmax-xmin, ymax-ymin); + PDF_stroke(ctxcanvas->pdf); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfrect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 1); + + PDF_moveto(ctxcanvas->pdf, xmin, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymin); + PDF_lineto(ctxcanvas->pdf, xmax, ymax); + PDF_lineto(ctxcanvas->pdf, xmin, ymax); + PDF_fill(ctxcanvas->pdf); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfbox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 0); + + if (w==h) + { + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_stroke(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); + + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + PDF_stroke(ctxcanvas->pdf); + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfarc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) + { + PDF_moveto(ctxcanvas->pdf, xc, yc); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, w/h, 1); + PDF_translate(ctxcanvas->pdf, -xc, -yc); + + PDF_moveto(ctxcanvas->pdf, xc, yc); + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*h, a1, a2); + + if (ctxcanvas->canvas->interior_style == CD_SOLID || + ctxcanvas->canvas->interior_style == CD_PATTERN) + PDF_fill(ctxcanvas->pdf); + else + { + PDF_lineto(ctxcanvas->pdf, xc, yc); + PDF_stroke(ctxcanvas->pdf); + } + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfsector(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) + { + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill_stroke(ctxcanvas->pdf); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + PDF_save(ctxcanvas->pdf); /* save to use the local transform */ + + /* local transform */ + PDF_translate(ctxcanvas->pdf, xc, yc); + PDF_scale(ctxcanvas->pdf, 1, w/h); + + PDF_arc(ctxcanvas->pdf, xc, yc, 0.5*w, a1, a2); + PDF_fill_stroke(ctxcanvas->pdf); + + PDF_restore(ctxcanvas->pdf); /* restore from local */ + } +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + cdfchord(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + double fontsize, a, d, linegap; + + if (ctxcanvas->font<0) + return; + + fontsize = PDF_get_value(ctxcanvas->pdf, "fontsize", 0); + a = PDF_get_value(ctxcanvas->pdf, "ascender", 0); + d = PDF_get_value(ctxcanvas->pdf, "descender", 0); + + /* linegap = PDF_info_font(ctxcanvas->pdf, 1, "linegap", ""); - not supported call */ + linegap = 0.23 * a; /* use default value for linegap */ + a += linegap; + d += linegap; /* since d<0, it is a subtraction */ + + a *= fontsize; + d *= fontsize; + + if (ascent) *ascent = (int)a; + if (descent) *descent = (int)(-d); + if (height) *height = (int)(a - d); + if (max_width) *max_width = (int)(PDF_info_textline(ctxcanvas->pdf, "W", 0, "width", "")/ctxcanvas->scale); +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int len, int *width, int *height) +{ + if (ctxcanvas->font<0) + return; + if (height) cdgetfontdim(ctxcanvas, NULL, height, NULL, NULL); + if (width) *width = (int)(PDF_info_textline(ctxcanvas->pdf, s, len, "width", "")/ctxcanvas->scale); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *s, int len) +{ + char temp[200], options[200]; + + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground), 0); + + strcpy(options, ""); + + sprintf(temp, "rotate=%g ", ctxcanvas->canvas->text_orientation); + strcat(options, temp); + + if (ctxcanvas->underline != 0) + strcat(options, "underline=true "); + else + strcat(options, "underline=false "); + + if (ctxcanvas->strikeover != 0) + strcat(options, "strikeout=true "); + else + strcat(options, "strikeout=false "); + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_NORTH: + sprintf(temp, "position={50 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_NORTH_EAST: + sprintf(temp, "position={100 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_NORTH_WEST: + sprintf(temp, "position={0 100} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_EAST: + sprintf(temp, "position={100 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_WEST: + sprintf(temp, "position={0 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_CENTER: + sprintf(temp, "position={50 50} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH_EAST: + sprintf(temp, "position={100 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH: + sprintf(temp, "position={50 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_SOUTH_WEST: + sprintf(temp, "position={0 0} matchbox { boxheight={ascender descender} }"); + strcat(options, temp); + break; + case CD_BASE_RIGHT: + sprintf(temp, "position={100 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + case CD_BASE_CENTER: + sprintf(temp, "position={50 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + case CD_BASE_LEFT: + sprintf(temp, "position={0 0} matchbox { boxheight={ascender none} }"); + strcat(options, temp); + break; + } + + PDF_fit_textline(ctxcanvas->pdf, s, len, x, y, options); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + cdftext(ctxcanvas, (double)x, (double)y, s, len); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (mode==CD_FILL) + { + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); + else + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding"); + } + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + if (mode == CD_BEZIER) + { + for (i=1; ipdf, poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + } + else + { + int hole_index = 0; + + for (i=1; iholes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + switch (mode) + { + case CD_CLOSED_LINES : + PDF_closepath_stroke(ctxcanvas->pdf); + break; + case CD_OPEN_LINES : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_BEZIER : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_FILL : + PDF_fill(ctxcanvas->pdf); + break; + } +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + return; + + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (mode==CD_FILL) + { + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "evenodd"); + else + PDF_set_parameter(ctxcanvas->pdf, "fillrule", "winding"); + } + + PDF_moveto(ctxcanvas->pdf, poly[0].x, poly[0].y); + + if (mode == CD_BEZIER) + { + for (i=1; ipdf, poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + } + else + { + int hole_index = 0; + + for (i=1; iholes && i == ctxcanvas->poly_holes[hole_index]) + { + PDF_moveto(ctxcanvas->pdf, poly[i].x, poly[i].y); + hole_index++; + } + else + PDF_lineto(ctxcanvas->pdf, poly[i].x, poly[i].y); + } + } + + switch (mode) + { + case CD_CLOSED_LINES : + PDF_closepath_stroke(ctxcanvas->pdf); + break; + case CD_OPEN_LINES : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_BEZIER : + PDF_stroke(ctxcanvas->pdf); + break; + case CD_FILL : + PDF_fill(ctxcanvas->pdf); + break; + } +} + +/******************************************************/ +/* attributes */ +/******************************************************/ + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + double mm = (72.0/25.4) / ctxcanvas->scale; + char options[80]; + + switch (style) + { + case CD_CONTINUOUS : /* empty dash */ + PDF_setdash(ctxcanvas->pdf, 0, 0); + break; + case CD_DASHED : + PDF_setdash(ctxcanvas->pdf, 3*mm, mm); + break; + case CD_DOTTED : + PDF_setdash(ctxcanvas->pdf, mm, mm); + break; + case CD_DASH_DOT : + sprintf(options, "dasharray={%g %g %g %g}", 3*mm, mm, mm, mm); + PDF_setdashpattern(ctxcanvas->pdf, options); + break; + case CD_DASH_DOT_DOT : + sprintf(options, "dasharray={%g %g %g %g %g %g}", 3*mm, mm, mm, mm, mm, mm); + PDF_setdashpattern(ctxcanvas->pdf, options); + break; + case CD_CUSTOM : + { + int i; + + strcpy(options, "dasharray={"); + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + { + char tmp[80]; + sprintf(tmp, "%g ", ctxcanvas->canvas->line_dashes[i]*mm); + strcat(options, tmp); + } + strcat(options, "}"); + PDF_setdashpattern(ctxcanvas->pdf, options); + } + break; + } + + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + if (width==0) width = 1; + + PDF_setlinewidth(ctxcanvas->pdf, width); + + return width; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + int cd2ps_join[] = {0, 2, 1}; + PDF_setlinejoin(ctxcanvas->pdf, cd2ps_join[join]); + return join; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + int cd2pdf_cap[] = {0, 2, 1}; + PDF_setlinecap(ctxcanvas->pdf, cd2pdf_cap[cap]); + return cap; +} + +static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, int (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)) +{ + int i, j; + unsigned char r, g, b; + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m, + ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1); + + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + for (j=0; jpdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + PDF_rect(ctxcanvas->pdf, i, j, 1, 1); + PDF_fill(ctxcanvas->pdf); + } + } + + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); +} + +static int long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + long* long_data = (long*)data; + (void)ctxcanvas; + cdDecodeColor(long_data[j*n+i], r, g, b); + return 1; +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ + make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb); +} + +static int uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + int ret = 1; + unsigned char* uchar_data = (unsigned char*)data; + if (uchar_data[j*n+i]) + { + cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); + ret = 1; + } + else + { + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); + if (ctxcanvas->canvas->back_opacity==CD_TRANSPARENT) + ret = -1; + } + + return ret; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ + make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); +} + +static void make_hatch(cdCtxCanvas *ctxcanvas, int style) +{ + unsigned char r, g, b; + int hsize = ctxcanvas->hatchboxsize - 1; + int hhalf = hsize / 2; + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, hsize + 1, hsize + 1, + ((double)hsize)*ctxcanvas->scale, ((double)hsize)*ctxcanvas->scale, 1); + + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + if (ctxcanvas->canvas->back_opacity==CD_OPAQUE) + { + cdDecodeColor(ctxcanvas->canvas->background, &r, &g, &b); + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + PDF_rect(ctxcanvas->pdf, 0, 0, hsize, hsize); + PDF_fill(ctxcanvas->pdf); + } + + cdDecodeColor(ctxcanvas->canvas->foreground, &r, &g, &b); + PDF_setcolor(ctxcanvas->pdf, "stroke", "rgb", ((double)r)/255, ((double)g)/255, ((double)b)/255, 0); + + switch(style) + { + case CD_HORIZONTAL: + PDF_moveto(ctxcanvas->pdf, 0, hhalf); + PDF_lineto(ctxcanvas->pdf, hsize, hhalf); + break; + case CD_VERTICAL: + PDF_moveto(ctxcanvas->pdf, hhalf, 0); + PDF_lineto(ctxcanvas->pdf, hhalf, hsize); + break; + case CD_BDIAGONAL: + PDF_moveto(ctxcanvas->pdf, 0, hsize); + PDF_lineto(ctxcanvas->pdf, hsize, 0); + break; + case CD_FDIAGONAL: + PDF_moveto(ctxcanvas->pdf, 0, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + break; + case CD_CROSS: + PDF_moveto(ctxcanvas->pdf, hsize, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + PDF_moveto(ctxcanvas->pdf, 0, hhalf); + PDF_lineto(ctxcanvas->pdf, hsize, hhalf); + break; + case CD_DIAGCROSS: + PDF_moveto(ctxcanvas->pdf, 0, 0); + PDF_lineto(ctxcanvas->pdf, hsize, hsize); + PDF_moveto(ctxcanvas->pdf, hsize, 0); + PDF_lineto(ctxcanvas->pdf, 0, hsize); + break; + } + + PDF_stroke(ctxcanvas->pdf); + + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + make_hatch(ctxcanvas, style); + return style; +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + int newfont, sizepixel; + char nativefontname[1024]; + const char* options = ""; + + if (cdStrEqualNoCase(type_face, "System")) + type_face = "Courier"; + + strcpy(nativefontname, type_face); + + if (cdStrEqualNoCase(type_face, "Courier") || + cdStrEqualNoCase(type_face, "Helvetica")) + { + if (style&CD_BOLD && style&CD_ITALIC) + strcat(nativefontname, "-BoldOblique"); + else + { + if (style&CD_BOLD) + strcat(nativefontname, "-Bold"); + + if (style&CD_ITALIC) + strcat(nativefontname, "-Oblique"); + } + } + else if (cdStrEqualNoCase(type_face, "Times")) + { + if ((style&3) == CD_PLAIN) + strcat(nativefontname, "-Roman"); + if (style&CD_BOLD && style&CD_ITALIC) + strcat(nativefontname, "-BoldItalic"); + else + { + if (style&CD_BOLD) + strcat(nativefontname, "-Bold"); + + if (style&CD_ITALIC) + strcat(nativefontname, "-Italic"); + } + } + else + { + switch(style&3) + { + case CD_PLAIN: + options = "fontstyle=normal"; + break; + case CD_BOLD: + options = "fontstyle=bold"; + break; + case CD_ITALIC: + options = "fontstyle=italic"; + break; + case CD_BOLD_ITALIC: + options = "fontstyle=bolditalic"; + break; + } + } + + newfont = PDF_load_font(ctxcanvas->pdf, nativefontname, 0, "auto", options); + if (newfont<0) + { + /* must reload the previous one */ + return 0; + } + ctxcanvas->font = newfont; + + sizepixel = cdGetFontSizePixels(ctxcanvas->canvas, size); + PDF_setfont(ctxcanvas->pdf, ctxcanvas->font, sizepixel); + + if (style&CD_UNDERLINE) + ctxcanvas->underline = 1; + else + ctxcanvas->underline = 0; + + if (style&CD_STRIKEOUT) + ctxcanvas->strikeover = 1; + else + ctxcanvas->strikeover = 0; + + return 1; +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); + + /* default coordinate system is in points, change it to pixels. */ + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + + if (matrix) + { + PDF_concat(ctxcanvas->pdf, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + else if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle); + PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } +} + +/******************************************************/ +/* client images */ +/******************************************************/ + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, image, rw, rh, rgb_size; + char options[80]; + unsigned char* rgb_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + rgb_data[d] = r[i*iw+j]; d++; + rgb_data[d] = g[i*iw+j]; d++; + rgb_data[d] = b[i*iw+j]; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + + sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, image, image_mask, rw, rh, alpha_size, rgb_size; + char options[80]; + unsigned char *rgb_data, *alpha_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + rgb_data[d] = r[i*iw+j]; d++; + rgb_data[d] = g[i*iw+j]; d++; + rgb_data[d] = b[i*iw+j]; d++; + } + + alpha_size = rw*rh; + alpha_data = (unsigned char*)malloc(alpha_size); + if (!alpha_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + alpha_data[d] = a[i*iw+j]; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0, alpha_data, alpha_size, ""); + + sprintf(options, "width=%d height=%d components=1 bpc=8 imagewarning=true", rw, rh); + image_mask = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_alpha", 0, options); + + sprintf(options, "width=%d height=%d components=3 bpc=8 masked=%d", rw, rh, image_mask); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_alpha", 0); + free(alpha_data); + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, d, rw, rh, image, rgb_size; + char options[80]; + unsigned char* rgb_data; + + if (xmin<0 || ymin<0 || xmax-xmin+1>iw || ymax-ymin+1>ih) return; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + rgb_size = 3*rw*rh; + rgb_data = (unsigned char*)malloc(rgb_size); + if (!rgb_data) return; + + d = 0; + for (i=ymax; i>=ymin; i--) + for (j=xmin; j<=xmax; j++) + { + unsigned char r, g, b; + cdDecodeColor(colors[index[i*iw+j]], &r, &g, &b); + rgb_data[d] = r; d++; + rgb_data[d] = g; d++; + rgb_data[d] = b; d++; + } + + PDF_create_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0, rgb_data, rgb_size, ""); + + sprintf(options, "width=%d height=%d components=3 bpc=8", rw, rh); + image = PDF_load_image(ctxcanvas->pdf, "raw", "cd_raw_rgb", 0, options); + + sprintf(options, "boxsize={%d %d} fitmethod=meet", w, h); + PDF_fit_image(ctxcanvas->pdf, image, x, y, options); + + PDF_delete_pvf(ctxcanvas->pdf, "cd_raw_rgb", 0); + free(rgb_data); +} + +/******************************************************/ +/* server images */ +/******************************************************/ + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + PDF_setcolor(ctxcanvas->pdf, "fill", "rgb", get_red(color), get_green(color), get_blue(color), 0); + + PDF_moveto(ctxcanvas->pdf, x, y); + PDF_circle(ctxcanvas->pdf, x, y, .5); + + PDF_fill(ctxcanvas->pdf); +} + +/******************************************************/ +/* custom attributes */ +/******************************************************/ + +static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hole; + + if (data == NULL) + { + ctxcanvas->holes = 0; + return; + } + + sscanf(data, "%d", &hole); + ctxcanvas->poly_holes[ctxcanvas->holes] = hole; + ctxcanvas->holes++; +} + +static char* get_poly_attrib(cdCtxCanvas *ctxcanvas) +{ + static char holes[10]; + sprintf(holes, "%d", ctxcanvas->holes); + return holes; +} + +static cdAttribute poly_attrib = +{ + "POLYHOLE", + set_poly_attrib, + get_poly_attrib +}; + +static void set_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hatchboxsize; + + if (data == NULL) + { + ctxcanvas->hatchboxsize = 8; + return; + } + + sscanf(data, "%d", &hatchboxsize); + ctxcanvas->hatchboxsize = hatchboxsize; +} + +static char* get_hatchboxsize_attrib(cdCtxCanvas *ctxcanvas) +{ + static char size[10]; + sprintf(size, "%d", ctxcanvas->hatchboxsize); + return size; +} + +static cdAttribute hatchboxsize_attrib = +{ + "HATCHBOXSIZE", + set_hatchboxsize_attrib, + get_hatchboxsize_attrib +}; + +static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + /* ignore ROTATE if transform is set */ + if (ctxcanvas->canvas->use_matrix) + return; + + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + } + + PDF_setmatrix(ctxcanvas->pdf, 1, 0, 0, 1, 0, 0); + + if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + PDF_translate(ctxcanvas->pdf, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + PDF_rotate(ctxcanvas->pdf, (double)ctxcanvas->rotate_angle); + PDF_translate(ctxcanvas->pdf, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } +} + +static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void set_pattern_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + if (data) + { + int n, m; + sscanf(data, "%dx%d", &n, &m); + + PDF_suspend_page(ctxcanvas->pdf, ""); + ctxcanvas->pattern = PDF_begin_pattern(ctxcanvas->pdf, n, m, + ((double)n)*ctxcanvas->scale, ((double)m)*ctxcanvas->scale, 1); + PDF_scale(ctxcanvas->pdf, ctxcanvas->scale, ctxcanvas->scale); + } + else + { + PDF_end_pattern(ctxcanvas->pdf); + PDF_resume_page(ctxcanvas->pdf, ""); + ctxcanvas->canvas->interior_style = CD_PATTERN; + } +} + +static cdAttribute pattern_attrib = +{ + "PATTERN", + set_pattern_attrib, + NULL +}; + +static void set_opacity_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int state; + + if (data) + { + sscanf(data, "%d", &ctxcanvas->opacity); + if (ctxcanvas->opacity < 0) ctxcanvas->opacity = 0; + if (ctxcanvas->opacity > 255) ctxcanvas->opacity = 255; + } + else + ctxcanvas->opacity = 255; + + /* reuse the extended graphics state if the opacity is the same */ + if (ctxcanvas->opacity_states[ctxcanvas->opacity] == -1) + { + char options[50]; + sprintf(options, "opacityfill=%g opacitystroke=%g", ctxcanvas->opacity/255.0, ctxcanvas->opacity/255.0); + state = PDF_create_gstate(ctxcanvas->pdf, options); + ctxcanvas->opacity_states[ctxcanvas->opacity] = state; + } + else + state = ctxcanvas->opacity_states[ctxcanvas->opacity]; + + PDF_set_gstate(ctxcanvas->pdf, state); +} + +static char* get_opacity_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[50]; + sprintf(data, "%d", ctxcanvas->opacity); + return data; +} + +static cdAttribute opacity_attrib = +{ + "OPACITY", + set_opacity_attrib, + get_opacity_attrib +}; + +static char* get_pdf_attrib(cdCtxCanvas *ctxcanvas) +{ + return (char*)ctxcanvas->pdf; +} + +static cdAttribute pdf_attrib = +{ + "PDF", + NULL, + get_pdf_attrib +}; + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char *line = (char *)data; + cdCtxCanvas *ctxcanvas; + char filename[10240] = ""; + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + line += cdGetFileName(line, filename); + if (filename[0] == 0) + return; + + ctxcanvas->pdf = PDF_new(); + if (!ctxcanvas->pdf) + { + free(ctxcanvas); + return; + } + + if (PDF_begin_document(ctxcanvas->pdf, filename, 0, "") == -1) + { + PDF_delete(ctxcanvas->pdf); + free(ctxcanvas); + return; + } + + PDF_set_parameter(ctxcanvas->pdf, "fontwarning", "false"); + PDF_set_parameter(ctxcanvas->pdf, "errorpolicy", "return"); + + cdRegisterAttribute(canvas, &poly_attrib); + cdRegisterAttribute(canvas, &hatchboxsize_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + cdRegisterAttribute(canvas, &opacity_attrib); + cdRegisterAttribute(canvas, &pattern_attrib); + cdRegisterAttribute(canvas, &pdf_attrib); + + setpdfdefaultvalues(ctxcanvas); + + while (*line != '\0') + { + while (*line != '\0' && *line != '-') + line++; + + if (*line != '\0') + { + float num; + line++; + switch (*line++) + { + case 'p': + { + int paper; + sscanf(line, "%d", &paper); + setpdfpapersize(ctxcanvas, paper); + break; + } + case 'w': + sscanf(line, "%g", &num); + ctxcanvas->width_mm = num; + ctxcanvas->width_pt = CD_MM2PT*ctxcanvas->width_mm; + break; + case 'h': + sscanf(line, "%g", &num); + ctxcanvas->height_mm = num; + ctxcanvas->height_pt = CD_MM2PT*ctxcanvas->height_mm; + break; + case 's': + sscanf(line, "%d", &(ctxcanvas->res)); + break; + case 'o': + ctxcanvas->landscape = 1; + break; + } + } + + while (*line != '\0' && *line != ' ') + line++; + } + + /* store the base canvas */ + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->ctxcanvas = ctxcanvas; + + if (ctxcanvas->landscape == 1) + { + _cdSwapDouble(ctxcanvas->width_pt, ctxcanvas->height_pt); + _cdSwapDouble(ctxcanvas->width_mm, ctxcanvas->height_mm); + } + + init_pdf(ctxcanvas); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFChord = cdfchord; + canvas->cxFText = cdftext; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxFClipArea = cdfcliparea; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxPattern = cdpattern; + canvas->cxStipple = cdstipple; + canvas->cxHatch = cdhatch; + canvas->cxFont = cdfont; + canvas->cxTransform = cdtransform; + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdPDFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE | + CD_CAP_REGION | CD_CAP_IMAGESRV | CD_CAP_TEXTSIZE | + CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextPDF(void) +{ + return &cdPDFContext; +} + +/* +p.set_info("Creator", "PDFlib Cookbook") +*/ diff --git a/cd/src/drv/cdpicture.c b/cd/src/drv/cdpicture.c new file mode 100755 index 0000000..ff4f532 --- /dev/null +++ b/cd/src/drv/cdpicture.c @@ -0,0 +1,1133 @@ +/** \file + * \brief CD Picture driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cdpicture.h" + + +/* codes for the primitives. +*/ +typedef enum _tPrim +{ + CDPIC_LINE, + CDPIC_RECT, + CDPIC_BOX, + CDPIC_ARC, + CDPIC_SECTOR, + CDPIC_CHORD, + CDPIC_TEXT, + CDPIC_POLY, + CDPIC_FLINE, + CDPIC_FRECT, + CDPIC_FBOX, + CDPIC_FARC, + CDPIC_FSECTOR, + CDPIC_FCHORD, + CDPIC_FTEXT, + CDPIC_FPOLY, + CDPIC_PIXEL, + CDPIC_IMAGEMAP, + CDPIC_IMAGERGB, + CDPIC_IMAGERGBA, +} tPrim; + +typedef struct _tFillAttrib +{ + long foreground, background; + int back_opacity; + int interior_style, hatch_style; + int fill_mode; + int pattern_w, pattern_h; + long* pattern; + int stipple_w, stipple_h; + unsigned char* stipple; +} tFillAttrib; + +typedef struct _tLineAttrib +{ + long foreground, background; + int back_opacity; + int line_style, line_width; + int line_cap, line_join; + int* line_dashes; + int line_dashes_count; +} tLineAttrib; + +typedef struct _tTextAttrib +{ + long foreground; + char* font_type_face; + int font_style, font_size; + int text_alignment; + double text_orientation; + char* native_font; +} tTextAttrib; + +typedef struct _tLBR +{ + int x1, y1, x2, y2; +} tLBR; /* Line or Box or Rect */ + +typedef struct _tfLBR +{ + double x1, y1, x2, y2; +} tfLBR; /* Line or Box or Rect */ + +typedef struct _tASC +{ + int xc, yc, w, h; + double angle1, angle2; +} tASC; /* Arc or Sector or Chord */ + +typedef struct _tfASC +{ + double xc, yc, w, h; + double angle1, angle2; +} tfASC; /* Arc or Sector or Chord */ + +typedef struct _tPoly +{ + int mode; + int n; + cdPoint* points; +} tPoly; /* Begin, Vertex and End */ + +typedef struct _tfPoly +{ + int mode; + int n; + cdfPoint* points; +} tfPoly; /* Begin, Vertex and End */ + +typedef struct _tText +{ + int x, y; + char *s; +} tText; /* Text */ + +typedef struct _tfText +{ + double x, y; + char *s; +} tfText; /* Text */ + +typedef struct _tPixel +{ + int x, y; + long color; +} tPixel; /* Pixel */ + +typedef struct _tImageMap +{ + int iw, ih; + unsigned char *index; + long int *colors; + int x, y, w, h; +} tImageMap; + +typedef struct _tImageRGBA +{ + int iw, ih; + unsigned char *r; + unsigned char *g; + unsigned char *b; + unsigned char *a; + int x, y, w, h; +} tImageRGBA; + +typedef struct _tPrimNode +{ + tPrim type; + void* param_buffer; /* dinamically allocated memory for the parameter */ + union { + tLBR lineboxrect; + tfLBR lineboxrectf; + tASC arcsectorchord; + tfASC arcsectorchordf; + tPoly poly; + tfPoly polyf; + tText text; + tfText textf; + tPixel pixel; + tImageMap imagemap; + tImageRGBA imagergba; + } param; + void* attrib_buffer; /* dinamically allocated memory for the attributes */ + union { + tLineAttrib line; + tFillAttrib fill; + tTextAttrib text; + } attrib; + struct _tPrimNode *next; +} tPrimNode; + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + /* primitives list */ + tPrimNode *prim_first, + *prim_last; + int prim_n; + + /* bounding box */ + int xmin, xmax, + ymin, ymax; +}; + +static void picUpdateSize(cdCtxCanvas *ctxcanvas) +{ + ctxcanvas->canvas->w = ctxcanvas->xmax-ctxcanvas->xmin+1; + ctxcanvas->canvas->h = ctxcanvas->ymax-ctxcanvas->ymin+1; + ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; + ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; +} + +static void picUpdateBBox(cdCtxCanvas *ctxcanvas, int x, int y, int ew) +{ + if (x+ew > ctxcanvas->xmax) + ctxcanvas->xmax = x+ew; + if (y+ew > ctxcanvas->ymax) + ctxcanvas->ymax = y+ew; + if (x-ew < ctxcanvas->xmin) + ctxcanvas->xmin = x-ew; + if (y-ew < ctxcanvas->ymin) + ctxcanvas->ymin = y-ew; + + picUpdateSize(ctxcanvas); +} + +static void picUpdateBBoxF(cdCtxCanvas *ctxcanvas, double x, double y, int ew) +{ + if ((int)ceil(x+ew) > ctxcanvas->xmax) + ctxcanvas->xmax = (int)ceil(x+ew); + if ((int)ceil(y+ew) > ctxcanvas->ymax) + ctxcanvas->ymax = (int)ceil(y+ew); + if ((int)floor(x-ew) < ctxcanvas->xmin) + ctxcanvas->xmin = (int)floor(x-ew); + if ((int)floor(y-ew) < ctxcanvas->ymin) + ctxcanvas->ymin = (int)floor(y-ew); + + picUpdateSize(ctxcanvas); +} + +static void picAddPrim(cdCtxCanvas *ctxcanvas, tPrimNode *prim) +{ + if (ctxcanvas->prim_n == 0) + ctxcanvas->prim_first = prim; + else + ctxcanvas->prim_last->next = prim; + + ctxcanvas->prim_last = prim; + ctxcanvas->prim_n++; +} + +static tPrimNode* primCreate(tPrim type) +{ + tPrimNode *prim = malloc(sizeof(tPrimNode)); + memset(prim, 0, sizeof(tPrimNode)); + prim->type = type; + return prim; +} + +static void primDestroy(tPrimNode *prim) +{ + if (prim->param_buffer) + free(prim->param_buffer); + if (prim->attrib_buffer) + free(prim->attrib_buffer); + free(prim); +} + +static void primAddAttrib_Line(tPrimNode *prim, cdCanvas *canvas) +{ + prim->attrib.line.foreground = canvas->foreground; + prim->attrib.line.background = canvas->background; + prim->attrib.line.back_opacity = canvas->back_opacity; + prim->attrib.line.line_style = canvas->line_style; + prim->attrib.line.line_width = canvas->line_width; + prim->attrib.line.line_cap = canvas->line_cap; + prim->attrib.line.line_join = canvas->line_join; + + if (canvas->line_style==CD_CUSTOM && canvas->line_dashes) + { + prim->attrib.line.line_dashes_count = canvas->line_dashes_count; + prim->attrib_buffer = malloc(canvas->line_dashes_count*sizeof(int)); + prim->attrib.line.line_dashes = prim->attrib_buffer; + memcpy(prim->attrib.line.line_dashes, canvas->line_dashes, canvas->line_dashes_count*sizeof(int)); + } +} + +static void primAddAttrib_Fill(tPrimNode *prim, cdCanvas *canvas) +{ + prim->attrib.fill.foreground = canvas->foreground; + prim->attrib.fill.background = canvas->background; + prim->attrib.fill.back_opacity = canvas->back_opacity; + prim->attrib.fill.interior_style = canvas->interior_style; + prim->attrib.fill.hatch_style = canvas->hatch_style; + prim->attrib.fill.fill_mode = canvas->fill_mode; + prim->attrib.fill.pattern_w = canvas->pattern_w; + prim->attrib.fill.pattern_h = canvas->pattern_h; + prim->attrib.fill.stipple_w = canvas->stipple_w; + prim->attrib.fill.stipple_h = canvas->stipple_h; + + if (canvas->interior_style==CD_PATTERN && canvas->pattern) + { + prim->attrib_buffer = malloc(canvas->pattern_size*sizeof(long)); + prim->attrib.fill.pattern = prim->attrib_buffer; + memcpy(prim->attrib.fill.pattern, canvas->pattern, canvas->pattern_size*sizeof(long)); + } + + if (canvas->interior_style==CD_STIPPLE && canvas->stipple) + { + prim->attrib_buffer = malloc(canvas->stipple_size*sizeof(long)); + prim->attrib.fill.stipple = prim->attrib_buffer; + memcpy(prim->attrib.fill.stipple, canvas->stipple, canvas->stipple_size*sizeof(long)); + } +} + +static void primAddAttrib_Text(tPrimNode *prim, cdCanvas *canvas) +{ + prim->attrib.text.foreground = canvas->foreground; + + prim->attrib.text.font_style = canvas->font_style; + prim->attrib.text.font_size = canvas->font_size; + prim->attrib.text.text_alignment = canvas->text_alignment; + prim->attrib.text.text_orientation = canvas->text_orientation; + + if (canvas->native_font[0]) + { + prim->attrib_buffer = cdStrDup(canvas->native_font); + prim->attrib.text.native_font = prim->attrib_buffer; + } + else + { + prim->attrib_buffer = cdStrDup(canvas->font_type_face); + prim->attrib.text.font_type_face = prim->attrib_buffer; + } +} + +static void primUpdateAttrib_Line(tPrimNode *prim, cdCanvas *canvas) +{ + cdCanvasSetBackground(canvas, prim->attrib.line.background); + cdCanvasSetForeground(canvas, prim->attrib.line.foreground); + cdCanvasBackOpacity(canvas, prim->attrib.line.back_opacity); + cdCanvasLineStyle(canvas, prim->attrib.line.line_style); + cdCanvasLineWidth(canvas, prim->attrib.line.line_width); + cdCanvasLineCap(canvas, prim->attrib.line.line_cap); + cdCanvasLineJoin(canvas, prim->attrib.line.line_join); + + if (prim->attrib.line.line_style==CD_CUSTOM && prim->attrib.line.line_dashes) + cdCanvasLineStyleDashes(canvas, prim->attrib.line.line_dashes, prim->attrib.line.line_dashes_count); +} + +void primUpdateAttrib_Fill(tPrimNode *prim, cdCanvas *canvas) +{ + cdCanvasSetBackground(canvas, prim->attrib.fill.background); + cdCanvasSetForeground(canvas, prim->attrib.fill.foreground); + cdCanvasBackOpacity(canvas, prim->attrib.fill.back_opacity); + cdCanvasFillMode(canvas, prim->attrib.fill.fill_mode); + + if (prim->attrib.fill.interior_style==CD_HATCH) + cdCanvasHatch(canvas, prim->attrib.fill.hatch_style); + else if (prim->attrib.fill.interior_style==CD_PATTERN && prim->attrib.fill.pattern) + cdCanvasPattern(canvas, prim->attrib.fill.pattern_w, prim->attrib.fill.pattern_h, prim->attrib.fill.pattern); + else if (prim->attrib.fill.interior_style==CD_STIPPLE && prim->attrib.fill.stipple) + cdCanvasStipple(canvas, prim->attrib.fill.stipple_w, prim->attrib.fill.stipple_h, prim->attrib.fill.stipple); + + cdCanvasInteriorStyle(canvas, prim->attrib.fill.interior_style); +} + +void primUpdateAttrib_Text(tPrimNode *prim, cdCanvas *canvas) +{ + cdCanvasSetForeground(canvas, prim->attrib.text.foreground); + cdCanvasTextAlignment(canvas, prim->attrib.text.text_alignment); + cdCanvasTextOrientation(canvas, prim->attrib.text.text_orientation); + + if (canvas->native_font[0]) + cdCanvasNativeFont(canvas, prim->attrib.text.native_font); + else + cdCanvasFont(canvas, prim->attrib.text.font_type_face, prim->attrib.text.font_style, prim->attrib.text.font_size); +} + +static void cdclear(cdCtxCanvas *ctxcanvas) +{ + tPrimNode *prim; + int i; + for (i = 0; i < ctxcanvas->prim_n; i++) + { + prim = ctxcanvas->prim_first; + ctxcanvas->prim_first = prim->next; + + primDestroy(prim); + } + + ctxcanvas->prim_n = 0; + ctxcanvas->prim_first = NULL; + ctxcanvas->prim_last = NULL; +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + tPrimNode *prim = primCreate(CDPIC_PIXEL); + prim->param.pixel.x = x; + prim->param.pixel.y = y; + prim->param.pixel.color = color; + picAddPrim(ctxcanvas, prim); + picUpdateBBox(ctxcanvas, x, y, 0); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + tPrimNode *prim = primCreate(CDPIC_LINE); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.lineboxrect.x1 = x1; + prim->param.lineboxrect.y1 = y1; + prim->param.lineboxrect.x2 = x2; + prim->param.lineboxrect.y2 = y2; + picAddPrim(ctxcanvas, prim); + picUpdateBBox(ctxcanvas, x1, y1, ctxcanvas->canvas->line_width); + picUpdateBBox(ctxcanvas, x2, y2, ctxcanvas->canvas->line_width); +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + tPrimNode *prim = primCreate(CDPIC_FLINE); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.lineboxrectf.x1 = x1; + prim->param.lineboxrectf.y1 = y1; + prim->param.lineboxrectf.x2 = x2; + prim->param.lineboxrectf.y2 = y2; + picAddPrim(ctxcanvas, prim); + picUpdateBBoxF(ctxcanvas, x1, y1, ctxcanvas->canvas->line_width); + picUpdateBBoxF(ctxcanvas, x2, y2, ctxcanvas->canvas->line_width); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + tPrimNode *prim = primCreate(CDPIC_RECT); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.lineboxrect.x1 = xmin; + prim->param.lineboxrect.y1 = ymin; + prim->param.lineboxrect.x2 = xmax; + prim->param.lineboxrect.y2 = ymax; + picAddPrim(ctxcanvas, prim); + picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); + picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + tPrimNode *prim = primCreate(CDPIC_FRECT); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.lineboxrectf.x1 = xmin; + prim->param.lineboxrectf.y1 = ymin; + prim->param.lineboxrectf.x2 = xmax; + prim->param.lineboxrectf.y2 = ymax; + picAddPrim(ctxcanvas, prim); + picUpdateBBoxF(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); + picUpdateBBoxF(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + tPrimNode *prim = primCreate(CDPIC_BOX); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.lineboxrect.x1 = xmin; + prim->param.lineboxrect.y1 = ymin; + prim->param.lineboxrect.x2 = xmax; + prim->param.lineboxrect.y2 = ymax; + picAddPrim(ctxcanvas, prim); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + tPrimNode *prim = primCreate(CDPIC_FBOX); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.lineboxrectf.x1 = xmin; + prim->param.lineboxrectf.y1 = ymin; + prim->param.lineboxrectf.x2 = xmax; + prim->param.lineboxrectf.y2 = ymax; + picAddPrim(ctxcanvas, prim); + picUpdateBBoxF(ctxcanvas, xmin, ymin, 0); + picUpdateBBoxF(ctxcanvas, xmax, ymax, 0); +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_ARC); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.arcsectorchord.xc = xc; + prim->param.arcsectorchord.yc = yc; + prim->param.arcsectorchord.w = w; + prim->param.arcsectorchord.h = h; + prim->param.arcsectorchord.angle1 = a1; + prim->param.arcsectorchord.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); + picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_FARC); + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.arcsectorchordf.xc = xc; + prim->param.arcsectorchordf.yc = yc; + prim->param.arcsectorchordf.w = w; + prim->param.arcsectorchordf.h = h; + prim->param.arcsectorchordf.angle1 = a1; + prim->param.arcsectorchordf.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, ctxcanvas->canvas->line_width); + picUpdateBBox(ctxcanvas, xmax, ymax, ctxcanvas->canvas->line_width); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_SECTOR); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.arcsectorchord.xc = xc; + prim->param.arcsectorchord.yc = yc; + prim->param.arcsectorchord.w = w; + prim->param.arcsectorchord.h = h; + prim->param.arcsectorchord.angle1 = a1; + prim->param.arcsectorchord.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); + picUpdateBBox(ctxcanvas, xc, yc, 0); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_FSECTOR); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.arcsectorchordf.xc = xc; + prim->param.arcsectorchordf.yc = yc; + prim->param.arcsectorchordf.w = w; + prim->param.arcsectorchordf.h = h; + prim->param.arcsectorchordf.angle1 = a1; + prim->param.arcsectorchordf.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); + picUpdateBBox(ctxcanvas, _cdRound(xc), _cdRound(yc), 0); +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_CHORD); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.arcsectorchord.xc = xc; + prim->param.arcsectorchord.yc = yc; + prim->param.arcsectorchord.w = w; + prim->param.arcsectorchord.h = h; + prim->param.arcsectorchord.angle1 = a1; + prim->param.arcsectorchord.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_FCHORD); + primAddAttrib_Fill(prim, ctxcanvas->canvas); + prim->param.arcsectorchordf.xc = xc; + prim->param.arcsectorchordf.yc = yc; + prim->param.arcsectorchordf.w = w; + prim->param.arcsectorchordf.h = h; + prim->param.arcsectorchordf.angle1 = a1; + prim->param.arcsectorchordf.angle2 = a2; + picAddPrim(ctxcanvas, prim); + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int len) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_TEXT); + primAddAttrib_Text(prim, ctxcanvas->canvas); + prim->param.text.x = x; + prim->param.text.y = y; + prim->param.text.s = cdStrDupN(text, len); + prim->param_buffer = prim->param.text.s; + picAddPrim(ctxcanvas, prim); + cdCanvasGetTextBox(ctxcanvas->canvas, x, y, prim->param.text.s, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); +} + +static void cdftext(cdCtxCanvas *ctxcanvas, double x, double y, const char *text, int len) +{ + int xmin, xmax, ymin, ymax; + tPrimNode *prim = primCreate(CDPIC_FTEXT); + primAddAttrib_Text(prim, ctxcanvas->canvas); + prim->param.textf.x = x; + prim->param.textf.y = y; + prim->param.textf.s = cdStrDupN(text, len); + prim->param_buffer = prim->param.textf.s; + picAddPrim(ctxcanvas, prim); + cdCanvasGetTextBox(ctxcanvas->canvas, _cdRound(x), _cdRound(y), prim->param.text.s, &xmin, &xmax, &ymin, &ymax); + picUpdateBBox(ctxcanvas, xmin, ymin, 0); + picUpdateBBox(ctxcanvas, xmax, ymax, 0); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + tPrimNode *prim; + if (mode == CD_CLIP || mode == CD_REGION) return; + prim = primCreate(CDPIC_POLY); + if (mode == CD_FILL) + primAddAttrib_Fill(prim, ctxcanvas->canvas); + else + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.poly.n = n; + prim->param.poly.points = malloc(n * sizeof(cdPoint)); + memcpy(prim->param.poly.points, poly, n * sizeof(cdPoint)); + prim->param_buffer = prim->param.poly.points; + picAddPrim(ctxcanvas, prim); + + for (i = 0; i < n; i++) + { + if (mode == CD_FILL) + picUpdateBBox(ctxcanvas, poly[i].x, poly[i].y, 0); + else + picUpdateBBox(ctxcanvas, poly[i].x, poly[i].y, ctxcanvas->canvas->line_width); + } +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i; + tPrimNode *prim; + if (mode == CD_CLIP || mode == CD_REGION) return; + prim = primCreate(CDPIC_FPOLY); + if (mode == CD_FILL) + primAddAttrib_Fill(prim, ctxcanvas->canvas); + else + primAddAttrib_Line(prim, ctxcanvas->canvas); + prim->param.polyf.n = n; + prim->param.polyf.points = malloc(n * sizeof(cdPoint)); + memcpy(prim->param.polyf.points, poly, n * sizeof(cdPoint)); + prim->param_buffer = prim->param.polyf.points; + picAddPrim(ctxcanvas, prim); + + for (i = 0; i < n; i++) + { + if (mode == CD_FILL) + picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), 0); + else + picUpdateBBox(ctxcanvas, _cdRound(poly[i].x), _cdRound(poly[i].y), ctxcanvas->canvas->line_width); + } +} + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int l, offset, size; + unsigned char *dr, *dg, *db; + + tPrimNode *prim = primCreate(CDPIC_IMAGERGB); + prim->param.imagergba.iw = xmax-xmin+1; + prim->param.imagergba.ih = ymax-ymin+1; + prim->param.imagergba.x = x; + prim->param.imagergba.y = y; + prim->param.imagergba.w = w; + prim->param.imagergba.h = h; + + size = prim->param.imagergba.iw*prim->param.imagergba.ih; + prim->param_buffer = malloc(3*size); + prim->param.imagergba.r = prim->param_buffer; + prim->param.imagergba.g = prim->param.imagergba.r + size; + prim->param.imagergba.b = prim->param.imagergba.g + size; + + offset = ymin*iw + xmin; + r += offset; + g += offset; + b += offset; + + dr = prim->param.imagergba.r; + dg = prim->param.imagergba.g; + db = prim->param.imagergba.b; + offset = prim->param.imagergba.iw; + + for (l = ymin; l <= ymax; l++) + { + memcpy(dr, r, offset); + memcpy(dg, g, offset); + memcpy(db, b, offset); + + r += iw; + g += iw; + b += iw; + dr += offset; + dg += offset; + db += offset; + } + + picUpdateBBox(ctxcanvas, x, y, 0); + picUpdateBBox(ctxcanvas, x+prim->param.imagergba.iw-1, y+prim->param.imagergba.ih-1, 0); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int l, offset, size; + unsigned char *dr, *dg, *db, *da; + + tPrimNode *prim = primCreate(CDPIC_IMAGERGBA); + prim->param.imagergba.iw = xmax-xmin+1; + prim->param.imagergba.ih = ymax-ymin+1; + prim->param.imagergba.x = x; + prim->param.imagergba.y = y; + prim->param.imagergba.w = w; + prim->param.imagergba.h = h; + + size = prim->param.imagergba.iw*prim->param.imagergba.ih; + prim->param_buffer = malloc(4*size); + prim->param.imagergba.r = prim->param_buffer; + prim->param.imagergba.g = prim->param.imagergba.r + size; + prim->param.imagergba.b = prim->param.imagergba.g + size; + prim->param.imagergba.a = prim->param.imagergba.b + size; + + offset = ymin*iw + xmin; + r += offset; + g += offset; + b += offset; + a += offset; + + dr = prim->param.imagergba.r; + dg = prim->param.imagergba.g; + db = prim->param.imagergba.b; + da = prim->param.imagergba.a; + offset = prim->param.imagergba.iw; + + for (l = ymin; l <= ymax; l++) + { + memcpy(dr, r, offset); + memcpy(dg, g, offset); + memcpy(db, b, offset); + memcpy(da, a, offset); + + r += iw; + g += iw; + b += iw; + a += iw; + dr += offset; + dg += offset; + db += offset; + da += offset; + } + + picUpdateBBox(ctxcanvas, x, y, 0); + picUpdateBBox(ctxcanvas, x+prim->param.imagergba.iw-1, y+prim->param.imagergba.ih-1, 0); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int c, l, n = 0, offset, size; + unsigned char *dindex; + long *dcolors; + + tPrimNode *prim = primCreate(CDPIC_IMAGEMAP); + prim->param.imagemap.iw = xmax-xmin+1; + prim->param.imagemap.ih = ymax-ymin+1; + prim->param.imagemap.x = x; + prim->param.imagemap.y = y; + prim->param.imagemap.w = w; + prim->param.imagemap.h = h; + + size = prim->param.imagemap.iw*prim->param.imagemap.ih; + prim->param_buffer = malloc(size + 256); + prim->param.imagemap.index = prim->param_buffer; + prim->param.imagemap.colors = (long*)(prim->param.imagemap.index + size); + + offset = ymin*iw + xmin; + index += offset; + + dindex = prim->param.imagemap.index; + dcolors = prim->param.imagemap.colors; + offset = iw - prim->param.imagemap.iw; + + for (l = ymin; l <= ymax; l++) + { + for (c = xmin; c <= xmax; c++) + { + if (*index > n) + n = *index; + + *dindex++ = *index++; + } + + index += offset; + } + + n++; + + for (c = 0; c < n; c++) + dcolors[c] = colors[c]; + + picUpdateBBox(ctxcanvas, x, y, 0); + picUpdateBBox(ctxcanvas, x+prim->param.imagemap.iw-1, y+prim->param.imagemap.ih-1, 0); +} + + +/**********/ +/* cdPlay */ +/**********/ + +typedef int(*_cdsizecb)(cdCanvas* canvas, int w, int h, double w_mm, double h_mm); +static _cdsizecb cdsizecb = NULL; + +static int cdregistercallback(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdsizecb = (_cdsizecb)func; + return CD_OK; + } + + return CD_ERROR; +} + +#define sMin1(_v) (_v == 0? 1: _v) + +#define sScaleX(_x) cdRound((_x - pic_xmin) * factorX + xmin) +#define sScaleY(_y) cdRound((_y - pic_ymin) * factorY + ymin) +#define sScaleW(_w) sMin1(cdRound(_w * factorX)) +#define sScaleH(_h) sMin1(cdRound(_h * factorY)) + +#define sfScaleX(_x) ((_x - pic_xmin) * factorX + xmin) +#define sfScaleY(_y) ((_y - pic_ymin) * factorY + ymin) +#define sfScaleW(_w) (_w * factorX) +#define sfScaleH(_h) (_h * factorY) + +static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + tPrimNode *prim; + cdCanvas* pic_canvas = (cdCanvas*)data; + cdCtxCanvas* ctxcanvas = pic_canvas->ctxcanvas; + int p, i, scale = 0, + pic_xmin = ctxcanvas->xmin, + pic_ymin = ctxcanvas->ymin; + double factorX = 1, factorY = 1; + + if ((ctxcanvas->xmax-ctxcanvas->xmin)!=0 && + (ctxcanvas->ymax-ctxcanvas->ymin)!=0 && + (xmax-xmin)!=0 && + (ymax-ymin)!=0) + { + scale = 1; + factorX = ((double)(xmax-xmin)) / (ctxcanvas->xmax-ctxcanvas->xmin); + factorY = ((double)(ymax-ymin)) / (ctxcanvas->ymax-ctxcanvas->ymin); + } + + if (cdsizecb) + { + int err; + err = cdsizecb(canvas, pic_canvas->w, pic_canvas->h, pic_canvas->w_mm, pic_canvas->h_mm); + if (err) + return CD_ERROR; + } + + prim = ctxcanvas->prim_first; + for (i = 0; i < ctxcanvas->prim_n; i++) + { + if (scale) + { + switch (prim->type) + { + case CDPIC_LINE: + primUpdateAttrib_Line(prim, canvas); + cdCanvasLine(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleY(prim->param.lineboxrect.y1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y2)); + break; + case CDPIC_FLINE: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasLine(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleY(prim->param.lineboxrectf.y1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y2)); + break; + case CDPIC_RECT: + primUpdateAttrib_Line(prim, canvas); + cdCanvasRect(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y1), sScaleY(prim->param.lineboxrect.y2)); + break; + case CDPIC_FRECT: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasRect(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y1), sfScaleY(prim->param.lineboxrectf.y2)); + break; + case CDPIC_BOX: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasBox(canvas, sScaleX(prim->param.lineboxrect.x1), sScaleX(prim->param.lineboxrect.x2), sScaleY(prim->param.lineboxrect.y1), sScaleY(prim->param.lineboxrect.y2)); + break; + case CDPIC_FBOX: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasBox(canvas, sfScaleX(prim->param.lineboxrectf.x1), sfScaleX(prim->param.lineboxrectf.x2), sfScaleY(prim->param.lineboxrectf.y1), sfScaleY(prim->param.lineboxrectf.y2)); + break; + case CDPIC_ARC: + primUpdateAttrib_Line(prim, canvas); + cdCanvasArc(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FARC: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasArc(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_SECTOR: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasSector(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FSECTOR: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasSector(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_CHORD: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasChord(canvas, sScaleX(prim->param.arcsectorchord.xc), sScaleY(prim->param.arcsectorchord.yc), sScaleW(prim->param.arcsectorchord.w), sScaleH(prim->param.arcsectorchord.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FCHORD: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasChord(canvas, sfScaleX(prim->param.arcsectorchordf.xc), sfScaleY(prim->param.arcsectorchordf.yc), sfScaleW(prim->param.arcsectorchordf.w), sfScaleH(prim->param.arcsectorchordf.h), prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_TEXT: + primUpdateAttrib_Text(prim, canvas); + cdCanvasText(canvas, sScaleX(prim->param.text.x), sScaleY(prim->param.text.y), prim->param.text.s); + break; + case CDPIC_FTEXT: + primUpdateAttrib_Text(prim, canvas); + cdfCanvasText(canvas, sfScaleX(prim->param.textf.x), sfScaleY(prim->param.textf.y), prim->param.text.s); + break; + case CDPIC_POLY: + if (prim->param.poly.mode == CD_FILL) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, prim->param.poly.mode); + for (p = 0; p < prim->param.poly.n; p++) + cdCanvasVertex(canvas, sScaleX(prim->param.poly.points[p].x), sScaleY(prim->param.poly.points[p].y)); + cdCanvasEnd(canvas); + break; + case CDPIC_FPOLY: + if (prim->param.poly.mode == CD_FILL) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, prim->param.polyf.mode); + for (p = 0; p < prim->param.polyf.n; p++) + cdfCanvasVertex(canvas, sfScaleX(prim->param.polyf.points[p].x), sfScaleY(prim->param.polyf.points[p].y)); + cdCanvasEnd(canvas); + break; + case CDPIC_IMAGERGB: + cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, sScaleX(prim->param.imagergba.x), sScaleY(prim->param.imagergba.y), sScaleW(prim->param.imagergba.w), sScaleH(prim->param.imagergba.h), 0, 0, 0, 0); + break; + case CDPIC_IMAGERGBA: + cdCanvasPutImageRectRGBA(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.a, sScaleX(prim->param.imagergba.x), sScaleY(prim->param.imagergba.y), sScaleW(prim->param.imagergba.w), sScaleH(prim->param.imagergba.h), 0, 0, 0, 0); + break; + case CDPIC_IMAGEMAP: + cdCanvasPutImageRectMap(canvas, prim->param.imagemap.iw, prim->param.imagemap.ih, prim->param.imagemap.index, prim->param.imagemap.colors, sScaleX(prim->param.imagemap.x), sScaleY(prim->param.imagemap.y), sScaleW(prim->param.imagemap.w), sScaleH(prim->param.imagemap.h), 0, 0, 0, 0); + break; + case CDPIC_PIXEL: + cdCanvasPixel(canvas, sScaleX(prim->param.pixel.x), sScaleY(prim->param.pixel.y), prim->param.pixel.color); + break; + } + } + else + { + switch (prim->type) + { + case CDPIC_LINE: + primUpdateAttrib_Line(prim, canvas); + cdCanvasLine(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.y1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y2); + break; + case CDPIC_FLINE: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasLine(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y2); + break; + case CDPIC_RECT: + primUpdateAttrib_Line(prim, canvas); + cdCanvasRect(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y1, prim->param.lineboxrect.y2); + break; + case CDPIC_FRECT: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasRect(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.y2); + break; + case CDPIC_BOX: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasBox(canvas, prim->param.lineboxrect.x1, prim->param.lineboxrect.x2, prim->param.lineboxrect.y1, prim->param.lineboxrect.y2); + break; + case CDPIC_FBOX: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasBox(canvas, prim->param.lineboxrectf.x1, prim->param.lineboxrectf.x2, prim->param.lineboxrectf.y1, prim->param.lineboxrectf.y2); + break; + case CDPIC_ARC: + primUpdateAttrib_Line(prim, canvas); + cdCanvasArc(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FARC: + primUpdateAttrib_Line(prim, canvas); + cdfCanvasArc(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_SECTOR: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasSector(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FSECTOR: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasSector(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_CHORD: + primUpdateAttrib_Fill(prim, canvas); + cdCanvasChord(canvas, prim->param.arcsectorchord.xc, prim->param.arcsectorchord.yc, prim->param.arcsectorchord.w, prim->param.arcsectorchord.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_FCHORD: + primUpdateAttrib_Fill(prim, canvas); + cdfCanvasChord(canvas, prim->param.arcsectorchordf.xc, prim->param.arcsectorchordf.yc, prim->param.arcsectorchordf.w, prim->param.arcsectorchordf.h, prim->param.arcsectorchord.angle1, prim->param.arcsectorchord.angle2); + break; + case CDPIC_TEXT: + primUpdateAttrib_Text(prim, canvas); + cdCanvasText(canvas, prim->param.text.x, prim->param.text.y, prim->param.text.s); + break; + case CDPIC_FTEXT: + primUpdateAttrib_Text(prim, canvas); + cdfCanvasText(canvas, prim->param.textf.x, prim->param.textf.y, prim->param.text.s); + break; + case CDPIC_POLY: + if (prim->param.poly.mode == CD_FILL) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, prim->param.poly.mode); + for (p = 0; p < prim->param.poly.n; p++) + cdCanvasVertex(canvas, prim->param.poly.points[p].x, prim->param.poly.points[p].y); + cdCanvasEnd(canvas); + break; + case CDPIC_FPOLY: + if (prim->param.poly.mode == CD_FILL) + primUpdateAttrib_Fill(prim, canvas); + else + primUpdateAttrib_Line(prim, canvas); + cdCanvasBegin(canvas, prim->param.polyf.mode); + for (p = 0; p < prim->param.polyf.n; p++) + cdfCanvasVertex(canvas, prim->param.polyf.points[p].x, prim->param.polyf.points[p].y); + cdCanvasEnd(canvas); + break; + case CDPIC_IMAGERGB: + cdCanvasPutImageRectRGB(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.x, prim->param.imagergba.y, prim->param.imagergba.w, prim->param.imagergba.h, 0, 0, 0, 0); + break; + case CDPIC_IMAGERGBA: + cdCanvasPutImageRectRGBA(canvas, prim->param.imagergba.iw, prim->param.imagergba.ih, prim->param.imagergba.r, prim->param.imagergba.g, prim->param.imagergba.b, prim->param.imagergba.a, prim->param.imagergba.x, prim->param.imagergba.y, prim->param.imagergba.w, prim->param.imagergba.h, 0, 0, 0, 0); + break; + case CDPIC_IMAGEMAP: + cdCanvasPutImageRectMap(canvas, prim->param.imagemap.iw, prim->param.imagemap.ih, prim->param.imagemap.index, prim->param.imagemap.colors, prim->param.imagemap.x, prim->param.imagemap.y, prim->param.imagemap.w, prim->param.imagemap.h, 0, 0, 0, 0); + break; + case CDPIC_PIXEL: + cdCanvasPixel(canvas, prim->param.pixel.x, prim->param.pixel.y, prim->param.pixel.color); + break; + } + } + + prim = prim->next; + } + + return CD_OK; +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + cdclear(ctxcanvas); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +/*******************/ +/* Canvas Creation */ +/*******************/ + +static void cdcreatecanvas(cdCanvas *canvas, void *data) +{ + char* strdata = (char*)data; + double res = 3.78; + cdCtxCanvas* ctxcanvas; + + sscanf(strdata, "%lg", &res); + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + /* update canvas context */ + canvas->w = 0; + canvas->h = 0; + canvas->w_mm = 0; + canvas->h_mm = 0; + canvas->bpp = 24; + canvas->xres = res; + canvas->yres = res; +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxClear = cdclear; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxFLine = cdfline; + canvas->cxRect = cdrect; + canvas->cxFRect = cdfrect; + canvas->cxBox = cdbox; + canvas->cxFBox = cdfbox; + canvas->cxArc = cdarc; + canvas->cxFArc = cdfarc; + canvas->cxSector = cdsector; + canvas->cxFSector = cdfsector; + canvas->cxChord = cdchord; + canvas->cxFChord = cdfchord; + canvas->cxText = cdtext; + canvas->cxFText = cdftext; + canvas->cxPoly = cdpoly; + canvas->cxFPoly = cdfpoly; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdPictureContext = +{ + CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_REGION | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE), + 0, + cdcreatecanvas, + cdinittable, + cdplay, + cdregistercallback, +}; + +cdContext* cdContextPicture(void) +{ + return &cdPictureContext; +} diff --git a/cd/src/drv/cdps.c b/cd/src/drv/cdps.c new file mode 100755 index 0000000..d5d62fe --- /dev/null +++ b/cd/src/drv/cdps.c @@ -0,0 +1,1838 @@ +/** \file + * \brief PS driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cdps.h" + + +#define mm2pt(x) (CD_MM2PT*(x)) + +#ifndef min +#define min(a, b) ((a)<(b)?(a):(b)) +#endif +#ifndef max +#define max(a, b) ((a)>(b)?(a):(b)) +#endif + +/* +** dada uma cor do CD, obtem uma de suas componentes, na faixa 0-1. +*/ +#define get_red(_) (((double)cdRed(_))/255.) +#define get_green(_) (((double)cdGreen(_))/255.) +#define get_blue(_) (((double)cdBlue(_))/255.) + +/* ATENTION: currentmatrix/setmatrix + Remeber that there is a tranformation set just after file open, to define margins and pixel scale. + So use transformations carefully. +*/ + +static unsigned char HatchBits[6][8] = { /* [style][y] (8x8) */ + {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */ + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */ + {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */ + {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */ + {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */ + {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */ + + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + FILE *file; /* Arquivo PS */ + int res; /* Resolucao */ + int pages; /* Numero total de paginas */ + double width; /* Largura do papel (points) */ + double height; /* Altura do papel (points) */ + double xmin, ymin; /* Definem as margens esquerda e inferior (points) */ + double xmax, ymax; /* Definem as margens direita e superior (points) */ + double bbxmin, bbymin; /* Definem a bounding box */ + double bbxmax, bbymax; /* Definem a bounding box */ + double bbmargin; /* Define a margem para a bounding box */ + double scale; /* Fator de conversao de coordenadas (pixel2points) */ + int eps; /* Postscrip encapsulado? */ + int level1; /* if true generates level 1 only function calls */ + int landscape; /* page orientation */ + int debug; /* print debug strings in the file */ + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + char *nativefontname[100]; /* Registra as fontes usadas */ + int num_native_font; + + int poly_holes[500]; + int holes; + +}; + + +/* +%F Ajusta o tamanho do papel em points. +*/ +static void setpspapersize(cdCtxCanvas *ctxcanvas, int size) +{ + static struct + { + int width; + int height; + } paper[] = + { + { 2393, 3391 }, /* A0 */ + { 1689, 2393 }, /* A1 */ + { 1192, 1689 }, /* A2 */ + { 842, 1192 }, /* A3 */ + { 595, 842 }, /* A4 */ + { 420, 595 }, /* A5 */ + { 612, 792 }, /* LETTER */ + { 612, 1008 } /* LEGAL */ + }; + + if (sizeCD_LEGAL) + return; + + ctxcanvas->width = (double)paper[size].width; + ctxcanvas->height = (double)paper[size].height; +} + +/* +%F Registra os valores default para impressao. +*/ +static void setpsdefaultvalues(cdCtxCanvas *ctxcanvas) +{ + /* all the other values are set to 0 */ + setpspapersize(ctxcanvas, CD_A4); + ctxcanvas->xmin = 25.4; /* ainda em mm, sera' convertido para points na init_ps */ + ctxcanvas->xmax = 25.4; + ctxcanvas->ymin = 25.4; + ctxcanvas->ymax = 25.4; + ctxcanvas->res = 300; +} + +/* +%F Insere o ponto (x, y) na BoundingBox corrente. +Nao leva em consideracao a espessura das linhas. +*/ +static void insertpoint(cdCtxCanvas *ctxcanvas, int x, int y) +{ + double xmin = x*ctxcanvas->scale + ctxcanvas->xmin - ctxcanvas->bbmargin; + double ymin = y*ctxcanvas->scale + ctxcanvas->ymin - ctxcanvas->bbmargin; + + double xmax = x*ctxcanvas->scale + ctxcanvas->xmin + ctxcanvas->bbmargin; + double ymax = y*ctxcanvas->scale + ctxcanvas->ymin + ctxcanvas->bbmargin; + + if (!ctxcanvas->bbxmin && !ctxcanvas->bbxmax && !ctxcanvas->bbymin && !ctxcanvas->bbymax) + { + ctxcanvas->bbxmin = xmin; + ctxcanvas->bbymin = ymin; + + ctxcanvas->bbxmax = xmax; + ctxcanvas->bbymax = ymax; + } + else + { + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->bbxmin = max(ctxcanvas->canvas->clip_rect.xmin*ctxcanvas->scale + ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin)); + ctxcanvas->bbymin = max(ctxcanvas->canvas->clip_rect.ymin*ctxcanvas->scale + ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin)); + + ctxcanvas->bbxmax = min(ctxcanvas->canvas->clip_rect.xmax*ctxcanvas->scale + ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax)); + ctxcanvas->bbymax = min(ctxcanvas->canvas->clip_rect.ymax*ctxcanvas->scale + ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax)); + } + else + { + ctxcanvas->bbxmin = max(ctxcanvas->xmin, min(ctxcanvas->bbxmin, xmin)); + ctxcanvas->bbymin = max(ctxcanvas->ymin, min(ctxcanvas->bbymin, ymin)); + + ctxcanvas->bbxmax = min(ctxcanvas->xmax, max(ctxcanvas->bbxmax, xmax)); + ctxcanvas->bbymax = min(ctxcanvas->ymax, max(ctxcanvas->bbymax, ymax)); + } + } +} + +/* +%F Ajusta a BoundingBox para conter o ponto (x,y). +Leva em consideracao a espessura das linhas. +*/ +static void bbox(cdCtxCanvas *ctxcanvas, int x, int y) +{ + if (ctxcanvas->canvas->line_width > 1) + { + insertpoint(ctxcanvas, x-ctxcanvas->canvas->line_width, y-ctxcanvas->canvas->line_width); + insertpoint(ctxcanvas, x+ctxcanvas->canvas->line_width, y+ctxcanvas->canvas->line_width); + } + else + insertpoint(ctxcanvas, x, y); +} + +static void fbbox(cdCtxCanvas *ctxcanvas, double x, double y) +{ + if (ctxcanvas->canvas->line_width > 1) + { + insertpoint(ctxcanvas, (int)(x-ctxcanvas->canvas->line_width), (int)(y-ctxcanvas->canvas->line_width)); + insertpoint(ctxcanvas, (int)(x+ctxcanvas->canvas->line_width), (int)(y+ctxcanvas->canvas->line_width)); + } + else + insertpoint(ctxcanvas, (int)x, (int)y); +} + +static char new_codes[] = {"\ +/newcodes % foreign character encodings\n\ +[\n\ +160/space 161/exclamdown 162/cent 163/sterling 164/currency\n\ +165/yen 166/brokenbar 167/section 168/dieresis 169/copyright\n\ +170/ordfeminine 171/guillemotleft 172/logicalnot 173/hyphen 174/registered\n\ +175/macron 176/degree 177/plusminus 178/twosuperior 179/threesuperior\n\ +180/acute 181/mu 182/paragraph 183/periodcentered 184/cedilla\n\ +185/onesuperior 186/ordmasculine 187/guillemotright 188/onequarter\n\ +189/onehalf 190/threequarters 191/questiondown 192/Agrave 193/Aacute\n\ +194/Acircumflex 195/Atilde 196/Adieresis 197/Aring 198/AE 199/Ccedilla\n\ +200/Egrave 201/Eacute 202/Ecircumflex 203/Edieresis 204/Igrave 205/Iacute\n\ +206/Icircumflex 207/Idieresis 208/Eth 209/Ntilde 210/Ograve 211/Oacute\n\ +212/Ocircumflex 213/Otilde 214/Odieresis 215/multiply 216/Oslash\n\ +217/Ugrave 218/Uacute 219/Ucircumflex 220/Udieresis 221/Yacute 222/Thorn\n\ +223/germandbls 224/agrave 225/aacute 226/acircumflex 227/atilde\n\ +228/adieresis 229/aring 230/ae 231/ccedilla 232/egrave 233/eacute\n\ +234/ecircumflex 235/edieresis 236/igrave 237/iacute 238/icircumflex\n\ +239/idieresis 240/eth 241/ntilde 242/ograve 243/oacute 244/ocircumflex\n\ +245/otilde 246/odieresis 247/divide 248/oslash 249/ugrave 250/uacute\n\ +251/ucircumflex 252/udieresis 253/yacute 254/thorn 255/ydieresis\n\ +] def\n\ +"}; + +static char change_font[] = {"\ +% change fonts using ISO Latin1 characters\n\ +/ChgFnt % size psname natname => font\n\ +{\n\ + dup FontDirectory exch known % is re-encoded name known?\n\ + { exch pop } % yes, get rid of long name\n\ + { dup 3 1 roll ReEncode } ifelse % no, re-encode it\n\ + findfont exch scalefont setfont\n\ +} def\n\ +"}; + +static char re_encode[] = {"\ +/ReEncode %\n\ +{\n\ + 12 dict begin\n\ + /newname exch def\n\ + /basename exch def\n\ + /basedict basename findfont def\n\ + /newfont basedict maxlength dict def\n\ + basedict\n\ + { exch dup /FID ne\n\ + { dup /Encoding eq\n\ + { exch dup length array copy newfont 3 1 roll put }\n\ + { exch newfont 3 1 roll put } ifelse\n\ + }\n\ + { pop pop } ifelse\n\ + } forall\n\ + newfont /FontName newname put\n\ + newcodes aload pop newcodes length 2 idiv\n\ + { newfont /Encoding get 3 1 roll put } repeat\n\ + newname newfont definefont pop\n\ + end\n\ +} def\n\ +"}; + +static void setcliprect(cdCtxCanvas* ctxcanvas, double xmin, double ymin, double xmax, double ymax) +{ + if (ctxcanvas->eps) /* initclip not allowed in EPS */ + return; + + fprintf(ctxcanvas->file, "initclip\n"); + + /* cliping geral para a margem */ + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin); + fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin); + fprintf(ctxcanvas->file, "C\n"); + fprintf(ctxcanvas->file, "clip\n"); + fprintf(ctxcanvas->file, "N\n"); + } + else + fprintf(ctxcanvas->file, "%g %g %g %g rectclip\n", xmin, ymin, xmax-xmin, ymax-ymin); +} + +static void set_default_matrix(cdCtxCanvas *ctxcanvas) +{ + if (ctxcanvas->eps) + fprintf(ctxcanvas->file, "oldmatrix setmatrix\n"); /* reset to current */ + else + { + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] defaultmatrix\n"); /* reset to default */ + fprintf(ctxcanvas->file, "setmatrix\n"); + } + + /* margin and scale */ + fprintf(ctxcanvas->file, "%g %g translate\n", ctxcanvas->xmin, ctxcanvas->ymin); + fprintf(ctxcanvas->file, "%g %g scale\n", ctxcanvas->scale, ctxcanvas->scale); +} + +/* +%F Inicializa o arquivo PS. +*/ +static void init_ps(cdCtxCanvas *ctxcanvas) +{ + double w, h; + + time_t now = time(NULL); + + ctxcanvas->scale = 72.0/ctxcanvas->res; + ctxcanvas->xmin = mm2pt(ctxcanvas->xmin); + ctxcanvas->xmax = ctxcanvas->width - mm2pt(ctxcanvas->xmax); + ctxcanvas->ymin = mm2pt(ctxcanvas->ymin); + ctxcanvas->ymax = ctxcanvas->height - mm2pt(ctxcanvas->ymax); + ctxcanvas->bbmargin = mm2pt(ctxcanvas->bbmargin); + + fprintf(ctxcanvas->file, "%%!PS-Adobe-3.0 %s\n", ctxcanvas->eps ? "EPSF-3.0":""); + fprintf(ctxcanvas->file, "%%%%Title: CanvasDraw\n"); + fprintf(ctxcanvas->file, "%%%%Creator: CanvasDraw\n"); + fprintf(ctxcanvas->file, "%%%%CreationDate: %s", asctime(localtime(&now))); + fprintf(ctxcanvas->file, "%%%%DocumentFonts: (atend)\n"); /* attend means at the end of the file, */ + fprintf(ctxcanvas->file, "%%%%Pages: (atend)\n"); /* see killcanvas */ + fprintf(ctxcanvas->file, "%%%%PageOrder: Ascend\n"); + fprintf(ctxcanvas->file, "%%%%LanguageLevel: %d\n", ctxcanvas->level1 ? 1: 2); + fprintf(ctxcanvas->file, "%%%%Orientation: %s\n", ctxcanvas->landscape ? "Landscape": "Portrait"); + + if (ctxcanvas->eps) + { + fprintf(ctxcanvas->file, "%%%%BoundingBox: (atend)\n"); + ctxcanvas->bbxmin = ctxcanvas->bbxmax = ctxcanvas->bbymin = ctxcanvas->bbymax = 0; + /* BoundingBox==Empty */ + } + + fprintf(ctxcanvas->file, "%%%%EndComments\n"); + fprintf(ctxcanvas->file, "%%%%BeginProlog\n"); + + fprintf(ctxcanvas->file, "/N {newpath} bind def\n"); + fprintf(ctxcanvas->file, "/C {closepath} bind def\n"); + fprintf(ctxcanvas->file, "/M {moveto} bind def\n"); + fprintf(ctxcanvas->file, "/L {lineto} bind def\n"); + fprintf(ctxcanvas->file, "/B {curveto} bind def\n"); + fprintf(ctxcanvas->file, "/S {stroke} bind def\n"); + fprintf(ctxcanvas->file, "/LL {moveto lineto stroke} bind def\n"); + + if (!ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "/RF {rectfill} bind def\n"); + fprintf(ctxcanvas->file, "/RS {rectstroke} bind def\n"); + } + + fprintf(ctxcanvas->file, "%%%%EndProlog\n"); + fprintf(ctxcanvas->file, "%%%%BeginSetup\n"); + + if (!ctxcanvas->eps && !ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "%%%%IncludeFeature: *Resolution %d\n", ctxcanvas->res); + fprintf(ctxcanvas->file, "%%%%BeginFeature: *PageSize\n"); + fprintf(ctxcanvas->file, "<< /PageSize [%g %g] >> setpagedevice\n", ctxcanvas->width, ctxcanvas->height); /* setpagedevice not allowed in EPS */ + fprintf(ctxcanvas->file, "%%%%EndFeature\n"); + } + + fprintf(ctxcanvas->file, "%%%%EndSetup\n"); + + fputs(new_codes, ctxcanvas->file); + fputs(change_font, ctxcanvas->file); + fputs(re_encode, ctxcanvas->file); + + w = ctxcanvas->xmax - ctxcanvas->xmin; + h = ctxcanvas->ymax - ctxcanvas->ymin; + + ctxcanvas->canvas->w = (int)(w/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */ + ctxcanvas->canvas->h = (int)(h/ctxcanvas->scale + 0.5); /* Converte p/ unidades do usuario */ + ctxcanvas->canvas->w_mm = w/CD_MM2PT; /* Converte p/ milimetros */ + ctxcanvas->canvas->h_mm = h/CD_MM2PT; /* Converte p/ milimetros */ + ctxcanvas->canvas->bpp = 24; + ctxcanvas->canvas->xres = ctxcanvas->canvas->w / ctxcanvas->canvas->w_mm; + ctxcanvas->canvas->yres = ctxcanvas->canvas->h / ctxcanvas->canvas->h_mm; + + fprintf(ctxcanvas->file, "%%%%Page: 1 1\n"); + ctxcanvas->pages = 1; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdCreateCanvas: Margin Begin\n"); + + if (ctxcanvas->eps) + fprintf(ctxcanvas->file, "/oldmatrix [0 0 0 0 0 0] currentmatrix def\n"); /* save current matrix */ + + set_default_matrix(ctxcanvas); + + /* cliping geral para a margem */ + setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdCreateCanvas: MarginEnd\n"); +} + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + int i; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdKillCanvas\n"); + + fprintf(ctxcanvas->file, "showpage\n"); + fprintf(ctxcanvas->file, "%%%%Trailer\n"); + fprintf(ctxcanvas->file, "%%%%Pages: %d 1\n", ctxcanvas->pages); + + if (ctxcanvas->eps) + { + int xmin = (int)ctxcanvas->bbxmin; + int xmax = (int)ctxcanvas->bbxmax; + int ymin = (int)ctxcanvas->bbymin; + int ymax = (int)ctxcanvas->bbymax; + if (xmax < ctxcanvas->bbxmax) xmax++; + if (ymax < ctxcanvas->bbymax) ymax++; + fprintf(ctxcanvas->file,"%%%%BoundingBox: %5d %5d %5d %5d\n",xmin,ymin,xmax,ymax); + } + + fprintf(ctxcanvas->file, "%%%%DocumentFonts:"); + + for (i = 0; i < ctxcanvas->num_native_font; i++) + { + fprintf(ctxcanvas->file, " %s", ctxcanvas->nativefontname[i]); + free(ctxcanvas->nativefontname[i]); + } + + putc('\n', ctxcanvas->file); + fprintf(ctxcanvas->file,"%%%%EOF"); + + fclose(ctxcanvas->file); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cddeactivate(cdCtxCanvas *ctxcanvas) +{ + fflush(ctxcanvas->file); +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style); +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple); +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern); + +static void update_fill(cdCtxCanvas *ctxcanvas, int fill) +{ + if (fill == 0) + { + /* called before a NON filled primitive */ + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill); + + fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground)); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill); + } + else + { + /* called before a filled primitive */ + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsUpdateFill %d Begin\n", fill); + + if (ctxcanvas->canvas->interior_style == CD_SOLID) + { + fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", get_red(ctxcanvas->canvas->foreground), + get_green(ctxcanvas->canvas->foreground), + get_blue(ctxcanvas->canvas->foreground)); + } + else if (!ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "cd_pattern\n"); + fprintf(ctxcanvas->file, "setpattern\n"); + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsUpdateFill %dEnd\n", fill); + } +} + +/* +%F Comeca uma nova pagina. +*/ +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdFlush Begin\n"); + + if (!ctxcanvas->eps) + { + fprintf(ctxcanvas->file, "gsave\n"); + + fprintf(ctxcanvas->file, "showpage\n"); + ctxcanvas->pages++; + fprintf(ctxcanvas->file, "%%%%Page: %d %d\n", ctxcanvas->pages, ctxcanvas->pages); + + fprintf(ctxcanvas->file, "grestore\n"); + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdFlushEnd\n"); +} + + +/******************************************************/ +/* coordinate transformation */ +/******************************************************/ + +static void cdfcliparea(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + if (ctxcanvas->canvas->clip_mode != CD_CLIPAREA) + return; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfClipArea Begin\n"); + + setcliprect(ctxcanvas, xmin, ymin, xmax, ymax); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfClipAreaEnd\n"); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int mode) +{ + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdClip %d Begin\n", mode); + + if (mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_mode = CD_CLIPAREA; + + setcliprect(ctxcanvas, (double)ctxcanvas->canvas->clip_rect.xmin, + (double)ctxcanvas->canvas->clip_rect.ymin, + (double)ctxcanvas->canvas->clip_rect.xmax, + (double)ctxcanvas->canvas->clip_rect.ymax); + } + else if (mode == CD_CLIPPOLYGON) + { + fprintf(ctxcanvas->file, "clip_polygon\n"); + } + else + { + /* margin clipping only */ + setcliprect(ctxcanvas, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdClip %dEnd\n", mode); + + return mode; +} + +/******************************************************/ +/* primitives */ +/******************************************************/ + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + update_fill(ctxcanvas, 0); + + fprintf(ctxcanvas->file, "N %d %d %d %d LL\n", x1, y1, x2, y2); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, x1, y1); + bbox(ctxcanvas, x2, y2); + } +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + update_fill(ctxcanvas, 0); + + fprintf(ctxcanvas->file, "N %g %g %g %g LL\n", x1, y1, x2, y2); + + if (ctxcanvas->eps) + { + fbbox(ctxcanvas, x1, y1); + fbbox(ctxcanvas, x2, y2); + } +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + update_fill(ctxcanvas, 0); + + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin); + fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax); + fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax); + fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin); + fprintf(ctxcanvas->file, "C S\n"); + } + else + fprintf(ctxcanvas->file, "%d %d %d %d RS\n", xmin, ymin, xmax - xmin, ymax - ymin); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdfrect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 0); + + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin); + fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin); + fprintf(ctxcanvas->file, "C S\n"); + } + else + fprintf(ctxcanvas->file, "%g %g %g %g RS\n", xmin, ymin, xmax - xmin, ymax - ymin); + + if (ctxcanvas->eps) + { + fbbox(ctxcanvas, xmin, ymin); + fbbox(ctxcanvas, xmax, ymax); + } +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + update_fill(ctxcanvas, 1); + + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d M\n", xmin, ymin); + fprintf(ctxcanvas->file, "%d %d L\n", xmin, ymax); + fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymax); + fprintf(ctxcanvas->file, "%d %d L\n", xmax, ymin); + fprintf(ctxcanvas->file, "C fill\n"); + } + else + fprintf(ctxcanvas->file, "%d %d %d %d RF\n", xmin, ymin, xmax - xmin, ymax - ymin); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdfbox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + update_fill(ctxcanvas, 1); + + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g M\n", xmin, ymin); + fprintf(ctxcanvas->file, "%g %g L\n", xmin, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymax); + fprintf(ctxcanvas->file, "%g %g L\n", xmax, ymin); + fprintf(ctxcanvas->file, "C fill\n"); + } + else + fprintf(ctxcanvas->file, "%g %g %g %g RF\n", xmin, ymin, xmax - xmin, ymax - ymin); + + if (ctxcanvas->eps) + { + fbbox(ctxcanvas, xmin, ymin); + fbbox(ctxcanvas, xmax, ymax); + } +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + update_fill(ctxcanvas, 0); + + if (w==h) /* Circulo: PS implementa direto */ + { + fprintf(ctxcanvas->file, "N %d %d %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdArc Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); /* fill new matrix from CTM */ + fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "S\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); /* back to CTM */ + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdArc EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 0); + + if (w==h) /* Circulo: PS implementa direto */ + { + fprintf(ctxcanvas->file, "N %g %g %g %g %g arc S\n", xc, yc, 0.5*w, a1, a2); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfArc Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", h/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "S\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfArc EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) /* Circulo: PS implementa direto */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Circle Begin\n"); + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d M\n", xc, yc); + fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector CircleEnd\n"); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdSector Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 M\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdSector EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + bbox(ctxcanvas, xc, yc); + } +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) /* Circulo: PS implementa direto */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Circle Begin\n"); + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g M\n", xc, yc); + fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector CircleEnd\n"); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfSector Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", h/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 M\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfSector EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + fbbox(ctxcanvas, xc, yc); + } +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) /* Circulo: PS implementa direto */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Circle Begin\n"); + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d %g %g %g arc\n", xc, yc, 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord CircleEnd\n"); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdChord Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%d %d translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", ((double)h)/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdChord EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(xc, yc, w, h, a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + update_fill(ctxcanvas, 1); + + if (w==h) /* Circulo: PS implementa direto */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Circle Begin\n"); + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g %g %g %g arc\n", xc, yc, 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord CircleEnd\n"); + } + else /* Elipse: mudar a escala p/ criar a partir do circulo */ + { + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfChord Ellipse Begin\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%g %g translate\n", xc, yc); + fprintf(ctxcanvas->file, "1 %g scale\n", h/w); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "0 0 %g %g %g arc\n", 0.5*w, a1, a2); + fprintf(ctxcanvas->file, "C fill\n"); + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfChord EllipseEnd\n"); + } + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + cdCanvasGetEllipseBox(_cdRound(xc), _cdRound(yc), _cdRound(w), _cdRound(h), a1, a2, &xmin, &xmax, &ymin, &ymax); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix); + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + int i; + int ascent, height, baseline; + + update_fill(ctxcanvas, 0); + + cdCanvasGetFontDim(ctxcanvas->canvas, NULL, &height, &ascent, NULL); + baseline = height - ascent; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdText Begin\n"); + + if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle) + set_default_matrix(ctxcanvas); + + fprintf(ctxcanvas->file, "N 0 0 M\n"); + putc('(', ctxcanvas->file); + + for (i=0; ifile); + putc(s[i], ctxcanvas->file); + } + + fprintf(ctxcanvas->file, ")\n"); + fprintf(ctxcanvas->file, "dup true charpath\n"); + fprintf(ctxcanvas->file, "flattenpath\n"); + fprintf(ctxcanvas->file, "pathbbox\n"); /* bbox na pilha: llx lly urx ury */ + fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: llx lly ury urx */ + fprintf(ctxcanvas->file, "4 1 roll\n"); /* roda: urx llx lly ury */ + fprintf(ctxcanvas->file, "exch\n"); /* troca o topo: urx llx ury lly */ + fprintf(ctxcanvas->file, "sub\n"); /* subtrai: urx llx h */ + fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: h urx llx */ + fprintf(ctxcanvas->file, "sub\n"); /* subtrai: h w */ + fprintf(ctxcanvas->file, "0 0\n"); /* empilha: h w 0 0 */ + fprintf(ctxcanvas->file, "4 -1 roll\n"); /* roda: w 0 0 h */ + + if (ctxcanvas->canvas->use_matrix || ctxcanvas->rotate_angle) + cdtransform(ctxcanvas, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL); + + fprintf(ctxcanvas->file, "gsave\n"); /* save to use local transform */ + fprintf(ctxcanvas->file, "%d %d translate\n", x, y); + + if (ctxcanvas->canvas->text_orientation != 0) + fprintf(ctxcanvas->file, "%g rotate\n", ctxcanvas->canvas->text_orientation); + + switch (ctxcanvas->canvas->text_alignment) /* Operacao em Y. topo da pilha: w x y h */ + { + case CD_NORTH: + case CD_NORTH_EAST: + case CD_NORTH_WEST: + fprintf(ctxcanvas->file, "%d sub sub\n", baseline); /* empilha, subtrai, subtrai: w x y-(h-baseline) */ + break; + case CD_EAST: + case CD_WEST: + case CD_CENTER: + fprintf(ctxcanvas->file, "2 div %d sub sub\n", baseline); /* empilha, divide, empilha, subtrai, subtrai: w x y-(h/2-baseline) */ + break; + case CD_SOUTH_EAST: + case CD_SOUTH: + case CD_SOUTH_WEST: + fprintf(ctxcanvas->file, "pop %d add\n", baseline); /* desempilha, empilha, adiciona: w x y+baseline */ + break; + case CD_BASE_RIGHT: + case CD_BASE_CENTER: + case CD_BASE_LEFT: + fprintf(ctxcanvas->file, "pop\n"); /* desempilha h: w x y */ + break; + } + + fprintf(ctxcanvas->file, "3 1 roll\n"); /* roda: y' w x */ + fprintf(ctxcanvas->file, "exch\n"); /* inverte: y' x w */ + + switch (ctxcanvas->canvas->text_alignment) /* Operacao em X, topo da pilha: x w */ + { + case CD_NORTH: + case CD_SOUTH: + case CD_CENTER: + case CD_BASE_CENTER: + fprintf(ctxcanvas->file, "2 div sub\n"); /* empilha, divide, subtrai: y' x-w/2 */ + break; + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + case CD_BASE_RIGHT: + fprintf(ctxcanvas->file, "sub\n"); /* subtrai: y' x-w */ + break; + case CD_SOUTH_WEST: + case CD_WEST: + case CD_NORTH_WEST: + case CD_BASE_LEFT: + fprintf(ctxcanvas->file, "pop\n"); /* desempilha: y' x */ + break; + } + + fprintf(ctxcanvas->file, "exch\n"); /* inverte: x' y' */ + fprintf(ctxcanvas->file, "M\n"); /* moveto */ + + fprintf(ctxcanvas->file, "show\n"); + + if (ctxcanvas->eps) + { + int xmin, xmax, ymin, ymax; + s = cdStrDupN(s, len); + cdCanvasGetTextBox(ctxcanvas->canvas, x, y, s, &xmin, &xmax, &ymin, &ymax); + free((char*)s); + bbox(ctxcanvas, xmin, ymin); + bbox(ctxcanvas, xmax, ymax); + } + + fprintf(ctxcanvas->file, "grestore\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdTextEnd\n"); +} + +static void cdpoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + if (mode == CD_CLIP) + { + if (ctxcanvas->eps) /* initclip not allowed in EPS */ + return; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode); + + fprintf(ctxcanvas->file, "/clip_polygon {\n"); + fprintf(ctxcanvas->file, "initclip\n"); + } + else + { + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPoly %d Begin\n", mode); + } + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d M\n", poly[0].x, poly[0].y); + + if (ctxcanvas->eps) + bbox(ctxcanvas, poly[0].x, poly[0].y); + + if (mode == CD_BEZIER) + { + for (i=1; ifile, "%d %d %d %d %d %d B\n", poly[i].x, poly[i].y, + poly[i+1].x, poly[i+1].y, + poly[i+2].x, poly[i+2].y); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, poly[i].x, poly[i].y); + bbox(ctxcanvas, poly[i+2].x, poly[i+2].y); + bbox(ctxcanvas, poly[i+3].x, poly[i+3].y); + } + } + } + else + { + int hole_index = 0; + + for (i=1; iholes && i == ctxcanvas->poly_holes[hole_index]) + { + fprintf(ctxcanvas->file, "%d %d M\n", poly[i].x, poly[i].y); + hole_index++; + } + else + fprintf(ctxcanvas->file, "%d %d L\n", poly[i].x, poly[i].y); + + if (ctxcanvas->eps) + bbox(ctxcanvas, poly[i].x, poly[i].y); + } + } + + switch (mode) + { + case CD_CLOSED_LINES : + fprintf(ctxcanvas->file, "C S\n"); + break; + case CD_OPEN_LINES : + fprintf(ctxcanvas->file, "S\n"); + break; + case CD_BEZIER : + fprintf(ctxcanvas->file, "S\n"); + break; + case CD_FILL : + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + break; + case CD_CLIP : + if (ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "C eoclip\n"); + else + fprintf(ctxcanvas->file, "C clip\n"); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "} bind def\n"); + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + fprintf(ctxcanvas->file, "clip_polygon\n"); + break; + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPoly %dEnd\n", mode); +} + +static void cdfpoly(cdCtxCanvas *ctxcanvas, int mode, cdfPoint* poly, int n) +{ + int i, hole_index = 0; + + if (mode == CD_CLIP) + { + if (ctxcanvas->eps) /* initclip not allowed in EPS */ + return; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode); + + fprintf(ctxcanvas->file, "/clip_polygon {\n"); + fprintf(ctxcanvas->file, "initclip\n"); + } + else + { + if (mode == CD_FILL) + update_fill(ctxcanvas, 1); + else + update_fill(ctxcanvas, 0); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdfPoly %d Begin\n", mode); + } + + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%g %g M\n", poly[0].x, poly[0].y); + + if (ctxcanvas->eps) + fbbox(ctxcanvas, poly[0].x, poly[0].y); + + for (i=1; iholes && i == ctxcanvas->poly_holes[hole_index]) + { + fprintf(ctxcanvas->file, "%g %g M\n", poly[i].x, poly[i].y); + hole_index++; + } + else + fprintf(ctxcanvas->file, "%g %g L\n", poly[i].x, poly[i].y); + + if (ctxcanvas->eps) + fbbox(ctxcanvas, poly[i].x, poly[i].y); + } + + switch (mode) + { + case CD_CLOSED_LINES : + fprintf(ctxcanvas->file, "C S\n"); + break; + case CD_OPEN_LINES : + fprintf(ctxcanvas->file, "S\n"); + break; + case CD_FILL : + if (ctxcanvas->holes || ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "eofill\n"); + else + fprintf(ctxcanvas->file, "fill\n"); + break; + case CD_CLIP : + if (ctxcanvas->canvas->fill_mode==CD_EVENODD) + fprintf(ctxcanvas->file, "C eoclip\n"); + else + fprintf(ctxcanvas->file, "C clip\n"); + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "} bind def\n"); + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + fprintf(ctxcanvas->file, "clip_polygon\n"); + break; + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdfPoly %dEnd\n", mode); +} + + +/******************************************************/ +/* attributes */ +/******************************************************/ + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + double mm = (72.0/25.4) / ctxcanvas->scale; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdLineStyle %d Begin\n", style); + + fprintf(ctxcanvas->file, "["); + + switch (style) + { + case CD_CONTINUOUS : /* empty dash */ + fprintf(ctxcanvas->file, " "); + break; + case CD_DASHED : + fprintf(ctxcanvas->file, "%g %g", 3*mm, mm); + break; + case CD_DOTTED : + fprintf(ctxcanvas->file, "%g %g", mm, mm); + break; + case CD_DASH_DOT : + fprintf(ctxcanvas->file, "%g %g %g %g", 3*mm, mm, mm, mm); + break; + case CD_DASH_DOT_DOT : + fprintf(ctxcanvas->file, "%g %g %g %g %g %g", 3*mm, mm, mm, mm, mm, mm); + break; + case CD_CUSTOM : + { + int i; + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + fprintf(ctxcanvas->file, "%g ", ctxcanvas->canvas->line_dashes[i]*mm); + } + break; + } + + fprintf(ctxcanvas->file, "] 0 setdash\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdLineStyle %dEnd\n", style); + + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + fprintf(ctxcanvas->file, "%d setlinewidth\n", width); + return width; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + int cd2ps_join[] = {0, 2, 1}; + fprintf(ctxcanvas->file, "%d setlinejoin\n", cd2ps_join[join]); + return join; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + int cd2ps_cap[] = {0, 2, 1}; + fprintf(ctxcanvas->file, "%d setlinecap\n", cd2ps_cap[cap]); + return cap; +} + +static void make_pattern(cdCtxCanvas *ctxcanvas, int n, int m, void* data, void (*data2rgb)(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b)) +{ + int i, j; + unsigned char r, g, b; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "\n%%cdPsMakePattern Begin\n"); + + fprintf(ctxcanvas->file, "/cd_pattern\n"); + fprintf(ctxcanvas->file, "currentfile %d string readhexstring\n", n*m*3); + + for (j=0; jfile, "%02x%02x%02x", (int)r, (int)g, (int)b); + } + + fprintf(ctxcanvas->file, "\n"); + } + + fprintf(ctxcanvas->file, "pop\n"); + fprintf(ctxcanvas->file, "/Pat exch def\n"); + fprintf(ctxcanvas->file, "<<\n"); + fprintf(ctxcanvas->file, " /PatternType 1\n"); + fprintf(ctxcanvas->file, " /PaintType 1\n"); + fprintf(ctxcanvas->file, " /TilingType 1\n"); + fprintf(ctxcanvas->file, " /BBox [0 0 %d %d]\n", n, m); + fprintf(ctxcanvas->file, " /XStep %d /YStep %d\n", n, m); + fprintf(ctxcanvas->file, " /PaintProc {\n"); + fprintf(ctxcanvas->file, " pop\n"); + fprintf(ctxcanvas->file, " %d %d 8\n", n, m); + fprintf(ctxcanvas->file, " matrix\n"); + fprintf(ctxcanvas->file, " Pat\n"); + fprintf(ctxcanvas->file, " false 3\n"); + fprintf(ctxcanvas->file, " colorimage\n"); + fprintf(ctxcanvas->file, " }\n"); + fprintf(ctxcanvas->file, ">>\n"); + fprintf(ctxcanvas->file, "matrix\n"); + fprintf(ctxcanvas->file, "makepattern\n"); + fprintf(ctxcanvas->file, "def\n"); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPsMakePatternEnd\n"); +} + +static void long2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + long* long_data = (long*)data; + (void)ctxcanvas; + cdDecodeColor(long_data[j*n+i], r, g, b); +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int n, int m, const long int *pattern) +{ + if (ctxcanvas->level1) + return; + + make_pattern(ctxcanvas, n, m, (void*)pattern, long2rgb); +} + +static void uchar2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + unsigned char* uchar_data = (unsigned char*)data; + if (uchar_data[j*n+i]) + cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); + else + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int n, int m, const unsigned char *stipple) +{ + if (ctxcanvas->level1) + return; + + make_pattern(ctxcanvas, n, m, (void*)stipple, uchar2rgb); +} + +static void ucharh2rgb(cdCtxCanvas *ctxcanvas, int n, int i, int j, void* data, unsigned char*r, unsigned char*g, unsigned char*b) +{ + unsigned char* uchar_data = (unsigned char*)data; + static unsigned char hatch; + (void)n; + if (i == 0) hatch = uchar_data[j]; + if (hatch & 0x80) + cdDecodeColor(ctxcanvas->canvas->foreground, r, g, b); + else + cdDecodeColor(ctxcanvas->canvas->background, r, g, b); + _cdRotateHatch(hatch); +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int style) +{ + if (ctxcanvas->level1) + return ctxcanvas->canvas->hatch_style; + + make_pattern(ctxcanvas, 8, 8, (void*)HatchBits[style], ucharh2rgb); + + return style; +} + +static void add_font_name(cdCtxCanvas *ctxcanvas, char *nativefontname) +{ + int size, i; + for (i = 0; i < ctxcanvas->num_native_font; i++) + { + if (cdStrEqualNoCase(ctxcanvas->nativefontname[i], nativefontname)) + return; + } + + size = strlen(nativefontname)+1; + ctxcanvas->nativefontname[ctxcanvas->num_native_font] = (char*)malloc(size); + memcpy(ctxcanvas->nativefontname[ctxcanvas->num_native_font], nativefontname, size); + ctxcanvas->num_native_font++; +} + +static char *findfont(const char* type_face, int style) +{ + static char font[1024]; + + static char *type[] = + { + "", /* CD_PLAIN */ + "-Bold", /* CD_BOLD */ + "-Oblique", /* CD_ITALIC */ + "-BoldOblique", /* CD_BOLD_ITALIC */ + + "-Roman", /* Plain p/ Times */ + "-Bold", /* Bold p/ Times */ + "-Italic", /* Italic p/ Times */ + "-BoldItalic" /* BoldItalic p/ Times */ + }; + + if (cdStrEqualNoCase(type_face, "System")) + type_face = "Courier"; + + if (cdStrEqualNoCase(type_face, "Times")) + style += 4; + + sprintf(font, "%s%s", type_face, type[style]); + + return font; +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + char *nativefontname = findfont(type_face, style&3); /* no underline or strikeout support */ + int size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size); + fprintf(ctxcanvas->file, "%d /%s /%s-Latin1 ChgFnt\n", size_pixel, nativefontname, nativefontname); + add_font_name(ctxcanvas, nativefontname); + return 1; +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + set_default_matrix(ctxcanvas); + + if (matrix) + { + fprintf(ctxcanvas->file, "[%g %g %g %g %g %g] concat\n", matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); + } + else + { + if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle); + fprintf(ctxcanvas->file, "%d %d translate\n", -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } + } +} + +/******************************************************/ +/* client images */ +/******************************************************/ + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, rw, rh; + rw = xmax-xmin+1; + rh = ymax-ymin+1; + (void)ih; + + if (ctxcanvas->level1) + return; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGB Start\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%d %d translate\n", x, y); + fprintf(ctxcanvas->file, "%d %d scale\n", w, h); + + fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh); + fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh); + fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw); + fprintf(ctxcanvas->file, "false 3\n"); + fprintf(ctxcanvas->file, "colorimage\n"); + + for (j=ymin; j<=ymax; j++) + { + for (i=xmin; i<=xmax; i++) + { + int pos = j*iw+i; + fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r[pos], (int)g[pos], (int)b[pos]); + } + + fprintf(ctxcanvas->file, "\n"); + } + + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, x, y); + bbox(ctxcanvas, x+rw-1, y+rh-1); + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectRGBEnd\n"); +} + +static int isgray(int size, const unsigned char *index, const long int *colors) +{ + int i, pal_size = 0; + unsigned char r, g, b; + + for (i = 0; i < size; i++) + { + if (index[i] > pal_size) + pal_size = index[i]; + } + + pal_size++; + + for (i = 0; i < pal_size; i++) + { + cdDecodeColor(colors[i], &r, &g, &b); + + if (i != r || r != g || g != b) + return 0; + } + + return 1; +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int i, j, rw, rh, is_gray; + rw = xmax-xmin+1; + rh = ymax-ymin+1; + (void)ih; + + is_gray = isgray(iw*ih, index, colors); + + if (!is_gray && ctxcanvas->level1) + return; + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMap Start\n"); + + fprintf(ctxcanvas->file, "[0 0 0 0 0 0] currentmatrix\n"); + fprintf(ctxcanvas->file, "%d %d translate\n", x, y); + fprintf(ctxcanvas->file, "%d %d scale\n", w, h); + + fprintf(ctxcanvas->file, "%d %d 8\n", rw, rh); + fprintf(ctxcanvas->file, "[%d 0 0 %d 0 0]\n", rw, rh); + fprintf(ctxcanvas->file, "{currentfile %d string readhexstring pop}\n", rw); + + if (is_gray) + { + fprintf(ctxcanvas->file, "image\n"); + + for (j=ymin; j<=ymax; j++) + { + for (i=xmin; i<=xmax; i++) + { + int pos = j*iw+i; + fprintf(ctxcanvas->file, "%02x", (int)index[pos]); + } + + fprintf(ctxcanvas->file, "\n"); + } + } + else + { + fprintf(ctxcanvas->file, "false 3\n"); + fprintf(ctxcanvas->file, "colorimage\n"); + + for (j=ymin; j<=ymax; j++) + { + for (i=xmin; i<=xmax; i++) + { + int pos = j*iw+i; + unsigned char r, g, b; + cdDecodeColor(colors[index[pos]], &r, &g, &b); + fprintf(ctxcanvas->file, "%02x%02x%02x", (int)r, (int)g, (int)b); + } + + fprintf(ctxcanvas->file, "\n"); + } + } + + fprintf(ctxcanvas->file, "setmatrix\n"); + + if (ctxcanvas->eps) + { + bbox(ctxcanvas, x, y); + bbox(ctxcanvas, x+rw-1, y+rh-1); + } + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPutImageRectMapEnd\n"); +} + +/******************************************************/ +/* server images */ +/******************************************************/ + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixel Start\n"); + + fprintf(ctxcanvas->file, "%g %g %g setrgbcolor\n", + get_red(color), get_green(color), get_blue(color)); + + if (ctxcanvas->level1) + { + fprintf(ctxcanvas->file, "N\n"); + fprintf(ctxcanvas->file, "%d %d 1 0 360 arc\n", x, y); + fprintf(ctxcanvas->file, "C fill\n"); + } + else + fprintf(ctxcanvas->file, "%d %d 1 1 RF\n", x, y); + + if (ctxcanvas->eps) + bbox(ctxcanvas, x, y); + + if (ctxcanvas->debug) fprintf(ctxcanvas->file, "%%cdPixelEnd\n"); +} + +/******************************************************/ +/* custom attributes */ +/******************************************************/ + +static void set_rotate_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + /* ignore ROTATE if transform is set */ + if (ctxcanvas->canvas->use_matrix) + return; + + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + } + + set_default_matrix(ctxcanvas); + + if (ctxcanvas->rotate_angle) + { + /* rotation = translate to point + rotation + translate back */ + fprintf(ctxcanvas->file, "%d %d translate\n", ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + fprintf(ctxcanvas->file, "%g rotate\n", (double)ctxcanvas->rotate_angle); + fprintf(ctxcanvas->file, "%d %d translate\n", -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } +} + +static char* get_rotate_attrib(cdCtxCanvas *ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void set_cmd_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + fprintf(ctxcanvas->file, data); +} + +static cdAttribute cmd_attrib = +{ + "CMD", + set_cmd_attrib, + NULL +}; + +static void set_poly_attrib(cdCtxCanvas *ctxcanvas, char* data) +{ + int hole; + + if (data == NULL) + { + ctxcanvas->holes = 0; + return; + } + + sscanf(data, "%d", &hole); + ctxcanvas->poly_holes[ctxcanvas->holes] = hole; + ctxcanvas->holes++; +} + +static char* get_poly_attrib(cdCtxCanvas *ctxcanvas) +{ + static char holes[10]; + sprintf(holes, "%d", ctxcanvas->holes); + return holes; +} + +static cdAttribute poly_attrib = +{ + "POLYHOLE", + set_poly_attrib, + get_poly_attrib +}; + +/* +%F Cria um novo canvas PS +Parametros passados em data: +nome nome do arquivo de saida <= 255 caracteres +-p[num] tamanho do papel (A0-5, LETTER, LEGAL) +-w[num] largura do papel em milimetros +-h[num] altura do papel em milimetros +-l[num] margem esquerda em milimetros +-r[num] margem direita em milimetros +-b[num] margem inferior em milimetros +-t[num] margem superior em milimetros +-s[num] resolucao em dpi +-e encapsulated postscript +-1 level 1 operators only +-d[num] margem da bbox em milimetros para eps +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char *line = (char *)data; + cdCtxCanvas *ctxcanvas; + char filename[10240] = ""; + + ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + line += cdGetFileName(line, filename); + if (filename[0] == 0) + return; + + if ((ctxcanvas->file = fopen(filename, "w")) == NULL) + { + free(ctxcanvas); + return; + } + + ctxcanvas->holes = 0; + cdRegisterAttribute(canvas, &poly_attrib); + cdRegisterAttribute(canvas, &cmd_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + + setpsdefaultvalues(ctxcanvas); + + while (*line != '\0') + { + while (*line != '\0' && *line != '-') + line++; + + if (*line != '\0') + { + float num; + line++; + switch (*line++) + { + case 'p': + { + int paper; + sscanf(line, "%d", &paper); + setpspapersize(ctxcanvas, paper); + break; + } + case 'w': + sscanf(line, "%g", &num); + ctxcanvas->width = mm2pt(num); + break; + case 'h': + sscanf(line, "%g", &num); + ctxcanvas->height = mm2pt(num); + break; + case 'l': + sscanf(line, "%g", &num); + ctxcanvas->xmin = num; + break; + case 'r': + sscanf(line, "%g", &num); + ctxcanvas->xmax = num; /* right margin, must be converted to xmax */ + break; + case 'b': + sscanf(line, "%g", &num); + ctxcanvas->ymin = num; + break; + case 't': + sscanf(line, "%g", &num); + ctxcanvas->ymax = num; /* top margin, must be converted to ymax */ + break; + case 's': + sscanf(line, "%d", &(ctxcanvas->res)); + break; + case 'e': + ctxcanvas->eps = 1; + break; + case 'o': + ctxcanvas->landscape = 1; + break; + case '1': + ctxcanvas->level1 = 1; + break; + case 'g': + ctxcanvas->debug = 1; + break; + case 'd': + sscanf(line, "%g", &num); + ctxcanvas->bbmargin = num; + break; + } + } + + while (*line != '\0' && *line != ' ') + line++; + } + + /* store the base canvas */ + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->ctxcanvas = ctxcanvas; + + if (ctxcanvas->landscape == 1) + { + _cdSwapDouble(ctxcanvas->width, ctxcanvas->height); + _cdSwapDouble(ctxcanvas->xmin, ctxcanvas->ymin); + _cdSwapDouble(ctxcanvas->xmax, ctxcanvas->ymax); + } + + init_ps(ctxcanvas); +} + +static void cdinittable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxFLine = cdfline; + canvas->cxFPoly = cdfpoly; + canvas->cxFRect = cdfrect; + canvas->cxFBox = cdfbox; + canvas->cxFArc = cdfarc; + canvas->cxFSector = cdfsector; + canvas->cxFChord = cdfchord; + canvas->cxClip = cdclip; + canvas->cxFClipArea = cdfcliparea; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxPattern = cdpattern; + canvas->cxStipple = cdstipple; + canvas->cxHatch = cdhatch; + canvas->cxFont = cdfont; + canvas->cxTransform = cdtransform; + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxDeactivate = cddeactivate; +} + +static cdContext cdPSContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_PALETTE | + CD_CAP_REGION | CD_CAP_IMAGESRV | + CD_CAP_BACKGROUND | CD_CAP_BACKOPACITY | CD_CAP_WRITEMODE | + CD_CAP_FONTDIM | CD_CAP_TEXTSIZE | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextPS(void) +{ + return &cdPSContext; +} diff --git a/cd/src/drv/cgm.c b/cd/src/drv/cgm.c new file mode 100755 index 0000000..e86baaf --- /dev/null +++ b/cd/src/drv/cgm.c @@ -0,0 +1,2280 @@ +/** \file + * \brief CGM library + * Extracted from GKS/PUC + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include +#include + +#include "cgm.h" + + +struct _cgmFunc +{ + /* write command header */ + void (*wch)( CGM *, int, int, int ); + + /* put colour index at colour index precision */ + void (*ci)( CGM *, unsigned long ); + + /* put color direct at colour direct precision */ + void (*cd)( CGM *, double ); + + /* put color direct at colour direct precision */ + void (*rgb)( CGM *, double, double, double ); + + /* put index at index precision */ + void (*ix)( CGM *, long ); + + /* put enum ( int*2 ) */ + void (*e)( CGM *, int, const char *l[] ); + + /* put int ( integer precision ) */ + void (*i)( CGM *, long ); + + /* put unsigned int ( integer precision ) */ + void (*u)( CGM *, unsigned long ); + + /* put real ( real precision ) */ + void (*r)( CGM *, double ); + + /* put string */ + void (*s)( CGM *, const char *, int ); + + /* put VDC at VDC mode and precision */ + void (*vdc)( CGM *, double ); + + /* put point at VDC mode and precision */ + void (*p)( CGM *, double, double ); + + /* put colour at colour mode and precision */ + void (*co)( CGM *, const void * ); + + /* put separator */ + void (*sep)( CGM *, const char * ); + + /* get column position */ + int (*get_col)( CGM * ); + + /* align at column number */ + void (*align)( CGM *, int ); + + /* nova linha */ + void (*nl)( CGM * ); + + /* terminate element */ + int (*term)( CGM * ); +}; + +typedef struct _cgmCommand +{ + const char *ct; + const char *c; +} cgmCommand; + +/************************************************ +* * +* Dados para nao-binario * +* * +************************************************/ + +/* delimiter elements */ + +static const cgmCommand _cgmX_NULL = { "" , "" }; +static const cgmCommand _cgmX_BEGMF = { "BEGMF" , "\x30\x20" }; +static const cgmCommand _cgmX_ENDMF = { "ENDMF" , "\x30\x21" }; +static const cgmCommand _cgmX_BEG_PIC = { "BEG_PIC" , "\x30\x22" }; +static const cgmCommand _cgmX_BEG_PIC_BODY = { "BEG_PIC_BODY" , "\x30\x23" }; +static const cgmCommand _cgmX_END_PIC = { "END_PIC" , "\x30\x24" }; + +/* metafile descriptor elements */ + +static const cgmCommand _cgmX_MF_VERSION = { "MF_VERSION" , "\x31\x20" }; +static const cgmCommand _cgmX_MF_DESC = { "MF_DESC" , "\x31\x21" }; +static const cgmCommand _cgmX_VDC_TYPE = { "VDC_TYPE" , "\x31\x22" }; +static const cgmCommand _cgmX_INTEGER_PREC = { "INTEGER_PREC" , "\x31\x23" }; +static const cgmCommand _cgmX_REAL_PREC = { "REAL_PREC" , "\x31\x24" }; +static const cgmCommand _cgmX_INDEX_PREC = { "INDEX_PREC" , "\x31\x25" }; +static const cgmCommand _cgmX_COLR_PREC = { "COLR_PREC" , "\x31\x26" }; +static const cgmCommand _cgmX_COLR_INDEX_PREC = { "COLR_INDEX_PREC" , "\x31\x27" }; +static const cgmCommand _cgmX_MAX_COLR_INDEX = { "MAX_COLR_INDEX" , "\x31\x28" }; +static const cgmCommand _cgmX_COLR_VALUE_EXT = { "COLR_VALUE_EXT" , "\x31\x29" }; +static const cgmCommand _cgmX_MF_ELEM_LIST = { "MF_ELEM_LIST" , "\x31\x2a" }; +static const cgmCommand _cgmX_BEG_MF_DEFAULTS = { "BEG_MF_DEFAULTS" , "\x31\x2b" }; +static const cgmCommand _cgmX_END_MF_DEFAULTS = { "END_MF_DEFAULTS" , "\x31\x2c" }; +static const cgmCommand _cgmX_FONT_LIST = { "FONT_LIST" , "\x31\x2d" }; +static const cgmCommand _cgmX_CHAR_SET_LIST = { "CHAR_SET_LIST" , "\x31\x2e" }; +static const cgmCommand _cgmX_CHAR_CODING = { "CHAR_CODING" , "\x31\x2f" }; + +/* picture descriptor elements */ + +static const cgmCommand _cgmX_SCALE_MODE = { "SCALE_MODE" , "\x30\x20" }; +static const cgmCommand _cgmX_COLR_MODE = { "COLR_MODE" , "\x30\x21" }; +static const cgmCommand _cgmX_LINE_WIDTH_MODE = { "LINE_WIDTH_MODE" , "\x30\x22" }; +static const cgmCommand _cgmX_MARKER_SIZE_MODE = { "MARKER_SIZE_MODE" , "\x30\x23" }; +static const cgmCommand _cgmX_EDGE_WIDTH_MODE = { "EDGE_WIDTH_MODE" , "\x30\x24" }; +static const cgmCommand _cgmX_VDC_EXTENT = { "VDC_EXT" , "\x30\x25" }; +static const cgmCommand _cgmX_BACK_COLR = { "BACK_COLR" , "\x30\x26" }; + +/* control elements */ + +static const cgmCommand _cgmX_VDC_INTEGER_PREC = { "VDC_INTEGER_PREC" , "\x30\x20" }; +static const cgmCommand _cgmX_VDC_REAL_PREC = { "VDC_REAL_PREC" , "\x30\x21" }; +static const cgmCommand _cgmX_AUX_COLR = { "AUX_COLR" , "\x30\x22" }; +static const cgmCommand _cgmX_TRANSPARENCY = { "TRANSPARENCY" , "\x30\x23" }; +static const cgmCommand _cgmX_CLIP_RECT = { "CLIP_RECT" , "\x30\x24" }; +static const cgmCommand _cgmX_CLIP = { "CLIP" , "\x30\x25" }; + +/* primitive elements */ + +static const cgmCommand _cgmX_LINE = { "LINE" , "\x20" }; +static const cgmCommand _cgmX_DISJT_LINE = { "DISJT_LINE" , "\x21" }; +static const cgmCommand _cgmX_MARKER = { "MARKER" , "\x22" }; +static const cgmCommand _cgmX_TEXT = { "TEXT" , "\x23" }; +static const cgmCommand _cgmX_RESTR_TEXT = { "RESTR_TEXT" , "\x24" }; +static const cgmCommand _cgmX_APND_TEXT = { "APND_TEXT" , "\x25" }; +static const cgmCommand _cgmX_POLYGON = { "POLYGON" , "\x26" }; +static const cgmCommand _cgmX_POLYGON_SET = { "POLYGON_SET" , "\x27" }; +static const cgmCommand _cgmX_CELL_ARRAY = { "CELL_ARRAY" , "\x28" }; +static const cgmCommand _cgmX_GDP = { "GDP" , "\x29" }; +static const cgmCommand _cgmX_RECT = { "RECT" , "\x2a" }; +static const cgmCommand _cgmX_CIRCLE = { "CIRCLE" , "\x34\x20" }; +static const cgmCommand _cgmX_ARC_3_PT = { "ARC_3_PT" , "\x34\x21" }; +static const cgmCommand _cgmX_ARC_3_PT_CLOSE = { "ARC_3_PT_CLOSE" , "\x34\x22" }; +static const cgmCommand _cgmX_ARC_CTR = { "ARC_CTR" , "\x34\x23" }; +static const cgmCommand _cgmX_ARC_CTR_CLOSE = { "ARC_CTR_CLOSE" , "\x34\x24" }; +static const cgmCommand _cgmX_ELLIPSE = { "ELLIPSE" , "\x34\x25" }; +static const cgmCommand _cgmX_ELLIP_ARC = { "ELLIP_ARC" , "\x34\x26" }; +static const cgmCommand _cgmX_ELLIP_ARC_CLOSE = { "ELLIP_ARC_CLOSE" , "\x34\x27" }; + +/* attribute elements */ + +static const cgmCommand _cgmX_LINE_INDEX = { "LINE_INDEX" , "\x35\x20" }; +static const cgmCommand _cgmX_LINE_TYPE = { "LINE_TYPE" , "\x35\x21" }; +static const cgmCommand _cgmX_LINE_WIDTH = { "LINE_WIDTH" , "\x35\x22" }; +static const cgmCommand _cgmX_LINE_COLR = { "LINE_COLR" , "\x35\x23" }; +static const cgmCommand _cgmX_MARKER_INDEX = { "MARKER_INDEX" , "\x35\x24" }; +static const cgmCommand _cgmX_MARKER_TYPE = { "MARKER_TYPE" , "\x35\x25" }; +static const cgmCommand _cgmX_MARKER_WIDTH = { "MARKER_SIZE" , "\x35\x26" }; +static const cgmCommand _cgmX_MARKER_COLR = { "MARKER_COLR" , "\x35\x27" }; +static const cgmCommand _cgmX_TEXT_INDEX = { "TEXT_INDEX" , "\x35\x30" }; +static const cgmCommand _cgmX_TEXT_FONT_INDEX = { "TEXT_FONT_INDEX" , "\x35\x31" }; +static const cgmCommand _cgmX_TEXT_PREC = { "TEXT_PREC" , "\x35\x32" }; +static const cgmCommand _cgmX_CHAR_EXPAN = { "CHAR_EXPAN" , "\x35\x33" }; +static const cgmCommand _cgmX_CHAR_SPACE = { "CHAR_SPACE" , "\x35\x34" }; +static const cgmCommand _cgmX_TEXT_COLR = { "TEXT_COLR" , "\x35\x35" }; +static const cgmCommand _cgmX_CHAR_HEIGHT = { "CHAR_HEIGHT" , "\x35\x36" }; +static const cgmCommand _cgmX_CHAR_ORI = { "CHAR_ORI" , "\x35\x37" }; +static const cgmCommand _cgmX_TEXT_PATH = { "TEXT_PATH" , "\x35\x38" }; +static const cgmCommand _cgmX_TEXT_ALIGN = { "TEXT_ALIGN" , "\x35\x39" }; +static const cgmCommand _cgmX_CHAR_SET_INDEX = { "CHAR_SET_INDEX" , "\x35\x3a" }; +static const cgmCommand _cgmX_ALT_CHAR_SET = { "ALT_CHAR_SET_INDEX" , "\x35\x3b" }; +static const cgmCommand _cgmX_FILL_INDEX = { "FILL_INDEX" , "\x36\x20" }; +static const cgmCommand _cgmX_INT_STYLE = { "INT_STYLE" , "\x36\x21" }; +static const cgmCommand _cgmX_FILL_COLR = { "FILL_COLR" , "\x36\x22" }; +static const cgmCommand _cgmX_HATCH_INDEX = { "HATCH_INDEX" , "\x36\x23" }; +static const cgmCommand _cgmX_PAT_INDEX = { "PAT_INDEX" , "\x36\x24" }; +static const cgmCommand _cgmX_EDGE_INDEX = { "EDGE_INDEX" , "\x36\x25" }; +static const cgmCommand _cgmX_EDGE_TYPE = { "EDGE_TYPE" , "\x36\x26" }; +static const cgmCommand _cgmX_EDGE_WIDTH = { "EDGE_WIDTH" , "\x36\x27" }; +static const cgmCommand _cgmX_EDGE_COLR = { "EDGE_COLR" , "\x36\x28" }; +static const cgmCommand _cgmX_EDGE_VIS = { "EDGE_VIS" , "\x36\x29" }; +static const cgmCommand _cgmX_FILL_REF_PT = { "FILL_REF_PT" , "\x36\x2a" }; +static const cgmCommand _cgmX_PAT_TABLE = { "PAT_TABLE" , "\x36\x2b" }; +static const cgmCommand _cgmX_PAT_SIZE = { "PAT_SIZE" , "\x36\x2c" }; +static const cgmCommand _cgmX_COLR_TABLE = { "COLR_TABLE" , "\x36\x30" }; +static const cgmCommand _cgmX_ASF = { "ASF" , "\x36\x31" }; + +/* escape elements */ + +static const cgmCommand _cgmX_ESCAPE = { "ESCAPE" , "\x37\x20" }; +static const cgmCommand _cgmX_DOMAIN_RING = { "DOMAIN_RING" , "\x37\x30" }; + +/* external elements */ + +static const cgmCommand _cgmX_MESSAGE = { "MESSAGE" , "\x37\x21" }; +static const cgmCommand _cgmX_APPL_DATA = { "APPL_DATA" , "\x37\x22" }; + +/* drawing sets */ +static const cgmCommand _cgmX_DRAWING_SET = { "drawing_set" , "\x40" }; +static const cgmCommand _cgmX_DRAWING_PLUS = { "drawing_plus" , "\x41" }; + +static const cgmCommand *_elements_list_sets[] = { + & _cgmX_DRAWING_SET, + & _cgmX_DRAWING_PLUS, + NULL }; + + +static const cgmCommand *delimiter[] = { + & _cgmX_NULL, + & _cgmX_BEGMF, + & _cgmX_ENDMF, + & _cgmX_BEG_PIC, + & _cgmX_BEG_PIC_BODY, + & _cgmX_END_PIC, + NULL }; + +static const cgmCommand *metafile[] = { + & _cgmX_END_MF_DEFAULTS, + & _cgmX_MF_VERSION, + & _cgmX_MF_DESC, + & _cgmX_VDC_TYPE, + & _cgmX_INTEGER_PREC, + & _cgmX_REAL_PREC, + & _cgmX_INDEX_PREC, + & _cgmX_COLR_PREC, + & _cgmX_COLR_INDEX_PREC, + & _cgmX_MAX_COLR_INDEX, + & _cgmX_COLR_VALUE_EXT, + & _cgmX_MF_ELEM_LIST, + & _cgmX_BEG_MF_DEFAULTS, + & _cgmX_FONT_LIST, + & _cgmX_CHAR_SET_LIST, + & _cgmX_CHAR_CODING, + NULL }; + +static const cgmCommand *picture[] = { + & _cgmX_NULL, + & _cgmX_SCALE_MODE, + & _cgmX_COLR_MODE, + & _cgmX_LINE_WIDTH_MODE, + & _cgmX_MARKER_SIZE_MODE, + & _cgmX_EDGE_WIDTH_MODE, + & _cgmX_VDC_EXTENT, + & _cgmX_BACK_COLR, + NULL }; + +static const cgmCommand *control[] = { + & _cgmX_NULL, + & _cgmX_VDC_INTEGER_PREC, + & _cgmX_VDC_REAL_PREC, + & _cgmX_AUX_COLR, + & _cgmX_TRANSPARENCY, + & _cgmX_CLIP_RECT, + & _cgmX_CLIP, + NULL }; + +static const cgmCommand *primitive[] = { + & _cgmX_NULL, + & _cgmX_LINE, + & _cgmX_DISJT_LINE, + & _cgmX_MARKER, + & _cgmX_TEXT, + & _cgmX_RESTR_TEXT, + & _cgmX_APND_TEXT, + & _cgmX_POLYGON, + & _cgmX_POLYGON_SET, + & _cgmX_CELL_ARRAY, + & _cgmX_GDP, + & _cgmX_RECT, + & _cgmX_CIRCLE, + & _cgmX_ARC_3_PT, + & _cgmX_ARC_3_PT_CLOSE, + & _cgmX_ARC_CTR, + & _cgmX_ARC_CTR_CLOSE, + & _cgmX_ELLIPSE, + & _cgmX_ELLIP_ARC, + & _cgmX_ELLIP_ARC_CLOSE, + NULL }; + +static const cgmCommand *attributes[] = { + & _cgmX_NULL, + & _cgmX_LINE_INDEX, + & _cgmX_LINE_TYPE, + & _cgmX_LINE_WIDTH, + & _cgmX_LINE_COLR, + & _cgmX_MARKER_INDEX, + & _cgmX_MARKER_TYPE, + & _cgmX_MARKER_WIDTH, + & _cgmX_MARKER_COLR, + & _cgmX_TEXT_INDEX, + & _cgmX_TEXT_FONT_INDEX, + & _cgmX_TEXT_PREC, + & _cgmX_CHAR_EXPAN, + & _cgmX_CHAR_SPACE, + & _cgmX_TEXT_COLR, + & _cgmX_CHAR_HEIGHT, + & _cgmX_CHAR_ORI, + & _cgmX_TEXT_PATH, + & _cgmX_TEXT_ALIGN, + & _cgmX_CHAR_SET_INDEX, + & _cgmX_ALT_CHAR_SET, + & _cgmX_FILL_INDEX, + & _cgmX_INT_STYLE, + & _cgmX_FILL_COLR, + & _cgmX_HATCH_INDEX, + & _cgmX_PAT_INDEX, + & _cgmX_EDGE_INDEX, + & _cgmX_EDGE_TYPE, + & _cgmX_EDGE_WIDTH, + & _cgmX_EDGE_COLR, + & _cgmX_EDGE_VIS, + & _cgmX_FILL_REF_PT, + & _cgmX_PAT_TABLE, + & _cgmX_PAT_SIZE, + & _cgmX_COLR_TABLE, + & _cgmX_ASF, + NULL }; + +static const cgmCommand *escape[] = { + & _cgmX_NULL, + & _cgmX_ESCAPE, + & _cgmX_DOMAIN_RING, + NULL }; + +static const cgmCommand *external[] = { + & _cgmX_NULL, + & _cgmX_MESSAGE, + & _cgmX_APPL_DATA, + NULL }; + +static const cgmCommand **comandos[] = { + _elements_list_sets, + delimiter, + metafile, + picture, + control, + primitive, + attributes, + escape, + external, + NULL }; + +#define unit (cgm->file) + +/************************************************ +* * +* listas de funcoes necessarias * +* * +************************************************/ + + +static void cgmb_wch ( CGM *, int, int, int ); /* write command header */ +static void cgmb_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */ +static void cgmb_cd ( CGM *, double ); /* put color direct at colour direct precision */ +static void cgmb_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */ +static void cgmb_ix ( CGM *, long ); /* put index at index precision */ +static void cgmb_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */ +static void cgmb_i ( CGM *, long ); /* put int ( integer precision ) */ +static void cgmb_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */ +static void cgmb_r ( CGM *, double ); /* put real ( real precision ) */ +static void cgmb_s ( CGM *, const char *, int ); /* put string */ +static void cgmb_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */ +static void cgmb_p ( CGM *, double, double ); /* put point at VDC mode and precision */ +static void cgmb_co ( CGM *, const void * ); /* put colour at colour mode and precision */ +static void cgmb_sep ( CGM *, const char * ); /* put separator */ +static int cgmb_get_col ( CGM * ); /* get column position */ +static void cgmb_align ( CGM *, int ); /* align at column number */ +static void cgmb_nl ( CGM * ); /* new line */ +static int cgmb_term ( CGM * ); /* terminate element */ + +static const CGMFUNC cgmf_binary = { + cgmb_wch , + cgmb_ci , + cgmb_cd , + cgmb_rgb , + cgmb_ix , + cgmb_e , + cgmb_i , + cgmb_u , + cgmb_r , + cgmb_s , + cgmb_vdc , + cgmb_p , + cgmb_co , + cgmb_sep , + cgmb_get_col, + cgmb_align , + cgmb_nl , + cgmb_term + }; + +static void cgmt_wch ( CGM *, int, int, int ); /* write command header */ +static void cgmt_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */ +static void cgmt_cd ( CGM *, double ); /* put color direct at colour direct precision */ +static void cgmt_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */ +static void cgmt_ix ( CGM *, long ); /* put index at index precision */ +static void cgmt_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */ +static void cgmt_i ( CGM *, long ); /* put int ( integer precision ) */ +static void cgmt_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */ +static void cgmt_r ( CGM *, double ); /* put real ( real precision ) */ +static void cgmt_s ( CGM *, const char *, int ); /* put string */ +static void cgmt_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */ +static void cgmt_p ( CGM *, double, double ); /* put point at VDC mode and precision */ +static void cgmt_co ( CGM *, const void * ); /* put colour at colour mode and precision */ +static void cgmt_sep ( CGM *, const char * ); /* put separator */ +static int cgmt_get_col ( CGM * ); /* get column position */ +static void cgmt_align ( CGM *, int ); /* align at column number */ +static void cgmt_nl ( CGM * ); /* new line */ +static int cgmt_term ( CGM * ); /* terminate element */ + +static const CGMFUNC cgmf_clear_text = { + cgmt_wch , + cgmt_ci , + cgmt_cd , + cgmt_rgb , + cgmt_ix , + cgmt_e , + cgmt_i , + cgmt_u , + cgmt_r , + cgmt_s , + cgmt_vdc , + cgmt_p , + cgmt_co , + cgmt_sep , + cgmt_get_col, + cgmt_align , + cgmt_nl , + cgmt_term + }; + +static void cgmc_wch ( CGM *, int, int, int ); /* write command header */ +static void cgmc_ci ( CGM *, unsigned long ); /* put colour index at colour index precision */ +static void cgmc_cd ( CGM *, double ); /* put color direct at colour direct precision */ +static void cgmc_rgb ( CGM *, double, double, double ); /* put color direct (rgb) at colour direct precision */ +static void cgmc_ix ( CGM *, long ); /* put index at index precision */ +static void cgmc_e ( CGM *, int, const char *l[] ); /* put enum ( int*2 ) */ +static void cgmc_i ( CGM *, long ); /* put int ( integer precision ) */ +static void cgmc_u ( CGM *, unsigned long ); /* put unsigned int ( integer precision ) */ +static void cgmc_r ( CGM *, double ); /* put real ( real precision ) */ +static void cgmc_s ( CGM *, const char *, int ); /* put string */ +static void cgmc_vdc ( CGM *, double ); /* put VDC at VDC mode and precision */ +static void cgmc_p ( CGM *, double, double ); /* put point at VDC mode and precision */ +static void cgmc_co ( CGM *, const void * ); /* put colour at colour mode and precision */ +static void cgmc_sep ( CGM *, const char * ); /* put separator */ +static int cgmc_get_col ( CGM * ); /* get column position */ +static void cgmc_align ( CGM *, int ); /* align at column number */ +static void cgmc_nl ( CGM * ); /* new line */ +static int cgmc_term ( CGM * ); /* terminate element */ + +static const CGMFUNC cgmf_character = { + cgmc_wch , + cgmc_ci , + cgmc_cd , + cgmc_rgb , + cgmc_ix , + cgmc_e , + cgmc_i , + cgmc_u , + cgmc_r , + cgmc_s , + cgmc_vdc , + cgmc_p , + cgmc_co , + cgmc_sep , + cgmc_get_col, + cgmc_align , + cgmc_nl , + cgmc_term + }; + +static const CGMFUNC *cgmf[] = { &cgmf_character, &cgmf_binary, &cgmf_clear_text }; + +/************************************************ +* * +* Funcoes para binario * +* * +************************************************/ + +#define cgmb_putw cgmb_putu16 +#define cgmb_putb(a,b) cgmb_putc((a),(int)(b)) + +static void cgmb_putw ( CGM *, unsigned ); + +static void cgmb_putc ( CGM *cgm, int b ) +{ + if ( cgm->op != -1 ) + { + register int i; + for ( i=cgm->op; i>=0; i-- ) + { + if ( cgm->bc[i] == 32766 - 2*i ) + { + long po = ftell(unit); + int op = cgm->op; + + cgm->op = -1; + fseek(unit, cgm->po[i] , SEEK_SET); + cgmb_putw ( cgm, (1 << 15) | (cgm->bc[i]) ); + + cgm->op = i - 1; + fseek(unit, po, SEEK_SET); + cgmb_putw ( cgm, 0 ); + + cgm->op = op; + cgm->bc[i] = 0; + cgm->po[i] = po; + } + cgm->bc[i] ++; + } + } + + fputc ( b, unit ); +} + + +static void cgmb_puti8 ( CGM *cgm, int b ) +{ + cgmb_putb ( cgm, b ); +} + +static void cgmb_puti16 ( CGM *cgm, int b ) +{ + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_puti24 ( CGM *cgm, long b ) +{ + cgmb_putb ( cgm, b >> 16 ); + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_puti32 ( CGM *cgm, long b ) +{ + cgmb_putb ( cgm, b >> 24 ); + cgmb_putb ( cgm, b >> 16 ); + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_putu8 ( CGM *cgm, unsigned int b ) +{ + cgmb_putb ( cgm, b ); +} + +static void cgmb_putu16 ( CGM *cgm, unsigned int b ) +{ + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_putu24 ( CGM *cgm, unsigned long b ) +{ + cgmb_putb ( cgm, b >> 16 ); + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_putu32 ( CGM *cgm, unsigned long b ) +{ + cgmb_putb ( cgm, b >> 24 ); + cgmb_putb ( cgm, b >> 16 ); + cgmb_putb ( cgm, b >> 8 ); + cgmb_putb ( cgm, b ); +} + +static void cgmb_putfl32 ( CGM *cgm, float b ) +{ + union { + float func; + long l; + } r; + r.func = b; + cgmb_putb ( cgm, r.l >> 24 ); + cgmb_putb ( cgm, r.l >> 16 ); + cgmb_putb ( cgm, r.l >> 8 ); + cgmb_putb ( cgm, r.l ); +} + +static void cgmb_putfl64 ( CGM *cgm, double b ) +{ + union { + double d; + long l[2]; + } r; + r.d = b; + cgmb_putb ( cgm, r.l[1] >> 24 ); + cgmb_putb ( cgm, r.l[1] >> 16 ); + cgmb_putb ( cgm, r.l[1] >> 8 ); + cgmb_putb ( cgm, r.l[1] ); + cgmb_putb ( cgm, r.l[0] >> 24 ); + cgmb_putb ( cgm, r.l[0] >> 16 ); + cgmb_putb ( cgm, r.l[0] >> 8 ); + cgmb_putb ( cgm, r.l[0] ); +} + +static void cgmb_putfx32 ( CGM *cgm, float b ) +{ + int si = ( int ) floor ( b ); + unsigned int ui = ( unsigned int ) ( (b - si) * 65536.0 ); + + cgmb_puti16 ( cgm, si ); + cgmb_puti16 ( cgm, ui ); +} + +static void cgmb_putfx64 ( CGM *cgm, double b ) +{ + long si = ( long ) floor ( b ); + unsigned long ui = ( unsigned long ) ( (b - si) * 65536.0 * 65536.0 ); + + cgmb_puti32 ( cgm, si ); + cgmb_puti32 ( cgm, ui ); +} + +static void cgmb_wch ( CGM* cgm, int c, int id, int len ) +{ + + /* if ( len & 1 ) len ++; */ /* word aligned */ + + if ( len > 30 ) + cgmb_putw ( cgm, (c << 12) | ( id << 5 ) | 31 ); + else + cgmb_putw ( cgm, (c << 12) | ( id << 5 ) | (int)(len) ); + + + cgm->op++; + + if ( len > 30 ) + { + cgm->po[cgm->op] = ftell(unit); + cgmb_putw ( cgm, 0 ); + } + else + cgm->po[cgm->op] = 0L; + + cgm->bc[cgm->op] = 0; + +} + +static void cgmb_ci ( CGM *cgm, unsigned long ci ) +{ + switch ( cgm->cix_prec ) + { + case 0: cgmb_putu8 ( cgm, (unsigned)ci ); break; + case 1: cgmb_putu16 ( cgm, (unsigned)ci ); break; + case 2: cgmb_putu24 ( cgm, ci ); break; + case 3: cgmb_putu32 ( cgm, ci ); break; + } +} + +static void cgmb_cd ( CGM *cgm, double cd ) +{ + unsigned long cv = (unsigned long) (cd * (pow(2.0, (cgm->cd_prec + 1) * 8.0) - 1)); + switch ( cgm->cd_prec ) + { + case 0: cgmb_putu8 ( cgm, (unsigned)cv ); break; + case 1: cgmb_putu16 ( cgm, (unsigned)cv ); break; + case 2: cgmb_putu24 ( cgm, cv ); break; + case 3: cgmb_putu32 ( cgm, cv ); break; + } +} + +static void cgmb_rgb ( CGM *cgm, double r, double g, double b ) +{ + cgmb_cd ( cgm, r ); + cgmb_cd ( cgm, g ); + cgmb_cd ( cgm, b ); +} + +static void cgmb_ix ( CGM *cgm, long ix ) +{ + switch ( cgm->ix_prec ) + { + case 0: cgmb_puti8 ( cgm, (int)ix ); break; + case 1: cgmb_puti16 ( cgm, (int)ix ); break; + case 2: cgmb_puti24 ( cgm, ix ); break; + case 3: cgmb_puti32 ( cgm, ix ); break; + } +} + +static void cgmb_e ( CGM *cgm, int e, const char *el[] ) +{ + cgmb_puti16 ( cgm, e ); +} + +static void cgmb_i ( CGM *cgm, long i ) +{ + switch ( cgm->int_prec ) + { + case 0: cgmb_puti8 ( cgm, (int)i ); break; + case 1: cgmb_puti16 ( cgm, (int)i ); break; + case 2: cgmb_puti24 ( cgm, i ); break; + case 3: cgmb_puti32 ( cgm, i ); break; + } +} + +static void cgmb_u ( CGM *cgm, unsigned long i ) +{ + switch ( cgm->int_prec ) + { + case 0: cgmb_putu8 ( cgm, (unsigned)i ); break; + case 1: cgmb_putu16 ( cgm, (unsigned)i ); break; + case 2: cgmb_putu24 ( cgm, i ); break; + case 3: cgmb_putu32 ( cgm, i ); break; + } +} + +static void cgmb_r ( CGM *cgm, double func ) +{ + switch ( cgm->real_prec ) + { + case 0: cgmb_putfl32 ( cgm, (float )func ); break; + case 1: cgmb_putfl64 ( cgm, (double)func ); break; + case 2: cgmb_putfx32 ( cgm, (float )func ); break; + case 3: cgmb_putfx64 ( cgm, (double)func ); break; + } +} + +static void cgmb_s ( CGM *cgm, const char *s, int len ) +{ + register unsigned i; + unsigned l = len; + int bc = 0; + + if ( l > 254 ) + { + cgmb_putu8(cgm,255); + if ( l > 32763 ) + cgmb_putu16 ( cgm, (1<<16) | 32763 ); + else + cgmb_putu16 ( cgm, l ); + bc = 1; + } + else + cgmb_putu8(cgm,l); + + for ( i=0; i 32764 ) + cgmb_putu16 ( cgm, (1<<16) | 32764 ); + else + cgmb_putu16 ( cgm, l ); + } + cgmb_putc ( cgm, s[i] ); + } +} + +static void cgmb_vdc ( CGM *cgm, double vdc) +{ + if ( cgm->vdc_type == 0 ) + switch ( cgm->vdc_int ) + { + case 0: cgmb_puti8 ( cgm, (int )vdc ); break; + case 1: + /* Evita overflow em ambientes de 32 bits */ + if (vdc < -32768) vdc = -32768; + else if (vdc > 32767) vdc = +32767; + cgmb_puti16 ( cgm, (int) vdc ); + break; + case 2: cgmb_puti24 ( cgm, (long)vdc ); break; + case 3: + /* Evita overflow em ambientes de 32 bits */ + if (vdc < (double)-2147483648.0) vdc = (double)-2147483648.0; + else if (vdc > (double)2147483647.0) vdc = (double)2147483647.0; + cgmb_puti32 ( cgm, (long)vdc ); + break; + + } + else + switch ( cgm->vdc_real ) + { + case 0: cgmb_putfl32 ( cgm, (float )vdc ); break; + case 1: cgmb_putfl64 ( cgm, (double)vdc ); break; + case 2: cgmb_putfx32 ( cgm, (float )vdc ); break; + case 3: cgmb_putfx64 ( cgm, (double)vdc ); break; + } + +} + +static void cgmb_p ( CGM *cgm, double x, double y) +{ + cgmb_vdc ( cgm, x ); + cgmb_vdc ( cgm, y ); +} + +static void cgmb_co ( CGM *cgm, const void * co) +{ + if ( cgm->clrsm == 0 ) /* indexed */ + { + unsigned long ci = *(unsigned long *)co; + cgmb_ci ( cgm, ci ); + } + else + { + double *cb = (double *) co; + cgmb_rgb ( cgm, cb[0], cb[1], cb[2] ); + } +} + +static void cgmb_sep ( CGM *cgm, const char * sep ) +{} + +static int cgmb_get_col ( CGM *cgm ) +{ + return 0; +} + +static void cgmb_align ( CGM *cgm, int n ) +{} + +static void cgmb_nl ( CGM *cgm ) +{} + +static int cgmb_term ( CGM *cgm ) +{ + if ( cgm->op != -1 ) + { + if ( cgm->bc[cgm->op] & 1 ) + { + cgmb_putb( cgm, 0 ); + cgm->bc[cgm->op] --; + } + + if ( cgm->po[cgm->op] != 0L ) + { + long po = ftell(unit); + int op = cgm->op; + + cgm->op = -1; + fseek ( unit, cgm->po[op], SEEK_SET); + cgmb_putw ( cgm, cgm->bc[op] ); + + fseek ( unit, po, SEEK_SET ); + cgm->op = op; + } + cgm->op --; + } + + return 0; +} + +/************************************************ +* * +* Funcoes para clear text * +* * +************************************************/ + +static void cgmt_wch ( CGM* cgm, int c, int id, int len ) +{ + cgm->cl += fprintf ( unit, "%s", comandos[c+1][id]->ct ); +} + +static void cgmt_ci ( CGM *cgm, unsigned long ci ) +{ + cgm->func->u ( cgm, ci ); +} + +static void cgmt_cd ( CGM *cgm, double cd ) +{ + unsigned long cv = (unsigned long) (cd * (pow(2.0, (cgm->cd_prec + 1) * 8.0) - 1)); + + cgm->func->u ( cgm, cv ); +} + +static void cgmt_rgb ( CGM *cgm, double r, double g, double b ) +{ + cgm->func->cd ( cgm, r ); + cgm->func->cd ( cgm, g ); + cgm->func->cd ( cgm, b ); +} + +static void cgmt_ix ( CGM *cgm, long ix ) +{ + cgm->func->i ( cgm, ix ); +} + +static void cgmt_e ( CGM *cgm, int e, const char *el[] ) +{ + cgm->cl += fprintf ( unit, " %s", el[e] ); +} + +static void cgmt_i ( CGM *cgm, long i ) +{ + cgm->cl += fprintf ( unit, " %ld", i ); +} + +static void cgmt_u ( CGM *cgm, unsigned long i ) +{ + cgm->cl += fprintf ( unit, " %lu", i ); +} + +static void cgmt_r ( CGM *cgm, double func ) +{ + cgm->cl += fprintf ( unit, " %g", func ); +} + +static void cgmt_s ( CGM *cgm, const char *s, int len ) +{ + register unsigned i; + fputc ( 34, unit ); + + for ( i=0; icl ++; + } + fputc ( s[i], unit ); + } + + fputc ( 34, unit ); + cgm->cl += len + 2; +} + +static void cgmt_vdc ( CGM *cgm, double vdc) +{ + if ( cgm->vdc_type == 0 ) + { + /* Evita overflow em ambientes de 32 bits */ + if (vdc < (double)-2147483648.0) vdc = (double)-2147483648.0; + else if (vdc > (double)2147483647.0) vdc = (double)2147483647.0; + + cgm->func->i ( cgm, (long) vdc ); + } + else + cgm->func->r ( cgm, vdc ); +} + +static void cgmt_p ( CGM *cgm, double x, double y) +{ + cgm->func->sep ( cgm, "(" ); + cgm->func->vdc ( cgm, x ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, y ); + cgm->func->sep ( cgm, ")" ); +} + +static void cgmt_co ( CGM *cgm, const void * co) +{ + if ( cgm->clrsm == 0 ) /* indexed */ + { + unsigned long ci = *(unsigned *)co; + cgm->func->ci ( cgm, ci ); + } + else + { + double *cb = (double *) co; + cgm->func->rgb ( cgm, cb[0], cb[1], cb[2] ); + } +} + +static void cgmt_sep ( CGM *cgm, const char * sep ) +{ + cgm->cl += fprintf ( unit, " %s", sep ); +} + +static int cgmt_get_col ( CGM *cgm ) +{ + return cgm->cl; +} + +static void cgmt_align ( CGM *cgm, int n ) +{ + for ( ; cgm->cl < n ; cgm->cl ++ ) + fputc ( ' ', unit ); +} + +static void cgmt_nl ( CGM *cgm ) +{ + fputc ( '\n', unit ); + cgm->cl = 1; +} + +static int cgmt_term ( CGM *cgm ) +{ + fputc ( ';', unit ); + cgm->func->nl(cgm); + return 0; +} + +/************************************************ +* * +* Funcoes para character * +* * +************************************************/ + +static void cgmc_wch ( CGM* cgm, int c, int id, int len ) +{ + cgm->cl += fprintf ( unit, "%s", comandos[c+1][id]->ct ); +} + +static void cgmc_ci ( CGM *cgm, unsigned long ci ) +{ + cgm->func->u ( cgm, ci ); +} + +static void cgmc_cd ( CGM *cgm, double cd ) +{ + cgm->func->r ( cgm, cd ); +} + +static void cgmc_rgb ( CGM *cgm, double r, double g, double b ) +{ + cgm->func->cd ( cgm, r ); + cgm->func->sep ( cgm, "," ); + cgm->func->cd ( cgm, g ); + cgm->func->sep ( cgm, "," ); + cgm->func->cd ( cgm, b ); +} + +static void cgmc_ix ( CGM *cgm, long ix ) +{ + cgm->func->i ( cgm, ix ); +} + +static void cgmc_e ( CGM *cgm, int e, const char *el[] ) +{ + cgm->cl += fprintf ( unit, " %s", el[e] ); +} + +static void cgmc_i ( CGM *cgm, long i ) +{ + cgm->cl += fprintf ( unit, " %ld", i ); +} + +static void cgmc_u ( CGM *cgm, unsigned long i ) +{ + cgm->cl += fprintf ( unit, " %lu", i ); +} + +static void cgmc_r ( CGM *cgm, double func ) +{ + cgm->cl += fprintf ( unit, " %g", func ); +} + +static void cgmc_s ( CGM *cgm, const char *s, int len ) +{ + register unsigned i; + fputc ( 34, unit ); + + for ( i=0; icl ++; + } + fputc ( s[i], unit ); + } + + fputc ( 34, unit ); + cgm->cl += len + 2; +} + +static void cgmc_vdc ( CGM *cgm, double vdc) +{ + if ( cgm->vdc_type == 0 ) + cgm->func->i ( cgm, (long) vdc ); + else + cgm->func->r ( cgm, vdc ); +} + +static void cgmc_p ( CGM *cgm, double x, double y) +{ + cgm->func->sep ( cgm, "(" ); + cgm->func->vdc ( cgm, x ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, y ); + cgm->func->sep ( cgm, ")" ); +} + +static void cgmc_co ( CGM *cgm, const void * co) +{ + if ( cgm->clrsm == 0 ) /* indexed */ + { + unsigned long ci = *(unsigned long *)co; + cgm->func->ci ( cgm, ci ); + } + else + { + double *cb = (double *) co; + cgm->func->rgb ( cgm, cb[0], cb[1], cb[2] ); + } +} + +static void cgmc_sep ( CGM *cgm, const char * sep ) +{ + cgm->cl += fprintf ( unit, " %s", sep ); +} + +static int cgmc_get_col ( CGM *cgm ) +{ + return cgm->cl; +} + +static void cgmc_align ( CGM *cgm, int n ) +{ + for ( ; cgm->cl < n ; cgm->cl ++ ) + fputc ( ' ', unit ); +} + +static void cgmc_nl ( CGM *cgm ) +{ + fputc ( '\n', unit ); + cgm->cl = 1; +} + +static int cgmc_term ( CGM *cgm ) +{ + fputc ( ';', unit ); + cgm->func->nl(cgm); + return 0; +} + +/************************************************ +* * +* independente de codificacao * +* * +************************************************/ + + +/* Definicoes de precisao */ + +static const long _cgm_int_precs[][2] = { + { -128, 127 }, /* 8 */ + { -32768L, 32767 }, /* 16 */ + { LONG_MIN >> 8, LONG_MAX >> 8 }, /* 24 */ + { LONG_MIN , LONG_MAX } }; /* 32 */ + +static int _cgm_ireal_precs[][4] = { + { 0, 9, 23, 0 }, /* float*32 */ + { 0, 12, 52, 0 }, /* float*64 */ + { 1, 16, 16, 5 }, /* fixed*32 */ + { 1, 32, 32, 9 } }; /* fixed*64 */ + +static double _cgm_rreal_precs[][2] = { + /* float*32 */ { 0, 0 }, /* Em Turbo C, FLT_MAX e DLB_MAX sao */ + /* float*64 */ { 0, 0 }, /* DEFINES para variaveis externas */ + /* fixed*32 */ { - (32769.0 - 1.0 / 65536.0), + 32768.0 - 1.0 / 65536.0 }, + /* fixed*64 */ { (double)(LONG_MIN) - ( 1 - 1 / ( 65536.0 * 65536.0 ) ), + (double)(LONG_MAX) + ( 1 - 1 / ( 65536.0 * 65536.0 ) ) } }; + +/* Enumeraveis genericos */ + +static const char *offon[] = { "OFF", "ON" }; + +/********************* +* Delimiter elements * +*********************/ + +CGM *cgm_begin_metafile ( char *file, int mode, char *header ) +{ + CGM *cgm; + int len; + + if ( (cgm = (CGM *)malloc ( sizeof (CGM) ) ) == NULL ) + return NULL; + +#ifdef __VAXC__ + + if ( mode == 2 ) + cgm->file = fopen ( file , "w" , "rfm=var", "rat=cr" ); + else + cgm->file = fopen ( file , "w+b", "rfm=var", "ctx=stm" ); + +#else + + if ( mode == 2 ) + cgm->file = fopen ( file , "w" ); + else + cgm->file = fopen ( file , "w+b" ); + +#endif + + if ( cgm->file == NULL ) + { + free ( cgm ); + return NULL; + } + + cgm->mode = mode; + cgm->func = cgmf[mode]; + + cgm->vdc_type = 0; + cgm->int_prec = 1; + cgm->real_prec = 2; + cgm->ix_prec = 1; + cgm->cd_prec = 0; + cgm->cix_prec = 0; + cgm->max_cix = 63; + + cgm->clrsm = 0; + cgm->lnwsm = 1; + cgm->mkssm = 1; + cgm->edwsm = 1; + cgm->vdc_int = 1; + cgm->vdc_real = 2; + + cgm->vdc_size = 2; + cgm->int_size = 2; + cgm->real_size = 4; + cgm->ix_size = 3; + cgm->cd_size = 3; + cgm->cix_size = 1; + cgm->clr_size = 1; + cgm->lnw_size = 4; + cgm->mks_size = 4; + cgm->edw_size = 4; + + cgm->cl = 1; + + cgm->op = -1; + + len = strlen(header); + cgm->func->wch ( cgm, 0, 1, len+1 ); + + cgm->func->s ( cgm, header, len ); + + cgm->func->term ( cgm ); + + _cgm_ireal_precs[0][3] = FLT_DIG; + _cgm_ireal_precs[1][3] = DBL_DIG; + + _cgm_rreal_precs[0][0] = - FLT_MAX; + _cgm_rreal_precs[0][1] = FLT_MAX; + _cgm_rreal_precs[1][0] = - DBL_MAX; + _cgm_rreal_precs[1][1] = DBL_MAX; + + return cgm; +} + +int cgm_end_metafile ( CGM *cgm ) +{ + cgm->func->wch ( cgm, 0, 2, 0 ); + cgm->func->term ( cgm ); + + fclose ( cgm->file ); + cgm->file = NULL; + free ( cgm ); + + return 0; +} + +int cgm_begin_picture (CGM *cgm, const char *s ) +{ + int len = strlen(s); + cgm->func->wch ( cgm, 0, 3, len+1 ); + cgm->func->s ( cgm, s, len ); + return cgm->func->term(cgm); +} + +int cgm_begin_picture_body ( CGM *cgm ) +{ + cgm->func->wch ( cgm, 0, 4, 0 ); + return cgm->func->term(cgm); +} + +int cgm_end_picture ( CGM *cgm ) +{ + cgm->func->wch ( cgm, 0, 5, 0 ); + return cgm->func->term(cgm); +} + +/******************************* +* Metafile Descriptor Elements * +*******************************/ + +int cgm_metafile_version ( CGM *cgm, long version ) +{ + cgm->func->wch ( cgm, 1, 1, cgm->int_size ); + + cgm->func->i ( cgm, version ); + + return cgm->func->term(cgm); +} + +int cgm_metafile_description ( CGM *cgm, const char *s ) +{ + int len = strlen(s); + cgm->func->wch ( cgm, 1, 2, 1+len); + cgm->func->s ( cgm, s, len ); + return cgm->func->term(cgm); +} + +int cgm_vdc_type ( CGM *cgm, int mode ) +{ + static const char *vdct[] = { "integer", "real" }; + cgm->func->wch ( cgm, 1, 3, 2 ); + cgm->func->e ( cgm, mode, vdct ); + + cgm->vdc_type = mode; + if ( cgm->vdc_type == 0 ) /* integer */ + cgm->vdc_size = cgm->vdc_int + 1; + else + cgm->vdc_size = ( _cgm_ireal_precs[cgm->vdc_real][1] + + _cgm_ireal_precs[cgm->vdc_real][2]) / 8; + + return cgm->func->term(cgm); +} + +int cgm_integer_precision ( CGM *cgm, int prec ) +{ + cgm->func->wch ( cgm, 1, 4, cgm->int_size ); + + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] ); + cgm->func->sep ( cgm, "," ); + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] ); + break; + } + + cgm->int_prec = prec/8-1; + cgm->int_size = prec/8; + + return cgm->func->term(cgm); +} + +int cgm_real_precision ( CGM *cgm, int mode ) +{ + cgm->func->wch ( cgm, 1, 5, 2 + 2*cgm->int_size ); + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->e ( cgm, _cgm_ireal_precs[mode][0] , NULL ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][1]) ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][2]) ); + break; + + case 2: /* clear text */ + cgm->func->r ( cgm, _cgm_rreal_precs[mode][0] ); + cgm->func->sep ( cgm, "," ); + cgm->func->r ( cgm, _cgm_rreal_precs[mode][1] ); + cgm->func->sep ( cgm, "," ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][3]) ); + break; + } + + cgm->real_prec = mode; + cgm->real_size = ( _cgm_ireal_precs[mode][1] + _cgm_ireal_precs[mode][2]) / 8; + + /* absolute scaling modes */ + if ( cgm->lnwsm == 1 ) cgm->lnw_size = cgm->real_size; + if ( cgm->mkssm == 1 ) cgm->mks_size = cgm->real_size; + if ( cgm->edwsm == 1 ) cgm->edw_size = cgm->real_size; + + return cgm->func->term(cgm); +} + +int cgm_index_precision ( CGM *cgm, int prec ) +{ + cgm->func->wch ( cgm, 1, 6, cgm->int_size ); + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] ); + cgm->func->sep ( cgm, "," ); + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] ); + break; + } + + cgm->ix_prec = prec/8-1; + cgm->ix_size = prec/8; + return cgm->func->term(cgm); +} + +int cgm_colour_precision ( CGM *cgm, int prec ) +{ + cgm->func->wch ( cgm, 1, 7, cgm->int_size ); + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, 1ul+ 2ul * (unsigned long)_cgm_int_precs[prec/8 - 1][1] ); + break; + } + + cgm->cd_prec = prec/8-1; + cgm->cd_size = 3*(prec/8); + + if ( cgm->clrsm == 1 ) /* direct */ + cgm->clr_size = cgm->cd_size; + + return cgm->func->term(cgm); +} + +int cgm_colour_index_precision ( CGM *cgm, int prec ) +{ + cgm->func->wch ( cgm, 1, 8, cgm->int_size ); + + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, 1ul+ 2ul * (unsigned long)_cgm_int_precs[prec/8 - 1][1] ); + break; + } + + cgm->cix_prec = prec/8-1; + cgm->cix_size = prec/8; + + if ( cgm->clrsm == 0 ) /* indexed */ + cgm->clr_size = cgm->cix_size; + + return cgm->func->term(cgm); +} + +int cgm_maximum_colour_index ( CGM *cgm, unsigned long ci ) +{ + cgm->func->wch ( cgm, 1, 9, cgm->cix_size ); + cgm->func->ci ( cgm, ci ); + return cgm->func->term(cgm); +} + +int cgm_colour_value_extent ( CGM *cgm, const double *black, + const double *white) +{ + cgm->func->wch ( cgm, 1, 10, 2 * cgm->cd_size ); + cgm->func->rgb ( cgm, black[0], black[1], black[2] ); + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 15 ); + cgm->func->rgb ( cgm, white[0], white[1], white[2] ); + return cgm->func->term(cgm); +} + +int cgm_metafile_element_list ( CGM *cgm, int n, const int *group, const int *element ) +{ + register int i; + cgm->func->wch ( cgm, 1, 11, 31 ); + cgm->func->sep ( cgm, "\x22" ); /* aspas */ + if ( cgm->mode == 1 ) cgm->func->i ( cgm, n ); + for ( i=0; imode == 1 ) /* binario */ + { + cgm->func->ix ( cgm, group[i] ); + cgm->func->ix ( cgm, element[i] ); + cgm->func->term( cgm ); + } + else + { + cgm->func->wch ( cgm, group[i], element[i], 0 ); + cgm->func->sep ( cgm, "" ); + } + } + cgm->func->sep ( cgm, "\x22" ); /* aspas */ + return cgm->func->term(cgm); +} + +int cgm_begin_metafile_defaults ( CGM *cgm ) +{ + cgm->func->wch ( cgm, 1, 12, 31 ); + + /* modo binario - deixa aberto */ + if ( cgm->mode == 1 ) /* binario */ + return 0; + + return cgm->func->term(cgm); +} + +int cgm_end_metafile_defaults ( CGM *cgm ) +{ + /* modo binario - ja estava aberto */ + if ( cgm->mode != 1 ) /* binario */ + cgm->func->wch ( cgm, 1, 0, 0 ); + + return cgm->func->term(cgm); +} + +int cgm_font_list ( CGM *cgm, const char *fl[] ) +{ + register int i; + + cgm->func->wch ( cgm, 1, 13, 31 ); + + for ( i=0; fl[i] != NULL; i++ ) + { + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 10 ); + cgm->func->s ( cgm, fl[i], strlen(fl[i]) ); + } + + return cgm->func->term(cgm); +} + +/****************************** +* Picture Descriptor Elements * +******************************/ + +int cgm_scaling_mode ( CGM *cgm, int mode, float metric ) +{ + static const char *sm[] = { "abstract", "metric" }; + cgm->func->wch ( cgm, 2, 1, 2 + 4 ); + cgm->func->e ( cgm, mode, sm ); + if ( cgm->mode == 1 ) + cgmb_putfl32 ( cgm, metric ); + else + cgm->func->r ( cgm, metric ); + return cgm->func->term(cgm); +} + +int cgm_colour_selection_mode ( CGM *cgm, int mode) +{ + static const char *csm[] = { "indexed", "direct" }; + cgm->func->wch ( cgm, 2, 2, 2 ); + cgm->func->e ( cgm, mode, csm ); + + cgm->clrsm = mode; + if ( mode == 0 ) /* indexed */ + cgm->clr_size = cgm->cix_size; + else + cgm->clr_size = cgm->cd_size; + + return cgm->func->term(cgm); +} + +static int _cgm_width_specify_mode ( CGM *cgm, int t, int mode) +{ + static const char *sm[] = { "abstract", "scaled" }; + cgm->func->wch ( cgm, 2, t, 2 ); + cgm->func->e ( cgm, mode, sm ); + return cgm->func->term(cgm); +} + +int cgm_line_width_specify_mode ( CGM *cgm, int mode) +{ + cgm->lnwsm = mode; + if ( mode == 0 ) + cgm->lnw_size = cgm->vdc_size; + else + cgm->lnw_size = cgm->real_size; + return _cgm_width_specify_mode ( cgm, 3, mode ); +} + +int cgm_marker_size_specify_mode ( CGM *cgm, int mode) +{ + cgm->mkssm = mode; + if ( mode == 0 ) + cgm->mks_size = cgm->vdc_size; + else + cgm->mks_size = cgm->real_size; + return _cgm_width_specify_mode ( cgm, 4, mode ); +} + +int cgm_edge_width_specify_mode ( CGM *cgm, int mode) +{ + cgm->edwsm = mode; + if ( mode == 0 ) + cgm->edw_size = cgm->vdc_size; + else + cgm->edw_size = cgm->real_size; + return _cgm_width_specify_mode ( cgm, 5, mode ); +} + +int cgm_vdc_extent ( CGM *cgm, double xmin, double ymin, + double xmax, double ymax ) +{ + cgm->func->wch ( cgm, 2, 6, 2*2*cgm->vdc_size ); + cgm->func->vdc ( cgm, xmin ); + cgm->func->vdc ( cgm, ymin ); + cgm->func->vdc ( cgm, xmax ); + cgm->func->vdc ( cgm, ymax ); + return cgm->func->term(cgm); +} + +int cgm_backgound_colour ( CGM *cgm, const double *cr ) +{ + cgm->func->wch ( cgm, 2, 7, cgm->cd_size ); + cgm->func->rgb ( cgm , cr[0], cr[1], cr[2] ); + return cgm->func->term(cgm); +} + +/******************* +* Control Elements * +*******************/ + +int cgm_vdc_integer_precision ( CGM *cgm, int prec ) +{ + cgm->func->wch ( cgm, 3, 1, cgm->int_size ); + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][0] ); + cgm->func->sep ( cgm, "," ); + cgm->func->i ( cgm, _cgm_int_precs[prec/8 - 1][1] ); + break; + } + + if ( cgm->vdc_type == 0 ) + cgm->vdc_size = prec/8; + + cgm->vdc_int = prec/8 - 1; + + if ( cgm->lnwsm == 0 && cgm->vdc_type == 0 ) cgm->lnw_size = cgm->vdc_size; + if ( cgm->mkssm == 0 && cgm->vdc_type == 0 ) cgm->mks_size = cgm->vdc_size; + if ( cgm->edwsm == 0 && cgm->vdc_type == 0 ) cgm->edw_size = cgm->vdc_size; + + return cgm->func->term(cgm); +} + +int cgm_vdc_real_precision ( CGM *cgm, int mode ) +{ + cgm->func->wch ( cgm, 3, 2, 2 + 2*cgm->int_size ); + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->e ( cgm, _cgm_ireal_precs[mode][0] , NULL ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][1]) ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][2]) ); + break; + + case 2: /* clear text */ + cgm->func->r ( cgm, _cgm_rreal_precs[mode][0] ); + cgm->func->sep ( cgm, "," ); + cgm->func->r ( cgm, _cgm_rreal_precs[mode][1] ); + cgm->func->sep ( cgm, "," ); + cgm->func->i ( cgm, (long)(_cgm_ireal_precs[mode][3]) ); + break; + } + + if ( cgm->vdc_type == 1 ) + cgm->vdc_size = ( _cgm_ireal_precs[mode][1] + _cgm_ireal_precs[mode][2]) / 8; + + cgm->vdc_real = mode; + + if ( cgm->lnwsm == 0 && cgm->vdc_type == 1 ) cgm->lnw_size = cgm->vdc_size; + if ( cgm->mkssm == 0 && cgm->vdc_type == 1 ) cgm->mks_size = cgm->vdc_size; + if ( cgm->edwsm == 0 && cgm->vdc_type == 1 ) cgm->edw_size = cgm->vdc_size; + + return cgm->func->term(cgm); +} + +int cgm_auxiliary_colour ( CGM *cgm, const void *c ) +{ + cgm->func->wch ( cgm, 3, 3, cgm->clr_size ); + + cgm->func->co ( cgm, c ) ; + + return cgm->func->term(cgm); +} + +int cgm_transparency ( CGM *cgm, int mode ) +{ + cgm->func->wch ( cgm, 3, 4, 2 ); + + cgm->func->e ( cgm, mode, offon ); + + return cgm->func->term(cgm); +} + +int cgm_clip_rectangle ( CGM *cgm, double xmin, double ymin, + double xmax, double ymax ) +{ + cgm->func->wch ( cgm, 3, 5, 4 * cgm->vdc_size ); + + cgm->func->vdc ( cgm, xmin ); + cgm->func->vdc ( cgm, ymin ); + cgm->func->vdc ( cgm, xmax ); + cgm->func->vdc ( cgm, ymax ); + + return cgm->func->term(cgm); +} + +int cgm_clip_indicator ( CGM *cgm, int mode ) +{ + cgm->func->wch ( cgm, 3, 6, 2 ); + + cgm->func->e ( cgm, mode, offon ); + + return cgm->func->term(cgm); +} + +/******************************* +* Graphical Primitive Elements * +*******************************/ + +static int _cgm_point ( CGM *cgm, double x, double y ) +{ + cgm->func->p ( cgm, x, y ); + return 0; +} + +static int _cgm_point_list ( CGM *cgm, int element, int n, const double *p) +{ + register int i; + cgm->func->wch ( cgm, 4, element, 2*n*cgm->vdc_size ); + + for ( i=0; i < 2*n; i+=2 ) + { + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 8 ); + _cgm_point ( cgm, p[i], p[i+1] ); + } + return cgm->func->term(cgm); +} + +int cgm_polyline ( CGM *cgm, int n, const double *p ) +{ + return _cgm_point_list ( cgm, 1, n, p ); +} + +int cgm_polymarker ( CGM *cgm, int n, const double *p ) +{ + return _cgm_point_list ( cgm, 3, n, p ); +} + +static int _cgm_text_piece ( CGM *cgm, int t, const char *s, int len) +{ + static const char *tt[] = { "NOT_FINAL", " FINAL" }; + cgm->func->e ( cgm, t, tt ); + cgm->func->s ( cgm, s , len); + return cgm->func->term(cgm); +} + +int cgm_text ( CGM *cgm, int tt, double x, double y, const char *s, int len ) +{ + cgm->func->wch ( cgm, 4, 4, 2 * cgm->vdc_size + len + 3 ); + cgm->func->p ( cgm, x, y ); + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 10 ); + + if ( cgm->mode == 2 ) /* clear text */ + { + while ( len > 50 ) + { + _cgm_text_piece ( cgm, 0, s, 50); + s += 50; + len -= 50; + + cgm->func->wch ( cgm, 4, 6, 2 * cgm->vdc_size + len + 1 ); + } + } + + return _cgm_text_piece ( cgm, tt, s, len ); +} + +int cgm_polygon ( CGM *cgm, int n, const double *p ) +{ + return _cgm_point_list ( cgm, 7, n, p ); +} + +static int _cgm_cell_rows ( CGM *cgm, long sx, long sy, int prec, const void *c ) +{ + register long i,j, brk; + + cgm->func->nl ( cgm ); + cgm->func->sep ( cgm, "(" ); + + if ( cgm->clrsm ) + brk = 5; + else + brk = 12; + + for ( i=0; i < sy; i++ ) + { + if ( i ) + { + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 3 ); + } + + for ( j=0; j < sx; j++) + { + if ( j && ( j % brk == 0 ) ) + { + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 3 ); + } + + cgm->func->co ( cgm, c ); + c = (void*)((char*)c+ (cgm->clrsm ? (3*sizeof(double)) : sizeof(int))); + + if ( ifunc->sep ( cgm, "," ); + } + } + + cgm->func->sep ( cgm, ")" ); + + return 0; +} + +int cgm_cell_array ( CGM *cgm, const double *p, long sx, long sy, int prec, const void *c ) +{ + register int i; + static const char *repmode[] = { "run lenght", "packed" }; + + cgm->func->wch ( cgm, 4, 9, 31 ); + + for ( i=0; i<3*2; i+=2 ) + _cgm_point ( cgm, p[i], p[i+1] ); + + cgm->func->nl (cgm ); + + cgm->func->i ( cgm, sx ); + cgm->func->i ( cgm, sy ); + + if ( prec == 0 ) + cgm->func->i ( cgm, (long)(prec) ); + else + { + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, 2 * ( _cgm_int_precs[prec/8 - 1][1] + 1) ); + break; + } + } + + if ( cgm->mode==1 ) cgm->func->e ( cgm, 1, repmode ); + + _cgm_cell_rows( cgm, sx, sy, prec, c ); + + return cgm->func->term(cgm); +} + +int cgm_rectangle ( CGM *cgm, const double *p ) +{ + return _cgm_point_list ( cgm, 11, 2, p ); +} + +static int _cgm_ellipse_CDP ( CGM *cgm, const double *c, const double *p1, + const double *p2 ) +{ + _cgm_point ( cgm, c[0], c[1] ); + _cgm_point ( cgm, p1[0], p1[1] ); + _cgm_point ( cgm, p2[0], p2[1] ); + + return 0; +} + +static int _cgm_ellipse_vectors ( CGM *cgm, double dxs, double dys, double dxe, + double dye ) +{ + cgm->func->vdc ( cgm, dxs ); + cgm->func->vdc ( cgm, dys ); + cgm->func->vdc ( cgm, dxe ); + cgm->func->vdc ( cgm, dye ); + + return 0; +} + +int cgm_elliptical_arc ( CGM *cgm, const double *c, const double *p1, + const double *p2, double dxs, double dys, double dxe, + double dye ) +{ + cgm->func->wch ( cgm, 4, 18, 10*cgm->vdc_size ); + + _cgm_ellipse_CDP ( cgm, c, p1, p2 ); + + _cgm_ellipse_vectors ( cgm, dxs, dys, dxe, dye ); + + return cgm->func->term(cgm); +} + +int cgm_elliptical_arc_close ( CGM *cgm, const double *c, const double *p1, + const double *p2, double dxs, double dys, + double dxe, double dye, int type ) +{ + static const char *ct[] = { "pie", "chord" }; + + cgm->func->wch ( cgm, 4, 19, 10*cgm->vdc_size + 2 ); + + _cgm_ellipse_CDP ( cgm, c, p1, p2 ); + + _cgm_ellipse_vectors ( cgm, dxs, dys, dxe, dye ); + + cgm->func->e ( cgm, type, ct ); + + return cgm->func->term(cgm); +} + +/********************* +* Attribute Elements * +*********************/ + +int cgm_line_bundle_index( CGM *cgm, long li) +{ + cgm->func->wch ( cgm, 5, 1, cgm->ix_size ); + cgm->func->ix ( cgm, li ); + return cgm->func->term(cgm); +} + +int cgm_line_type( CGM *cgm, long lt) +{ + cgm->func->wch ( cgm, 5, 2, cgm->ix_size ); + cgm->func->ix ( cgm, lt ); + return cgm->func->term(cgm); +} + +int cgm_line_width( CGM *cgm, double lw) +{ + cgm->func->wch ( cgm, 5, 3, cgm->lnw_size ); + + if ( cgm->lnwsm == 0 ) /* absolute */ + cgm->func->vdc ( cgm, lw ); + else + cgm->func->r ( cgm, lw ); + + return cgm->func->term(cgm); +} + +int cgm_line_colour( CGM *cgm, const void *lc) +{ + cgm->func->wch ( cgm, 5, 4, cgm->clr_size ); + cgm->func->co ( cgm, lc ); + return cgm->func->term(cgm); +} + +int cgm_marker_bundle_index( CGM *cgm, long mi) +{ + cgm->func->wch ( cgm, 5, 5, cgm->ix_size ); + cgm->func->ix ( cgm, mi ); + return cgm->func->term(cgm); +} + +int cgm_marker_type( CGM *cgm, long mt) +{ + cgm->func->wch ( cgm, 5, 6, cgm->ix_size ); + cgm->func->ix ( cgm, mt ); + return cgm->func->term(cgm); +} + +int cgm_marker_size( CGM *cgm, double ms) +{ + cgm->func->wch ( cgm, 5, 7, cgm->mks_size ); + + if ( cgm->mkssm == 0 ) /* absolute */ + cgm->func->vdc ( cgm, ms ); + else + cgm->func->r ( cgm, ms ); + + return cgm->func->term(cgm); +} + +int cgm_marker_colour( CGM *cgm, const void *mc) +{ + cgm->func->wch ( cgm, 5, 8, cgm->clr_size ); + cgm->func->co ( cgm, mc ); + return cgm->func->term(cgm); +} + +int cgm_text_bundle_index( CGM *cgm, long ti) +{ + cgm->func->wch ( cgm, 5, 9, cgm->ix_size ); + cgm->func->ix ( cgm, ti ); + return cgm->func->term(cgm); +} + +int cgm_text_font_index( CGM *cgm, long fi) +{ + cgm->func->wch ( cgm, 5, 10, cgm->ix_size ); + cgm->func->ix ( cgm, fi ); + return cgm->func->term(cgm); +} + +int cgm_text_precision( CGM *cgm, int tp) +{ + static const char *txprec[] = { "STRING", "CHAR", "STROKE" }; + cgm->func->wch ( cgm, 5, 11, 2 ); + cgm->func->e ( cgm, tp, txprec ); + return cgm->func->term(cgm); +} + +int cgm_char_expansion_factor ( CGM *cgm, double expan ) +{ + cgm->func->wch ( cgm, 5, 12, cgm->real_size ); + cgm->func->r ( cgm, expan ); + return cgm->func->term(cgm); +} + +int cgm_char_spacing ( CGM *cgm, double spacing ) +{ + cgm->func->wch ( cgm, 5, 13, cgm->real_size ); + cgm->func->r ( cgm, spacing ); + return cgm->func->term(cgm); +} + +int cgm_text_colour( CGM *cgm, const void *tc) +{ + cgm->func->wch ( cgm, 5, 14, cgm->clr_size ); + cgm->func->co ( cgm, tc ); + return cgm->func->term(cgm); +} + +int cgm_char_height ( CGM *cgm, double height ) +{ + cgm->func->wch ( cgm, 5, 15, cgm->vdc_size ); + cgm->func->vdc ( cgm, height ); + return cgm->func->term(cgm); +} + +int cgm_char_orientation ( CGM *cgm, double chupx, double chupy, + double chbsx, double chbsy ) +{ + cgm->func->wch ( cgm, 5, 16, 4*cgm->vdc_size ); + cgm->func->sep ( cgm, "% char up %" ); + cgm->func->vdc ( cgm, chupx ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, chupy ); + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 8 ); + cgm->func->sep ( cgm, "% char base %" ); + cgm->func->vdc ( cgm, chbsx ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, chbsy ); + return cgm->func->term(cgm); +} + +int cgm_text_path ( CGM *cgm, int tp) +{ + static const char *txpath[] = { "RIGHT", "LEFT", "UP", "DOWN" }; + cgm->func->wch ( cgm, 5, 17, 2 ); + cgm->func->e ( cgm, tp, txpath ); + return cgm->func->term(cgm); +} + +int cgm_text_alignment ( CGM *cgm, int hor, int ver , double ch, double cv) +{ + static const char *txhor[] = { "NORMHORIZ", "LEFT", "CTR", "RIGHT", "CONTHORIZ" }; + static const char *txver[] = { "NORMVERT", "TOP", "CAP", "HALF", "BASE", + "BOTTOM", "CONTHORIZ" }; + + cgm->func->wch ( cgm, 5, 18, 2*2 + 2*cgm->real_size ); + cgm->func->e ( cgm, hor, txhor ); + cgm->func->e ( cgm, ver, txver ); + cgm->func->r ( cgm, ch ); + cgm->func->r ( cgm, cv ); + return cgm->func->term(cgm); +} + +int cgm_fill_bundle_index( CGM *cgm, long fi) +{ + cgm->func->wch ( cgm, 5, 21, cgm->ix_size ); + cgm->func->ix ( cgm, fi ); + return cgm->func->term(cgm); +} + +int cgm_interior_style( CGM *cgm, int is) +{ + static const char *style[]= { "HOLLOW", "SOLID", "PAT", "HATCH", "EMPTY" }; + cgm->func->wch ( cgm, 5, 22, 2 ); + cgm->func->e ( cgm, is, style ); + return cgm->func->term(cgm); +} + +int cgm_fill_colour( CGM *cgm, const void *fc) +{ + cgm->func->wch ( cgm, 5, 23, cgm->clr_size ); + cgm->func->co ( cgm, fc ); + return cgm->func->term(cgm); +} + +int cgm_hatch_index( CGM *cgm, long hi) +{ + cgm->func->wch ( cgm, 5, 24, cgm->ix_size ); + cgm->func->ix ( cgm, hi ); + return cgm->func->term(cgm); +} + +int cgm_pattern_index( CGM *cgm, long pi) +{ + cgm->func->wch ( cgm, 5, 25, cgm->ix_size ); + cgm->func->ix ( cgm, pi ); + return cgm->func->term(cgm); +} + +int cgm_edge_width( CGM *cgm, double ew) +{ + cgm->func->wch ( cgm, 5, 28, cgm->edw_size ); + + if ( cgm->lnwsm == 0 ) /* absolute */ + cgm->func->vdc ( cgm, ew ); + else + cgm->func->r ( cgm, ew ); + + return cgm->func->term(cgm); +} + +int cgm_edge_colour( CGM *cgm, const void *ec) +{ + cgm->func->wch ( cgm, 5, 29, cgm->clr_size ); + cgm->func->co ( cgm, ec ); + return cgm->func->term(cgm); +} + +int cgm_edge_visibility ( CGM *cgm, int mode ) +{ + cgm->func->wch ( cgm, 5, 30, 2 ); + cgm->func->e ( cgm, mode, offon ); + return cgm->func->term(cgm); +} + +int cgm_fill_reference_point ( CGM *cgm, double rpx, double rpy ) +{ + cgm->func->wch ( cgm, 5, 31, 2*cgm->vdc_size ); + _cgm_point ( cgm, rpx, rpy ); + return cgm->func->term(cgm); +} + +int cgm_pattern_table ( CGM *cgm, long pi, long sx, long sy, int prec, const void *c) +{ + cgm->func->wch ( cgm, 5, 32, 31 ); + cgm->func->ix ( cgm, pi ); + + cgm->func->i ( cgm, sx ); + cgm->func->i ( cgm, sy ); + + if ( prec == 0 ) + cgm->func->i ( cgm, (long)(prec) ); + else + { + switch ( cgm->mode ) + { + case 0: /* character */ + break; + + case 1: /* binary */ + cgm->func->i ( cgm, (long)(prec) ); + break; + + case 2: /* clear text */ + cgm->func->i ( cgm, 2 * ( _cgm_int_precs[prec/8 - 1][1] + 1) ); + break; + } + } + + _cgm_cell_rows( cgm, sx, sy, prec, c ); + + return cgm->func->term(cgm); +} + +int cgm_pattern_size ( CGM *cgm, double hx, double hy, double wx, double wy ) +{ + cgm->func->wch ( cgm, 5, 33, 4*cgm->vdc_size ); + cgm->func->sep ( cgm, "% height %" ); + cgm->func->vdc ( cgm, hx ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, hy ); + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 8 ); + cgm->func->sep ( cgm, "% width %" ); + cgm->func->vdc ( cgm, wx ); + cgm->func->sep ( cgm, "," ); + cgm->func->vdc ( cgm, wy ); + return cgm->func->term(cgm); +} + +int cgm_colour_table ( CGM *cgm, long ci, long n, const double *cb ) +{ + register long i=n; + + if ( n > 31 ) n = 31; + + cgm->func->wch ( cgm, 5, 34, cgm->int_size+n*cgm->cd_size ); + cgm->func->i ( cgm, ci ); + + n = i; + + for ( i=0; ifunc->nl ( cgm ); + cgm->func->align ( cgm, 18 ); + } + cgm->func->rgb ( cgm, cb[(int)i], cb[(int)i+1], cb[(int)i+2] ); + } + + return cgm->func->term(cgm); +} + +static void _cgm_asf_pair ( CGM *cgm, int asft, int asfv ) +{ + static const char *asfvl[] = { "INDIV", "BUNDLED" }; + static const char *asftl[] = { + "LINE_TYPE", "LINE_WIDTH", "LINE_COLR", + "MARKER_TYPE", "MARKER_SIZE", "MARKER_COLR", + "TEXT_FONT_INDEX", "TEXT_PREC", "CHAR_EXP", "CHAR_SPACE", "TEXT_COLR", + "INT_STYLE", "FILL_COLR", "HATCH_INDEX", "PAT_INDEX", + "EDGE_TYPE", "EDGE_WIDTH", "EDGE_COLR", + "ALL", "ALL_LINE", "ALL_MARKER", "ALL_TEXT", "ALL_FILL", "ALL_EDGE" + }; + + cgm->func->nl ( cgm ); + cgm->func->align ( cgm, 4 ); + cgm->func->e ( cgm, asft, asftl ); + cgm->func->e ( cgm, asfv, asfvl ); +} + +int cgm_asfs ( CGM *cgm, int n, const int *asfts, const int* asfvs ) +{ + register int i; + cgm->func->wch ( cgm, 5, 35, 2*n* 2 ); + + for ( i=0; ifunc->term(cgm); +} + +/***************** +* Escape Element * +*****************/ + +/******************** +* External elements * +********************/ + +int cgm_message ( CGM *cgm, int action, const char *s) +{ + static const char *ac[] = { "NOACTION", "ACTION" }; + cgm->func->wch ( cgm, 7, 2, 2 + strlen(s)+1 ); + cgm->func->e ( cgm, action, ac ); + cgm->func->s ( cgm, s, strlen(s) ); + return cgm->func->term(cgm); +} diff --git a/cd/src/drv/cgm.h b/cd/src/drv/cgm.h new file mode 100755 index 0000000..632ebeb --- /dev/null +++ b/cd/src/drv/cgm.h @@ -0,0 +1,156 @@ +/** \file + * \brief CGM library + * Extracted from GKS/PUC + * + * See Copyright Notice in cd.h + */ + +#ifndef __CGM_H +#define __CGM_H + +typedef struct _cgmFunc CGMFUNC; + +typedef struct { + FILE *file; /* file pointer */ + + const CGMFUNC *func; /* functions */ + + int mode; /* character, binary, clear text */ + + int vdc_type, /* integer, real */ + int_prec, /* 8, 16, 24, 32 */ + real_prec, /* float*32, float*64, fixed*32, fixed*64 */ + ix_prec, /* 8, 16, 24, 32 */ + cd_prec, /* 8, 16, 24, 32 */ + cix_prec, /* 8, 16, 24, 32 */ + max_cix; /* maximum colour index */ + + int clrsm, /* indexed, direct */ + lnwsm, /* absolute, scaled */ + mkssm, /* absolute, scaled */ + edwsm; /* absolute, scaled */ + int vdc_int, /* X, 16, 24, 32 */ + vdc_real; /* float*32, float*64, fixed*32, fixed*64 */ + + int vdc_size, /* 2, 3, 4, 8 */ + int_size, /* 1, 2, 3, 4 */ + real_size, /* 4, 8 */ + ix_size, /* 1, 2, 3, 4 */ + cd_size, /* 1, 2, 3, 4 */ + cix_size, /* 1, 2, 3, 4 */ + clr_size, /* 3 * cd_size , cix_size */ + lnw_size, /* 2, 3, 4, 8 */ + mks_size, /* 2, 3, 4, 8 */ + edw_size; /* 2, 3, 4, 8 */ + + int cl; /* coluna para alinhamento */ + + int op; /* commands opened */ + int bc[5]; /* bytes count for command */ + long po[5]; /* position offset do arquivo */ +} CGM; + +CGM *cgm_begin_metafile ( char *, int, char * ); +int cgm_end_metafile ( CGM * ); +int cgm_begin_picture ( CGM *, const char * ); +int cgm_begin_picture_body ( CGM * ); +int cgm_end_picture ( CGM * ); +int cgm_metafile_version ( CGM *, long ); +int cgm_metafile_description ( CGM *, const char * ); +int cgm_vdc_type ( CGM *, int ); +int cgm_integer_precision ( CGM *, int ); +int cgm_real_precision ( CGM *, int ); +int cgm_index_precision ( CGM *, int ); +int cgm_colour_precision ( CGM *, int ); +int cgm_colour_index_precision ( CGM *, int ); +int cgm_maximum_colour_index ( CGM *, unsigned long ); +int cgm_colour_value_extent ( CGM *, const double *, const double * ); +int cgm_metafile_element_list ( CGM *, int, const int *, const int * ); +int cgm_begin_metafile_defaults ( CGM * ); +int cgm_end_metafile_defaults ( CGM * ); +int cgm_font_list ( CGM *, const char *l[] ); +int cgm_scaling_mode ( CGM *, int, float ); +int cgm_colour_selection_mode ( CGM *, int ); +int cgm_line_width_specify_mode ( CGM *, int ); +int cgm_marker_size_specify_mode( CGM *, int ); +int cgm_edge_width_specify_mode ( CGM *, int ); +int cgm_vdc_extent ( CGM *, double, double, double, double ); +int cgm_backgound_colour ( CGM *, const double * ); +int cgm_vdc_integer_precision ( CGM *, int ); +int cgm_vdc_real_precision ( CGM *, int ); +int cgm_auxiliary_colour ( CGM *, const void * ); +int cgm_transparency ( CGM *, int ); +int cgm_clip_rectangle ( CGM *, double, double, double, double ); +int cgm_clip_indicator ( CGM *, int ); +int cgm_polyline ( CGM *, int, const double * ); +int cgm_polymarker ( CGM *, int, const double * ); +int cgm_text ( CGM *, int, double, double, const char *, int); +int cgm_polygon ( CGM *, int, const double * ); +int cgm_cell_array ( CGM *, const double *, long, long, int, const void * ); +int cgm_rectangle ( CGM *, const double * ); +int cgm_elliptical_arc ( CGM *, const double *, const double *, const double *, double, double, double, double ); +int cgm_elliptical_arc_close ( CGM *, const double *, const double *, const double *, double, double, double, double, int ); +int cgm_line_bundle_index ( CGM *, long ); +int cgm_line_type ( CGM *, long ); +int cgm_line_width ( CGM *, double ); +int cgm_line_colour ( CGM *, const void * ); +int cgm_marker_bundle_index ( CGM *, long ); +int cgm_marker_type ( CGM *, long ); +int cgm_marker_size ( CGM *, double ); +int cgm_marker_colour ( CGM *, const void * ); +int cgm_text_bundle_index ( CGM *, long ); +int cgm_text_font_index ( CGM *, long ); +int cgm_text_precision ( CGM *, int ); +int cgm_char_expansion_factor ( CGM *, double ); +int cgm_char_spacing ( CGM *, double ); +int cgm_text_colour ( CGM *, const void * ); +int cgm_char_height ( CGM *, double ); +int cgm_char_orientation ( CGM *, double, double, double, double ); +int cgm_text_path ( CGM *, int ); +int cgm_text_alignment ( CGM *, int, int, double, double ); +int cgm_fill_bundle_index ( CGM *, long ); +int cgm_interior_style ( CGM *, int ); +int cgm_fill_colour ( CGM *, const void * ); +int cgm_hatch_index ( CGM *, long ); +int cgm_pattern_index ( CGM *, long ); +int cgm_edge_width ( CGM *, double ); +int cgm_edge_colour ( CGM *, const void * ); +int cgm_edge_visibility ( CGM *, int ); +int cgm_fill_reference_point ( CGM *, double, double ); +int cgm_pattern_table ( CGM *, long, long, long, int, const void * ); +int cgm_pattern_size ( CGM *, double, double, double, double ); +int cgm_colour_table ( CGM *, long, long, const double * ); +int cgm_asfs ( CGM *, int, const int *, const int * ); +int cgm_message ( CGM *, int, const char * ); + +enum { + LINE_SOLID=1, + LINE_DASH=2, + LINE_DOT=3, + LINE_DASH_DOT=4, + LINE_DASH_DOT_DOT=5 + }; + +enum { + MARKER_DOT=1, + MARKER_PLUS=2, + MARKER_ASTERISK=3, + MARKER_CIRCLE=4, + MARKER_CROSS=5 + }; + +enum { + HOLLOW, + SOLID, + PAT, + HATCH, + EMPTY + }; + +enum { /* encoding */ + CD_CHARACTER, + CD_BIN, + CD_CLEAR_TEXT + }; + +#endif diff --git a/cd/src/gdiplus/cdcontextplus.def b/cd/src/gdiplus/cdcontextplus.def new file mode 100755 index 0000000..92175a6 --- /dev/null +++ b/cd/src/gdiplus/cdcontextplus.def @@ -0,0 +1,9 @@ +EXPORTS + cdInitContextPlus + cdInitGdiPlus + cdwpCreateCanvas + cdwpGdiPlusStartup + cdwpGdiPlusShutdown + cdwpInitTable + cdwpUpdateCanvas + cdwpKillCanvas diff --git a/cd/src/gdiplus/cdwclpp.cpp b/cd/src/gdiplus/cdwclpp.cpp new file mode 100755 index 0000000..719713f --- /dev/null +++ b/cd/src/gdiplus/cdwclpp.cpp @@ -0,0 +1,206 @@ +/** \file + * \brief Windows GDI+ Clipboard Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdclipbd.h" +#include "cdmf.h" +#include "cdemf.h" + +#include +#include +#include + +#include "cdmf_private.h" + + +static void cdkillcanvasCLIPBDMF (cdCtxCanvas* ctxcanvas) +{ + HANDLE Handle, hFile; + char* buffer; + DWORD dwSize, nBytesRead; + char filename[10240]; + cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas; + + /* guardar antes de remover o canvas */ + strcpy(filename, mfcanvas->filename); + + OpenClipboard(NULL); + EmptyClipboard(); + + cdkillcanvasMF(mfcanvas); /* this will close the file */ + + hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + dwSize = GetFileSize (hFile, NULL) ; + + Handle = GlobalAlloc(GMEM_MOVEABLE, dwSize+1); + buffer = (char*)GlobalLock(Handle); + ReadFile(hFile, buffer, dwSize, &nBytesRead, NULL); + buffer[dwSize] = 0; + GlobalUnlock(Handle); + + CloseHandle(hFile); + + SetClipboardData(CF_TEXT, Handle); + + CloseClipboard(); +} + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + + OpenClipboard(NULL); + EmptyClipboard(); + + if (ctxcanvas->wtype == CDW_EMF) + { + HENHMETAFILE hEmf = ctxcanvas->metafile->GetHENHMETAFILE(); + SetClipboardData(CF_ENHMETAFILE, hEmf); + delete ctxcanvas->metafile; + } + else + { + HBITMAP hBitmap; + ctxcanvas->bitmap->GetHBITMAP(ctxcanvas->bg, &hBitmap); + SetClipboardData(CF_BITMAP, hBitmap); + delete ctxcanvas->bitmap; + } + + CloseClipboard(); + + delete ctxcanvas; +} + +/* +%F cdCreateCanvas para Clipboard +O DC pode ser um WMF ou um BITMAP. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char* strsize = (char*)data; + int w = 0, h = 0, wtype = CDW_EMF; /* default clipboard type */ + double res = 0; /* used only for BMP */ + Metafile* metafile = NULL; + Bitmap* bitmap = NULL; + Graphics* graphics; + + /* Inicializa parametros */ + if (strsize == NULL) + return; + + if (strstr(strsize, "-b") != NULL) + wtype = CDW_BMP; + else if (strstr(strsize, "-m") != NULL) + wtype = -1; /* CD METAFILE */ + + if (wtype != -1) + { + sscanf(strsize,"%dx%d %g",&w, &h, &res); + if (w == 0 || h == 0) + return; + } + + if (wtype == CDW_EMF) + { + HDC ScreenDC = GetDC(NULL); + /* LOGPIXELS can not be used for EMF */ + canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + + Rect frameRect(0, 0, (int)(100 * w / canvas->xres), (int)(100 * h / canvas->yres)); + + metafile = new Metafile(ScreenDC, frameRect, MetafileFrameUnitGdi, EmfTypeEmfPlusDual, NULL); + ReleaseDC(NULL, ScreenDC); + + if (!metafile) + return; + + graphics = new Graphics(metafile); + } + else if (wtype == CDW_BMP) + { + if (!res) + { + HDC ScreenDC = GetDC(NULL); + canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + ReleaseDC(NULL, ScreenDC); + } + else + { + canvas->xres = res; + canvas->yres = res; + } + + bitmap = new Bitmap(w, h, PixelFormat24bppRGB); + if (!bitmap) + return; + + bitmap->SetResolution((REAL)(canvas->xres*25.4), (REAL)(canvas->xres*25.4)); + + graphics = new Graphics(bitmap); + } + + if (wtype == -1) + { + char filename[1024]; + char tmpPath[512]; + char str[1024]; + + GetTempPath(512, tmpPath); + GetTempFileName(tmpPath, "~cd", 0, filename); + + sprintf(str, "%s %s", filename, strsize); + cdcreatecanvasMF(canvas, str); + } + else + { + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, wtype); + + canvas->w = w; + canvas->h = h; + canvas->bpp = 24; + + if (wtype == CDW_BMP) + ctxcanvas->bitmap = bitmap; + else + ctxcanvas->metafile = metafile; + } +} + +static void cdinittable(cdCanvas* canvas) +{ + if (canvas->invert_yaxis == 0) /* a simple way to distinguish MF from WIN */ + { + cdinittableMF(canvas); + canvas->cxKillCanvas = cdkillcanvasCLIPBDMF; + } + else + { + cdwpInitTable(canvas); + canvas->cxKillCanvas = cdkillcanvas; + } +} + +static cdContext cdClipboardContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_FLUSH | CD_CAP_YAXIS | + CD_CAP_PLAY | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_FPRIMTIVES ), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +extern "C" { +cdContext* cdContextClipboardPlus(void) +{ + return &cdClipboardContext; +} +} diff --git a/cd/src/gdiplus/cdwdbufp.cpp b/cd/src/gdiplus/cdwdbufp.cpp new file mode 100755 index 0000000..95cfe2e --- /dev/null +++ b/cd/src/gdiplus/cdwdbufp.cpp @@ -0,0 +1,164 @@ +/** \file + * \brief Windows GDI+ Double Buffer + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cddbuf.h" +#include +#include + + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + + if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer; + delete ctxcanvas->bitmap; + + delete ctxcanvas; +} + +static void cddeactivate(cdCtxCanvas* ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + /* this is done in the canvas_dbuffer context */ + cdCanvasDeactivate(canvas_dbuffer); +} + +static void cdflush(cdCtxCanvas* ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + if (ctxcanvas->dirty || ctxcanvas->bitmap_dbuffer == NULL) + { + ctxcanvas->dirty = 0; + if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer; + ctxcanvas->bitmap_dbuffer = new CachedBitmap(ctxcanvas->bitmap, canvas_dbuffer->ctxcanvas->graphics); + } + + ctxcanvas->graphics->Flush(FlushIntentionSync); + + /* this is done in the canvas_dbuffer context */ + /* Flush can be affected by Origin and Clipping, but not WriteMode */ + canvas_dbuffer->ctxcanvas->graphics->ResetTransform(); + + int x = 0, y = 0; + if (canvas_dbuffer->use_origin) + { + x += canvas_dbuffer->origin.x; + if (canvas_dbuffer->invert_yaxis) + y -= canvas_dbuffer->origin.y; // top down shift + else + y += canvas_dbuffer->origin.y; + } + + int old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE); + canvas_dbuffer->ctxcanvas->graphics->DrawCachedBitmap(ctxcanvas->bitmap_dbuffer, x, y); + canvas_dbuffer->ctxcanvas->graphics->Flush(FlushIntentionSync); + cdCanvasWriteMode(canvas_dbuffer, old_writemode); +} + +static int cdactivate(cdCtxCanvas* ctxcanvas) +{ + int w, h; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* this is done in the canvas_dbuffer context */ + /* this will update canvas size */ + cdCanvasActivate(canvas_dbuffer); + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + /* check if the size changed */ + if (w != ctxcanvas->canvas->w || + h != ctxcanvas->canvas->h) + { + delete ctxcanvas->graphics; + delete ctxcanvas->bitmap; + if (ctxcanvas->bitmap_dbuffer) delete ctxcanvas->bitmap_dbuffer; + ctxcanvas->bitmap_dbuffer = NULL; + + Bitmap* bitmap = new Bitmap(w, h, PixelFormat24bppRGB); + bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4)); + + ctxcanvas->bitmap = bitmap; + ctxcanvas->graphics = new Graphics(bitmap); + + ctxcanvas->canvas->w = w; + ctxcanvas->canvas->h = h; + + ctxcanvas->dirty = 1; + + cdwpUpdateCanvas(ctxcanvas); + } + + return CD_OK; +} + +/* +%F cdCreateCanvas para DBuffer. +O DC é um BITMAP em memoria. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + int w, h; + cdCanvas* canvas_dbuffer = (cdCanvas*)data; + if (!canvas_dbuffer) + return; + + cdCanvasActivate(canvas_dbuffer); /* Update size */ + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + Bitmap* bitmap = new Bitmap(w, h, PixelFormat24bppRGB); + bitmap->SetResolution((REAL)(canvas_dbuffer->xres*25.4), (REAL)(canvas_dbuffer->yres*25.4)); + + Graphics imggraphics(bitmap); + imggraphics.Clear(Color::White); + + Graphics* graphics = new Graphics(bitmap); + + canvas->w = w; + canvas->h = h; + canvas->bpp = 24; + + /* Initialize base driver */ + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_BMP); + + ctxcanvas->bitmap = bitmap; + ctxcanvas->canvas_dbuffer = canvas_dbuffer; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwpInitTable(canvas); + + canvas->cxActivate = cdactivate; + canvas->cxDeactivate = cddeactivate; + canvas->cxFlush = cdflush; + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdDBufferContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +extern "C" { +cdContext* cdContextDBufferPlus(void) +{ + return &cdDBufferContext; +} +} diff --git a/cd/src/gdiplus/cdwemfp.cpp b/cd/src/gdiplus/cdwemfp.cpp new file mode 100755 index 0000000..38b4200 --- /dev/null +++ b/cd/src/gdiplus/cdwemfp.cpp @@ -0,0 +1,105 @@ +/** \file + * \brief Windows GDI+ EMF Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdemf.h" +#include +#include + + + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + delete ctxcanvas->metafile; + delete ctxcanvas; +} + +/* +%F cdCreateCanvas para EMF. +O DC é um EMF em memoria. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ + char* strdata = (char*)data; + char filename[10240] = ""; + Metafile* metafile; + + /* Inicializa parametros */ + if (strdata == NULL) + return; + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + int w = 0, h = 0; + sscanf(strdata,"%dx%d", &w, &h); + if (w == 0 || h == 0) + return; + + { + /* Verifica se o arquivo pode ser aberto para escrita */ + FILE* file = fopen(filename, "wb"); + if (file == NULL) + return; + fclose(file); + } + + { + HDC ScreenDC = GetDC(NULL); + /* LOGPIXELS can not be used for EMF */ + canvas->xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + canvas->yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + + Rect frameRect(0, 0, (int)(100 * w / canvas->xres), (int)(100 * h / canvas->yres)); + + metafile = new Metafile(cdwpString2Unicode(filename, strlen(filename)), + ScreenDC, frameRect, MetafileFrameUnitGdi, EmfTypeEmfPlusDual, NULL); + + ReleaseDC(NULL, ScreenDC); + } + + canvas->w = w; + canvas->h = h; + canvas->bpp = 24; + + Graphics* graphics = new Graphics(metafile); + + /* Inicializa driver WIN32 */ + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_EMF); + + /* Inicializacao de variaveis particulares para o EMF */ + ctxcanvas->metafile = metafile; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwpInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdEMFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_FLUSH | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES | + CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +extern "C" { +cdContext* cdContextEMFPlus(void) +{ + return &cdEMFContext; +} +} + + diff --git a/cd/src/gdiplus/cdwgdiplus.c b/cd/src/gdiplus/cdwgdiplus.c new file mode 100755 index 0000000..a6862bc --- /dev/null +++ b/cd/src/gdiplus/cdwgdiplus.c @@ -0,0 +1,42 @@ +/** \file + * \brief GDI+ Control + * + * See Copyright Notice in cd.h + */ + +#include "cd.h" +#include "cd_private.h" +#include "cdgdiplus.h" +#include +#include + +cdContext* cdContextNativeWindowPlus(void); +cdContext* cdContextImagePlus(void); +cdContext* cdContextDBufferPlus(void); +cdContext* cdContextPrinterPlus(void); +cdContext* cdContextEMFPlus(void); +cdContext* cdContextClipboardPlus(void); +void cdwpGdiPlusStartup(int debug); + +void cdInitGdiPlus(void) +{ + cdInitContextPlus(); +} + +void cdInitContextPlus(void) +{ + cdContext* ctx_list[NUM_CONTEXTPLUS]; + memset(ctx_list, 0, sizeof(ctx_list)); + + ctx_list[CD_CTX_NATIVEWINDOW] = cdContextNativeWindowPlus(); + ctx_list[CD_CTX_IMAGE] = cdContextImagePlus(); + ctx_list[CD_CTX_DBUFFER] = cdContextDBufferPlus(); + ctx_list[CD_CTX_PRINTER] = cdContextPrinterPlus(); + ctx_list[CD_CTX_EMF] = cdContextEMFPlus(); + ctx_list[CD_CTX_CLIPBOARD] = cdContextClipboardPlus(); + + cdInitContextPlusList(ctx_list); + + cdwpGdiPlusStartup(0); +} + diff --git a/cd/src/gdiplus/cdwimgp.cpp b/cd/src/gdiplus/cdwimgp.cpp new file mode 100755 index 0000000..697ff40 --- /dev/null +++ b/cd/src/gdiplus/cdwimgp.cpp @@ -0,0 +1,65 @@ +/** \file + * \brief Windows GDI+ Image Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdimage.h" +#include +#include + + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + delete ctxcanvas; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + if (data == NULL) + return; + + cdCtxImage* ctximage = ((cdImage*)data)->ctximage; + + /* Inicializa parametros */ + if (ctximage == NULL) + return; + + Graphics* graphics = new Graphics(ctximage->bitmap); + + canvas->w = ctximage->w; + canvas->h = ctximage->h; + canvas->bpp = ctximage->bpp; + + /* Inicializa driver Image */ + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_BMP); + + ctxcanvas->bitmap = ctximage->bitmap; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwpInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdImageContext = +{ + CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES ), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +extern "C" { +cdContext* cdContextImagePlus(void) +{ + return &cdImageContext; +} +} diff --git a/cd/src/gdiplus/cdwinp.cpp b/cd/src/gdiplus/cdwinp.cpp new file mode 100755 index 0000000..1cbed3c --- /dev/null +++ b/cd/src/gdiplus/cdwinp.cpp @@ -0,0 +1,2338 @@ +/** \file + * \brief Windows GDI+ Base Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdgdiplus.h" +#include "wd.h" +#include +#include +#include + +static void cdstipple(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *index); + +void cdwpShowStatus(const char* title, Status status) +{ + char* status_str = ""; + switch(status) + { + case Ok: status_str = "Ok"; break; + case GenericError: status_str = "GenericError"; break; + case InvalidParameter: status_str = "InvalidParameter"; break; + case OutOfMemory: status_str = "OutOfMemory"; break; + case ObjectBusy: status_str = "ObjectBusy"; break; + case InsufficientBuffer: status_str = "InsufficientBuffer"; break; + case NotImplemented: status_str = "NotImplemented"; break; + case Win32Error: status_str = "Win32Error"; break; + case WrongState: status_str = "WrongState"; break; + case Aborted: status_str = "Aborted"; break; + case FileNotFound: status_str = "FileNotFound"; break; + case ValueOverflow: status_str = "ValueOverflow"; break; + case AccessDenied: status_str = "AccessDenied"; break; + case UnknownImageFormat: status_str = "UnknownImageFormat"; break; + case FontFamilyNotFound: status_str = "FontFamilyNotFound"; break; + case FontStyleNotFound: status_str = "FontStyleNotFound"; break; + case NotTrueTypeFont: status_str = "NotTrueTypeFont"; break; + case UnsupportedGdiplusVersion: status_str = "UnsupportedGdiplusVersion"; break; + case GdiplusNotInitialized: status_str = "GdiplusNotInitialized"; break; + case PropertyNotFound: status_str = "PropertyNotFound"; break; + case PropertyNotSupported: status_str = "PropertyNotSupported"; break; + } + + if (status != Ok) + MessageBox(NULL, status_str, title, MB_OK); +} + +/* +%F Libera memoria e handles alocados pelo driver Windows. +*/ +void cdwpKillCanvas(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->clip_poly) delete[] ctxcanvas->clip_poly; + if (ctxcanvas->clip_region) delete ctxcanvas->clip_region; + if (ctxcanvas->new_region) delete ctxcanvas->new_region; + if (ctxcanvas->font) delete ctxcanvas->font; + if (ctxcanvas->wdpoly) delete ctxcanvas->wdpoly; + + delete ctxcanvas->fillBrush; + delete ctxcanvas->lineBrush; + delete ctxcanvas->linePen; + + delete ctxcanvas->graphics; + + /* ctxcanvas e´ liberado em cada driver */ +} + +static int cdwpSetTransform(cdCtxCanvas* ctxcanvas, Matrix &transformMatrix, const double* matrix) +{ + if (matrix) + { + // configure a bottom-up coordinate system + Matrix Matrix1((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1)); + transformMatrix.Multiply(&Matrix1); + // add the global transform + Matrix Matrix2((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]); + transformMatrix.Multiply(&Matrix2); + return 1; + } + else if (ctxcanvas->rotate_angle) + { + /* the rotation must be corrected because of the Y axis orientation */ + transformMatrix.Translate((REAL)ctxcanvas->rotate_center_x, (REAL)_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); + transformMatrix.Rotate((REAL)-ctxcanvas->rotate_angle); + transformMatrix.Translate((REAL)-ctxcanvas->rotate_center_x, (REAL)-_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y)); + return 1; + } + + return 0; +} + +static void cdwpUpdateTransform(cdCtxCanvas* ctxcanvas) +{ + Matrix transformMatrix; + ctxcanvas->graphics->ResetTransform(); // reset to the identity. + if (cdwpSetTransform(ctxcanvas, transformMatrix, ctxcanvas->canvas->use_matrix? ctxcanvas->canvas->matrix: NULL)) + ctxcanvas->graphics->SetTransform(&transformMatrix); +} + +/*********************************************************************/ +/* +%S Cor +*/ +/*********************************************************************/ + +static Color sColor2Windows(long int cd_color) +{ + return Color(cdAlpha(cd_color),cdRed(cd_color),cdGreen(cd_color),cdBlue(cd_color)); +} + +static void sUpdateFillBrush(cdCtxCanvas* ctxcanvas) +{ + // must update the fill brush that is dependent from the Foreground and Background Color. + BrushType type = ctxcanvas->fillBrush->GetType(); + switch(type) + { + case BrushTypeSolidColor: + { + SolidBrush* solidbrush = (SolidBrush*)ctxcanvas->fillBrush; + solidbrush->SetColor(ctxcanvas->fg); + break; + } + case BrushTypeHatchFill: + { + HatchBrush* hatchbrush = (HatchBrush*)ctxcanvas->fillBrush; + HatchStyle hatchStyle = hatchbrush->GetHatchStyle(); + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new HatchBrush(hatchStyle, ctxcanvas->fg, ctxcanvas->bg); + break; + } + case BrushTypeLinearGradient: + { + LinearGradientBrush* gradientbrush = (LinearGradientBrush*)ctxcanvas->fillBrush; + gradientbrush->SetLinearColors(ctxcanvas->fg, ctxcanvas->bg); + break; + } + case BrushTypeTextureFill: + { + // only stipple depends on Foreground and Background Color. + if (ctxcanvas->canvas->interior_style == CD_STIPPLE) + { + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + } + break; + } + } +} + +static long int cdforeground(cdCtxCanvas* ctxcanvas, long int color) +{ + ctxcanvas->fg = sColor2Windows(color); + ctxcanvas->linePen->SetColor(ctxcanvas->fg); + ctxcanvas->lineBrush->SetColor(ctxcanvas->fg); + + sUpdateFillBrush(ctxcanvas); + + return color; +} + +static Color sSetAlpha(const Color& c, BYTE alpha) +{ + return Color(alpha, c.GetRed(), c.GetGreen(), c.GetBlue()); +} + +static long int cdbackground(cdCtxCanvas* ctxcanvas, long int color) +{ + ctxcanvas->bg = sColor2Windows(color); + + if ((ctxcanvas->canvas->back_opacity == CD_TRANSPARENT) && + (cdAlpha(ctxcanvas->canvas->background) == 255)) + ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)0); + + sUpdateFillBrush(ctxcanvas); + + return color; +} + +static int cdbackopacity(cdCtxCanvas* ctxcanvas, int opacity) +{ + switch (opacity) + { + case CD_TRANSPARENT: + ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)0); + break; + case CD_OPAQUE: + ctxcanvas->bg = sSetAlpha(ctxcanvas->bg, (BYTE)255); + break; + } + + sUpdateFillBrush(ctxcanvas); + + return opacity; +} + +static void cdpalette(cdCtxCanvas* ctxcanvas, int pal_size, const long int *colors, int mode) +{ + (void)mode; + + if (ctxcanvas->wtype == CDW_BMP && + (ctxcanvas->bitmap->GetPixelFormat() == PixelFormat1bppIndexed || + ctxcanvas->bitmap->GetPixelFormat() == PixelFormat4bppIndexed || + ctxcanvas->bitmap->GetPixelFormat() == PixelFormat8bppIndexed)) + { + UINT size = ctxcanvas->bitmap->GetPaletteSize(); + ColorPalette* palette = new ColorPalette [size]; + + palette->Count = pal_size; + palette->Flags = 0; + + for (int c = 0; c < pal_size; c++) + { + palette->Entries[c] = sColor2Windows(colors[c]).GetValue(); + } + + ctxcanvas->bitmap->SetPalette(palette); + delete palette; + } +} + +/*********************************************************************/ +/* +%S Canvas e clipping +*/ +/*********************************************************************/ + +static void sClipRect(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->clip_region) + delete ctxcanvas->clip_region; + + Rect rect(ctxcanvas->canvas->clip_rect.xmin, + ctxcanvas->canvas->clip_rect.ymin, + ctxcanvas->canvas->clip_rect.xmax-ctxcanvas->canvas->clip_rect.xmin+1, + ctxcanvas->canvas->clip_rect.ymax-ctxcanvas->canvas->clip_rect.ymin+1); + + ctxcanvas->clip_region = new Region(rect); + + ctxcanvas->graphics->SetClip(ctxcanvas->clip_region); +} + +static void sClipPoly(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->clip_region) + delete ctxcanvas->clip_region; + + GraphicsPath path; + path.SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n); + ctxcanvas->clip_region = new Region(&path); + + ctxcanvas->graphics->SetClip(ctxcanvas->clip_region); +} + +static int cdclip(cdCtxCanvas* ctxcanvas, int clip_mode) +{ + switch (clip_mode) + { + case CD_CLIPOFF: + ctxcanvas->graphics->ResetClip(); + if (ctxcanvas->clip_region) + delete ctxcanvas->clip_region; + ctxcanvas->clip_region = NULL; + break; + case CD_CLIPAREA: + sClipRect(ctxcanvas); + break; + case CD_CLIPPOLYGON: + sClipPoly(ctxcanvas); + break; + case CD_CLIPREGION: + if (ctxcanvas->clip_region) + delete ctxcanvas->clip_region; + ctxcanvas->clip_region = ctxcanvas->new_region->Clone(); + ctxcanvas->graphics->SetClip(ctxcanvas->clip_region); + break; + } + + return clip_mode; +} + +static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_rect.xmin = xmin; + ctxcanvas->canvas->clip_rect.xmax = xmax; + ctxcanvas->canvas->clip_rect.ymin = ymin; + ctxcanvas->canvas->clip_rect.ymax = ymax; + + sClipRect(ctxcanvas); + } +} + +static void cdnewregion(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->new_region) + delete ctxcanvas->new_region; + ctxcanvas->new_region = new Region(); + ctxcanvas->new_region->MakeEmpty(); +} + +static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_region) + return 0; + + if (ctxcanvas->new_region->IsVisible(x, y)) + return 1; + + return 0; +} + +static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_region) + return; + + ctxcanvas->new_region->Translate(x, y); +} + +static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + Rect rect; + + if (!ctxcanvas->new_region) + return; + + ctxcanvas->new_region->GetBounds(&rect, ctxcanvas->graphics); + + *xmin = rect.X; + *xmax = rect.X+rect.Width-1; + *ymin = rect.Y; + *ymax = rect.Y+rect.Height-1; +} + +static void sCombineRegion(cdCtxCanvas* ctxcanvas, Region& region) +{ + switch(ctxcanvas->canvas->combine_mode) + { + case CD_UNION: + ctxcanvas->new_region->Union(®ion); + break; + case CD_INTERSECT: + ctxcanvas->new_region->Intersect(®ion); + break; + case CD_DIFFERENCE: + ctxcanvas->new_region->Exclude(®ion); + break; + case CD_NOTINTERSECT: + ctxcanvas->new_region->Xor(®ion); + break; + } +} + +/******************************************************************/ +/* +%S Primitivas e seus atributos +*/ +/******************************************************************/ + +static int cdlinestyle(cdCtxCanvas* ctxcanvas, int style) +{ + switch (style) + { + case (CD_CONTINUOUS): + { + ctxcanvas->linePen->SetDashStyle(DashStyleSolid); + break; + } + case CD_DASHED: + { + if (ctxcanvas->canvas->line_width == 1) + { + REAL dashed[2] = {18.0f, 6.0f}; + ctxcanvas->linePen->SetDashPattern(dashed, 2); + } + else + ctxcanvas->linePen->SetDashStyle(DashStyleDash); + break; + } + case CD_DOTTED: + { + if (ctxcanvas->canvas->line_width == 1) + { + REAL dotted[2] = {3.0f, 3.0f}; + ctxcanvas->linePen->SetDashPattern(dotted, 2); + } + else + ctxcanvas->linePen->SetDashStyle(DashStyleDot); + break; + } + case CD_DASH_DOT: + { + if (ctxcanvas->canvas->line_width == 1) + { + REAL dash_dot[6] = {9.0f, 6.0f, 3.0f, 6.0f}; + ctxcanvas->linePen->SetDashPattern(dash_dot, 4); + } + else + ctxcanvas->linePen->SetDashStyle(DashStyleDashDot); + break; + } + case CD_DASH_DOT_DOT: + { + if (ctxcanvas->canvas->line_width == 1) + { + REAL dash_dot_dot[6] = {9.0f, 3.0f, 3.0f, 3.0f, 3.0f, 3.0f}; + ctxcanvas->linePen->SetDashPattern(dash_dot_dot, 6); + } + else + ctxcanvas->linePen->SetDashStyle(DashStyleDashDotDot); + break; + } + case CD_CUSTOM: + { + REAL* dash_style = new REAL [ctxcanvas->canvas->line_dashes_count]; + for (int i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + dash_style[i] = (REAL)ctxcanvas->canvas->line_dashes[i]/(REAL)ctxcanvas->canvas->line_width; + ctxcanvas->linePen->SetDashPattern(dash_style, ctxcanvas->canvas->line_dashes_count); + delete [] dash_style; + break; + } + } + + return style; +} + +static int cdlinecap(cdCtxCanvas* ctxcanvas, int cap) +{ + LineCap cd2win_lcap[] = {LineCapFlat, LineCapSquare, LineCapRound}; + DashCap cd2win_dcap[] = {DashCapFlat, DashCapFlat, DashCapRound}; + + ctxcanvas->linePen->SetLineCap(cd2win_lcap[cap], cd2win_lcap[cap], cd2win_dcap[cap]); + + return cap; +} + +static int cdlinejoin(cdCtxCanvas* ctxcanvas, int join) +{ + LineJoin cd2win_join[] = {LineJoinMiter, LineJoinBevel, LineJoinRound}; + + ctxcanvas->linePen->SetLineJoin(cd2win_join[join]); + + return join; +} + +static int cdlinewidth(cdCtxCanvas* ctxcanvas, int width) +{ + ctxcanvas->linePen->SetWidth((REAL)width); + cdlinestyle(ctxcanvas, ctxcanvas->canvas->line_style); + return width; +} + +static int cdhatch(cdCtxCanvas* ctxcanvas, int hatch_style) +{ + HatchStyle hatchStyle; + + switch (hatch_style) + { + default: // CD_HORIZONTAL: + hatchStyle = HatchStyleHorizontal; + break; + case CD_VERTICAL: + hatchStyle = HatchStyleVertical; + break; + case CD_FDIAGONAL: + hatchStyle = HatchStyleForwardDiagonal; + break; + case CD_BDIAGONAL: + hatchStyle = HatchStyleBackwardDiagonal; + break; + case CD_CROSS: + hatchStyle = HatchStyleCross; + break; + case CD_DIAGCROSS: + hatchStyle = HatchStyleDiagonalCross; + break; + } + + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new HatchBrush(hatchStyle, ctxcanvas->fg, ctxcanvas->bg); + + return hatch_style; +} + +static void cdstipple(cdCtxCanvas* ctxcanvas, int w, int h, const unsigned char *index) +{ + ULONG* bitmap_data = new ULONG [w*h]; + + for(int j = 0; j < h; j++) + { + int line_offset_index; + int line_offset = j*w; + if (ctxcanvas->canvas->invert_yaxis) + line_offset_index = ((h - 1) - j)*w; // Fix up side down + else + line_offset_index = line_offset; + + for(int i = 0; i < w; i++) + { + if (index[line_offset_index+i] != 0) + bitmap_data[line_offset+i] = ctxcanvas->fg.GetValue(); + else + bitmap_data[line_offset+i] = ctxcanvas->bg.GetValue(); + } + } + + Bitmap StippleImage(w, h, 4*w, PixelFormat32bppARGB, (BYTE*)bitmap_data); + StippleImage.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new TextureBrush(&StippleImage); + + delete bitmap_data; +} + +static void cdpattern(cdCtxCanvas* ctxcanvas, int w, int h, const long int *colors) +{ + int stride = 4*w; + BYTE* bitmap_data = new BYTE [stride*h]; + + for(int j = 0; j < h; j++) + { + int line_offset_colors; + int line_offset = j*stride; + if (ctxcanvas->canvas->invert_yaxis) + line_offset_colors = ((h - 1) - j)*w; // Fix up side down + else + line_offset_colors = j*w; + memcpy(bitmap_data + line_offset, colors + line_offset_colors, stride); + + // Fix alpha values + for(int i = 3; i < stride; i+=4) + bitmap_data[line_offset+i] = ~bitmap_data[line_offset+i]; + } + + Bitmap PatternImage(w, h, stride, PixelFormat32bppARGB, bitmap_data); + PatternImage.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new TextureBrush(&PatternImage); + + delete bitmap_data; +} + +static int cdinteriorstyle(cdCtxCanvas* ctxcanvas, int style) +{ + switch (style) + { + case CD_SOLID: + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new SolidBrush(ctxcanvas->fg); + break; + case CD_HATCH: + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + break; + case CD_STIPPLE: + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + break; + case CD_PATTERN: + cdpattern(ctxcanvas, ctxcanvas->canvas->pattern_w, ctxcanvas->canvas->pattern_h, ctxcanvas->canvas->pattern); + break; + } + + return style; +} + +static void cdline(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) +{ + ctxcanvas->graphics->DrawLine(ctxcanvas->linePen, x1, y1, x2, y2); + ctxcanvas->dirty = 1; +} + +static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + Rect rect(xmin, ymin, xmax-xmin, ymax-ymin); // in this case Size = Max - Min + ctxcanvas->graphics->DrawRectangle(ctxcanvas->linePen, rect); + ctxcanvas->dirty = 1; +} + +static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1); + if (ctxcanvas->canvas->new_region) + { + Region region(rect); + sCombineRegion(ctxcanvas, region); + } + else + { + ctxcanvas->graphics->FillRectangle(ctxcanvas->fillBrush, rect); + ctxcanvas->dirty = 1; + } +} + +static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2) +{ + if (ctxcanvas->canvas->invert_yaxis) + { + // GDI+ angle are clock-wise by default + *angle1 *= -1; + *angle2 *= -1; + } +} + +static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + Rect rect(xc - w/2, yc - h/2, w, h); + if (angle1 == 0 && angle2 == 360) + ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect); + else + { + cdwpFixAngles(ctxcanvas, &angle1, &angle2); + ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1)); + } + ctxcanvas->dirty = 1; +} + +static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + Rect rect(xc - w/2, yc - h/2, w, h); + if (ctxcanvas->canvas->new_region) + { + GraphicsPath path; + if (angle1==0 && angle2==360) + path.AddEllipse(rect); + else + { + cdwpFixAngles(ctxcanvas, &angle1, &angle2); + path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1)); + } + Region region(&path); + sCombineRegion(ctxcanvas, region); + } + else + { + // complete the remaining pixels using an Arc + Pen pen(ctxcanvas->fillBrush); + + if (angle1==0 && angle2==360) + { + ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect); + ctxcanvas->graphics->DrawEllipse(&pen, rect); + } + else + { + cdwpFixAngles(ctxcanvas, &angle1, &angle2); + ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1)); + ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1)); + } + ctxcanvas->dirty = 1; + } +} + +static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + Rect rect(xc - w/2, yc - h/2, w, h); + if (ctxcanvas->canvas->new_region) + { + GraphicsPath path; + if (angle1==0 && angle2==360) + path.AddEllipse(rect); + else + { + cdwpFixAngles(ctxcanvas, &angle1, &angle2); + path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1)); + path.CloseFigure(); + } + Region region(&path); + sCombineRegion(ctxcanvas, region); + } + else + { + if (angle1==0 && angle2==360) + ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect); + else + { + GraphicsPath path; + cdwpFixAngles(ctxcanvas, &angle1, &angle2); + path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1)); + ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path); + } + Pen pen(ctxcanvas->fillBrush); // complete the remaining pixels using an Arc + ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1)); + ctxcanvas->dirty = 1; + } +} + +static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + switch( mode ) + { + case CD_BEZIER: + if (n < 4) return; + ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (Point*)poly, n); + break; + case CD_FILLSPLINE: + if (n < 4) return; + if (ctxcanvas->canvas->new_region) + { + GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + path.AddClosedCurve((Point*)poly, n); + Region region(&path); + sCombineRegion(ctxcanvas, region); + } + else + ctxcanvas->graphics->FillClosedCurve(ctxcanvas->fillBrush, (Point*)poly, n); + break; + case CD_SPLINE: + if (n < 4) return; + ctxcanvas->graphics->DrawClosedCurve(ctxcanvas->linePen, (Point*)poly, n); + break; + case CD_CLOSED_LINES: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + /* continue */ + case CD_OPEN_LINES: + ctxcanvas->graphics->DrawLines(ctxcanvas->linePen, (Point*)poly, n); + break; + case CD_FILLGRADIENT: + { + int count = n; + PathGradientBrush* brush = new PathGradientBrush((Point*)poly, n); + brush->SetSurroundColors(ctxcanvas->pathGradient, &count); + brush->SetCenterColor(ctxcanvas->pathGradient[n]); + ctxcanvas->graphics->FillPolygon(brush, (Point*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + } + break; + case CD_FILL: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + if (ctxcanvas->canvas->new_region) + { + GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + path.AddPolygon((Point*)poly, n); + Region region(&path); + sCombineRegion(ctxcanvas, region); + } + else + ctxcanvas->graphics->FillPolygon(ctxcanvas->fillBrush, (Point*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + break; + case CD_CLIP: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + + if (ctxcanvas->clip_poly) + delete[] ctxcanvas->clip_poly; + + ctxcanvas->clip_poly = new Point [n]; + + Point* pnt = (Point*)poly; + int t = n; + int nc = 1; + + ctxcanvas->clip_poly[0] = *pnt; + pnt++; + + for (int i = 1; i < t-1; i++, pnt++) + { + if (!((pnt->X == ctxcanvas->clip_poly[nc-1].X && pnt->X == (pnt + 1)->X) || + (pnt->Y == ctxcanvas->clip_poly[nc-1].Y && pnt->Y == (pnt + 1)->Y))) + { + ctxcanvas->clip_poly[nc] = *pnt; + nc++; + } + } + + ctxcanvas->clip_poly_n = nc; + + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + sClipPoly(ctxcanvas); + + break; + } + + ctxcanvas->dirty = 1; +} + +WCHAR* cdwpString2Unicode(const char* s, int len) +{ + static WCHAR wstr[10240] = L""; + if (len >= 10240) len = 10239; + MultiByteToWideChar(CP_ACP, 0, s, -1, wstr, len+1); + return wstr; +} + +static int cdwpCompensateHeight(int height) +{ + return (int)floor(height/10. + 0.5); /* 10% */ +} + +static void cdgettextsize(cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height) +{ + RectF boundingBox; + + ctxcanvas->graphics->MeasureString(cdwpString2Unicode(s, len), len, + ctxcanvas->font, PointF(0,0), + &boundingBox); + if (width) + *width = (int)boundingBox.Width; + + if (height) + *height = (int)boundingBox.Height - cdwpCompensateHeight(ctxcanvas->fontinfo.height); +} + +static void sTextBox(cdCtxCanvas* ctxcanvas, WCHAR *ws, int len, int x, int y, int *w, int *h, int *xmin, int *ymin) +{ + int ydir = 1; + if (ctxcanvas->canvas->invert_yaxis) + ydir = -1; + + RectF boundingBox; + ctxcanvas->graphics->MeasureString(ws, len, + ctxcanvas->font, PointF(0,0), + &boundingBox); + *w = (int)boundingBox.Width; + *h = (int)boundingBox.Height - cdwpCompensateHeight(ctxcanvas->fontinfo.height); + + // distance from bottom to baseline + int baseline = ctxcanvas->fontinfo.height - ctxcanvas->fontinfo.ascent; + + // move to bottom-left + cdTextTranslatePoint(ctxcanvas->canvas, x, y, *w, *h, baseline, xmin, ymin); + + // move to top-left + *ymin += ydir * (*h); +} + +static void cdwpCanvasGetTextHeight(cdCanvas* canvas, int x, int y, int w, int h, int *hbox) +{ + int xmin, xmax, ymin, ymax; + + // distance from bottom to baseline + int baseline = canvas->ctxcanvas->fontinfo.height - canvas->ctxcanvas->fontinfo.ascent; + + /* move to bottom-left */ + cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin); + + xmax = xmin + w-1; + ymax = ymin + h-1; + + if (canvas->text_orientation) + { + double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + int rectY[4]; + + cdRotatePointY(canvas, xmin, ymin, x, y, &rectY[0], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymin, x, y, &rectY[1], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymax, x, y, &rectY[2], sin_theta, cos_theta); + cdRotatePointY(canvas, xmin, ymax, x, y, &rectY[3], sin_theta, cos_theta); + + ymin = ymax = rectY[0]; + if (rectY[1] < ymin) ymin = rectY[1]; + if (rectY[2] < ymin) ymin = rectY[2]; + if (rectY[3] < ymin) ymin = rectY[3]; + if (rectY[1] > ymax) ymax = rectY[1]; + if (rectY[2] > ymax) ymax = rectY[2]; + if (rectY[3] > ymax) ymax = rectY[3]; + } + + *hbox = ymax-ymin+1; +} + +static void cdwpTextTransform(cdCtxCanvas* ctxcanvas, int *x, int *y, int w, int h, Matrix &transformMatrix) +{ + int hbox; + double* matrix = ctxcanvas->canvas->matrix; + Matrix m1; + + cdwpCanvasGetTextHeight(ctxcanvas->canvas, *x, *y, w, h, &hbox); + + // configure a bottom-up coordinate system + m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(ctxcanvas->canvas->h-1)); + transformMatrix.Multiply(&m1); + + // add the global transform + m1.SetElements((REAL)matrix[0], (REAL)matrix[1], (REAL)matrix[2], (REAL)matrix[3], (REAL)matrix[4], (REAL)matrix[5]); + transformMatrix.Multiply(&m1); + + // move to (x,y) and remove a vertical offset since text reference point is top-left + m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)1, (REAL)*x, (REAL)(*y - (hbox-1))); + transformMatrix.Multiply(&m1); + + // invert the text vertical orientation, relative to itself + m1.SetElements((REAL)1, (REAL)0, (REAL)0, (REAL)-1, (REAL)0, (REAL)(hbox-1)); + transformMatrix.Multiply(&m1); + + *x = 0; + *y = 0; +} + +static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s, int len) +{ + Matrix transformMatrix; + int use_transform = 0, w, h; + WCHAR* ws = cdwpString2Unicode(s, len); + + if (ctxcanvas->canvas->text_orientation) + { + transformMatrix.Translate((REAL)x, (REAL)y); + transformMatrix.Rotate((REAL)-ctxcanvas->canvas->text_orientation); + transformMatrix.Translate((REAL)-x, (REAL)-y); + use_transform = 1; + } + + // Move (x,y) to top-left + sTextBox(ctxcanvas, ws, len, x, y, &w, &h, &x, &y); + + if (ctxcanvas->canvas->use_matrix) + { + cdwpTextTransform(ctxcanvas, &x, &y, w, h, transformMatrix); + use_transform = 1; + } + else if (cdwpSetTransform(ctxcanvas, transformMatrix, NULL)) + use_transform = 1; + + if (ctxcanvas->canvas->new_region) + { + GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding); + + if (use_transform) + path.Transform(&transformMatrix); + + FontFamily family; + ctxcanvas->font->GetFamily(&family); + path.AddString(ws, len, &family, ctxcanvas->font->GetStyle(), + ctxcanvas->font->GetSize(), + Point(x, y), NULL); + + Region region(&path); + sCombineRegion(ctxcanvas, region); + return; + } + + if (use_transform) + ctxcanvas->graphics->SetTransform(&transformMatrix); + + ctxcanvas->graphics->DrawString(ws, len, + ctxcanvas->font, PointF((REAL)x, (REAL)y), + ctxcanvas->lineBrush); + + if (use_transform) + cdwpUpdateTransform(ctxcanvas); // reset transform + + ctxcanvas->dirty = 1; +} + +static int sDesign2Pixel(int x, REAL size, int height) +{ + return (int)((x * size) / height); +} + +static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size) +{ + FontFamily* fontFamily; + + if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Monospace")) + fontFamily = new FontFamily(L"Courier New"); + else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Serif")) + fontFamily = new FontFamily(L"Times New Roman"); + else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Sans")) + fontFamily = new FontFamily(L"Arial"); + else if (cdStrEqualNoCase(type_face, "System")) + fontFamily = FontFamily::GenericSansSerif()->Clone(); + else + fontFamily = new FontFamily(cdwpString2Unicode(type_face, strlen(type_face))); + + REAL emSize = (REAL)(cdGetFontSizePixels(ctxcanvas->canvas, size)); + + INT fontStyle = FontStyleRegular; + if (style&CD_BOLD) fontStyle |= FontStyleBold; + if (style&CD_ITALIC) fontStyle |= FontStyleItalic; + if (style&CD_UNDERLINE) fontStyle |= FontStyleUnderline; + if (style&CD_STRIKEOUT) fontStyle |= FontStyleStrikeout; + + if (ctxcanvas->font) delete ctxcanvas->font; + ctxcanvas->font = new Font(fontFamily, emSize, fontStyle, UnitPixel); + + REAL fontSize = ctxcanvas->font->GetSize(); + int emHeight = fontFamily->GetEmHeight(fontStyle); + ctxcanvas->fontinfo.height = sDesign2Pixel(fontFamily->GetLineSpacing(fontStyle), fontSize, emHeight); + ctxcanvas->fontinfo.ascent = sDesign2Pixel(fontFamily->GetCellAscent(fontStyle), fontSize, emHeight); + ctxcanvas->fontinfo.descent = sDesign2Pixel(fontFamily->GetCellDescent(fontStyle), fontSize, emHeight); + + delete fontFamily; + + return 1; +} + +static int cdnativefont(cdCtxCanvas* ctxcanvas, const char* nativefont) +{ + int size = 12, bold = 0, italic = 0, underline = 0, strikeout = 0, style = CD_PLAIN; + char type_face[1024]; + + if (nativefont[0] == '-' && nativefont[1] == 'd') + { + COLORREF rgbColors; + LOGFONT lf; + ctxcanvas->font->GetLogFontA(ctxcanvas->graphics, &lf); + + CHOOSEFONT cf; + ZeroMemory(&cf, sizeof(CHOOSEFONT)); + + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = GetForegroundWindow(); + cf.lpLogFont = &lf; + cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT; + rgbColors = cf.rgbColors = ctxcanvas->fg.ToCOLORREF(); + + if (!ChooseFont(&cf)) + return 0; + + if (rgbColors != cf.rgbColors) + cdCanvasSetForeground(ctxcanvas->canvas, cdEncodeColor(GetRValue(cf.rgbColors),GetGValue(cf.rgbColors),GetBValue(cf.rgbColors))); + + bold = lf.lfWeight>FW_NORMAL? 1: 0; + italic = lf.lfItalic; + size = lf.lfHeight; + strcpy(type_face, lf.lfFaceName); + underline = lf.lfUnderline; + strikeout = lf.lfStrikeOut; + + if (bold) style |= CD_BOLD; + if (italic) style |= CD_ITALIC; + if (underline) style |= CD_UNDERLINE; + if (strikeout) style |= CD_STRIKEOUT; + } + else + { + if (!cdParseIupWinFont(nativefont, type_face, &style, &size)) + { + if (!cdParsePangoFont(nativefont, type_face, &style, &size)) + return 0; + } + + if (style&CD_BOLD) + bold = 1; + if (style&CD_ITALIC) + italic = 1; + if (style&CD_UNDERLINE) + underline = 1; + if (style&CD_STRIKEOUT) + strikeout = 1; + } + + REAL emSize = (REAL)(cdGetFontSizePixels(ctxcanvas->canvas, size)); + + INT fontStyle = FontStyleRegular; + if (bold) fontStyle |= FontStyleBold; + if (italic) fontStyle |= FontStyleItalic; + if (underline) fontStyle |= FontStyleUnderline; + if (strikeout) fontStyle |= FontStyleStrikeout; + + const char* new_type_face = type_face; + if (strstr(type_face, "Times") != NULL) + new_type_face = "Times"; + + if (strstr(type_face, "Courier") != NULL) + new_type_face = "Courier"; + + if (strstr(type_face, "Arial") != NULL) + new_type_face = "Helvetica"; + + if (strstr(type_face, "Helv") != NULL) + new_type_face = "Helvetica"; + + FontFamily *fontFamily; + if (strstr(type_face, "System") != NULL) + { + new_type_face = "System"; + fontFamily = FontFamily::GenericSansSerif()->Clone(); + } + else + fontFamily = new FontFamily(cdwpString2Unicode(type_face, strlen(type_face))); + + if (!fontFamily->IsAvailable()) + { + delete fontFamily; + return 0; + } + + Font* font = new Font(fontFamily, emSize, fontStyle, UnitPixel); + if (!font->IsAvailable()) + { + delete fontFamily; + delete font; + return 0; + } + + if (ctxcanvas->font) delete ctxcanvas->font; + ctxcanvas->font = font; + + REAL fontSize = ctxcanvas->font->GetSize(); + int emHeight = fontFamily->GetEmHeight(fontStyle); + ctxcanvas->fontinfo.height = sDesign2Pixel(fontFamily->GetLineSpacing(fontStyle), fontSize, emHeight); + ctxcanvas->fontinfo.ascent = sDesign2Pixel(fontFamily->GetCellAscent(fontStyle), fontSize, emHeight); + ctxcanvas->fontinfo.descent = sDesign2Pixel(fontFamily->GetCellDescent(fontStyle), fontSize, emHeight); + + delete fontFamily; + + /* update cdfont parameters */ + ctxcanvas->canvas->font_style = style; + ctxcanvas->canvas->font_size = size; + strcpy(ctxcanvas->canvas->font_type_face, new_type_face); + + return 1; +} + +static void cdgetfontdim(cdCtxCanvas* ctxcanvas, int *max_width, int *line_height, int *ascent, int *descent) +{ + if (max_width) + { + RectF boundingBox; + ctxcanvas->graphics->MeasureString(L"W", 2, + ctxcanvas->font, PointF(0,0), + &boundingBox); + *max_width = (int)(boundingBox.Width/2); + } + + if (line_height) + *line_height = ctxcanvas->fontinfo.height; + + if (ascent) + *ascent = ctxcanvas->fontinfo.ascent; + + if (descent) + *descent = ctxcanvas->fontinfo.descent; +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + Matrix transformMatrix; + ctxcanvas->graphics->ResetTransform(); // reset to the identity. + + if (matrix) + ctxcanvas->canvas->invert_yaxis = 0; + else + ctxcanvas->canvas->invert_yaxis = 1; + + if (cdwpSetTransform(ctxcanvas, transformMatrix, matrix)) + ctxcanvas->graphics->SetTransform(&transformMatrix); +} + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF) + ctxcanvas->graphics->ResetClip(); + + ctxcanvas->graphics->Clear(sSetAlpha(ctxcanvas->bg, (BYTE)255)); + + if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF) + cdclip(ctxcanvas, ctxcanvas->canvas->clip_mode); + + ctxcanvas->dirty = 1; +} + +/******************************************************************/ +/* +%S Funcoes de imagens do cliente +*/ +/******************************************************************/ + +static void sRGB2Bitmap(Bitmap& image, int width, int height, const unsigned char *red, + const unsigned char *green, + const unsigned char *blue, + int xmin, int xmax, int ymin, int ymax, int topdown) +{ + BitmapData bitmapData; + Rect rect(0,0,image.GetWidth(),image.GetHeight()); + image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData); + + int line_offset; + for(int j = 0; j < rect.Height; j++) + { + if (topdown) + line_offset = (height - (ymax - j) - 1)*width; + else + line_offset = (ymax - j)*width; + + BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride; + + for(int i = 0; i < rect.Width; i++) + { + int offset = line_offset + i + xmin; + int offset_data = i*3; + line_data[offset_data+0] = blue[offset]; + line_data[offset_data+1] = green[offset]; + line_data[offset_data+2] = red[offset]; + } + } + + image.UnlockBits(&bitmapData); +} + +static void sRGBA2Bitmap(Bitmap& image, int width, int height, const unsigned char *red, + const unsigned char *green, + const unsigned char *blue, + const unsigned char *alpha, + int xmin, int xmax, int ymin, int ymax, int topdown) +{ + BitmapData bitmapData; + Rect rect(0,0,image.GetWidth(),image.GetHeight()); + image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData); + + int line_offset; + for(int j = 0; j < rect.Height; j++) + { + if (topdown) + line_offset = (height - (ymax - j) - 1)*width; + else + line_offset = (ymax - j)*width; + + BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride; + + for(int i = 0; i < rect.Width; i++) + { + int offset = line_offset + i + xmin; + int offset_data = i*4; + line_data[offset_data+0] = blue? blue[offset]: 0; + line_data[offset_data+1] = green? green[offset]: 0; + line_data[offset_data+2] = red? red[offset]: 0; + line_data[offset_data+3] = alpha[offset]; + } + } + + image.UnlockBits(&bitmapData); +} + +static void sAlpha2Bitmap(Bitmap& image, int width, int height, const unsigned char *alpha, + int xmin, int xmax, int ymin, int ymax, int topdown) +{ + BitmapData bitmapData; + Rect rect(0,0,image.GetWidth(),image.GetHeight()); + image.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData); + + int line_offset; + for(int j = 0; j < rect.Height; j++) + { + if (topdown) + line_offset = (height - (ymax - j) - 1)*width; + else + line_offset = (ymax - j)*width; + + BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride; + + for(int i = 0; i < rect.Width; i++) + { + int offset = line_offset + i + xmin; + int offset_data = i*4; + line_data[offset_data+3] = alpha[offset]; + } + } + + image.UnlockBits(&bitmapData); +} + +/* +GDI+ does not natively work with palettized images. + +GDI+ will not try to draw on a palettized image as it would +require color reducing the drawing result. + +GDI+ will work natively with 32bpp image data behind the scenes anyway so +there is no economy in trying to work with 8bpp images. + +Full support for palettized images was on the feature list but it did not +make the cut for version 1 of GDI+. +*/ + +static void sMap2Bitmap(Bitmap& image, int width, int height, const unsigned char *index, + const long int *colors, + int xmin, int xmax, int ymin, int ymax, int topdown) +{ + BitmapData bitmapData; + Rect rect(0,0,image.GetWidth(),image.GetHeight()); + image.LockBits(&rect, ImageLockModeWrite, PixelFormat24bppRGB, &bitmapData); + + int line_offset; + for(int j = 0; j < rect.Height; j++) + { + if (topdown) + line_offset = (height - (ymax - j) - 1)*width; + else + line_offset = (ymax - j)*width; + + BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride; + + for(int i = 0; i < rect.Width; i++) + { + int map_index = index[line_offset + i + xmin]; + long color = colors[map_index]; + + int offset_data = i*3; + line_data[offset_data+0] = cdBlue(color); + line_data[offset_data+1] = cdGreen(color); + line_data[offset_data+2] = cdRed(color); + } + } + + image.UnlockBits(&bitmapData); +} + +static void sBitmap2RGB(Bitmap& image, unsigned char *red, unsigned char *green, unsigned char *blue) +{ + BitmapData bitmapData; + Rect rect(0,0,image.GetWidth(),image.GetHeight()); + image.LockBits(&rect, ImageLockModeRead, PixelFormat24bppRGB, &bitmapData); + + for(int j = 0; j < rect.Height; j++) + { + int line_offset = ((rect.Height-1) - j)*rect.Width; + + BYTE* line_data = (BYTE*)bitmapData.Scan0 + j*bitmapData.Stride; + + for(int i = 0; i < rect.Width; i++) + { + int offset = line_offset + i; + int offset_data = i*3; + blue[offset] = line_data[offset_data+0]; + green[offset] = line_data[offset_data+1]; + red[offset] = line_data[offset_data+2]; + } + } + + image.UnlockBits(&bitmapData); +} + +static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned char *green, unsigned char *blue, + int x, int y, int w, int h) +{ + Matrix transformMatrix; + ctxcanvas->graphics->GetTransform(&transformMatrix); + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->ResetTransform(); // reset to the identity. + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + y = _cdInvertYAxis(ctxcanvas->canvas, y); + + int yr = y - (h - 1); /* y starts at the bottom of the image */ + Bitmap image(w, h, PixelFormat24bppRGB); + image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + Graphics* imggraphics = new Graphics(&image); + + if (ctxcanvas->wtype == CDW_BMP) + { + imggraphics->DrawImage(ctxcanvas->bitmap, + Rect(0, 0, w, h), + x, yr, w, h, UnitPixel, + NULL, NULL, NULL); + } + else + { + HDC hdc = ctxcanvas->graphics->GetHDC(); + HDC img_hdc = imggraphics->GetHDC(); + + BitBlt(img_hdc,0,0,w,h,hdc,x,yr,SRCCOPY); + + imggraphics->ReleaseHDC(img_hdc); + ctxcanvas->graphics->ReleaseHDC(hdc); + } + + delete imggraphics; + + sBitmap2RGB(image, red, green, blue); + + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->SetTransform(&transformMatrix); +} + +static void sFixImageY(cdCanvas* canvas, int *topdown, int *y, int *h) +{ + if (canvas->invert_yaxis) + { + if (*h < 0) + *topdown = 1; + else + *topdown = 0; + } + else + { + if (*h < 0) + *topdown = 0; + else + *topdown = 1; + } + + if (*h < 0) + *h = -(*h); // y is at top-left corner (UNDOCUMENTED FEATURE) + + if (!(*topdown)) + *y -= ((*h) - 1); // move Y to top-left corner, since it was at the bottom of the image +} + +static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *index, + const long int *colors, + int x, int y, int w, int h, + int xmin, int xmax, int ymin, int ymax) +{ + int topdown; + Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat24bppRGB); + image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + sFixImageY(ctxcanvas->canvas, &topdown, &y, &h); + sMap2Bitmap(image, width, height, index, colors, xmin, xmax, ymin, ymax, topdown); + + ImageAttributes imageAttributes; + if (ctxcanvas->use_img_transp) + imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap); + + if(ctxcanvas->use_img_points) + { + Point pts[3]; + pts[0] = ctxcanvas->img_points[0]; + pts[1] = ctxcanvas->img_points[1]; + pts[2] = ctxcanvas->img_points[2]; + if (ctxcanvas->canvas->invert_yaxis) + { + pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y); + pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y); + pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y); + } + ctxcanvas->graphics->DrawImage(&image, pts, 3, + 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel, + &imageAttributes, NULL, NULL); + } + else + { + REAL bw = (REAL)image.GetWidth(); + REAL bh = (REAL)image.GetHeight(); + if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf + if (h > bh) bh-=0.5; + ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h), + 0, 0, bw, bh, UnitPixel, + &imageAttributes, NULL, NULL); + } + + ctxcanvas->dirty = 1; +} + +static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red, + const unsigned char *green, + const unsigned char *blue, + int x, int y, int w, int h, + int xmin, int xmax, int ymin, int ymax) +{ + int topdown; + Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat24bppRGB); + image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + sFixImageY(ctxcanvas->canvas, &topdown, &y, &h); + sRGB2Bitmap(image, width, height, red, green, blue, xmin, xmax, ymin, ymax, topdown); + + ImageAttributes imageAttributes; + if (ctxcanvas->use_img_transp) + imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap); + + if(ctxcanvas->use_img_points) + { + Point pts[3]; + pts[0] = ctxcanvas->img_points[0]; + pts[1] = ctxcanvas->img_points[1]; + pts[2] = ctxcanvas->img_points[2]; + if (ctxcanvas->canvas->invert_yaxis) + { + pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y); + pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y); + pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y); + } + ctxcanvas->graphics->DrawImage(&image, pts, 3, + 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel, + &imageAttributes, NULL, NULL); + } + else + { + REAL bw = (REAL)image.GetWidth(); + REAL bh = (REAL)image.GetHeight(); + if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf + if (h > bh) bh-=0.5; + ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h), + 0, 0, bw, bh, UnitPixel, + &imageAttributes, NULL, NULL); + } + + ctxcanvas->dirty = 1; +} + +static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red, + const unsigned char *green, + const unsigned char *blue, + const unsigned char *alpha, + int x, int y, int w, int h, + int xmin, int xmax, int ymin, int ymax) +{ + int topdown; + Bitmap image(xmax-xmin+1, ymax-ymin+1, PixelFormat32bppARGB); + image.SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + + sFixImageY(ctxcanvas->canvas, &topdown, &y, &h); + sRGBA2Bitmap(image, width, height, red, green, blue, alpha, xmin, xmax, ymin, ymax, topdown); + + ImageAttributes imageAttributes; + if(ctxcanvas->use_img_points) + { + Point pts[3]; + pts[0] = ctxcanvas->img_points[0]; + pts[1] = ctxcanvas->img_points[1]; + pts[2] = ctxcanvas->img_points[2]; + if (ctxcanvas->canvas->invert_yaxis) + { + pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y); + pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y); + pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y); + } + ctxcanvas->graphics->DrawImage(&image, pts, 3, + 0, 0, image.GetWidth(), image.GetHeight(), UnitPixel, + &imageAttributes, NULL, NULL); + } + else + { + REAL bw = (REAL)image.GetWidth(); + REAL bh = (REAL)image.GetHeight(); + if (w > bw) bw-=0.5; // Fix the problem of not using PixelOffsetModeHalf + if (h > bh) bh-=0.5; + ctxcanvas->graphics->DrawImage(&image, RectF((REAL)x, (REAL)y, (REAL)w, (REAL)h), + 0, 0, bw, bh, UnitPixel, + &imageAttributes, NULL, NULL); + } + + ctxcanvas->dirty = 1; +} + +/********************************************************************/ +/* +%S Funcoes de imagens do servidor +*/ +/********************************************************************/ + +static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int cd_color) +{ + if (!ctxcanvas->graphics->IsVisible(x, y)) + return; + + if (ctxcanvas->wtype == CDW_BMP) + { + ctxcanvas->bitmap->SetPixel(x, y, sColor2Windows(cd_color)); + } + else + { + if (ctxcanvas->canvas->use_matrix) + { + Point p = Point(x, y); + ctxcanvas->graphics->TransformPoints(CoordinateSpacePage, CoordinateSpaceWorld, &p, 1); + x = p.X; + y = p.Y; + } + HDC hdc = ctxcanvas->graphics->GetHDC(); + SetPixelV(hdc, x, y, sColor2Windows(cd_color).ToCOLORREF()); + ctxcanvas->graphics->ReleaseHDC(hdc); + } + + ctxcanvas->dirty = 1; +} + +static int sFormat2Bpp(PixelFormat pixelFormat) +{ + switch(pixelFormat) + { + case PixelFormat1bppIndexed: + return 1; + case PixelFormat4bppIndexed: + return 4; + case PixelFormat8bppIndexed: + return 8; + case PixelFormat16bppARGB1555: + case PixelFormat16bppGrayScale: + case PixelFormat16bppRGB555: + case PixelFormat16bppRGB565: + return 16; + case PixelFormat24bppRGB: + return 24; + case PixelFormat32bppARGB: + case PixelFormat32bppPARGB: + case PixelFormat32bppRGB: + return 32; + case PixelFormat48bppRGB: + return 48; + case PixelFormat64bppARGB: + case PixelFormat64bppPARGB: + return 64; + } + + return 0; +} + +static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height) +{ + cdCtxImage *ctximage = new cdCtxImage; + ctximage->alpha = NULL; + + if (ctxcanvas->img_format) + { + ctximage->bitmap = new Bitmap(width, height, ctxcanvas->img_format==24? PixelFormat24bppRGB: PixelFormat32bppARGB); + if (!ctximage->bitmap) + { + delete ctximage; + return NULL; + } + + if (ctxcanvas->img_format==32 && ctxcanvas->img_alpha) + ctximage->alpha = ctxcanvas->img_alpha; + + ctximage->bitmap->SetResolution(ctxcanvas->graphics->GetDpiX(), ctxcanvas->graphics->GetDpiX()); + } + else + { + ctximage->bitmap = new Bitmap(width, height, ctxcanvas->graphics); + if (!ctximage->bitmap) + { + delete ctximage; + return NULL; + } + } + + ctximage->w = width; + ctximage->h = height; + + ctximage->bpp = sFormat2Bpp(ctximage->bitmap->GetPixelFormat()); + ctximage->xres = ctximage->bitmap->GetHorizontalResolution() / 25.4; + ctximage->yres = ctximage->bitmap->GetVerticalResolution() / 25.4; + + ctximage->w_mm = ctximage->w / ctximage->xres; + ctximage->h_mm = ctximage->h / ctximage->yres; + + Graphics imggraphics(ctximage->bitmap); + imggraphics.Clear(Color::White); + + return ctximage; +} + +static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y) +{ + Matrix transformMatrix; + ctxcanvas->graphics->GetTransform(&transformMatrix); + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->ResetTransform(); // reset to the identity. + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + y = _cdInvertYAxis(ctxcanvas->canvas, y); + + int yr = y - (ctximage->h - 1); /* y0 starts at the bottom of the image */ + + if (ctxcanvas->wtype == CDW_BMP) + { + Graphics imggraphics(ctximage->bitmap); + + imggraphics.DrawImage(ctxcanvas->bitmap, + Rect(0, 0, ctximage->w,ctximage->h), + x, yr, ctximage->w, ctximage->h, UnitPixel, + NULL, NULL, NULL); + } + else + { + Graphics imggraphics(ctximage->bitmap); + + HDC hdc = ctxcanvas->graphics->GetHDC(); + HDC img_hdc = imggraphics.GetHDC(); + + BitBlt(img_hdc,0,0,ctximage->w,ctximage->h,hdc,x,yr,SRCCOPY); + + imggraphics.ReleaseHDC(img_hdc); + ctxcanvas->graphics->ReleaseHDC(hdc); + } + + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->SetTransform(&transformMatrix); +} + +static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x0, int y0, int xmin, int xmax, int ymin, int ymax) +{ + int yr = y0 - (ymax-ymin+1)+1; /* y0 starts at the bottom of the image */ + + INT srcx = xmin; + INT srcy = (ctximage->h-1)-ymax; + INT srcwidth = xmax-xmin+1; + INT srcheight = ymax-ymin+1; + Rect destRect(x0, yr, srcwidth, srcheight); + + ImageAttributes imageAttributes; + + if (ctxcanvas->use_img_transp) + imageAttributes.SetColorKey(ctxcanvas->img_transp[0], ctxcanvas->img_transp[1], ColorAdjustTypeBitmap); + + if (ctximage->bpp == 32 && ctximage->alpha) + { + sAlpha2Bitmap(*ctximage->bitmap, ctximage->w, ctximage->h, ctximage->alpha, + 0, ctximage->w-1, 0, ctximage->h-1, 0); + } + + if(ctxcanvas->use_img_points) + { + Point pts[3]; + pts[0] = ctxcanvas->img_points[0]; + pts[1] = ctxcanvas->img_points[1]; + pts[2] = ctxcanvas->img_points[2]; + if (ctxcanvas->canvas->invert_yaxis) + { + pts[0].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].Y); + pts[1].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].Y); + pts[2].Y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].Y); + } + ctxcanvas->graphics->DrawImage(ctximage->bitmap, pts, 3, + srcx, srcy, srcwidth, srcheight, UnitPixel, + &imageAttributes, NULL, NULL); + } + else + { + ctxcanvas->graphics->DrawImage(ctximage->bitmap, destRect, + srcx, srcy, srcwidth, srcheight, UnitPixel, + &imageAttributes, NULL, NULL); + } + + ctxcanvas->dirty = 1; +} + +static void cdkillimage(cdCtxImage *ctximage) +{ + delete ctximage->bitmap; + delete ctximage; +} + +static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + Matrix transformMatrix; + ctxcanvas->graphics->GetTransform(&transformMatrix); + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->ResetTransform(); // reset to the identity. + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + { + dy = -dy; + ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); + ymax = _cdInvertYAxis(ctxcanvas->canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + if (ctxcanvas->wtype == CDW_BMP) + { + Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1); + + Bitmap* bitmap = ctxcanvas->bitmap->Clone(rect, ctxcanvas->bitmap->GetPixelFormat()); + + rect.Offset(dx, dy); + + ctxcanvas->graphics->DrawImage(bitmap, rect, + 0, 0, rect.Width, rect.Height, UnitPixel, + NULL, NULL, NULL); + delete bitmap; + } + else + { + RECT rect; + rect.left = xmin; + rect.right = xmax+1; + rect.top = ymin; + rect.bottom = ymax+1; + + HDC hdc = ctxcanvas->graphics->GetHDC(); + ScrollDC(hdc, dx, dy, &rect, NULL, NULL, NULL); + ctxcanvas->graphics->ReleaseHDC(hdc); + } + + ctxcanvas->dirty = 1; + + if (!transformMatrix.IsIdentity()) + ctxcanvas->graphics->SetTransform(&transformMatrix); +} + +static void cdflush(cdCtxCanvas* ctxcanvas) +{ + ctxcanvas->graphics->Flush(FlushIntentionSync); +} + +/********************************************************************/ +/* +%S Atributos personalizados +*/ +/********************************************************************/ + +static void set_img_format_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + ctxcanvas->img_format = 0; + else + { + int bpp = 0; + sscanf(data, "%d", &bpp); + if (bpp == 0) + return; + + if (bpp == 32) + ctxcanvas->img_format = 32; + else + ctxcanvas->img_format = 24; + } +} + +static char* get_img_format_attrib(cdCtxCanvas* ctxcanvas) +{ + if (!ctxcanvas->img_format) + return NULL; + + if (ctxcanvas->img_format == 32) + return "32"; + else + return "24"; +} + +static cdAttribute img_format_attrib = +{ + "IMAGEFORMAT", + set_img_format_attrib, + get_img_format_attrib +}; + +static void set_img_alpha_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + ctxcanvas->img_alpha = NULL; + else + ctxcanvas->img_alpha = (unsigned char*)data; +} + +static char* get_img_alpha_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->img_alpha; +} + +static cdAttribute img_alpha_attrib = +{ + "IMAGEALPHA", + set_img_alpha_attrib, + get_img_alpha_attrib +}; + +static void set_img_transp_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + ctxcanvas->use_img_transp = 0; + else + { + int r1, g1, b1, r2, g2, b2; + ctxcanvas->use_img_transp = 1; + sscanf(data, "%d %d %d %d %d %d", &r1, &g1, &b1, &r2, &g2, &b2); + ctxcanvas->img_transp[0] = Color((BYTE)r1, (BYTE)g1, (BYTE)b1); + ctxcanvas->img_transp[1] = Color((BYTE)r2, (BYTE)g2, (BYTE)b2); + } +} + + +static char* get_img_transp_attrib(cdCtxCanvas* ctxcanvas) +{ + if (!ctxcanvas->use_img_transp) + return NULL; + + int r1 = ctxcanvas->img_transp[0].GetRed(); + int g1 = ctxcanvas->img_transp[0].GetGreen(); + int b1 = ctxcanvas->img_transp[0].GetBlue(); + int r2 = ctxcanvas->img_transp[1].GetRed(); + int g2 = ctxcanvas->img_transp[1].GetGreen(); + int b2 = ctxcanvas->img_transp[1].GetBlue(); + + static char data[50]; + sprintf(data, "%d %d %d %d %d %d", r1, g1, b1, r2, g2, b2); + return data; +} + +static cdAttribute img_transp_attrib = +{ + "IMAGETRANSP", + set_img_transp_attrib, + get_img_transp_attrib +}; + +static void set_gradientcolor_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + // used by CD_FILLGRADIENT + if (data) + { + int r, g, b, cur_vertex; + sscanf(data, "%d %d %d", &r, &g, &b); + + cur_vertex = ctxcanvas->canvas->poly_n; + if (cur_vertex < 500) + ctxcanvas->pathGradient[cur_vertex] = Color((BYTE)r, (BYTE)g, (BYTE)b); + } +} + +static cdAttribute gradientcolor_attrib = +{ + "GRADIENTCOLOR", + set_gradientcolor_attrib, + NULL +}; + +static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + int x1, y1, x2, y2; + sscanf(data, "%d %d %d %d", &x1, &y1, &x2, &y2); + + Point p1 = Point(x1, y1); + Point p2 = Point(x2, y2); + ctxcanvas->gradient[0] = p1; + ctxcanvas->gradient[1] = p2; + if (ctxcanvas->canvas->invert_yaxis) + { + p1.Y = _cdInvertYAxis(ctxcanvas->canvas, p1.Y); + p2.Y = _cdInvertYAxis(ctxcanvas->canvas, p2.Y); + } + delete ctxcanvas->fillBrush; + ctxcanvas->fillBrush = new LinearGradientBrush(p1, p2, ctxcanvas->fg, ctxcanvas->bg); + } +} + +static char* get_linegradient_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + sprintf(data, "%d %d %d %d", ctxcanvas->gradient[0].X, + ctxcanvas->gradient[0].Y, + ctxcanvas->gradient[1].X, + ctxcanvas->gradient[1].Y); + + return data; +} + +static cdAttribute linegradient_attrib = +{ + "LINEGRADIENT", + set_linegradient_attrib, + get_linegradient_attrib +}; + +static void set_linecap_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + LineCap cap = LineCapFlat; + + switch(data[0]) + { + case 'T': + cap = LineCapTriangle; + ctxcanvas->linePen->SetDashCap(DashCapTriangle); + break; + case 'N': + cap = LineCapNoAnchor; + break; + case 'S': + cap = LineCapSquareAnchor; + break; + case 'R': + cap = LineCapRoundAnchor; + break; + case 'D': + cap = LineCapDiamondAnchor; + break; + case 'A': + cap = LineCapArrowAnchor; + break; + default: + return; + } + + ctxcanvas->linePen->SetStartCap(cap); + ctxcanvas->linePen->SetEndCap(cap); + } +} + +static cdAttribute linecap_attrib = +{ + "LINECAP", + set_linecap_attrib, + NULL +}; + +static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + /* ignore ROTATE if transform is set */ + if (ctxcanvas->canvas->use_matrix) + return; + + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + } + + cdwpUpdateTransform(ctxcanvas); +} + +static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void set_img_points_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + int p[6]; + + if (!data) + { + ctxcanvas->use_img_points = 0; + return; + } + + sscanf(data, "%d %d %d %d %d %d", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]); + + ctxcanvas->img_points[0] = Point(p[0], p[1]); + ctxcanvas->img_points[1] = Point(p[2], p[3]); + ctxcanvas->img_points[2] = Point(p[4], p[5]); + + ctxcanvas->use_img_points = 1; +} + +static char* get_img_points_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->use_img_points) + return NULL; + + sprintf(data, "%d %d %d %d %d %d", ctxcanvas->img_points[0].X, + ctxcanvas->img_points[0].Y, + ctxcanvas->img_points[1].X, + ctxcanvas->img_points[1].Y, + ctxcanvas->img_points[2].X, + ctxcanvas->img_points[2].Y); + + return data; +} + +static cdAttribute img_points_attrib = +{ + "IMAGEPOINTS", + set_img_points_attrib, + get_img_points_attrib +}; + +static BOOL Is_WinXP_or_Later(void) +{ + OSVERSIONINFO osvi; + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx (&osvi); + + BOOL bIsWindowsXPorLater = + (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && + ( (osvi.dwMajorVersion > 5) || ( (osvi.dwMajorVersion == 5) && + (osvi.dwMinorVersion >= 1))); + + return bIsWindowsXPorLater; +} + +static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data || data[0] == '0') + { + ctxcanvas->graphics->SetInterpolationMode(InterpolationModeNearestNeighbor); + ctxcanvas->graphics->SetSmoothingMode(SmoothingModeNone); + ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintSingleBitPerPixelGridFit); + ctxcanvas->antialias = 0; + } + else + { + ctxcanvas->graphics->SetInterpolationMode(InterpolationModeBilinear); + ctxcanvas->graphics->SetSmoothingMode(SmoothingModeAntiAlias); + if (Is_WinXP_or_Later()) + ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintClearTypeGridFit); + else + ctxcanvas->graphics->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit); +/* ctxcanvas->graphics->SetPixelOffsetMode(PixelOffsetModeHalf); + Do NOT set PixelOffsetMode because some graphic objects move their position and size. +*/ + ctxcanvas->antialias = 1; + } +} + +static char* get_aa_attrib(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->antialias) + return "1"; + else + return "0"; +} + +static cdAttribute aa_attrib = +{ + "ANTIALIAS", + set_aa_attrib, + get_aa_attrib +}; + +static void set_window_rgn(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + HRGN hrgn = ctxcanvas->new_region->GetHRGN(ctxcanvas->graphics); + SetWindowRgn(ctxcanvas->hWnd, hrgn, TRUE); + } + else + SetWindowRgn(ctxcanvas->hWnd, NULL, TRUE); +} + +static cdAttribute window_rgn_attrib = +{ + "WINDOWRGN", + set_window_rgn, + NULL +}; + +static char* get_hdc_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->hDC; +} + +static cdAttribute hdc_attrib = +{ + "HDC", + NULL, + get_hdc_attrib +}; + +static char* get_gdiplus_attrib(cdCtxCanvas* ctxcanvas) +{ + (void)ctxcanvas; + return "1"; +} + +static cdAttribute gdiplus_attrib = +{ + "GDI+", + NULL, + get_gdiplus_attrib +}; + +void cdwpUpdateCanvas(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->wtype == CDW_EMF && ctxcanvas->metafile) // first update metafile is NULL. + { + MetafileHeader metaHeader; + ctxcanvas->metafile->GetMetafileHeader(&metaHeader); + ctxcanvas->canvas->xres = metaHeader.GetDpiX() / 25.4; + ctxcanvas->canvas->yres = metaHeader.GetDpiY() / 25.4; + } + else + { + ctxcanvas->canvas->xres = ctxcanvas->graphics->GetDpiX() / 25.4; + ctxcanvas->canvas->yres = ctxcanvas->graphics->GetDpiY() / 25.4; + } + + ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; + ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + + ctxcanvas->graphics->SetPageScale(1); + ctxcanvas->graphics->SetPageUnit(UnitPixel); + ctxcanvas->graphics->SetCompositingMode(CompositingModeSourceOver); + ctxcanvas->graphics->SetCompositingQuality(CompositingQualityDefault); + + if (ctxcanvas->antialias) + set_aa_attrib(ctxcanvas, "1"); + else + set_aa_attrib(ctxcanvas, NULL); + + cdwpUpdateTransform(ctxcanvas); +} + +/* +%F Cria o canvas para o driver Windows. +*/ +cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype) +{ + cdCtxCanvas* ctxcanvas = new cdCtxCanvas; + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + /* update canvas context */ + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + ctxcanvas->wtype = wtype; + ctxcanvas->graphics = graphics; + + ctxcanvas->linePen = new Pen(Color()); + ctxcanvas->lineBrush = new SolidBrush(Color()); + ctxcanvas->fillBrush = new SolidBrush(Color()); + ctxcanvas->font = NULL; // will be created in the update default attrib + + set_aa_attrib(ctxcanvas, "1"); // default is ANTIALIAS=1 + + ctxcanvas->fg = Color(); // black + ctxcanvas->bg = Color(255, 255, 255); // white + + canvas->invert_yaxis = 1; + + ctxcanvas->clip_poly = NULL; + ctxcanvas->clip_poly_n = 0; + ctxcanvas->clip_region = NULL; + ctxcanvas->new_region = NULL; + + cdRegisterAttribute(canvas, &img_points_attrib); + cdRegisterAttribute(canvas, &img_transp_attrib); + cdRegisterAttribute(canvas, &img_format_attrib); + cdRegisterAttribute(canvas, &img_alpha_attrib); + cdRegisterAttribute(canvas, &aa_attrib); + cdRegisterAttribute(canvas, &gradientcolor_attrib); + cdRegisterAttribute(canvas, &linegradient_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + cdRegisterAttribute(canvas, &linecap_attrib); + cdRegisterAttribute(canvas, &hdc_attrib); + cdRegisterAttribute(canvas, &window_rgn_attrib); + cdRegisterAttribute(canvas, &gdiplus_attrib); + + cdwpUpdateCanvas(ctxcanvas); + + return ctxcanvas; +} + +static ULONG_PTR cd_gdiplusToken = NULL; + +static void __stdcall DebugEvent(DebugEventLevel level, char* msg) +{ + (void)level; + MessageBox(NULL, msg, "GDI+ Debug", 0); +} + +void cdwpGdiPlusStartup(int debug) +{ + if (cd_gdiplusToken == NULL) + { + GdiplusStartupInput input; + if (debug) + input.DebugEventCallback = DebugEvent; + + // Initialize GDI+. + GdiplusStartup(&cd_gdiplusToken, &input, NULL); + } +} + +void cdwpGdiPlusShutdown(void) +{ + if (cd_gdiplusToken) + GdiplusShutdown(cd_gdiplusToken); +} + +void cdwpInitTable(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas = canvas->ctxcanvas; + + canvas->cxFlush = cdflush; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + + canvas->cxNewRegion = cdnewregion; + canvas->cxIsPointInRegion = cdispointinregion; + canvas->cxOffsetRegion = cdoffsetregion; + canvas->cxGetRegionBox = cdgetregionbox; + + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxPalette = cdpalette; + canvas->cxTransform = cdtransform; + + if (ctxcanvas->wtype == CDW_WIN || ctxcanvas->wtype == CDW_BMP) + { + canvas->cxClear = cdclear; + + canvas->cxGetImageRGB = cdgetimagergb; + + canvas->cxCreateImage = cdcreateimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxKillImage = cdkillimage; + + canvas->cxScrollArea = cdscrollarea; + } +} diff --git a/cd/src/gdiplus/cdwinp.h b/cd/src/gdiplus/cdwinp.h new file mode 100755 index 0000000..0c4ae55 --- /dev/null +++ b/cd/src/gdiplus/cdwinp.h @@ -0,0 +1,112 @@ +/** \file + * \brief Windows GDI+ Base Driver + * + * See Copyright Notice in cd.h + */ + +#ifndef __CDWINP_H +#define __CDWINP_H + +#include +#include +using namespace Gdiplus; + +#include "cd.h" +#include "cd_private.h" + + +/* Contexto de cada imagem no servidor */ +struct _cdCtxImage +{ + Bitmap *bitmap; /* bitmap associado */ + int w; /* largura da imagem */ + int h; /* altura da imagem */ + double w_mm, h_mm; /* size in mm */ + double xres, yres; /* resolution in pixels/mm */ + int bpp; + unsigned char* alpha; /* the alpha values must be stored here to be used at putimage */ +}; + +/* Contexto de todos os canvas GDI+ (CanvasContext). */ +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + Graphics *graphics; + + Pen *linePen; + SolidBrush *lineBrush; + Brush *fillBrush; + Color fg, bg; /* foreground, backgound */ + Font *font; + + struct + { + int height; + int ascent; + int descent; + } fontinfo; + + Point *clip_poly; /* coordenadas do pixel no X,Y */ + int clip_poly_n; /* numero de pontos correntes */ + Region *clip_region; + + Region *new_region; + + int max_points; + PointF *wdpoly; // cache buffer for wdpoly + Point *cdpoly; // alias to cache buffer (float=int) + + int antialias; + + Point gradient[2]; + + Color pathGradient[500]; + + int img_format; + unsigned char* img_alpha; + + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + Point img_points[3]; + int use_img_points; + + Color img_transp[2]; + int use_img_transp; + + int wtype; /* Flag indicando qual o tipo de superficie */ + + HWND hWnd; /* CDW_WIN handle */ + HDC hDC; /* GDI Device Context handle */ + int release_dc; + + HANDLE printerHandle; // Used by the printer driver + + Metafile* metafile; /* CDW_EMF handle */ + Bitmap* bitmap; /* CDW_BMP handle */ + + int dirty; // Used by the double buffer driver + CachedBitmap* bitmap_dbuffer; /* not the image_dbuffer, just a cache */ + cdCanvas* canvas_dbuffer; +}; + +enum{CDW_WIN, CDW_BMP, CDW_EMF}; + +cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype); +void cdwpKillCanvas(cdCtxCanvas* ctxcanvas); + +void cdwpInitTable(cdCanvas* canvas); +void cdwpUpdateCanvas(cdCtxCanvas* canvas); + +WCHAR* cdwpString2Unicode(const char* s, int len); +void cdwpShowStatus(const char* title, Status status); + +extern "C" { +void cdwpGdiPlusStartup(int debug); +void cdwpGdiPlusShutdown(void); +} + +#endif /* ifndef CDWINP_H */ + diff --git a/cd/src/gdiplus/cdwnativep.cpp b/cd/src/gdiplus/cdwnativep.cpp new file mode 100755 index 0000000..fffd044 --- /dev/null +++ b/cd/src/gdiplus/cdwnativep.cpp @@ -0,0 +1,138 @@ +/** \file + * \brief Windows GDI+ Native Window Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdnative.h" +#include +#include + + +static int cdactivate(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->hWnd) + { + RECT rect; + GetClientRect(ctxcanvas->hWnd, &rect); + int w = rect.right - rect.left; + int h = rect.bottom - rect.top; + int bpp = cdGetScreenColorPlanes(); + + if(ctxcanvas->canvas->w != w || + ctxcanvas->canvas->h != h || + ctxcanvas->canvas->bpp != bpp) + { + ctxcanvas->canvas->w = w; + ctxcanvas->canvas->h = h; + ctxcanvas->canvas->bpp = bpp; + + delete ctxcanvas->graphics; + ctxcanvas->graphics = new Graphics(ctxcanvas->hWnd); + + cdwpUpdateCanvas(ctxcanvas); + } + } + + return CD_OK; +} + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + + if (ctxcanvas->release_dc) + ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); + + delete ctxcanvas; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + HWND hWnd = NULL; + HDC hDC = NULL; + Graphics* graphics; + int release_dc = 0; + + if (!data) + { + hDC = GetDC(NULL); + release_dc = 1; + + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + + graphics = new Graphics(hDC); + } + else if (IsWindow((HWND)data)) + { + hWnd = (HWND)data; + release_dc = 0; + + RECT rect; + GetClientRect(hWnd, &rect); + canvas->w = rect.right - rect.left; + canvas->h = rect.bottom - rect.top; + + graphics = new Graphics(hWnd); + } + else /* can be a HDC or a string */ + { + DWORD objtype = GetObjectType((HGDIOBJ)data); + if (objtype == OBJ_DC || objtype == OBJ_MEMDC || + objtype == OBJ_ENHMETADC || objtype == OBJ_METADC) + { + hDC = (HDC)data; + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + } + else + { + hDC = NULL; + canvas->w = 0; + canvas->h = 0; + sscanf((char*)data,"%p %dx%d", &hDC, &canvas->w, &canvas->h); + + if (!hDC || !canvas->w || !canvas->h) + return; + } + + graphics = new Graphics(hDC); + release_dc = 0; + } + + canvas->bpp = cdGetScreenColorPlanes(); + + /* Inicializa driver WIN32 */ + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_WIN); + ctxcanvas->hWnd = hWnd; + ctxcanvas->hDC = hDC; + ctxcanvas->release_dc = release_dc; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwpInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxActivate = cdactivate; +} + +static cdContext cdNativeContext = +{ + CD_CAP_ALL & ~(CD_CAP_FLUSH | CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES ), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +extern "C" { +cdContext* cdContextNativeWindowPlus(void) +{ + return &cdNativeContext; +} +} diff --git a/cd/src/gdiplus/cdwprnp.cpp b/cd/src/gdiplus/cdwprnp.cpp new file mode 100755 index 0000000..3d2b9f7 --- /dev/null +++ b/cd/src/gdiplus/cdwprnp.cpp @@ -0,0 +1,158 @@ +/** \file + * \brief Windows GDI+ Printer Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdwinp.h" +#include "cdprint.h" +#include +#include +#include + +/* +%F cdKillCanvas para Printer. +Termina a pagina e termina o documento, enviando-o para a impressora. +*/ +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + cdwpKillCanvas(ctxcanvas); + + EndPage(ctxcanvas->hDC); + EndDoc(ctxcanvas->hDC); + + ClosePrinter(ctxcanvas->printerHandle); + DeleteDC(ctxcanvas->hDC); + + delete ctxcanvas; +} + +/* +%F cdFlush para Printer. +Termina uma pagina e inicia outra. +*/ +static void cdflush(cdCtxCanvas* ctxcanvas) +{ + delete ctxcanvas->graphics; + EndPage(ctxcanvas->hDC); + + StartPage(ctxcanvas->hDC); + ctxcanvas->graphics = new Graphics(ctxcanvas->hDC, ctxcanvas->printerHandle); + + cdwpUpdateCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char *data_str = (char*) data; + char docname[256] = "CD - Canvas Draw Document"; + int dialog = 0; + + /* Inicializa parametros */ + if (data_str == NULL) + return; + + if (data_str[0] != 0) + { + const char *ptr = strstr(data_str, "-d"); + + if (ptr != NULL) + dialog = 1; + + if (data_str[0] != '-') + { + strcpy(docname, data_str); + + if (dialog) + docname[ptr - data_str - 1] = 0; + } + } + + PRINTDLG pd; + ZeroMemory(&pd, sizeof(PRINTDLG)); + pd.lStructSize = sizeof(PRINTDLG); + pd.nCopies = 1; + + if (dialog) + { + pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | PD_COLLATE | PD_NOPAGENUMS | PD_NOSELECTION; + pd.hwndOwner = GetForegroundWindow(); + } + else + { + pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT; + } + + if (!PrintDlg(&pd)) + { + if(pd.hDevMode) + GlobalFree(pd.hDevMode); + if(pd.hDevNames) + GlobalFree(pd.hDevNames); + return; + } + + HDC hDC = pd.hDC; + + DEVMODE* devideMode = (DEVMODE*)GlobalLock(pd.hDevMode); + HANDLE printerHandle; + OpenPrinter((char*)devideMode->dmDeviceName, &printerHandle, NULL); + GlobalUnlock(pd.hDevMode); + + { + /* Inicializa documento */ + DOCINFO docInfo; + ZeroMemory(&docInfo, sizeof(docInfo)); + docInfo.cbSize = sizeof(docInfo); + docInfo.lpszDocName = docname; + + StartDoc(hDC, &docInfo); + } + + StartPage(hDC); + + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + canvas->bpp = GetDeviceCaps(hDC, BITSPIXEL); + + Graphics* graphics = new Graphics(hDC, printerHandle); + + /* Inicializa driver WIN32 */ + cdCtxCanvas* ctxcanvas = cdwpCreateCanvas(canvas, graphics, CDW_EMF); + + ctxcanvas->hDC = hDC; + ctxcanvas->printerHandle = printerHandle; + + if(pd.hDevMode) + GlobalFree(pd.hDevMode); + if(pd.hDevNames) + GlobalFree(pd.hDevNames); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwpInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxFlush = cdflush; +} + +static cdContext cdPrinterContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES | + CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +extern "C" { +cdContext* cdContextPrinterPlus(void) +{ + return &cdPrinterContext; +} +} + diff --git a/cd/src/intcgm/bparse.c b/cd/src/intcgm/bparse.c new file mode 100755 index 0000000..c0ffada --- /dev/null +++ b/cd/src/intcgm/bparse.c @@ -0,0 +1,1660 @@ +#include /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */ +#include /* strlen, strncpy */ +#include /* malloc, free */ +#include "cd.h" +#include "cdcgm.h" +#include "list.h" +#include "types.h" +#include "bparse.h" +#include "intcgm.h" +#include "intcgm2.h" +#include "intcgm4.h" +#include "intcgm6.h" + +/********************* +* Delimiter elements * +*********************/ + +int cgmb_noop ( void ) +{ + return 0; +} + +int cgmb_begmtf ( void ) +{ + char *header = NULL; + + if ( intcgm_cgm.len ) + { + if ( cgmb_s ( &header ) ) return 1; + } + + if (cdcgmbegmtfcb) + { + int err; + err = cdcgmbegmtfcb ( intcgm_canvas, &intcgm_view_xmin, &intcgm_view_ymin, &intcgm_view_xmax, &intcgm_view_ymax ); + if ( err==CD_ABORT ) return -1; + } + + return 0; +} + +int cgmb_endmtf ( void ) +{ + return 0; +} + +int cgmb_begpic ( void ) +{ + char *s = NULL; + + if ( intcgm_cgm.first ) + intcgm_cgm.first = 0; + else + cdCanvasFlush(intcgm_canvas); + + if ( intcgm_color_table==NULL ) + { + if ( intcgm_cgm.max_cix < 1 ) intcgm_cgm.max_cix = 1; + + intcgm_color_table = (trgb *) malloc ( sizeof(trgb)*(intcgm_cgm.max_cix+1) ); + + intcgm_color_table[0].red = 255; + intcgm_color_table[0].green = 255; + intcgm_color_table[0].blue = 255; + intcgm_color_table[1].red = 0; + intcgm_color_table[1].green = 0; + intcgm_color_table[1].blue = 0; + } + + cdCanvasClip(intcgm_canvas, CD_CLIPAREA); + + if ( cgmb_s ( &s ) ) return 1; + + if (cdcgmbegpictcb) + { + int err; + err = cdcgmbegpictcb ( intcgm_canvas, s ); + if ( err==CD_ABORT ) return -1; + } + + return 0; +} + +int cgmb_begpib ( void ) +{ + if (cdcgmbegpictbcb) + { + int err; + err = cdcgmbegpictbcb ( intcgm_canvas, 1., 1., intcgm_scale_factor_x, intcgm_scale_factor_y, + intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor, + intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor, + intcgm_cgm.drawing_mode, + intcgm_vdc_ext.xmin, intcgm_vdc_ext.ymin, intcgm_vdc_ext.xmax, intcgm_vdc_ext.ymax ); + + if ( err==CD_ABORT ) return -1; + } + + if (cdcgmsizecb) + { + int err, w, h; + double w_mm=0., h_mm=0.; + + w = intcgm_view_xmax-intcgm_view_xmin+1; + h = intcgm_view_ymax-intcgm_view_ymin+1; + + if ( intcgm_cgm.vdc_type==INTEGER ) + { + w = (int) (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x); + h = (int) (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y); + if ( intcgm_cgm.scaling_mode.mode==METRIC ) + { + w_mm = w * intcgm_cgm.scaling_mode.scale_factor; + h_mm = h * intcgm_cgm.scaling_mode.scale_factor; + } + } + else + { + if ( intcgm_cgm.scaling_mode.mode==METRIC ) + { + w_mm = (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x) * intcgm_cgm.scaling_mode.scale_factor; + h_mm = (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y) * intcgm_cgm.scaling_mode.scale_factor; + } + } + + err = cdcgmsizecb ( intcgm_canvas, w, h, w_mm, h_mm ); + if ( err==CD_ABORT ) return -1; + } + + return 0; +} + +int cgmb_endpic ( void ) +{ + return 0; +} + +/******************************* +* Metafile Descriptor Elements * +*******************************/ + +int cgmb_mtfver ( void ) +{ + long version; + + if ( cgmb_i ( &version ) ) return 1; + + return 0; +} + +int cgmb_mtfdsc ( void ) +{ + char *s = NULL; + + if ( cgmb_s ( &s ) ) return 1; + + return 0; +} + +int cgmb_vdctyp ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.vdc_type) ) ) return 1; + + return 0; +} + +int cgmb_intpre ( void ) +{ + long prec; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( prec==8 ) intcgm_cgm.int_prec.b_prec = 0; + else if ( prec==16 ) intcgm_cgm.int_prec.b_prec = 1; + else if ( prec==24 ) intcgm_cgm.int_prec.b_prec = 2; + else if ( prec==32 ) intcgm_cgm.int_prec.b_prec = 3; + + return 0; +} + +int cgmb_realpr ( void ) +{ + short mode = 0, i1; + long i2, i3; + + if ( cgmb_e ( &i1 ) ) return 1; + if ( cgmb_i ( &i2 ) ) return 1; + if ( cgmb_i ( &i3 ) ) return 1; + + if ( i1 == 0 && i2 == 9 && i3 == 23 ) mode = 0; + else if ( i1 == 0 && i2 == 12 && i3 == 52 ) mode = 1; + else if ( i1 == 1 && i2 == 16 && i3 == 16 ) mode = 2; + else if ( i1 == 1 && i2 == 32 && i3 == 32 ) mode = 3; + + intcgm_cgm.real_prec.b_prec = mode; + + return 0; +} + +int cgmb_indpre ( void ) +{ + long prec; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( prec==8 ) intcgm_cgm.ix_prec.b_prec = 0; + else if ( prec==16 ) intcgm_cgm.ix_prec.b_prec = 1; + else if ( prec==24 ) intcgm_cgm.ix_prec.b_prec = 2; + else if ( prec==32 ) intcgm_cgm.ix_prec.b_prec = 3; + + return 0; +} + +int cgmb_colpre ( void ) +{ + long prec; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( prec==8 ) intcgm_cgm.cd_prec = 0; + else if ( prec==16 ) intcgm_cgm.cd_prec = 1; + else if ( prec==24 ) intcgm_cgm.cd_prec = 2; + else if ( prec==32 ) intcgm_cgm.cd_prec = 3; + + return 0; +} + +int cgmb_colipr ( void ) +{ + long prec; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( prec==8 ) intcgm_cgm.cix_prec = 0; + else if ( prec==16 ) intcgm_cgm.cix_prec = 1; + else if ( prec==24 ) intcgm_cgm.cix_prec = 2; + else if ( prec==32 ) intcgm_cgm.cix_prec = 3; + + return 0; +} + +int cgmb_maxcoi ( void ) +{ + if ( cgmb_ci ( (unsigned long *)&(intcgm_cgm.max_cix) ) ) return 1; + + intcgm_color_table = (trgb *) realloc ( intcgm_color_table, sizeof(trgb)*(intcgm_cgm.max_cix+1) ); + + intcgm_color_table[0].red = 255; + intcgm_color_table[0].green = 255; + intcgm_color_table[0].blue = 255; + intcgm_color_table[1].red = 0; + intcgm_color_table[1].green = 0; + intcgm_color_table[1].blue = 0; + + return 0; +} + +int cgmb_covaex ( void ) +{ + if ( cgmb_rgb ( &(intcgm_cgm.color_ext.black.red), &(intcgm_cgm.color_ext.black.green), &(intcgm_cgm.color_ext.black.blue) ) ) return 1; + if ( cgmb_rgb ( &(intcgm_cgm.color_ext.white.red), &(intcgm_cgm.color_ext.white.green), &(intcgm_cgm.color_ext.white.blue) ) ) return 1; + + return 0; +} + +int cgmb_mtfell ( void ) +{ + long group, element; + long n, i; + + if ( cgmb_i ( &n ) ) return 1; + + for ( i=0; i> 5; + + c = ( b & 0xF000 ) >> 12; + + cont = 0; + + if ( len > 30 ) + { + b = ((unsigned char)buff[count] << 8) | (unsigned char)buff[count+1]; + count += 2; + + intcgm_cgm.bl += 2; + + len = b & 0x7FFF; + cont = ( b & 0x8000 ); + } + + intcgm_cgm.len = len; + + if ( intcgm_cgm.len ) + { + if ( intcgm_cgm.len>intcgm_cgm.buff.size ) + intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len ); + + memcpy ( intcgm_cgm.buff.dados, &buff[count], intcgm_cgm.len ); + count += intcgm_cgm.len; + + intcgm_cgm.bl += intcgm_cgm.len; + + if ( len & 1 ) + { + count++; + intcgm_cgm.bl += 1; + } + + while ( cont ) + { + unsigned short b; + int old_len = intcgm_cgm.len; + + intcgm_cgm.bl += 2; + + b = ((unsigned char)buff[count] << 8) | (unsigned char)buff[count+1]; + count += 2; + + cont = ( b & 0x8000 ); + + len = b & 0x7fff; + + intcgm_cgm.len += len; + + if ( intcgm_cgm.len>intcgm_cgm.buff.size ) + intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len ); + + memcpy ( &intcgm_cgm.buff.dados[old_len], &buff[count], len ); + count += len; + + if ( len & 1 ) + { + count++; + + intcgm_cgm.bl += 1; + } + } + } + + if ( cgmb_exec_comand ( c, id ) ) return 1; + totbc += count; + /*count=0;*/ + } + + return 0; +} + +int cgmb_fntlst ( void ) +{ + char *fl = NULL; + + if ( intcgm_text_att.font_list==NULL ) intcgm_text_att.font_list = cgm_NewList(); + + while ( intcgm_cgm.bc < intcgm_cgm.len ) + { + if ( cgmb_s ( &fl ) ) return 1; + + cgm_AppendList ( intcgm_text_att.font_list, fl ); + } + + return 0; +} + +int cgmb_chslst ( void ) +{ + short mode; + char *s = NULL; + + while ( intcgm_cgm.bc < intcgm_cgm.len ) + { + if ( cgmb_e ( &mode ) ) return 1; + if ( cgmb_s ( &s ) ) return 1; + } + + return 0; +} + +int cgmb_chcdac ( void ) +{ + short mode; + + if ( cgmb_e ( &mode ) ) return 1; + + return 0; +} + + +/****************************** +* Picture Descriptor Elements * +******************************/ + +int cgmb_sclmde ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.scaling_mode.mode) ) ) return 1; + if ( intcgm_cgm.real_prec.b_prec==1 ) + { + if ( cgmb_getfl64 ( &(intcgm_cgm.scaling_mode.scale_factor) ) ) return 1; + } + else + { + float f; + if ( cgmb_getfl32 ( (float *) &f ) ) return 1; + if ( f<1e-20 ) f = 1; + intcgm_cgm.scaling_mode.scale_factor = f; + } + + if ( intcgm_cgm.scaling_mode.mode==ABSTRACT ) intcgm_cgm.scaling_mode.scale_factor=1.; + + intcgm_cgm.drawing_mode = ABSTRACT; + + if (cdcgmsclmdecb) + { + int err; + err = cdcgmsclmdecb ( intcgm_canvas, intcgm_cgm.scaling_mode.mode, &intcgm_cgm.drawing_mode, &intcgm_cgm.scaling_mode.scale_factor ); + if ( err==CD_ABORT ) return -1; + } + + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + { + intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin ); + intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax ); + intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin ); + intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax ); + } + else + { + intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor; + } + + return 0; +} + +int cgmb_clslmd ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.clrsm) ) ) return 1; + + return 0; +} + +int cgmb_lnwdmd ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.lnwsm) ) ) return 1; + + return 0; +} + +int cgmb_mkszmd ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.mkssm) ) ) return 1; + + return 0; +} + +int cgmb_edwdmd ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.edwsm) ) ) return 1; + + return 0; +} + +int cgmb_vdcext ( void ) +{ + if ( cgmb_p ( &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y) ) ) return 1; + if ( cgmb_p ( &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ) ) return 1; + + if (cdcgmvdcextcb) + { + int err; + err = cdcgmvdcextcb( intcgm_canvas, intcgm_cgm.vdc_type, &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y), + &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ); + if (err==CD_ABORT) return -1; + } + + cgm_do_vdcext ( intcgm_cgm.vdc_ext.first, intcgm_cgm.vdc_ext.second ); + + return 0; +} + +int cgmb_bckcol ( void ) +{ + if ( cgmb_rgb ( &(intcgm_cgm.back_color.red), &(intcgm_cgm.back_color.green), &(intcgm_cgm.back_color.blue) ) ) return 1; + + cgm_do_bckcol ( intcgm_cgm.back_color ); + + return 0; +} + +/******************* +* Control Elements * +*******************/ + +int cgmb_vdcipr ( void ) +{ + long prec; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( prec==8 ) intcgm_cgm.vdc_int.b_prec = 0; + else if ( prec==16 ) intcgm_cgm.vdc_int.b_prec = 1; + else if ( prec==24 ) intcgm_cgm.vdc_int.b_prec = 2; + else if ( prec==32 ) intcgm_cgm.vdc_int.b_prec = 3; + + return 0; +} + +int cgmb_vdcrpr ( void ) +{ + short i1; + long mode = 0, i2, i3; + + if ( cgmb_e ( &i1 ) ) return 1; + if ( cgmb_i ( &i2 ) ) return 1; + if ( cgmb_i ( &i3 ) ) return 1 ; + + if ( i1 == 0 && i2 == 9 && i3 == 23 ) mode = 0; + else if ( i1 == 0 && i2 == 12 && i3 == 52 ) mode = 1; + else if ( i1 == 1 && i2 == 16 && i3 == 16 ) mode = 2; + else if ( i1 == 1 && i2 == 32 && i3 == 32 ) mode = 3; + + intcgm_cgm.vdc_real.b_prec = mode; + + return 0; +} + +int cgmb_auxcol ( void ) +{ + if ( cgmb_co ( &(intcgm_cgm.aux_color) ) ) return 1; + + return 0; +} + +int cgmb_transp ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.transparency) ) ) return 1; + + cgm_do_transp ( intcgm_cgm.transparency ); + + return 0; +} + +int cgmb_clprec ( void ) +{ + if ( cgmb_p ( &(intcgm_cgm.clip_rect.first.x), &(intcgm_cgm.clip_rect.first.y) ) ) return 1; + if ( cgmb_p ( &(intcgm_cgm.clip_rect.second.x), &(intcgm_cgm.clip_rect.second.y) ) ) return 1; + + cgm_do_clprec ( intcgm_cgm.clip_rect.first, intcgm_cgm.clip_rect.second ); + + return 0; +} + +int cgmb_clpind ( void ) +{ + if ( cgmb_e ( &(intcgm_cgm.clip_ind) ) ) return 1; + + cgm_do_clpind ( intcgm_cgm.clip_ind ); + + return 0; +} + +/******************************* +* Graphical Primitive Elements * +*******************************/ + +static tpoint *_intcgm_point_list ( int *np ) +{ + *np=0; + + while ( intcgm_cgm.bc < intcgm_cgm.len ) + { + if ( cgmb_p ( &(intcgm_point_list[*np].x), &(intcgm_point_list[*np].y) ) ) return NULL; + ++(*np); + if ( *np==intcgm_npoints) + { + intcgm_npoints *= 2; + intcgm_point_list = (tpoint *) realloc ( intcgm_point_list, intcgm_npoints*sizeof(tpoint) ); + } + } + + return intcgm_point_list; +} + +int cgmb_polyln ( void ) +{ + tpoint *pts; + int np; + + pts = _intcgm_point_list ( &np ); + if ( pts==NULL ) return 1; + + cgm_do_polyln ( np, pts ); + + return 0; +} + +int cgmb_djtply ( void ) +{ + tpoint *pts; + int np; + + pts = _intcgm_point_list ( &np ); + if ( pts==NULL ) return 1; + + cgm_do_djtply ( np, pts ); + + return 0; +} + +int cgmb_polymk ( void ) +{ + tpoint *pts; + int np; + + pts = _intcgm_point_list ( &np ); + if ( pts==NULL ) return 1; + + cgm_do_polymk ( np, pts ); + + return 0; +} + +int cgmb_text ( void ) +{ + tpoint pos; + char *s = NULL; + short t; + + if ( cgmb_p ( &pos.x, &pos.y ) ) return 1; + if ( cgmb_e ( &t ) ) return 1; + if ( cgmb_s ( &s ) ) return 1; + + cgm_do_text ( NORM_TEXT, s, pos ); + + free ( s ); + + return 0; +} + +int cgmb_rsttxt ( void ) +{ + double height, width; + tpoint pos; + char *s = NULL; + short t; + + if ( cgmb_vdc ( &width ) ) return 1; + if ( cgmb_vdc ( &height ) ) return 1; + if ( cgmb_p ( &pos.x, &pos.y ) ) return 1; + if ( cgmb_e ( &t ) ) return 1; + if ( cgmb_s ( &s ) ) return 1; + + intcgm_text_att.height = height; + + cgm_do_text ( RESTRICTED_TEXT, s, pos ); + + if ( s!= NULL ) free ( s ); + + return 0; +} + +int cgmb_apdtxt ( void ) +{ + char *s = NULL; + short t; + + if ( cgmb_e ( &t ) ) return 1; + if ( cgmb_s ( &s ) ) return 1; + + if ( s==NULL ) free ( s ); + + return 0; +} + +int cgmb_polygn ( void ) +{ + tpoint *pts; + int np; + static int porra=0; + + porra++; + + pts = _intcgm_point_list ( &np ); + if ( pts==NULL ) return 1; + + cgm_do_polygn ( np, pts ); + + return 0; +} + +static int _intcgm_vertex_list ( tpoint **pts, short **flags, int *np ) +{ + int intcgm_block=500; + + *np=0; + *pts = (tpoint *) malloc ( intcgm_block*sizeof(tpoint) ); + *flags = (short *) malloc ( intcgm_block*sizeof(short) ); + + while ( intcgm_cgm.bc < intcgm_cgm.len ) + { + if ( cgmb_p ( &((*pts)[*np].x), &((*pts)[*np].y) ) ) return 1; + if ( cgmb_e ( &((*flags)[*np]) ) ) return 1; + + ++(*np); + if ( *np==intcgm_block) + { + intcgm_block *= 2; + *pts = (tpoint *) realloc ( *pts, intcgm_block*sizeof(tpoint) ); + *flags = (short *) realloc ( *flags, intcgm_block*sizeof(short) ); + } + } + + return 0; +} + +int cgmb_plgset ( void ) +{ + tpoint *pts; + short *flags; + int np; + + if ( _intcgm_vertex_list ( &pts, &flags, &np ) ) return 1; + + cgm_do_plgset( NO, np, pts, flags ); + + free ( pts ); + free ( flags ); + + return 0; +} + +int cgmb_cellar ( void ) +{ + register int i, j, k; + long prec; + long sx, sy; + short mode; + int b; + unsigned char dummy; + tpoint corner1, corner2, corner3; + tcolor *cell; + + if ( cgmb_p ( &(corner1.x), &(corner1.y) ) ) return 1; + if ( cgmb_p ( &(corner2.x), &(corner2.y) ) ) return 1; + if ( cgmb_p ( &(corner3.x), &(corner3.y) ) ) return 1; + + if ( cgmb_i ( &sx ) ) return 1; + if ( cgmb_i ( &sy ) ) return 1; + + if ( cgmb_i ( &prec ) ) return 1; + + if ( cgmb_e ( &mode ) ) return 1; + + cell = (tcolor *) malloc ( sx*sy*sizeof(tcolor) ); + + if ( mode ) + for ( k=0; k *intcgm_block) + { + *intcgm_block *= 2; + *sout = (char *) realloc(*sout,sizeof(char)*(*intcgm_block)); + if ( *sout==NULL ) return 1; + } + + strcat(*sout,sin); + strcat(*sout," "); + + return 0; +} + +int intcgm_generalized_drawing_primitive_4 ( void ) +{ + long j, i; + tpoint pt[4]; + unsigned char c; + double r; + char *s=NULL, tmp[80]; + int intcgm_block = 500, slen = 0; + int id = -4; + + s = (char *) malloc ( intcgm_block*sizeof(char) ); + + strcpy ( s, "" ); + + for ( j=0; j<4; j++ ) + { + if ( cgmb_p ( &(pt[j].x), &(pt[j].y) ) ) return 1; + } + + if ( cgmb_getc(&c) ) return 1; + if ( cgmb_getc(&c) ) return 1; + + for ( j=0; j<6; j++ ) + { + if ( cgmb_r(&r) ) return 1; + sprintf(tmp,"%g",r); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + } + + if ( cgmb_i(&i) ) return 1; + sprintf(tmp,"%ld",i); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + + if ( cgmb_i(&sample_type) ) return 1; + sprintf(tmp,"%ld",sample_type); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + + if ( cgmb_i(&n_samples) ) return 1; + sprintf(tmp,"%ld",n_samples); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + + for ( j=0; j<2; j++ ) + { + if ( cgmb_r(&r) ) return 1; + sprintf(tmp,"%g",r); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + } + + for ( j=0; j<4; j++ ) + { + if ( cgmb_i(&i) ) return 1; + sprintf(tmp,"%ld",i); + if ( BuildString ( tmp, &s, &slen, &intcgm_block ) ) return 1; + } + + cgm_do_gdp ( id, pt, s ); + + free(s); + + return 0; +} + +typedef int (*_getdata) (void *); + +int intcgm_generalized_drawing_primitive_5 ( void ) +{ + int (*getdata) (void *); + void *data; + char format[10]; + int i; + char *s, tmp[80]; + int intcgm_block = 500, slen = 0; + long id=-5; + + s = (char *) malloc ( sizeof(char)*intcgm_block ); + + strcpy ( s, "" ); + + switch ( sample_type ) + { + case 0: + getdata = (_getdata) cgmb_geti16; + data = (short *) malloc ( sizeof(short) ); + if ( data==NULL ) return 1; + strcpy ( format, "%d\0" ); + break; + case 1: + getdata = (_getdata) cgmb_geti32; + data = (long *) malloc ( sizeof(long) ); + if ( data==NULL ) return 1; + strcpy ( format, "%d\0" ); + break; + case 2: + getdata = (_getdata) cgmb_getfl32; + data = (float *) malloc ( sizeof(float) ); + if ( data==NULL ) return 1; + strcpy ( format, "%g\0" ); + break; + case 3: + getdata = (_getdata) cgmb_geti8; + data = (signed char *) malloc ( sizeof(signed char) ); + if ( data==NULL ) return 1; + strcpy ( format, "%d\0" ); + break; + case 4: + getdata = (_getdata) cgmb_geti16; + data = (short *) malloc ( sizeof(short) ); + if ( data==NULL ) return 1; + strcpy ( format, "%d\0" ); + break; + case 5: + getdata = (_getdata) cgmb_geti8; + data = (signed char *) malloc ( sizeof(signed char) ); + if ( data==NULL ) return 1; + strcpy ( format, "%d\0" ); + break; + } + + for ( i=0; iindex) ) ) return 1; + + if ( cgmb_i ( &(pat->nx) ) ) return 1; + if ( cgmb_i ( &(pat->ny) ) ) return 1; + + if ( cgmb_i ( &(localp) ) ) return 1; + + pat->pattern = (tcolor *) malloc ( pat->nx*pat->ny*sizeof(tcolor) ); + + for ( i=0; i<(pat->nx*pat->ny); i++ ) + { + if ( cgmb_getpixel ( &(pat->pattern[i]), localp ) ) return 1; + } + + cgm_AppendList ( intcgm_fill_att.pat_list, pat ); + + return 0; +} + +int cgmb_patsiz ( void ) +{ + if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.height.x) ) ) return 1; + if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.height.y) ) ) return 1; + if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.width.x) ) ) return 1; + if ( cgmb_vdc ( &(intcgm_fill_att.pat_size.width.y) ) ) return 1; + + return 0; +} + +int cgmb_coltab ( void ) +{ + unsigned long starting_index, i; + int p[] = {8, 16, 24, 32}; + int n = (intcgm_cgm.len-intcgm_cgm.cix_prec)/(3*(p[intcgm_cgm.cd_prec]/8)); + + if ( cgmb_ci ( &(starting_index) ) ) return 1; + + for ( i=starting_index; itype) ) ) return 1; + if ( cgmb_e ( &(pair->value) ) ) return 1; + + cgm_AppendList ( intcgm_asf_list, pair ); + } + + return 0; +} + +/***************** +* Escape Element * +*****************/ + +/******************** +* External elements * +********************/ + +int cgmb_escape ( void ) /* escape */ +{ +#if 1 + + { + int i; + unsigned char c; + for ( i=0; i +#include + +#include + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm6.h" + +#include "circle.h" + +#define DIM 360 + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#define PI180 PI/180. +#define TWOPI 2*PI +#define VARCS TWOPI/32. + +int cgm_poly_circle ( double xc, double yc, double radius, double angi, double angf, int fechado ) +{ + double coseno, seno; + double xs, ys; + + coseno = cos (VARCS); + seno = sin (VARCS); + + xs = radius * cos(angi); + ys = radius * sin(angi); + + cdCanvasBegin(intcgm_canvas, cgm_setintstyle(intcgm_fill_att.int_style) ); + + if ( fechado==CLOSED_PIE ) cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) ); + + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) ); + + while ( (angi+VARCS) < angf ) + { + double xe = xs; + xs = xs * coseno - ys * seno; + ys = ys * coseno + xe * seno; + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) ); + angi += VARCS; + } + + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc+radius*cos(angf)), cgm_vdcy2canvas(yc+radius*sin(angf)) ); + + cdCanvasEnd(intcgm_canvas); + + return 0; +} + +int cgm_line_circle ( double xc, double yc, double radius, double angi, double angf, int fechado ) +{ + double coseno, seno; + double xant, yant, firstx, firsty; + double xs, ys; + + /* GERA O DESENHO DO CIRCULO/ARCO */ + + coseno = cos (VARCS); + seno = sin (VARCS); + + xs = radius * cos(angi); + ys = radius * sin(angi); + + if ( fechado==CLOSED_PIE ) + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc), cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) ); + + xant = firstx = xc+xs; + yant = firsty = yc+ys; + + while ( (angi+VARCS) < angf ) + { + double xe = xs; + xs = xs * coseno - ys * seno; + ys = ys * coseno + xe * seno; + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(xc+xs), cgm_vdcy2canvas(yc+ys) ); + xant = xc+xs; + yant = yc+ys; + angi += VARCS; + } + + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), + cgm_vdcx2canvas(xc+radius*cos(angf)), cgm_vdcy2canvas(yc+radius*sin(angf)) ); + + xant = xc+radius*cos(angf); + yant = yc+radius*sin(angf); + + if ( fechado==CLOSED_PIE ) + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) ); + else if ( fechado==CLOSED_CHORD ) + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(xant), cgm_vdcy2canvas(yant), cgm_vdcx2canvas(firstx), cgm_vdcy2canvas(firsty) ); + + return 0; +} + diff --git a/cd/src/intcgm/circle.h b/cd/src/intcgm/circle.h new file mode 100755 index 0000000..3209c0f --- /dev/null +++ b/cd/src/intcgm/circle.h @@ -0,0 +1,3 @@ +int cgm_poly_circle ( double xc, double yc, double radius, double angi, double angf, int fechado ); +int cgm_line_circle ( double xc, double yc, double radius, double angi, double angf, int fechado ); + diff --git a/cd/src/intcgm/ellipse.c b/cd/src/intcgm/ellipse.c new file mode 100755 index 0000000..8d6889c --- /dev/null +++ b/cd/src/intcgm/ellipse.c @@ -0,0 +1,143 @@ +#include +#include + +#include + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm6.h" +#include "ellipse.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +#define ANGMIN 0.00001 + +/* Adjust the circle parametrization for the elipsis parametrization */ +double cgm_AdjArc ( double arc, double w, double h ) +{ + double value; + + if ((fabs(w*sin(arc))<1e-99) && (fabs(h*cos(arc))<1e-99)) + value = 0.0; + else + value = atan2(w*sin(arc), h*cos(arc)); + + if ( arc > PI ) value += 2*PI; + if ( arc < -PI ) value -= 2*PI; + + return value; +} + + +/* Desenha um arco de Elipse */ + +void cgm_ElpArc ( double xc, double yc, double w, double h, double r, double a1, + double a2, int n, int tipo ) + +{ + + /* Onde: + + (xc,yc) Centro + (w,h) Largura e altura (diametro na direcao dos eixos principais) + r Inclinacao dos eixos principais com relacao x e y + a1,a2 Angulos incial e final do arco [-360,+360] + Note-se que o sentido e' dado pela diferenca a2-a1, + ou seja, 30 a 330 e' trigonometrico + 30 a -30 e' horario + n Numero de segmentos da poligonal equivalente + (64 parece ser um bom numero) + tipo 0=aberto 1=fechado(torta) 2=fechado(corda) */ + + double da, c, s, sx, sy, ang, xant, yant; + double px, py, tx, ty, txant, tyant, dx, dy; + int i, inicio; + +/* Reduz de diametro a raio */ + + w = w/2; + h = h/2; + +/* Transforma graus em radianos e ajusta a os angulos da parametrizacao */ + + a1 = cgm_AdjArc(a1,w,h); + + a2 = cgm_AdjArc(a2,w,h); + + if ( a2>a1 ) + ang = a2 - a1; + else + ang = 2*PI - ( a1 - a2 ); + +/* Gera os pontos do arco centrado na origem com os eixos em x e y */ + + da = ang/n; + c = cos(da); + s = sin(da); + sx = -w*s/h; + sy = h*s/w; + + if ( tipo==1 || tipo==2 ) + { + long int cor; + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + cdCanvasBegin(intcgm_canvas, cgm_setintstyle(intcgm_fill_att.int_style) ); + } + else + { + long int cor; + int size = (int)floor(intcgm_line_att.width+.5); + cdCanvasLineStyle (intcgm_canvas, intcgm_line_att.type ); + cdCanvasLineWidth (intcgm_canvas, size>0? size: 1 ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + } + + dx = (fabs(r)>ANGMIN) ? sin(r) : 0; + dy = (fabs(r)>ANGMIN) ? cos(r) : 1; + + xant = w*cos(a1); + yant = h*sin(a1); + + txant = xc+dy*xant-dx*yant; /* Inclina (se for o caso) e translada */ + tyant = yc+dx*xant+dy*yant; /* Inclina (se for o caso) e translada */ + + if ( tipo==1 ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(xc), cgm_vdcy2canvas(yc) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) ); + inicio = 2; + } + else if ( tipo==2 ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant) ); + inicio = 1; + } + + for ( i=inicio; i<=(n+inicio-1); i++ ) + { + px = c*xant+sx*yant; + py = sy*xant+c*yant; + + tx = xc+dy*px-dx*py; /* Inclina (se for o caso) e translada */ + ty = yc+dx*px+dy*py; /* Inclina (se for o caso) e translada */ + + if ( tipo==0 ) + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(txant), cgm_vdcy2canvas(tyant), cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) ); + else + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(tx), cgm_vdcy2canvas(ty) ); + + xant = px; + yant = py; + txant = tx; + tyant = ty; + } + +/* Desenha */ + + if ( tipo==1 || tipo==2 ) cdCanvasEnd(intcgm_canvas); +} diff --git a/cd/src/intcgm/ellipse.h b/cd/src/intcgm/ellipse.h new file mode 100755 index 0000000..80980ff --- /dev/null +++ b/cd/src/intcgm/ellipse.h @@ -0,0 +1,3 @@ +void cgm_ElpArc ( double, double, double, double, double, double, double, int, int ); +double cgm_AdjArc ( double arc, double w, double h ); + diff --git a/cd/src/intcgm/intcgm.h b/cd/src/intcgm/intcgm.h new file mode 100755 index 0000000..c106ee0 --- /dev/null +++ b/cd/src/intcgm/intcgm.h @@ -0,0 +1,84 @@ +typedef int (*CGM_FUNC) (void); + +#ifdef _INTCGM1_C_ + +t_cgm intcgm_cgm; +cdCanvas* intcgm_canvas = NULL; + +tlimit intcgm_vdc_ext; +double intcgm_scale_factor_x; +double intcgm_scale_factor_y; +double intcgm_scale_factor_mm_x; +double intcgm_scale_factor_mm_y; +double intcgm_scale_factor; +int intcgm_view_xmin, intcgm_view_ymin, intcgm_view_xmax, intcgm_view_ymax; +double intcgm_clip_xmin, intcgm_clip_ymin, intcgm_clip_xmax, intcgm_clip_ymax; + +_line_att intcgm_line_att = { 1, LINE_SOLID, 1., {1} }; + +_marker_att intcgm_marker_att = { 3, MARK_ASTERISK, 1., {1} }; + +_text_att intcgm_text_att = { 1, 1, NULL, 0, CD_PLAIN, 8, STRING, 1., 0., {1}, .1, + {0,1}, {1,0}, PATH_RIGHT, {NORMHORIZ,NORMVERT,0.,0.} }; + +_fill_att intcgm_fill_att = { 1, HOLLOW, {1}, 1, 1, {0,0}, NULL, {{0.,0.},{0.,0.}} }; + +_edge_att intcgm_edge_att = { 1, EDGE_SOLID, 1., {1}, OFF }; + +trgb *intcgm_color_table; +int intcgm_block; + +TList *intcgm_asf_list; + +tpoint *intcgm_point_list; +int intcgm_npoints; + +CGM_FUNC intcgm_funcs[] = { NULL, &cgmb_rch, &cgmt_rch }; + +#else + +extern t_cgm intcgm_cgm; +extern cdCanvas* intcgm_canvas; + +extern tlimit intcgm_vdc_ext; +extern double intcgm_scale_factor_x; +extern double intcgm_scale_factor_y; +extern double intcgm_scale_factor_mm_x; +extern double intcgm_scale_factor_mm_y; +extern double intcgm_scale_factor; +extern int intcgm_view_xmin, intcgm_view_ymin, intcgm_view_xmax, intcgm_view_ymax; +extern double intcgm_clip_xmin, intcgm_clip_ymin, intcgm_clip_xmax, intcgm_clip_ymax; + +extern _line_att intcgm_line_att; + +extern _marker_att intcgm_marker_att; + +extern _text_att intcgm_text_att; + +extern _fill_att intcgm_fill_att; + +extern _edge_att intcgm_edge_att; + +extern trgb *intcgm_color_table; +extern int intcgm_block; + +extern TList *intcgm_asf_list; + +extern tpoint *intcgm_point_list; +extern int intcgm_npoints; + +extern CGM_FUNC *intcgm_funcs; + +#endif + +typedef struct _tasf { + short type; + short value; + } tasf; + +typedef struct _pat_table { + long index; + long nx, ny; + tcolor *pattern; + } pat_table; + diff --git a/cd/src/intcgm/intcgm1.c b/cd/src/intcgm/intcgm1.c new file mode 100755 index 0000000..d4b2399 --- /dev/null +++ b/cd/src/intcgm/intcgm1.c @@ -0,0 +1,291 @@ +#define _INTCGM1_C_ + +#include /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */ +#include /* malloc, free */ +#include /* strlen */ +#include /* floor */ + +#ifdef SunOS +#include /* SEEK_SET, SEEK_END */ +#endif + +#include /* FLT_MIN, FLT_MAX */ +#include /* INT_MIN, INT_MAX */ + +#include "cd.h" +#include "cdcgm.h" + +#include "list.h" +#include "types.h" +#include "intcgm2.h" +#include "intcgm.h" +#include "bparse.h" + +static int isitbin ( char *fname ) +{ + unsigned char ch[2]; + int erro, c, id; + unsigned short b; + FILE *f = fopen ( fname, "rb" ); + if (!f) + return 0; + + erro = fread ( ch, 1, 2, f ); + + b = (ch[0] << 8) + ch[1]; + + id = ( b & 0x0FE0 ) >> 5; + + c = ( b & 0xF000 ) >> 12; + + fclose(f); + + if ( c==0 && id==1 ) + return 1; + else + return 0; +} + +static int cgmplay ( char* filename, int xmn, int xmx, int ymn, int ymx ) +{ + intcgm_view_xmin = xmn; + intcgm_view_xmax = xmx; + intcgm_view_ymin = ymn; + intcgm_view_ymax = ymx; + + intcgm_scale_factor_x = 1; + intcgm_scale_factor_y = 1; + intcgm_scale_factor = 1; + + intcgm_block = 500; + intcgm_npoints = 500; + intcgm_cgm.buff.size = 1024; + + intcgm_point_list = (tpoint *) malloc ( sizeof(tpoint)*intcgm_npoints); + intcgm_cgm.buff.dados = (char *) malloc ( sizeof(char) * intcgm_cgm.buff.size ); + + if ( isitbin(filename) ) + { + intcgm_cgm.fp = fopen ( filename, "rb" ); + if (!intcgm_cgm.fp) + { + free(intcgm_point_list); + free(intcgm_cgm.buff.dados); + return CD_ERROR; + } + + fseek ( intcgm_cgm.fp, 0, SEEK_END ); + intcgm_cgm.file_size = ftell ( intcgm_cgm.fp ); + fseek ( intcgm_cgm.fp, 0, SEEK_SET ); + + intcgm_cgm.mode = 1; + intcgm_cgm.cgmf = intcgm_funcs[intcgm_cgm.mode]; + + intcgm_cgm.int_prec.b_prec = 1; + intcgm_cgm.real_prec.b_prec = 2; + intcgm_cgm.ix_prec.b_prec = 1; + intcgm_cgm.cd_prec = 0; + intcgm_cgm.cix_prec = 0; + intcgm_cgm.vdc_int.b_prec = 1; + intcgm_cgm.vdc_real.b_prec = 2; + } + else + { + intcgm_cgm.fp = fopen ( filename, "r" ); + if (!intcgm_cgm.fp) + { + free(intcgm_point_list); + free(intcgm_cgm.buff.dados); + return CD_ERROR; + } + + fseek ( intcgm_cgm.fp, 0, SEEK_END ); + intcgm_cgm.file_size = ftell ( intcgm_cgm.fp ); + fseek ( intcgm_cgm.fp, 0, SEEK_SET ); + + intcgm_cgm.mode = 2; + intcgm_cgm.cgmf = intcgm_funcs[intcgm_cgm.mode]; + + intcgm_cgm.int_prec.t_prec.minint = -32767; + intcgm_cgm.int_prec.t_prec.maxint = 32767; + intcgm_cgm.real_prec.t_prec.minreal = -32767; + intcgm_cgm.real_prec.t_prec.maxreal = 32767; + intcgm_cgm.real_prec.t_prec.digits = 4; + intcgm_cgm.ix_prec.t_prec.minint = 0; + intcgm_cgm.ix_prec.t_prec.maxint = 127; + intcgm_cgm.cd_prec = 127; + intcgm_cgm.vdc_int.t_prec.minint = -32767; + intcgm_cgm.vdc_int.t_prec.maxint = 32767; + intcgm_cgm.vdc_real.t_prec.minreal = 0; + intcgm_cgm.vdc_real.t_prec.maxreal = 1; + intcgm_cgm.vdc_real.t_prec.digits = 4; + } + + intcgm_cgm.first = 1; + intcgm_cgm.len = 0; + intcgm_cgm.vdc_type = INTEGER; + intcgm_cgm.max_cix = 63; + intcgm_cgm.scaling_mode.mode = ABSTRACT; + intcgm_cgm.scaling_mode.scale_factor = 1.; + intcgm_cgm.drawing_mode = ABSTRACT; + intcgm_cgm.clrsm = INDEXED; + intcgm_cgm.lnwsm = SCALED; + intcgm_cgm.mkssm = SCALED; + intcgm_cgm.edwsm = SCALED; + intcgm_cgm.vdc_ext.first.x = 0; + intcgm_cgm.vdc_ext.first.y = 0; + intcgm_cgm.vdc_ext.second.x = 32767; + intcgm_cgm.vdc_ext.second.y = 32767; + intcgm_cgm.back_color.red = 0; + intcgm_cgm.back_color.green = 0; + intcgm_cgm.back_color.blue = 0; + intcgm_cgm.aux_color.rgb.red = 0; + intcgm_cgm.aux_color.rgb.green = 0; + intcgm_cgm.aux_color.rgb.blue = 0; + intcgm_cgm.color_ext.black.red = 0; + intcgm_cgm.color_ext.black.green = 0; + intcgm_cgm.color_ext.black.blue = 0; + intcgm_cgm.color_ext.white.red = 255; + intcgm_cgm.color_ext.white.green = 255; + intcgm_cgm.color_ext.white.blue = 255; + intcgm_cgm.transparency = ON; + intcgm_cgm.clip_rect.first.x = 0; + intcgm_cgm.clip_rect.first.y = 0; + intcgm_cgm.clip_rect.second.x = 32767; + intcgm_cgm.clip_rect.second.y = 32767; + intcgm_cgm.clip_ind = ON; + intcgm_cgm.bc = 0; + intcgm_cgm.bl= 0; + intcgm_cgm.cl = 0; + + intcgm_line_att.index = 1; + intcgm_line_att.type = LINE_SOLID; + intcgm_line_att.width = 1; + intcgm_line_att.color.ind = 1; + + intcgm_marker_att.index = 1; + intcgm_marker_att.type = 1; + intcgm_marker_att.size = 1; + intcgm_marker_att.color.ind = 1; + + intcgm_text_att.index = 1; + intcgm_text_att.font_index = 1; + intcgm_text_att.font_list = NULL; + intcgm_text_att.font = 0; + intcgm_text_att.style = CD_PLAIN; + intcgm_text_att.size = 8; + intcgm_text_att.prec = STRING; + intcgm_text_att.exp_fact = 1; + intcgm_text_att.char_spacing = 0; + intcgm_text_att.color.ind = 1; + intcgm_text_att.height = 1; + intcgm_text_att.char_up.x = 0; + intcgm_text_att.char_up.y = 1; + intcgm_text_att.char_base.x = 1; + intcgm_text_att.char_base.y = 0; + intcgm_text_att.path = PATH_RIGHT; + intcgm_text_att.alignment.hor = NORMHORIZ; + intcgm_text_att.alignment.ver = NORMVERT; + intcgm_text_att.alignment.cont_hor = 0; + intcgm_text_att.alignment.cont_ver = 0; + + intcgm_fill_att.index = 1; + intcgm_fill_att.int_style = HOLLOW; + intcgm_fill_att.color.ind = 1; + intcgm_fill_att.hatch_index = 1; + intcgm_fill_att.pat_index = 1; + intcgm_fill_att.ref_pt.x = 0; + intcgm_fill_att.ref_pt.y = 0; + intcgm_fill_att.pat_list = NULL; + intcgm_fill_att.pat_size.height.x = 0; + intcgm_fill_att.pat_size.height.y = 0; + intcgm_fill_att.pat_size.height.x = 0; + intcgm_fill_att.pat_size.width.y = 0; + + intcgm_edge_att.index = 1; + intcgm_edge_att.type = EDGE_SOLID; + intcgm_edge_att.width = 1; + intcgm_edge_att.color.ind = 1; + intcgm_edge_att.visibility = OFF; + + cdCanvasLineWidth(intcgm_canvas, 1); + + intcgm_color_table = (trgb *) malloc ( sizeof(trgb)*intcgm_cgm.max_cix); + intcgm_color_table[0].red = 255; + intcgm_color_table[0].green = 255; + intcgm_color_table[0].blue = 255; + intcgm_color_table[1].red = 0; + intcgm_color_table[1].green = 0; + intcgm_color_table[1].blue = 0; + + while ( !(*intcgm_cgm.cgmf)() ){}; + + if ( intcgm_point_list!=NULL ) + { + free(intcgm_point_list); + intcgm_point_list = NULL; + } + + if ( intcgm_cgm.buff.dados!=NULL ) + { + free(intcgm_cgm.buff.dados); + intcgm_cgm.buff.dados = NULL; + } + + if ( intcgm_color_table!=NULL ) + { + free(intcgm_color_table); + intcgm_color_table = NULL; + } + + fclose(intcgm_cgm.fp); + + return CD_OK; +} + +_cdcgmsizecb cdcgmsizecb = NULL; +_cdcgmbegmtfcb cdcgmbegmtfcb = NULL; +_cdcgmcountercb cdcgmcountercb = NULL; +_cdcgmsclmdecb cdcgmsclmdecb = NULL; +_cdcgmvdcextcb cdcgmvdcextcb = NULL; +_cdcgmbegpictcb cdcgmbegpictcb = NULL; +_cdcgmbegpictbcb cdcgmbegpictbcb = NULL; + +int cdRegisterCallbackCGM(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdcgmsizecb = (_cdcgmsizecb)func; + return CD_OK; + case CD_CGMBEGMTFCB: + cdcgmbegmtfcb = (_cdcgmbegmtfcb)func; + return CD_OK; + case CD_CGMCOUNTERCB: + cdcgmcountercb = (_cdcgmcountercb)func; + return CD_OK; + case CD_CGMSCLMDECB: + cdcgmsclmdecb = (_cdcgmsclmdecb)func; + return CD_OK; + case CD_CGMVDCEXTCB: + cdcgmvdcextcb = (_cdcgmvdcextcb)func; + return CD_OK; + case CD_CGMBEGPICTCB: + cdcgmbegpictcb = (_cdcgmbegpictcb)func; + return CD_OK; + case CD_CGMBEGPICTBCB: + cdcgmbegpictbcb = (_cdcgmbegpictbcb)func; + return CD_OK; + } + + return CD_ERROR; +} + +int cdplayCGM(cdCanvas* _canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + int ret; + intcgm_canvas = _canvas; + ret = cgmplay((char*)data, xmin, xmax, ymin, ymax); + _canvas = NULL; + return ret; +} diff --git a/cd/src/intcgm/intcgm2.c b/cd/src/intcgm/intcgm2.c new file mode 100755 index 0000000..b6be7ee --- /dev/null +++ b/cd/src/intcgm/intcgm2.c @@ -0,0 +1,1651 @@ +#include /* FILE, ftell, fseek, fputc, fopen, fclose, fputs, fprintf */ +#include /* strlen */ +#include +#include +#include +#include "cd.h" +#include "cdcgm.h" +#include "list.h" +#include "types.h" +#include "bparse.h" +#include "tparse.h" +#include "intcgm.h" +#include "intcgm6.h" +#include "tparse.h" + +typedef struct { + const char *nome; + int (*func) (void); + } comando; + +/************************************************** +*************************************************** +** ** +** FUNCOES CGM ** +** ** +*************************************************** +**************************************************/ + +/************************************************ +* * +* Dados para nao-binario * +* * +************************************************/ + +/* delimiter elements */ + +comando _cgmt_NULL = { "", NULL }; +comando _cgmt_BEGMF = { "begmf", &cgmt_begmtf }; +comando _cgmt_ENDMF = { "endmf", &cgmt_endmtf }; +comando _cgmt_BEG_PIC = { "begpic", &cgmt_begpic }; +comando _cgmt_BEG_PIC_BODY = { "begpicbody", &cgmt_begpib }; +comando _cgmt_END_PIC = { "endpic", &cgmt_endpic }; + +/* metafile descriptor elements */ + +comando _cgmt_MF_VERSION = { "mfversion", cgmt_mtfver }; +comando _cgmt_MF_DESC = { "mfdesc", cgmt_mtfdsc }; +comando _cgmt_VDC_TYPE = { "vdctype", cgmt_vdctyp }; +comando _cgmt_INTEGER_PREC = { "integerprec", cgmt_intpre }; +comando _cgmt_REAL_PREC = { "realprec", cgmt_realpr }; +comando _cgmt_INDEX_PREC = { "indexprec", cgmt_indpre }; +comando _cgmt_COLR_PREC = { "colrprec", cgmt_colpre }; +comando _cgmt_COLR_INDEX_PREC = { "colrindexprec", cgmt_colipr }; +comando _cgmt_MAX_COLR_INDEX = { "maxcolrindex", cgmt_maxcoi }; +comando _cgmt_COLR_VALUE_EXT = { "colrvalueext", cgmt_covaex }; +comando _cgmt_MF_ELEM_LIST = { "mfelemlist", cgmt_mtfell }; +comando _cgmt_BEG_MF_DEFAULTS = { "begmfdefaults", cgmt_bmtfdf }; +comando _cgmt_END_MF_DEFAULTS = { "endmfdefaults", cgmt_emtfdf }; +comando _cgmt_FONT_LIST = { "fontlist", cgmt_fntlst }; +comando _cgmt_CHAR_SET_LIST = { "charsetlist", cgmt_chslst }; +comando _cgmt_CHAR_CODING = { "charcoding", cgmt_chcdac }; + +/* picture descriptor elements */ + +comando _cgmt_SCALE_MODE = { "scalemode", cgmt_sclmde }; +comando _cgmt_COLR_MODE = { "colrmode", cgmt_clslmd }; +comando _cgmt_LINE_WIDTH_MODE = { "linewidthmode", cgmt_lnwdmd }; +comando _cgmt_MARKER_SIZE_MODE = { "markersizemode", cgmt_mkszmd }; +comando _cgmt_EDGE_WIDTH_MODE = { "edgewidthmode", cgmt_edwdmd }; +comando _cgmt_VDC_EXTENT = { "vdcext", cgmt_vdcext }; +comando _cgmt_BACK_COLR = { "backcolr", cgmt_bckcol }; + +/* control elements */ + +comando _cgmt_VDC_INTEGER_PREC = { "vdcintegerprec", cgmt_vdcipr }; +comando _cgmt_VDC_REAL_PREC = { "vdcrealprec", cgmt_vdcrpr }; +comando _cgmt_AUX_COLR = { "auxcolr", cgmt_auxcol }; +comando _cgmt_TRANSPARENCY = { "transparency", cgmt_transp }; +comando _cgmt_CLIP_RECT = { "cliprect", cgmt_clprec }; +comando _cgmt_CLIP = { "clip", cgmt_clpind }; + +/* primitive elements */ + +comando _cgmt_LINE = { "line", cgmt_polyln }; +comando _cgmt_INCR_LINE = { "incrline", cgmt_incply }; +comando _cgmt_DISJT_LINE = { "disjtline", cgmt_djtply }; +comando _cgmt_INCR_DISJT_LINE = { "incrdisjt_line", cgmt_indjpl }; +comando _cgmt_MARKER = { "marker", cgmt_polymk }; +comando _cgmt_INCR_MARKER = { "incrmarker", cgmt_incplm }; +comando _cgmt_TEXT = { "text", cgmt_text }; +comando _cgmt_RESTR_TEXT = { "restrtext", cgmt_rsttxt }; +comando _cgmt_APND_TEXT = { "apndtext", cgmt_apdtxt }; +comando _cgmt_POLYGON = { "polygon", cgmt_polygn }; +comando _cgmt_INCR_POLYGON = { "incrpolygon", cgmt_incplg }; +comando _cgmt_POLYGON_SET = { "polygonset", cgmt_plgset }; +comando _cgmt_INCR_POLYGON_SET = { "incrpolygonset", cgmt_inpgst }; +comando _cgmt_CELL_ARRAY = { "cellarray", cgmt_cellar }; +comando _cgmt_GDP = { "gdp", cgmt_gdp }; +comando _cgmt_RECT = { "rect", cgmt_rect }; +comando _cgmt_CIRCLE = { "circle", cgmt_circle }; +comando _cgmt_ARC_3_PT = { "arc3pt", cgmt_circ3p }; +comando _cgmt_ARC_3_PT_CLOSE = { "arc3ptclose", cgmt_cir3pc }; +comando _cgmt_ARC_CTR = { "arcctr", cgmt_circnt }; +comando _cgmt_ARC_CTR_CLOSE = { "arcctr_close", cgmt_ccntcl }; +comando _cgmt_ELLIPSE = { "ellipse", cgmt_ellips }; +comando _cgmt_ELLIP_ARC = { "elliparc", cgmt_ellarc }; +comando _cgmt_ELLIP_ARC_CLOSE = { "elliparcclose", cgmt_ellacl }; + +/* attribute elements */ + +comando _cgmt_LINE_INDEX = { "lineindex", cgmt_lnbdin }; +comando _cgmt_LINE_TYPE = { "linetype", cgmt_lntype }; +comando _cgmt_LINE_WIDTH = { "linewidth", cgmt_lnwidt }; +comando _cgmt_LINE_COLR = { "linecolr", cgmt_lncolr }; +comando _cgmt_MARKER_INDEX = { "markerindex", cgmt_mkbdin }; +comando _cgmt_MARKER_TYPE = { "markertype", cgmt_mktype }; +comando _cgmt_MARKER_WIDTH = { "markersize", cgmt_mksize }; +comando _cgmt_MARKER_COLR = { "markercolr", cgmt_mkcolr }; +comando _cgmt_TEXT_INDEX = { "textindex", cgmt_txbdin }; +comando _cgmt_TEXT_FONT_INDEX = { "textfontindex", cgmt_txftin }; +comando _cgmt_TEXT_PREC = { "textprec", cgmt_txtprc }; +comando _cgmt_CHAR_EXPAN = { "charexpan", cgmt_chrexp }; +comando _cgmt_CHAR_SPACE = { "charspace", cgmt_chrspc }; +comando _cgmt_TEXT_COLR = { "textcolr", cgmt_txtclr }; +comando _cgmt_CHAR_HEIGHT = { "charheight", cgmt_chrhgt }; +comando _cgmt_CHAR_ORI = { "charori", cgmt_chrori }; +comando _cgmt_TEXT_PATH = { "textpath", cgmt_txtpat }; +comando _cgmt_TEXT_ALIGN = { "textalign", cgmt_txtali }; +comando _cgmt_CHAR_SET_INDEX = { "charsetindex", cgmt_chseti }; +comando _cgmt_ALT_CHAR_SET = { "altcharsetindex", cgmt_achsti }; +comando _cgmt_FILL_INDEX = { "fillindex", cgmt_fillin }; +comando _cgmt_INT_STYLE = { "intstyle", cgmt_intsty }; +comando _cgmt_FILL_COLR = { "fillcolr", cgmt_fillco }; +comando _cgmt_HATCH_INDEX = { "hatchindex", cgmt_hatind }; +comando _cgmt_PAT_INDEX = { "patindex", cgmt_patind }; +comando _cgmt_EDGE_INDEX = { "edgeindex", cgmt_edgind }; +comando _cgmt_EDGE_TYPE = { "edgetype", cgmt_edgtyp }; +comando _cgmt_EDGE_WIDTH = { "edgewidth", cgmt_edgwid }; +comando _cgmt_EDGE_COLR = { "edgecolr", cgmt_edgcol }; +comando _cgmt_EDGE_VIS = { "edgevis", cgmt_edgvis }; +comando _cgmt_FILL_REF_PT = { "fillrefpt", cgmt_fillrf }; +comando _cgmt_PAT_TABLE = { "pattable", cgmt_pattab }; +comando _cgmt_PAT_SIZE = { "patsize", cgmt_patsiz }; +comando _cgmt_COLR_TABLE = { "colrtable", cgmt_coltab }; +comando _cgmt_ASF = { "asf", cgmt_asf }; + +/* escape elements */ + +comando _cgmt_ESCAPE = { "escape", cgmt_escape }; +comando _cgmt_DOMAIN_RING = { "domainring", NULL }; + +/* external elements */ + +comando _cgmt_MESSAGE = { "message", cgmt_messag }; +comando _cgmt_APPL_DATA = { "appldata", cgmt_appdta }; + +comando *_cgmt_delimiter[] = { + &_cgmt_NULL, + &_cgmt_BEGMF, + &_cgmt_ENDMF, + &_cgmt_BEG_PIC, + &_cgmt_BEG_PIC_BODY, + &_cgmt_END_PIC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +comando *_cgmt_metafile[] = { + &_cgmt_END_MF_DEFAULTS, + &_cgmt_MF_VERSION, + &_cgmt_MF_DESC, + &_cgmt_VDC_TYPE, + &_cgmt_INTEGER_PREC, + &_cgmt_REAL_PREC, + &_cgmt_INDEX_PREC, + &_cgmt_COLR_PREC, + &_cgmt_COLR_INDEX_PREC, + &_cgmt_MAX_COLR_INDEX, + &_cgmt_COLR_VALUE_EXT, + &_cgmt_MF_ELEM_LIST, + &_cgmt_BEG_MF_DEFAULTS, + &_cgmt_FONT_LIST, + &_cgmt_CHAR_SET_LIST, + &_cgmt_CHAR_CODING, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +comando *_cgmt_picture[] = { + &_cgmt_NULL, + &_cgmt_SCALE_MODE, + &_cgmt_COLR_MODE, + &_cgmt_LINE_WIDTH_MODE, + &_cgmt_MARKER_SIZE_MODE, + &_cgmt_EDGE_WIDTH_MODE, + &_cgmt_VDC_EXTENT, + &_cgmt_BACK_COLR, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; + +comando *_cgmt_control[] = { + &_cgmt_NULL, + &_cgmt_VDC_INTEGER_PREC, + &_cgmt_VDC_REAL_PREC, + &_cgmt_AUX_COLR, + &_cgmt_TRANSPARENCY, + &_cgmt_CLIP_RECT, + &_cgmt_CLIP, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL }; + +comando *_cgmt_primitive[] = { + &_cgmt_NULL, + &_cgmt_LINE, + &_cgmt_INCR_LINE, + &_cgmt_DISJT_LINE, + &_cgmt_INCR_DISJT_LINE, + &_cgmt_MARKER, + &_cgmt_INCR_MARKER, + &_cgmt_TEXT, + &_cgmt_RESTR_TEXT, + &_cgmt_APND_TEXT, + &_cgmt_POLYGON, + &_cgmt_INCR_POLYGON, + &_cgmt_POLYGON_SET, + &_cgmt_INCR_POLYGON_SET, + &_cgmt_CELL_ARRAY, + &_cgmt_GDP, + &_cgmt_RECT, + &_cgmt_CIRCLE, + &_cgmt_ARC_3_PT, + &_cgmt_ARC_3_PT_CLOSE, + &_cgmt_ARC_CTR, + &_cgmt_ARC_CTR_CLOSE, + &_cgmt_ELLIPSE, + &_cgmt_ELLIP_ARC, + &_cgmt_ELLIP_ARC_CLOSE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +comando *_cgmt_attributes[] = { + &_cgmt_NULL, + &_cgmt_LINE_INDEX, + &_cgmt_LINE_TYPE, + &_cgmt_LINE_WIDTH, + &_cgmt_LINE_COLR, + &_cgmt_MARKER_INDEX, + &_cgmt_MARKER_TYPE, + &_cgmt_MARKER_WIDTH, + &_cgmt_MARKER_COLR, + &_cgmt_TEXT_INDEX, + &_cgmt_TEXT_FONT_INDEX, + &_cgmt_TEXT_PREC, + &_cgmt_CHAR_EXPAN, + &_cgmt_CHAR_SPACE, + &_cgmt_TEXT_COLR, + &_cgmt_CHAR_HEIGHT, + &_cgmt_CHAR_ORI, + &_cgmt_TEXT_PATH, + &_cgmt_TEXT_ALIGN, + &_cgmt_CHAR_SET_INDEX, + &_cgmt_ALT_CHAR_SET, + &_cgmt_FILL_INDEX, + &_cgmt_INT_STYLE, + &_cgmt_FILL_COLR, + &_cgmt_HATCH_INDEX, + &_cgmt_PAT_INDEX, + &_cgmt_EDGE_INDEX, + &_cgmt_EDGE_TYPE, + &_cgmt_EDGE_WIDTH, + &_cgmt_EDGE_COLR, + &_cgmt_EDGE_VIS, + &_cgmt_FILL_REF_PT, + &_cgmt_PAT_TABLE, + &_cgmt_PAT_SIZE, + &_cgmt_COLR_TABLE, + &_cgmt_ASF, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; + +comando *_cgmt_escape[] = { + &_cgmt_NULL, + &_cgmt_ESCAPE, + &_cgmt_DOMAIN_RING, + NULL}; + +comando *_cgmt_external[] = { + &_cgmt_NULL, + &_cgmt_MESSAGE, + &_cgmt_APPL_DATA, + NULL }; + +comando *_cgmt_segment[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +comando *_cgmt_NULL_NULL[] = { + &_cgmt_NULL, + NULL }; + +comando **_cgmt_comandos[] = { + _cgmt_NULL_NULL, + _cgmt_delimiter, + _cgmt_metafile, + _cgmt_picture, + _cgmt_control, + _cgmt_primitive, + _cgmt_attributes, + _cgmt_escape, + _cgmt_external, + _cgmt_segment, + NULL }; + +/************************************************ +* * +* Dados para binario * +* * +************************************************/ + +/* delimiter elements */ + +CGM_FUNC _cgmb_NULL = NULL; + +CGM_FUNC _cgmb_NOOP = &cgmb_noop; +CGM_FUNC _cgmb_BEGMF = &cgmb_begmtf; +CGM_FUNC _cgmb_ENDMF = &cgmb_endmtf; +CGM_FUNC _cgmb_BEG_PIC = &cgmb_begpic; +CGM_FUNC _cgmb_BEG_PIC_BODY = &cgmb_begpib; +CGM_FUNC _cgmb_END_PIC = &cgmb_endpic; + +/* metafile descriptor elements */ + +CGM_FUNC _cgmb_MF_VERSION = &cgmb_mtfver; +CGM_FUNC _cgmb_MF_DESC = &cgmb_mtfdsc; +CGM_FUNC _cgmb_VDC_TYPE = &cgmb_vdctyp; +CGM_FUNC _cgmb_INTEGER_PREC = &cgmb_intpre; +CGM_FUNC _cgmb_REAL_PREC = &cgmb_realpr; +CGM_FUNC _cgmb_INDEX_PREC = &cgmb_indpre; +CGM_FUNC _cgmb_COLR_PREC = &cgmb_colpre; +CGM_FUNC _cgmb_COLR_INDEX_PREC = &cgmb_colipr; +CGM_FUNC _cgmb_MAX_COLR_INDEX = &cgmb_maxcoi; +CGM_FUNC _cgmb_COLR_VALUE_EXT = &cgmb_covaex; +CGM_FUNC _cgmb_MF_ELEM_LIST = &cgmb_mtfell; +CGM_FUNC _cgmb_MF_DEFAULTS_RPL = &cgmb_bmtfdf; +CGM_FUNC _cgmb_FONT_LIST = &cgmb_fntlst; +CGM_FUNC _cgmb_CHAR_SET_LIST = &cgmb_chslst; +CGM_FUNC _cgmb_CHAR_CODING = &cgmb_chcdac; + +/* picture descriptor elements */ + +CGM_FUNC _cgmb_SCALE_MODE = &cgmb_sclmde; +CGM_FUNC _cgmb_COLR_MODE = &cgmb_clslmd; +CGM_FUNC _cgmb_LINE_WIDTH_MODE = &cgmb_lnwdmd; +CGM_FUNC _cgmb_MARKER_SIZE_MODE = &cgmb_mkszmd; +CGM_FUNC _cgmb_EDGE_WIDTH_MODE = &cgmb_edwdmd; +CGM_FUNC _cgmb_VDC_EXTENT = &cgmb_vdcext; +CGM_FUNC _cgmb_BACK_COLR = &cgmb_bckcol; + +/* control elements */ + +CGM_FUNC _cgmb_VDC_INTEGER_PREC = &cgmb_vdcipr; +CGM_FUNC _cgmb_VDC_REAL_PREC = &cgmb_vdcrpr; +CGM_FUNC _cgmb_AUX_COLR = &cgmb_auxcol; +CGM_FUNC _cgmb_TRANSPARENCY = &cgmb_transp; +CGM_FUNC _cgmb_CLIP_RECT = &cgmb_clprec; +CGM_FUNC _cgmb_CLIP = &cgmb_clpind; + +/* primitive elements */ + +CGM_FUNC _cgmb_LINE = &cgmb_polyln; +CGM_FUNC _cgmb_DISJT_LINE = &cgmb_djtply; +CGM_FUNC _cgmb_MARKER = &cgmb_polymk; +CGM_FUNC _cgmb_TEXT = &cgmb_text; +CGM_FUNC _cgmb_RESTR_TEXT = &cgmb_rsttxt; +CGM_FUNC _cgmb_APND_TEXT = &cgmb_apdtxt; +CGM_FUNC _cgmb_POLYGON = &cgmb_polygn; +CGM_FUNC _cgmb_POLYGON_SET = &cgmb_plgset; +CGM_FUNC _cgmb_CELL_ARRAY = &cgmb_cellar; +CGM_FUNC _cgmb_GDP = &cgmb_gdp; +CGM_FUNC _cgmb_RECT = &cgmb_rect; +CGM_FUNC _cgmb_CIRCLE = &cgmb_circle; +CGM_FUNC _cgmb_ARC_3_PT = &cgmb_circ3p; +CGM_FUNC _cgmb_ARC_3_PT_CLOSE = &cgmb_cir3pc; +CGM_FUNC _cgmb_ARC_CTR = &cgmb_circnt; +CGM_FUNC _cgmb_ARC_CTR_CLOSE = &cgmb_ccntcl; +CGM_FUNC _cgmb_ELLIPSE = &cgmb_ellips; +CGM_FUNC _cgmb_ELLIP_ARC = &cgmb_ellarc; +CGM_FUNC _cgmb_ELLIP_ARC_CLOSE = &cgmb_ellacl; + +/* attribute elements */ + +CGM_FUNC _cgmb_LINE_INDEX = &cgmb_lnbdin; +CGM_FUNC _cgmb_LINE_TYPE = &cgmb_lntype; +CGM_FUNC _cgmb_LINE_WIDTH = &cgmb_lnwidt; +CGM_FUNC _cgmb_LINE_COLR = &cgmb_lncolr; +CGM_FUNC _cgmb_MARKER_INDEX = &cgmb_mkbdin; +CGM_FUNC _cgmb_MARKER_TYPE = &cgmb_mktype; +CGM_FUNC _cgmb_MARKER_WIDTH = &cgmb_mksize; +CGM_FUNC _cgmb_MARKER_COLR = &cgmb_mkcolr; +CGM_FUNC _cgmb_TEXT_INDEX = &cgmb_txbdin; +CGM_FUNC _cgmb_TEXT_FONT_INDEX = &cgmb_txftin; +CGM_FUNC _cgmb_TEXT_PREC = &cgmb_txtprc; +CGM_FUNC _cgmb_CHAR_EXPAN = &cgmb_chrexp; +CGM_FUNC _cgmb_CHAR_SPACE = &cgmb_chrspc; +CGM_FUNC _cgmb_TEXT_COLR = &cgmb_txtclr; +CGM_FUNC _cgmb_CHAR_HEIGHT = &cgmb_chrhgt; +CGM_FUNC _cgmb_CHAR_ORI = &cgmb_chrori; +CGM_FUNC _cgmb_TEXT_PATH = &cgmb_txtpat; +CGM_FUNC _cgmb_TEXT_ALIGN = &cgmb_txtali; +CGM_FUNC _cgmb_CHAR_SET_INDEX = &cgmb_chseti; +CGM_FUNC _cgmb_ALT_CHAR_SET = &cgmb_achsti; +CGM_FUNC _cgmb_FILL_INDEX = &cgmb_fillin; +CGM_FUNC _cgmb_INT_STYLE = &cgmb_intsty; +CGM_FUNC _cgmb_FILL_COLR = &cgmb_fillco; +CGM_FUNC _cgmb_HATCH_INDEX = &cgmb_hatind; +CGM_FUNC _cgmb_PAT_INDEX = &cgmb_patind; +CGM_FUNC _cgmb_EDGE_INDEX = &cgmb_edgind; +CGM_FUNC _cgmb_EDGE_TYPE = &cgmb_edgtyp; +CGM_FUNC _cgmb_EDGE_WIDTH = &cgmb_edgwid; +CGM_FUNC _cgmb_EDGE_COLR = &cgmb_edgcol; +CGM_FUNC _cgmb_EDGE_VIS = &cgmb_edgvis; +CGM_FUNC _cgmb_FILL_REF_PT = &cgmb_fillrf; +CGM_FUNC _cgmb_PAT_TABLE = &cgmb_pattab; +CGM_FUNC _cgmb_PAT_SIZE = &cgmb_patsiz; +CGM_FUNC _cgmb_COLR_TABLE = &cgmb_coltab; +CGM_FUNC _cgmb_ASF = &cgmb_asf; + +/* escape elements */ + +CGM_FUNC _cgmb_ESCAPE = &cgmb_escape; + +/* external elements */ + +CGM_FUNC _cgmb_MESSAGE = &cgmb_messag; +CGM_FUNC _cgmb_APPL_DATA = &cgmb_appdta; + +CGM_FUNC *_cgmb_delimiter[] = { + &_cgmb_NOOP, + &_cgmb_BEGMF, + &_cgmb_ENDMF, + &_cgmb_BEG_PIC, + &_cgmb_BEG_PIC_BODY, + &_cgmb_END_PIC, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_metafile[] = { + &_cgmb_NULL, + &_cgmb_MF_VERSION, + &_cgmb_MF_DESC, + &_cgmb_VDC_TYPE, + &_cgmb_INTEGER_PREC, + &_cgmb_REAL_PREC, + &_cgmb_INDEX_PREC, + &_cgmb_COLR_PREC, + &_cgmb_COLR_INDEX_PREC, + &_cgmb_MAX_COLR_INDEX, + &_cgmb_COLR_VALUE_EXT, + &_cgmb_MF_ELEM_LIST, + &_cgmb_MF_DEFAULTS_RPL, + &_cgmb_FONT_LIST, + &_cgmb_CHAR_SET_LIST, + &_cgmb_CHAR_CODING, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_picture[] = { + &_cgmb_NULL, + &_cgmb_SCALE_MODE, + &_cgmb_COLR_MODE, + &_cgmb_LINE_WIDTH_MODE, + &_cgmb_MARKER_SIZE_MODE, + &_cgmb_EDGE_WIDTH_MODE, + &_cgmb_VDC_EXTENT, + &_cgmb_BACK_COLR, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_control[] = { + &_cgmb_NULL, + &_cgmb_VDC_INTEGER_PREC, + &_cgmb_VDC_REAL_PREC, + &_cgmb_AUX_COLR, + &_cgmb_TRANSPARENCY, + &_cgmb_CLIP_RECT, + &_cgmb_CLIP, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_primitive[] = { + &_cgmb_NULL, + &_cgmb_LINE, + &_cgmb_DISJT_LINE, + &_cgmb_MARKER, + &_cgmb_TEXT, + &_cgmb_RESTR_TEXT, + &_cgmb_APND_TEXT, + &_cgmb_POLYGON, + &_cgmb_POLYGON_SET, + &_cgmb_CELL_ARRAY, + &_cgmb_GDP, + &_cgmb_RECT, + &_cgmb_CIRCLE, + &_cgmb_ARC_3_PT, + &_cgmb_ARC_3_PT_CLOSE, + &_cgmb_ARC_CTR, + &_cgmb_ARC_CTR_CLOSE, + &_cgmb_ELLIPSE, + &_cgmb_ELLIP_ARC, + &_cgmb_ELLIP_ARC_CLOSE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_attributes[] = { + &_cgmb_NULL, + &_cgmb_LINE_INDEX, + &_cgmb_LINE_TYPE, + &_cgmb_LINE_WIDTH, + &_cgmb_LINE_COLR, + &_cgmb_MARKER_INDEX, + &_cgmb_MARKER_TYPE, + &_cgmb_MARKER_WIDTH, + &_cgmb_MARKER_COLR, + &_cgmb_TEXT_INDEX, + &_cgmb_TEXT_FONT_INDEX, + &_cgmb_TEXT_PREC, + &_cgmb_CHAR_EXPAN, + &_cgmb_CHAR_SPACE, + &_cgmb_TEXT_COLR, + &_cgmb_CHAR_HEIGHT, + &_cgmb_CHAR_ORI, + &_cgmb_TEXT_PATH, + &_cgmb_TEXT_ALIGN, + &_cgmb_CHAR_SET_INDEX, + &_cgmb_ALT_CHAR_SET, + &_cgmb_FILL_INDEX, + &_cgmb_INT_STYLE, + &_cgmb_FILL_COLR, + &_cgmb_HATCH_INDEX, + &_cgmb_PAT_INDEX, + &_cgmb_EDGE_INDEX, + &_cgmb_EDGE_TYPE, + &_cgmb_EDGE_WIDTH, + &_cgmb_EDGE_COLR, + &_cgmb_EDGE_VIS, + &_cgmb_FILL_REF_PT, + &_cgmb_PAT_TABLE, + &_cgmb_PAT_SIZE, + &_cgmb_COLR_TABLE, + &_cgmb_ASF, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }; + +CGM_FUNC *_cgmb_escape[] = { + &_cgmb_NULL, + &_cgmb_ESCAPE, + NULL}; + +CGM_FUNC *_cgmb_external[] = { + &_cgmb_NULL, + &_cgmb_MESSAGE, + &_cgmb_APPL_DATA, + NULL }; + +CGM_FUNC *_cgmb_segment[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; + +CGM_FUNC **_cgmb_comandos[] = { + _cgmb_delimiter, + _cgmb_metafile, + _cgmb_picture, + _cgmb_control, + _cgmb_primitive, + _cgmb_attributes, + _cgmb_escape, + _cgmb_external, + _cgmb_segment, + NULL }; + +/************************************************ +* * +* Funcoes para binario * +* * +************************************************/ + +int cgm_getfilepos ( void ) +{ + if (cdcgmcountercb) + return cdcgmcountercb ( intcgm_canvas, (ftell ( intcgm_cgm.fp )*100.)/intcgm_cgm.file_size ); + + return 0; +} + +#define cgmb_getw cgmb_getu16 +#define cgmb_getb(b) cgmb_getc((unsigned char *)(b)) + +static void cgmb_donothing ( void ) +{ + intcgm_cgm.bc=intcgm_cgm.len; +} + +int cgmb_exec_comand ( int classe, int id ) +{ + int err; + + if ( _cgmb_comandos[classe][id]==NULL ) + { + cgmb_donothing(); + return 0; + } + + err = (*_cgmb_comandos[classe][id])(); + + if ( err == -1 ) + return 1; + else if ( err ) + { + cgmb_donothing(); + return 0; + } + + return 0; +} + +int cgmb_getbit ( unsigned char *b ) +{ + static unsigned char b1; + + if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 ) + { + b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc]; + intcgm_cgm.bc++; + + if ( intcgm_cgm.bc > intcgm_cgm.len ) + { + return 1; + } + + intcgm_cgm.pc=0; + } + + *b = b1; + + switch ( intcgm_cgm.pc ) + { + case 0: + *b = ( *b | 0x0080 ) >> 7; + break; + case 1: + *b = ( *b | 0x0040 ) >> 6; + break; + case 2: + *b = ( *b | 0x0020 ) >> 5; + break; + case 3: + *b = ( *b | 0x0010 ) >> 4; + break; + case 4: + *b = ( *b | 0x0008 ) >> 3; + break; + case 5: + *b = ( *b | 0x0004 ) >> 2; + break; + case 6: + *b = ( *b | 0x0002 ) >> 1; + break; + case 7: + *b = ( *b | 0x0001 ); + break; + } + + intcgm_cgm.pc++; + + return 0; +} + +int cgmb_get2bit ( unsigned char *b ) +{ + static unsigned char b1; + + if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 ) + { + b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc]; + intcgm_cgm.bc++; + + if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1; + + intcgm_cgm.pc=0; + } + + *b = b1; + + switch ( intcgm_cgm.pc ) + { + case 0: + *b = ( *b | 0x00C0 ) >> 6; + break; + case 2: + *b = ( *b | 0x0030 ) >> 4; + break; + case 4: + *b = ( *b | 0x000C ) >> 2; + break; + case 6: + *b = ( *b | 0x0003 ); + break; + } + + intcgm_cgm.pc += 2; + + return 0; +} + + +int cgmb_get4bit ( unsigned char *b ) +{ + static unsigned char b1; + + if ( intcgm_cgm.pc==0 || intcgm_cgm.pc==8 ) + { + b1 = intcgm_cgm.buff.dados[intcgm_cgm.bc]; + intcgm_cgm.bc++; + + if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1; + + intcgm_cgm.pc=0; + } + + *b = b1; + + switch ( intcgm_cgm.pc ) + { + case 0: + *b = ( *b | 0x00F0 ) >> 4; + break; + case 4: + *b = ( *b | 0x000F ); + break; + } + + intcgm_cgm.pc += 4; + + return 0; +} + +int cgmb_getw ( unsigned short * ); + +int cgmb_getc ( unsigned char *b ) +{ + *b = intcgm_cgm.buff.dados[intcgm_cgm.bc]; + intcgm_cgm.bc++; + + if ( intcgm_cgm.bc > intcgm_cgm.len ) return 1; + + return 0; +} + +int cgmb_geti8 ( signed char *b ) +{ + unsigned char b1; + + if ( cgmb_getb ( &b1 ) ) return 1; + + *b = (signed char) b1; + + return 0; +} + +int cgmb_geti16 ( short *b ) +{ + unsigned char b1, b2; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + + *b = ( b1<<8 ) | b2; + + return 0; +} + +int cgmb_geti24 ( long *b ) +{ + unsigned char b1, b2, b3; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + + *b = ( b1<<16 ) | ( b2<<8 ) | b3; + + return 0; +} + +int cgmb_geti32 ( long *b ) +{ + unsigned char b1, b2, b3, b4; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + if ( cgmb_getb ( &b4 ) ) return 1; + + *b = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4; + + return 0; +} + +int cgmb_getu8 ( unsigned char *b ) +{ + if ( cgmb_getb ( b ) ) return 1; + + return 0; +} + +int cgmb_getu16 ( unsigned short *b ) +{ + unsigned char b1, b2; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + + *b = ( b1<<8 ) | b2; + + return 0; +} + +int cgmb_getu24 ( unsigned long *b ) +{ + unsigned char b1, b2, b3; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + + *b = ( b1<<16 ) | ( b2<<8 ) | b3; + + return 0; +} + +int cgmb_getu32 ( unsigned long *b ) +{ + unsigned char b1, b2, b3, b4; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + if ( cgmb_getb ( &b4 ) ) return 1; + + *b = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4; + + return 0; +} + +int cgmb_getfl32 ( float *b ) +{ + unsigned char b1, b2, b3, b4; + union { + float f; + long l; + } r; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + if ( cgmb_getb ( &b4 ) ) return 1; + + r.l = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4; + *b = r.f; + + return 0; +} + +int cgmb_getfl64 ( double *b ) +{ + unsigned char b1, b2, b3, b4, b5, b6, b7, b8; + union { + double d; + long l[2]; + } r; + + if ( cgmb_getb ( &b1 ) ) return 1; + if ( cgmb_getb ( &b2 ) ) return 1; + if ( cgmb_getb ( &b3 ) ) return 1; + if ( cgmb_getb ( &b4 ) ) return 1; + if ( cgmb_getb ( &b5 ) ) return 1; + if ( cgmb_getb ( &b6 ) ) return 1; + if ( cgmb_getb ( &b7 ) ) return 1; + if ( cgmb_getb ( &b8 ) ) return 1; + + r.l[1] = ( b1<<24 ) | ( b2<<16 ) | ( b3<<8 ) | b4; + r.l[0] = ( b5<<24 ) | ( b6<<16 ) | ( b7<<8 ) | b8; + *b = r.d; + + return 0; +} + +int cgmb_getfx32 ( float *b ) +{ + short si; + unsigned short ui; + + if ( cgmb_geti16 ( &si ) ) return 1; + if ( cgmb_getu16 ( &ui ) ) return 1; + + *b = (float) ( si + ( ui / 65536.0 ) ); + + return 0; +} + +int cgmb_getfx64 ( double *b ) +{ + long si, ui; + + if ( cgmb_geti32 ( &si ) ) return 1; + if ( cgmb_geti32 ( &ui ) ) return 1; + + *b = si + ( (unsigned short) ui / ( 65536.0 * 65536.0 ) ); + + return 0; +} + +int cgmb_ter ( void ) +{ + return 0; +} + +int cgmb_rch ( void ) +{ + int c, id, len, cont, i; + unsigned char ch[2], dummy; + unsigned short b; + int erro; + + if ( intcgm_cgm.bc!=intcgm_cgm.len ) + { + return 1; + } + + intcgm_cgm.bc = 0; + + erro = fread ( ch, 1, 2, intcgm_cgm.fp ); + if ( erro<2 ) return 1; + + intcgm_cgm.bl += 2; + + b = (ch[0] << 8) + ch[1]; + + len = b & 0x001F; + + id = ( b & 0x0FE0 ) >> 5; + + c = ( b & 0xF000 ) >> 12; + + cont = 0; + + if ( len > 30 ) + { + erro = fread ( ch, 1, 2, intcgm_cgm.fp ); + if ( erro<2 ) return 1; + + intcgm_cgm.bl += 2; + + b = (ch[0] << 8) + ch[1]; + + len = b & 0x7FFF; + cont = ( b & 0x8000 ); + } + + intcgm_cgm.len = len; + + if ( intcgm_cgm.len ) + { + if ( intcgm_cgm.len>intcgm_cgm.buff.size ) + intcgm_cgm.buff.dados = (char *) realloc ( intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len ); + + erro = fread ( intcgm_cgm.buff.dados, 1, intcgm_cgm.len, intcgm_cgm.fp ); + if ( errointcgm_cgm.buff.size ) + intcgm_cgm.buff.dados = (char *) realloc ( (char *)intcgm_cgm.buff.dados, sizeof(char) * intcgm_cgm.len ); + + erro = fread ( &intcgm_cgm.buff.dados[old_len], 1, len, intcgm_cgm.fp ); + if ( erro 254 ) + { + if ( cgmb_getu16 ( &l1 ) ) return 1; + cont = ( l1 & 0x8000); + l1 &= 0x7fff; + } + else + cont = 0; + + s = (char *)realloc ( (unsigned char *)s, (sizeof ( char ) * l1) + 1 ); + + for ( i=0; inome )==0 ) + { + int r = (*_cgmt_comandos[i][j]->func)(); + cgm_getfilepos (); + return r; + } + } + } + + + return 0; +} + +int cgmt_i ( long *i ) +{ + cgmt_getsep(); + + cgmt_getcom(); + + if ( fscanf( intcgm_cgm.fp, "%ld", i ) ) return 0; + + return 1; +} + +int cgmt_ci ( unsigned long *ci ) +{ + return cgmt_i ( (long*)ci ); +} + +int cgmt_cd ( unsigned long *cd ) +{ + return cgmt_i ( (long *) cd ); +} + +int cgmt_rgb ( unsigned long *r, unsigned long *g, unsigned long *b ) +{ + if ( cgmt_cd ( r ) ) return 1; + + if ( cgmt_cd ( g ) ) return 1; + + if ( cgmt_cd ( b ) ) return 1; + + return 0; +} + +int cgmt_ix ( long *ix ) +{ + return cgmt_i ( (long *) ix ); +} + +int cgmt_e ( short *e, const char **el ) +{ + char chr[256]; + int i; + char *pt; + + cgmt_getsep(); + + cgmt_getcom(); + + fscanf ( intcgm_cgm.fp, "%[^ \r\n\t\v\f,/;%\"\']", chr ); + + strlower(chr); + + pt = strtok(chr,"_$"); + + while ( (pt = strtok ( NULL, "_$" )) ) + strcat ( chr, pt ); + + for ( i=0; el[i]!=NULL; i++ ) + if ( strcmp( chr, el[i] ) == 0 ) + { + *e = i; + return 0; + }; + + return 1; +} + +int cgmt_r ( double *f ) +{ + cgmt_getsep(); + + cgmt_getcom(); + + if ( fscanf( intcgm_cgm.fp, "%lg", f ) ) return 0; + + return 1; +} + +int cgmt_s ( char **str ) +{ + char c, delim; + int intcgm_block = 80; + int i = 0; + + *str = (char *) malloc ( intcgm_block*sizeof(char) ); + + strcpy ( *str, "" ); + + cgmt_getsep(); + + cgmt_getcom(); + + delim = fgetc ( intcgm_cgm.fp ); + + if ( delim != '"' && delim != '\'' ) return 1; + + do + { + if ( (c=fgetc(intcgm_cgm.fp))==delim ) + if ( (c=fgetc(intcgm_cgm.fp))==delim ) + (*str)[i++] = c; + else + { + ungetc(c,intcgm_cgm.fp); + break; + } + else + (*str)[i++] = c; + + if ( (i+1)==intcgm_block ) + { + intcgm_block *= 2; + + *str = (char *) realloc ( *str, intcgm_block*sizeof(char) ); + } + } while ( 1 ); + + (*str)[i] = '\0'; + + /* addcounter();*/ + + return 0; +} + +int cgmt_vdc ( double *vdc ) +{ + long l; + + if ( intcgm_cgm.vdc_type==0 ) + { + if ( cgmt_i ( &l ) ) return 1; + *vdc = (double) l; + return 0; + } + else + return cgmt_r ( vdc ); +} + +int cgmt_p ( double *x, double *y ) +{ + cgmt_getparentheses(); + + if ( cgmt_vdc ( x ) ) return 1; + + if ( cgmt_vdc ( y ) ) return 1; + + cgmt_getparentheses(); + + return 0; +} + +int cgmt_co ( void *co ) +{ + if ( intcgm_cgm.clrsm == 0 ) /* indexed */ + { + unsigned long *ci = (unsigned long*)co; + if ( cgmt_ci ( ci ) ) return 1; + } + else + { + unsigned long *cb = (unsigned long *) co; + if ( cgmt_rgb ( &cb[0], &cb[1], &cb[2] ) ) return 1; + } + + return 0; +} diff --git a/cd/src/intcgm/intcgm2.h b/cd/src/intcgm/intcgm2.h new file mode 100755 index 0000000..d7f5204 --- /dev/null +++ b/cd/src/intcgm/intcgm2.h @@ -0,0 +1,52 @@ + +int cgm_getfilepos ( void ); + +int cgmb_exec_comand ( int, int ); +int cgmb_geti8 ( signed char * ); +int cgmb_geti16 ( short * ); +int cgmb_geti24 ( long * ); +int cgmb_geti32 ( long * ); +int cgmb_getu8 ( unsigned char * ); +int cgmb_getu16 ( unsigned short * ); +int cgmb_getu24 ( unsigned long * ); +int cgmb_getu32 ( unsigned long * ); +int cgmb_getfl32 ( float * ); +int cgmb_getfl64 ( double * ); +int cgmb_getfx32 ( float * ); +int cgmb_getfx64 ( double * ); +int cgmb_ter ( void ); +int cgmb_rch ( void ); +int cgmb_ci ( unsigned long * ); +int cgmb_cd ( unsigned long * ); +int cgmb_rgb ( unsigned long *, unsigned long *, unsigned long * ); +int cgmb_ix ( long * ); +int cgmb_e ( short * ); +int cgmb_i ( long * ); +int cgmb_u ( unsigned long * ); +int cgmb_r ( double * ); +int cgmb_s ( char ** ); +int cgmb_vdc ( double * ); +int cgmb_p ( double *, double * ); +int cgmb_co ( void * ); +int cgmb_getpixel ( void *, int ); +int cgmb_getc ( unsigned char * ); + +char *cgmt_getsep ( void ); +void cgmt_getcom ( void ); +char *cgmt_getparentheses ( void ); +int cgmt_ter ( void ); +int cgmt_rch ( void ); +int cgmt_i ( long * ); +int cgmt_ci ( unsigned long * ); +int cgmt_cd ( unsigned long * ); +int cgmt_rgb ( unsigned long *, unsigned long *, unsigned long * ); +int cgmt_ix ( long * ); +int cgmt_e ( short *, const char ** ); +int cgmt_r ( double * ); +int cgmt_s ( char ** ); +int cgmt_vdc ( double * ); +int cgmt_p ( double *, double * ); +int cgmt_co ( void * ); + + + diff --git a/cd/src/intcgm/intcgm4.c b/cd/src/intcgm/intcgm4.c new file mode 100755 index 0000000..4c8afe0 --- /dev/null +++ b/cd/src/intcgm/intcgm4.c @@ -0,0 +1,1265 @@ +#define _INTCGM4_C_ + +#include +#include +#include + +#include +#include + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm2.h" +#include "intcgm4.h" +#include "intcgm6.h" +#include "ellipse.h" +#include "circle.h" +#include "sism.h" + +#ifndef PI +#define PI 3.1415931 +#endif +#define TWOPI 2*PI + +static double myhypot ( double x, double y ) +{ + return sqrt ( x*x + y*y ); +} + +int cgm_do_vdcext ( tpoint first, tpoint second ) +{ + double width, height; + double tmp; + double razao_vp; + double razao_wn; + int w_pixel, h_pixel; + double w_mm, h_mm; + + if ( first.x > second.x ) + { + tmp = first.x; + first.x = second.x; + second.x = tmp; + } + + if ( first.y > second.y ) + { + tmp = first.y; + first.y = second.y; + second.y = tmp; + } + + width = intcgm_view_xmax-intcgm_view_xmin+1; + height = intcgm_view_ymax-intcgm_view_ymin+1; + + razao_vp = (double) width/ (double) height; + razao_wn = (second.x-first.x) / (second.y-first.y); + + if ( razao_vp > razao_wn ) + { + first.x -= ((second.y-first.y)*razao_vp - (second.x-first.x)) / 2.; + second.x = (second.y-first.y)*razao_vp+first.x; + } + else + { + first.y -= ((second.x-first.x)/razao_vp - (second.y-first.y)) / 2.; + second.y = (second.x-first.x)/razao_vp+first.y; + } + + intcgm_vdc_ext.xmin = first.x; + intcgm_vdc_ext.xmax = second.x; + intcgm_vdc_ext.ymin = first.y; + intcgm_vdc_ext.ymax = second.y; + + intcgm_scale_factor_x = width/(second.x-first.x); + intcgm_scale_factor_y = height/(second.y-first.y); + intcgm_scale_factor = sqrt(width * width + height * height)/sqrt((second.x-first.x)+(second.y-first.y)); + cdCanvasGetSize (intcgm_canvas, &w_pixel, &h_pixel, &w_mm, &h_mm ); + intcgm_scale_factor_mm_x = w_pixel/w_mm; + intcgm_scale_factor_mm_y = h_pixel/h_mm; + + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + { + intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin ); + intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax ); + intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin ); + intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax ); + } + else + { + intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor; + } + + cdCanvasClipArea (intcgm_canvas, cgm_vdcx2canvas(first.x), cgm_vdcx2canvas(second.x), + cgm_vdcy2canvas(first.y), cgm_vdcy2canvas(second.y) ); + cdCanvasClip(intcgm_canvas, CD_CLIPOFF ); + + return 0; +} + +int cgm_do_bckcol ( trgb rgb ) +{ + long int cor = cdEncodeColor ( (unsigned char) rgb.red, + (unsigned char) rgb.green, + (unsigned char) rgb.blue ); + + cdCanvasSetBackground (intcgm_canvas, cor ); + + return 0; +} + +int cgm_do_transp ( int transparency ) +{ + if ( transparency ) + cdCanvasBackOpacity (intcgm_canvas, CD_TRANSPARENT ); + else + cdCanvasBackOpacity (intcgm_canvas, CD_OPAQUE ); + + return 0; +} + +int cgm_do_clprec ( tpoint first, tpoint second ) +{ + double tmp; + + if ( first.x > second.x ) + { + tmp = first.x; + first.x = second.x; + second.x = tmp; + } + + if ( first.y > second.y ) + { + tmp = first.y; + first.y = second.y; + second.y = tmp; + } + + cdCanvasClipArea (intcgm_canvas, cgm_vdcx2canvas(first.x), cgm_vdcx2canvas(second.x), + cgm_vdcy2canvas(first.y), cgm_vdcy2canvas(second.y) ); + + return 0; +} + +int cgm_do_clpind ( int indicator ) +{ + if ( indicator ) + cdCanvasClip(intcgm_canvas, CD_CLIPAREA ); + else + cdCanvasClip(intcgm_canvas, CD_CLIPOFF ); + + return 0; +} + +int cgm_do_polyln ( int n_points, tpoint *pt ) +{ + int i; + long int cor; + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + cgm_getpolybbox ( pt, n_points, &bb_xmin, &bb_ymin, &bb_xmax, &bb_ymax ); + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES ); + + for ( i=0; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cdCanvasBegin(intcgm_canvas, CD_OPEN_LINES ); + + x = pt[0].x; y = pt[0].y; + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) ); + + for ( i=1; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + if ( n_points < 2 ) return 1; + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + for ( i=0; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + if ( n_points < 2 ) return 1; + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + pt[1].x = pt[0].x + pt[1].x; pt[1].y = pt[0].y + pt[1].y; + cdCanvasLine (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y), + cgm_vdcx2canvas(pt[1].x), cgm_vdcy2canvas(pt[1].y) ); + + for ( i=2; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_setmarktype ( intcgm_marker_att.type ); + cgm_setmarksize ( intcgm_marker_att.size ); + cor = cgm_getcolor ( intcgm_marker_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + for ( i=0; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_setmarktype ( intcgm_marker_att.type ); + cgm_setmarksize ( intcgm_marker_att.size ); + cor = cgm_getcolor ( intcgm_marker_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cdCanvasMark (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) ); + + for ( i=1; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinewidth ( intcgm_line_att.width ); + + if ( intcgm_fill_att.int_style!=HOLLOW && intcgm_fill_att.int_style!=EMPTY ) + { + cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) ); + + for ( i=0; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) ); + + p.x = pt[0].x; p.y = pt[0].y; + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(pt[0].x), cgm_vdcy2canvas(pt[0].y) ); + + for ( i=1; i intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + intcgm_edge_att.visibility = OFF; + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + if ( intcgm_fill_att.int_style!=HOLLOW && intcgm_fill_att.int_style!=EMPTY ) + { + cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) ); + start = 1; + for ( i=0; i corner2.x ) ? corner1.x : corner2.x; + bb_ymin = ( corner1.y < corner2.y ) ? corner1.y : corner2.y; + bb_ymax = ( corner1.y > corner2.y ) ? corner1.y : corner2.y; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + r = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) ); + g = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) ); + b = (unsigned char *) malloc ( nx*ny*sizeof(unsigned char) ); + + cx1 = cgm_vdcx2canvas(corner1.x); + cy1 = cgm_vdcy2canvas(corner1.y); + cx2 = cgm_vdcx2canvas(corner2.x); + cy2 = cgm_vdcy2canvas(corner2.y); + cx3 = cgm_vdcx2canvas(corner3.x); + cy3 = cgm_vdcy2canvas(corner3.y); + +#if 1 + if ( cx1cy3 ) + { + for ( i=0; icx3 && cy2==cy3 ) + { + tmp = nx; nx = ny; ny = tmp; + for ( i=0; icy3 && cx2>cx3 && cy2==cy3 ) + { + tmp = nx; nx = ny; ny = tmp; + for ( i=0; icx3 && cy1==cy3 && cx2==cx3 && cy2>cy3 ) + { + for ( i=0; icy3 && cx2cx3 && cy1==cy3 && cx2==cx3 && cy2cx2 ) + { + tmp = cx1; + cx1 = cx2; + cx2 = tmp; + } + + if ( cy1>cy2 ) + { + tmp = cy1; + cy1 = cy2; + cy2 = tmp; + } +#endif + + cdCanvasPutImageRectRGB (intcgm_canvas, nx, ny, r, g, b, cx1, cy1, cx2-cx1+1, cy2-cy1+1,0,0,0,0 ); + + free(r); + free(g); + free(b); + + return 0; +} + +int cgm_do_gdp ( int identifier, tpoint *pt, char *data_rec ) +{ + if ( identifier==-4 ) + cgm_sism4 ( pt, data_rec ); + else if ( identifier==-5 ) + cgm_sism5 ( data_rec ); + + return 0; +} + +int cgm_do_rect ( tpoint point1, tpoint point2 ) +{ + long int cor; + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + bb_xmin = ( point1.x < point2.x ) ? point1.x : point2.x; + bb_xmax = ( point1.x > point2.x ) ? point1.x : point2.x; + bb_ymin = ( point1.y < point2.y ) ? point1.y : point2.y; + bb_ymax = ( point1.y > point2.y ) ? point1.y : point2.y; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cdCanvasBegin(intcgm_canvas, cgm_setintstyle ( intcgm_fill_att.int_style ) ); + + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point1.x), cgm_vdcy2canvas(point1.y) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point2.x), cgm_vdcy2canvas(point1.y) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point2.x), cgm_vdcy2canvas(point2.y) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(point1.x), cgm_vdcy2canvas(point2.y) ); + + cdCanvasEnd (intcgm_canvas); + + return 0; +} + +int cgm_do_circle ( tpoint center, double radius ) +{ + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + bb_xmin = center.x - radius; + bb_xmax = center.x + radius; + bb_ymin = center.y - radius; + bb_ymax = center.y + radius; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin|| + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + if ( intcgm_fill_att.int_style!=EMPTY ) + { + long int cor; + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + + if ( intcgm_fill_att.int_style!=EMPTY ) + cgm_poly_circle ( center.x, center.y, radius, 0, TWOPI, CLOSED_CHORD ); + else + cgm_line_circle ( center.x, center.y, radius, 0, TWOPI, CLOSED_CHORD ); + } + + if ( intcgm_edge_att.visibility==ON ) + { + long int cor; + + cor = cgm_getcolor ( intcgm_edge_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinestyle ( intcgm_edge_att.type ); + cgm_setlinewidth ( intcgm_edge_att.width ); + + cgm_line_circle ( center.x, center.y, radius, 0., TWOPI, CLOSED_CHORD ); + } + + return 0; +} + +static double angulo ( double cx, double cy, double px, double py ) +{ + double ang; + if ((fabs(py-cy)<1e-9) && (fabs(px-cx)<1e-9)) + ang = 0.0; + else + ang = atan2 ( py - cy , px - cx ); + + if ( ang<0.) ang = TWOPI - fabs(ang); + + return ang; +} + +static void solve2 ( double m[][2], double *b, double *x ) +{ + double det; + + det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; + + if ( det==0.0 ) return; + + x[0] = ( b[0]*m[1][1] - b[1]*m[1][0] ) / det; + x[1] = ( m[0][0]*b[1] - m[0][1]*b[0] ) / det; +} + +static void getcenter ( double xs, double ys, double xi, double yi, double xe, double ye, + double *xc, double *yc ) +{ + double c[2]; + + double x2, y2, x3, y3, m[2][2], b[2]; + + x2 = xi - xs; + y2 = yi - ys; + x3 = xe - xs; + y3 = ye - ys; + + m[0][0] = 2*x2; + m[1][0] = 2*y2; + m[0][1] = 2*x3; + m[1][1] = 2*y3; + b[0] = x2*x2 + y2*y2; + b[1] = x3*x3 + y3*y3; + + solve2 ( m, b, c ); + + *xc = c[0] + xs; + *yc = c[1] + ys; +} + +int cgm_do_circ3p ( tpoint starting, tpoint intermediate, tpoint ending ) +{ + long int cor; + double xc, yc; + double angi, angm, angf; + double radius; + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + cor = cgm_getcolor ( intcgm_line_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + + getcenter ( starting.x, starting.y, intermediate.x, intermediate.y, ending.x, ending.y, &xc, &yc ); + + angi = angulo( xc, yc, starting.x, starting.y ); + angm = angulo( xc, yc, intermediate.x, intermediate.y ); + angf = angulo( xc, yc, ending.x, ending.y ); + + if ( angm intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_line_circle ( xc, yc, radius, angi, angf, OPEN ); + + return 0; +} + +int cgm_do_circ3pc ( tpoint starting, tpoint intermediate, tpoint ending, int close_type ) +{ + long int cor; + double xc, yc; + double angi, angm, angf; + double radius; + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinestyle ( intcgm_line_att.type ); + cgm_setlinewidth ( intcgm_line_att.width ); + + getcenter ( starting.x, starting.y, intermediate.x, intermediate.y, ending.x, ending.y, &xc, &yc ); + + angi = angulo( xc, yc, starting.x, starting.y ); + angm = angulo( xc, yc, intermediate.x, intermediate.y ); + angf = angulo( xc, yc, ending.x, ending.y ); + + radius = sqrt ( (starting.x-xc)*(starting.x-xc) + (starting.y-yc)*(starting.y-yc) ); + + bb_xmin = xc - radius; + bb_xmax = xc + radius; + bb_ymin = yc - radius; + bb_ymax = yc + radius; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + if ( angm intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinewidth ( intcgm_line_att.width ); + + angi = angulo( center.x, center.y, start.x, start.y ); + angf = angulo( center.x, center.y, end.x, end.y ); + + if ( angf intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cor = cgm_getcolor ( intcgm_fill_att.color ); + cdCanvasSetForeground (intcgm_canvas, cor ); + + cgm_setlinewidth ( intcgm_line_att.width ); + + angi = angulo( center.x, center.y, start.x, start.y ); + angf = angulo( center.x, center.y, end.x, end.y ); + + if ( angf intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, 0-inc, TWOPI-inc, 64, 2 ); + + return 0; +} + +int cgm_do_ellarc ( tpoint center, tpoint first_CDP, tpoint second_CDP, + tpoint start, tpoint end ) +{ + double w = myhypot ( first_CDP.x-center.x, first_CDP.y-center.y ); + double h = myhypot ( second_CDP.x-center.x, second_CDP.y-center.y ); + double inc = atan2 ( first_CDP.y-center.y, first_CDP.x-center.x ); + double a1 = atan2 ( start.y, start.x ); + double a2 = atan2 ( end.y, end.x ); + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + bb_xmin = center.x - w; + bb_xmax = center.x + w; + bb_ymin = center.y - h; + bb_ymax = center.y + h; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, a1-inc, a2-inc, 64, 0 ); + + return 0; +} + +int cgm_do_ellacl ( tpoint center, tpoint first_CDP, tpoint second_CDP, + tpoint start, tpoint end, int close_type ) +{ + double w = myhypot ( first_CDP.x-center.x, first_CDP.y-center.y ); + double h = myhypot ( second_CDP.x-center.x, second_CDP.y-center.y ); + double inc = atan2 ( first_CDP.y-center.y, first_CDP.x-center.x ); + double a1 = atan2 ( start.y, start.x ); + double a2 = atan2 ( end.y, end.x ); + + double bb_xmin, bb_ymin, bb_xmax, bb_ymax; + + bb_xmin = center.x - w; + bb_xmax = center.x + w; + bb_ymin = center.y - h; + bb_ymax = center.y + h; + +#if 0 + if ( cgm_vdcx2canvas(bb_xmin) > intcgm_view_xmax || cgm_vdcx2canvas(bb_xmax) < intcgm_view_xmin || + cgm_vdcy2canvas(bb_ymin) > intcgm_view_ymax || cgm_vdcy2canvas(bb_ymax) < intcgm_view_ymin ) return 0; +#else + if ( bb_xmin > intcgm_clip_xmax || bb_xmax < intcgm_clip_xmin || + bb_ymin > intcgm_clip_ymax || bb_ymax < intcgm_clip_ymin ) return 0; +#endif + + cgm_ElpArc ( center.x, center.y, w*2., h*2., inc, a1-inc, a2-inc, 64, close_type+1 ); + + return 0; +} + +int cgm_do_text_height ( double height ) +{ + cgm_setfont ( intcgm_text_att.font, intcgm_text_att.style, height ); + + return 0; +} + diff --git a/cd/src/intcgm/intcgm4.h b/cd/src/intcgm/intcgm4.h new file mode 100755 index 0000000..4b12873 --- /dev/null +++ b/cd/src/intcgm/intcgm4.h @@ -0,0 +1,28 @@ +int cgm_do_vdcext ( tpoint, tpoint ); +int cgm_do_bckcol ( trgb ); +int cgm_do_transp ( int ); +int cgm_do_clprec ( tpoint, tpoint ); +int cgm_do_clpind ( int ); +int cgm_do_polyln ( int, tpoint * ); +int cgm_do_incply ( int, tpoint * ); +int cgm_do_djtply ( int, tpoint * ); +int cgm_do_indpl ( int, tpoint * ); +int cgm_do_polymk ( int, tpoint * ); +int cgm_do_incplm ( int, tpoint * ); +int cgm_do_text ( int, char *, tpoint ); +int cgm_do_txtalign ( int hor, int ver ); +int cgm_do_polygn ( int, tpoint * ); +int cgm_do_incplg ( int, tpoint * ); +int cgm_do_plgset( int, int, tpoint *, short * ); +int cgm_do_cellar ( tpoint, tpoint, tpoint, int, int, long, tcolor * ); +int cgm_do_gdp ( int, tpoint *, char * ); +int cgm_do_rect ( tpoint point1, tpoint point2 ); +int cgm_do_circle ( tpoint, double ); +int cgm_do_circ3p ( tpoint, tpoint, tpoint ); +int cgm_do_circ3pc ( tpoint, tpoint, tpoint, int ); +int cgm_do_circcnt ( tpoint, tpoint, tpoint, double ); +int cgm_do_ccntcl ( tpoint, tpoint, tpoint, double, int ); +int cgm_do_ellips ( tpoint, tpoint, tpoint ); +int cgm_do_ellarc ( tpoint, tpoint, tpoint, tpoint, tpoint ); +int cgm_do_ellacl ( tpoint, tpoint, tpoint, tpoint, tpoint, int ); +int cgm_do_text_height ( double ); diff --git a/cd/src/intcgm/intcgm6.c b/cd/src/intcgm/intcgm6.c new file mode 100755 index 0000000..c23afee --- /dev/null +++ b/cd/src/intcgm/intcgm6.c @@ -0,0 +1,253 @@ +#include +#include +#include +#include + +#include + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm2.h" +#include "intcgm6.h" + +void cgm_setlinestyle ( int type ) +{ + switch ( type ) + { + case LINE_SOLID: + cdCanvasLineStyle (intcgm_canvas, CD_CONTINUOUS ); + break; + case LINE_DASH: + cdCanvasLineStyle (intcgm_canvas, CD_DASHED ); + break; + case LINE_DOT: + cdCanvasLineStyle (intcgm_canvas, CD_DOTTED ); + break; + case LINE_DASH_DOT: + cdCanvasLineStyle (intcgm_canvas, CD_DASH_DOT ); + break; + case LINE_DASH_DOT_DOT: + cdCanvasLineStyle (intcgm_canvas, CD_DASH_DOT_DOT ); + break; + } +} + +void cgm_setlinewidth ( double width ) +{ + int w; + if ( intcgm_cgm.lnwsm == ABSOLUTE ) + w = cgm_delta_vdc2canvas(width); + else + w = (int)floor ( width+0.5 ); + + cdCanvasLineWidth (intcgm_canvas, w>0?w:1 ); +} + +void cgm_setmarktype ( int type ) +{ + switch ( type ) + { + case MARK_DOT: + cdCanvasMarkType (intcgm_canvas, CD_STAR ); + break; + case MARK_PLUS: + cdCanvasMarkType (intcgm_canvas, CD_PLUS ); + break; + case MARK_ASTERISK: + cdCanvasMarkType (intcgm_canvas, CD_X ); + break; + case MARK_CIRCLE: + cdCanvasMarkType (intcgm_canvas, CD_CIRCLE ); + break; + case MARK_CROSS: + cdCanvasMarkType (intcgm_canvas, CD_PLUS ); + break; + } +} + +void cgm_setmarksize ( double size ) +{ + if ( intcgm_cgm.lnwsm == ABSOLUTE ) + cdCanvasMarkSize (intcgm_canvas, cgm_delta_vdc2canvas(size) ); + else + cdCanvasMarkSize (intcgm_canvas, (int)floor ( size*0.5 ) ); +} + +long int *cgm_setpattern ( pat_table pat ) +{ + int i; + long int *cor = (long int *) malloc ( pat.nx*pat.ny*sizeof(long int) ); + + for ( i=0; iindex==intcgm_fill_att.pat_index ) break; + } + + p = (long int *) malloc ( pat->nx*pat->ny*sizeof(long int) ); + + for ( i=0; inx*pat->ny; i++ ) + { + if ( intcgm_cgm.clrsm==DIRECT ) + p[i] = cdEncodeColor ((unsigned char)(pat->pattern[i].rgb.red*255./intcgm_cgm.color_ext.white.red), + (unsigned char)(pat->pattern[i].rgb.green*255./intcgm_cgm.color_ext.white.green), + (unsigned char)(pat->pattern[i].rgb.blue*255./intcgm_cgm.color_ext.white.blue) ); + else + p[i] = cdEncodeColor ((unsigned char)(intcgm_color_table[pat->pattern[i].ind].red*255/intcgm_cgm.color_ext.white.red), + (unsigned char)(intcgm_color_table[pat->pattern[i].ind].green*255/intcgm_cgm.color_ext.white.green), + (unsigned char)(intcgm_color_table[pat->pattern[i].ind].blue*255/intcgm_cgm.color_ext.white.blue) ); + } + + cdCanvasPattern(intcgm_canvas, pat->nx, pat->ny, (long *) p ); + + return CD_FILL; + } + else if ( style==HATCH ) + { + cdCanvasHatch (intcgm_canvas, intcgm_fill_att.hatch_index-1 ); + return CD_FILL; + } + else + return CD_CLOSED_LINES; +} + +long int cgm_getcolor ( tcolor cor ) +{ + + if ( intcgm_cgm.clrsm==INDEXED ) + return cdEncodeColor ((unsigned char)(intcgm_color_table[cor.ind].red*255/intcgm_cgm.color_ext.white.red), + (unsigned char)(intcgm_color_table[cor.ind].green*255/intcgm_cgm.color_ext.white.green), + (unsigned char)(intcgm_color_table[cor.ind].blue*255/intcgm_cgm.color_ext.white.blue) ); + else + return cdEncodeColor ((unsigned char)(cor.rgb.red*255/intcgm_cgm.color_ext.white.red), + (unsigned char)(cor.rgb.green*255/intcgm_cgm.color_ext.white.green), + (unsigned char)(cor.rgb.blue*255/intcgm_cgm.color_ext.white.blue) ); +} + +int cgm_vdcx2canvas ( double vdc ) +{ + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + return (int) floor ( intcgm_scale_factor_x*(vdc-intcgm_vdc_ext.xmin)+.5 ) + intcgm_view_xmin; + else + return (int) floor ( intcgm_scale_factor_mm_x*(vdc-intcgm_vdc_ext.xmin)*intcgm_cgm.scaling_mode.scale_factor + + intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor + .5 ); +} + +int cgm_vdcy2canvas ( double vdc ) +{ + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + return (int) floor ( intcgm_scale_factor_y*(vdc-intcgm_vdc_ext.ymin)+.5 ) + intcgm_view_ymin; + else + return (int) floor ( intcgm_scale_factor_mm_y*(vdc-intcgm_vdc_ext.ymin)*intcgm_cgm.scaling_mode.scale_factor + + intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor + .5 ); +} + +int cgm_delta_vdc2canvas ( double vdc ) +{ + int delta = (int) cgm_vdcx2canvas(intcgm_vdc_ext.xmin+vdc) - (int) cgm_vdcx2canvas(intcgm_vdc_ext.xmin); + return delta; +} + +double cgm_canvas2vdcx ( int x ) +{ + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + return (double) (x-intcgm_view_xmin)/intcgm_scale_factor_x + intcgm_vdc_ext.xmin; + else + return (double) (x-intcgm_view_xmin)/(intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor) + intcgm_vdc_ext.xmin; +} + +double cgm_canvas2vdcy ( int y ) +{ + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + return (double) (y-intcgm_view_ymin)/intcgm_scale_factor_y + intcgm_vdc_ext.ymin; + else + return (double) (y-intcgm_view_ymin)/(intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor) + intcgm_vdc_ext.ymin; +} + +void cgm_getpolybbox ( tpoint *pt, int n_points, double *bb_xmin, double *bb_ymin, + double *bb_xmax, double *bb_ymax ) +{ + int i; + + *bb_xmin = *bb_xmax = pt[0].x; + *bb_ymin = *bb_ymax = pt[0].y; + + for ( i=1; i *bb_xmax ) *bb_xmax = pt[i].x; + if ( pt[i].y < *bb_ymin ) *bb_ymin = pt[i].y; + else if ( pt[i].y > *bb_ymax ) *bb_ymax = pt[i].y; + } +} + +void cgm_getincpolybbox ( tpoint *pt, int n_points, double *bb_xmin, double *bb_ymin, + double *bb_xmax, double *bb_ymax ) +{ + int i; + double px, py; + + px = *bb_xmin = *bb_xmax = pt[0].x; + py = *bb_ymin = *bb_ymax = pt[0].y; + + for ( i=1; i *bb_xmax ) *bb_xmax = px; + if ( py < *bb_ymin ) *bb_ymin = py; + else if ( py > *bb_ymax ) *bb_ymax = py; + } +} + +int cgm_setfont ( int font, int style, double height ) +{ + int size; + int cy; + char* type_face; + + cy = cgm_delta_vdc2canvas ( height ); + size = (int) floor (((cy/intcgm_scale_factor_mm_y)/0.353)+0.5); + switch (font) + { + case 0: + type_face = "System"; + break; + case 1: + type_face = "Courier"; + break; + case 2: + type_face = "Times"; + break; + case 3: + type_face = "Helvetica"; + break; + default: + return 0; + } + + cdCanvasFont(intcgm_canvas, type_face, style, size ); + + return 0; +} diff --git a/cd/src/intcgm/intcgm6.h b/cd/src/intcgm/intcgm6.h new file mode 100755 index 0000000..fde660e --- /dev/null +++ b/cd/src/intcgm/intcgm6.h @@ -0,0 +1,15 @@ +void cgm_setlinestyle ( int ); +void cgm_setlinewidth ( double ); +void cgm_setmarktype ( int ); +void cgm_setmarksize ( double ); +long int cgm_getcolor ( tcolor ); +long int *cgm_setpattern ( pat_table ); +int cgm_setfont ( int, int, double ); +int cgm_setintstyle ( int ); +int cgm_vdcx2canvas ( double ); +int cgm_vdcy2canvas ( double ); +int cgm_delta_vdc2canvas ( double ); +double cgm_canvas2vdcx ( int ); +double cgm_canvas2vdcy ( int ); +void cgm_getpolybbox ( tpoint *, int, double *n, double *, double *, double * ); +void cgm_getincpolybbox ( tpoint *, int, double *, double *, double *, double * ); diff --git a/cd/src/intcgm/list.c b/cd/src/intcgm/list.c new file mode 100755 index 0000000..6fefbbc --- /dev/null +++ b/cd/src/intcgm/list.c @@ -0,0 +1,117 @@ +/* +* list.c +* Generic List Manager +* TeCGraf +* +*/ + +#include +#include +#include "list.h" + +TList *cgm_NewList ( void ) +{ + TList *l = (TList *) malloc ( sizeof (TList) ); + + list_nba(l) = 8; + list_head(l) = (void **)malloc(list_nba(l)*sizeof(void*)); + list_n(l) = 0; + + return l; +} + +TList *cgm_AppendList ( TList *l, void *i ) +{ + if ( l == NULL ) + return NULL; + + if (list_n(l) == list_nba(l)) + { + list_nba(l) += 32; + list_head(l) = (void **)realloc(list_head(l),list_nba(l)*sizeof(void*)); + } + + list_head(l)[list_n(l)]=i; + list_n(l)++; + + return l; +} + +TList *cgm_AddList ( TList *l, int n, void *info ) +{ + int i; + + if ( l == NULL) + return NULL; + + if ( n < 1) + n=1; + + if ( n > list_n(l) ) + return cgm_AppendList( l, info ); + + --n; /* o usuario ve a lista iniciando em 1 e a */ + /* lista e' implementada iniciando em 0 */ + + if (list_n(l) == list_nba(l)) + { + list_nba(l) *= 2; + list_head(l) = (void **)realloc(list_head(l),list_nba(l)*sizeof(void*)); + } + + for (i=list_n(l)-1; i>=n; --i) + list_head(l)[i+1]=list_head(l)[i]; + + list_head(l)[n]=info; + list_n(l)++; + return l; +} + +TList *cgm_DelList ( TList *l, int n ) +{ + int i; + + if ( l == NULL || list_n(l) == 0 || n < 0) + return NULL; + + if ( n < 1) + n=1; + + if ( n > list_n(l)) + n=list_n(l); + + --n; /* o usuario ve a lista iniciando em 1 e a */ + /* lista e' implementada iniciando em 0 */ + list_n(l)--; + + for (i=n; i list_n(l) ? NULL : list_head(l)[n-1]; +} + +int cgm_DelEntry ( TList *l, void *entry ) +{ + int i=1; + + if ( l == NULL || list_n(l) == 0) + return 0; + + for (i=0; i< list_n(l); ++i) + if (list_head(l)[i]==entry) + { + cgm_DelList(l,i+1); /* o usuario ve a lista iniciando em 1 e a */ + /* lista e' implementada iniciando em 0 */ + return i+1; + } + return 0; +} + diff --git a/cd/src/intcgm/list.h b/cd/src/intcgm/list.h new file mode 100755 index 0000000..c661a7c --- /dev/null +++ b/cd/src/intcgm/list.h @@ -0,0 +1,30 @@ + +/* +* list.h +* prototipos das funcoes de manipulacao de lista +* TeCGraf +* 27 Ago 93 +*/ + +#ifndef __LIST_H__ +#define __LIST_H__ + +typedef struct TList_ + { + void **h; /* head */ + int nba; + int n; /* Numero de elementos na lista */ + } TList; + +#define list_head(l) ((l)->h) +#define list_n(l) ((l)->n) +#define list_nba(l) ((l)->nba) + +TList *cgm_NewList ( void ); +TList *cgm_AppendList ( TList *, void * ); +TList *cgm_AddList ( TList *, int, void * ); +TList *cgm_DelList ( TList *, int ); +void *cgm_GetList ( TList *, int ); +int cgm_DelEntry ( TList *, void * ); + +#endif diff --git a/cd/src/intcgm/sism.c b/cd/src/intcgm/sism.c new file mode 100755 index 0000000..9946ac3 --- /dev/null +++ b/cd/src/intcgm/sism.c @@ -0,0 +1,392 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "list.h" +#include "types.h" +#include "intcgm.h" +#include "intcgm2.h" +#include "intcgm6.h" + +static tpoint trace_start_pos, base_direction, amp_direction, trace_direction; +static double bline_sc_f, amp_sc_f, trc_st_f, VA_bline_offset, pos_clp_lmt, + neg_clp_lmt, pos_bckfil_bnd, neg_bckfil_bnd; +static int trace_dsp_md, samp_type, n_samp, wig_trc_mod, nul_clr_i, n_trace; +static double *sample; +static long *coind; +static int trace=0; + +void cgm_sism4 ( tpoint *pt, char *data_rec ) +{ + sscanf ( data_rec, "%lg %lg %lg %lg %lg %lg %d %d %d %lg %lg %*d %d %d %d", + &bline_sc_f, &_sc_f, &trc_st_f, &VA_bline_offset, &pos_clp_lmt, + &neg_clp_lmt, &trace_dsp_md, &samp_type, &n_samp, &pos_bckfil_bnd, + &neg_bckfil_bnd, &wig_trc_mod, &nul_clr_i, &n_trace ); + + trace_start_pos = pt[0]; + base_direction = pt[1]; + amp_direction = pt[2]; + trace_direction = pt[3]; + trace = 0; +} + +/* adjust the samples to the amplitude direction vector */ +static void dirvet ( double dx ) +{ + int i; + + for ( i=0; imn && samp2mx) + { + x[n] = min + dx; + y[n++] = interpl(i,y1,y2,min); + x[n] = max + dx; + y[n++] = interpl(i,y1,y2,max); + x[n] = max + dx; + y[n++] = y2; + x[n] = min + dx; + y[n++] = y2; + } + + else if ( (samp1>mn && samp1mn && samp2mn && samp1mx ) + { + x[n] = min + dx; + y[n++] = y1; + x[n] = sample[i] + dx; + y[n++] = y1; + x[n] = max + dx; + y[n++] = interpl(i,y1,y2,max); + x[n] = max + dx; + y[n++] = y2; + x[n] = min + dx; + y[n++] = y2; + } + + else if ( samp1>mx && samp2>mx ) + { + x[n] = min + dx; + y[n++] = y1; + x[n] = max + dx; + y[n++] = y1; + x[n] = max + dx; + y[n++] = y2; + x[n] = min + dx; + y[n++] = y2; + } + + else if ( samp1>mx && samp2mn ) + { + x[n] = min + dx; + y[n++] = y1; + x[n] = max + dx; + y[n++] = y1; + x[n] = max + dx; + y[n++] = interpl(i,y1,y2,max); + x[n] = sample[i+1] + dx; + y[n++] = y2; + x[n] = min + dx; + y[n++] = y2; + } + + else if ( samp1>mn && samp10 ) + { + if ( cordep ) + { + cor = cdEncodeColor ( (unsigned char)((intcgm_color_table[coind[i]].red*255)/intcgm_cgm.color_ext.white.red), + (unsigned char)((intcgm_color_table[coind[i]].green*255)/intcgm_cgm.color_ext.white.green), + (unsigned char)((intcgm_color_table[coind[i]].blue*255)/intcgm_cgm.color_ext.white.blue) ); + cdCanvasSetForeground (intcgm_canvas, cor ); + } + + cdCanvasBegin(intcgm_canvas, CD_FILL ); + + for ( j=0; jnegclp && sample[i]negclp && sample[i+1]negclp && sample[i+1]posclp ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(negclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,negclp)) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) ); + } + else if ( sample[i]>negclp && sample[i]posclp ) + { + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(sample[i] + dx), cgm_vdcy2canvas(y1) ); + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) ); + } + else if ( sample[i]>posclp && sample[i+1]negclp ) + cdCanvasVertex (intcgm_canvas, cgm_vdcx2canvas(posclp + dx), cgm_vdcy2canvas(interpl(i,y1,y2,posclp)) ); + else if ( sample[i]>posclp && sample[i+1]negclp && sample[i] 7 ) + coind = (long *) malloc ( n_samp*sizeof(long) ); + + for ( i=0; i= 64 ) + mode = 64; + else if ( trace_mode >= 32 ) + mode = 32; + else if ( trace_mode >= 16 ) + mode = 16; + else if ( trace_mode >= 8 ) + mode = 8; + else if ( trace_mode >= 4 ) + mode = 4; + else if ( trace_mode >= 2 ) + mode = 2; + else if ( trace_mode == 1 ) + mode = 1; + + switch ( mode ) + { + case 64: + neg_clp = neg_clp_lmt; + pos_clp = ( pos_clp_lmt < 0 ) ? pos_clp_lmt : 0; + vasamp ( mode, pos_clp, neg_clp, 1 ); + trace_mode -= 64; + break; + case 32: + neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0; + pos_clp = pos_clp_lmt; + vasamp ( mode, pos_clp, neg_clp, 1 ); + trace_mode -= 32; + break; + case 16: + bgclfl( mode ); + trace_mode -= 16; + break; + case 8: + bgclfl( mode ); + trace_mode -= 8; + break; + case 4: + neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0; + pos_clp = pos_clp_lmt; + vasamp ( mode, pos_clp, neg_clp, 0 ); + trace_mode -= 4; + break; + case 2: + neg_clp = ( neg_clp_lmt > 0 ) ? neg_clp_lmt : 0; + pos_clp = pos_clp_lmt; + vasamp ( mode, pos_clp, neg_clp, 0 ); + trace_mode -= 2; + break; + case 1: + wiggle ( pos_clp_lmt, neg_clp_lmt ); + trace_mode -= 1; + break; + } + } while ( trace_mode != 0 ); + + free(sample); + + if ( trace_dsp_md > 7 ) + free(coind); +} diff --git a/cd/src/intcgm/sism.h b/cd/src/intcgm/sism.h new file mode 100755 index 0000000..f2f08f0 --- /dev/null +++ b/cd/src/intcgm/sism.h @@ -0,0 +1,3 @@ +void cgm_sism4 ( tpoint *, char * ); +void cgm_sism5 ( char * ); + diff --git a/cd/src/intcgm/tparse.c b/cd/src/intcgm/tparse.c new file mode 100755 index 0000000..9bc47b3 --- /dev/null +++ b/cd/src/intcgm/tparse.c @@ -0,0 +1,1370 @@ +#define _INTCGM2_C_ + +#include +#include +#include + +#include +#include + +#include "list.h" +#include "types.h" +#include "bparse.h" +#include "intcgm.h" +#include "intcgm2.h" +#include "intcgm4.h" +#include "intcgm6.h" + +int cgmt_begmtf ( void ) /* begin metafile */ +{ + char *str=NULL; + + if ( cgmt_s ( &str ) ) return 1; + + if (cdcgmbegmtfcb) + { + int err; + err = cdcgmbegmtfcb ( intcgm_canvas, &intcgm_view_xmin, &intcgm_view_ymin, &intcgm_view_xmax, &intcgm_view_ymax ); + if ( err==CD_ABORT ) return -1; + } + + free(str); + + return cgmt_ter(); +} + +int cgmt_endmtf ( void ) /* end metafile */ +{ + cgmt_ter(); + return 1; +} + +int cgmt_begpic ( void ) /* begin picture */ +{ + char *string=NULL; + + if ( intcgm_cgm.first ) + intcgm_cgm.first = 0; + else + cdCanvasFlush(intcgm_canvas); + + cdCanvasClip(intcgm_canvas, CD_CLIPAREA); + + if ( cgmt_s ( &string ) ) return 1; + + if (cdcgmbegpictcb) + { + int err; + err = cdcgmbegpictcb ( intcgm_canvas, string ); + if ( err==CD_ABORT ) return -1; + } + + free(string); + + return cgmt_ter(); +} + +int cgmt_begpib ( void ) /* begin picture body */ +{ + if (cdcgmbegpictbcb) + { + int err; + err = cdcgmbegpictbcb ( intcgm_canvas, 1., 1., intcgm_scale_factor_x, intcgm_scale_factor_y, + intcgm_scale_factor_mm_x*intcgm_cgm.scaling_mode.scale_factor, + intcgm_scale_factor_mm_y*intcgm_cgm.scaling_mode.scale_factor, + intcgm_cgm.drawing_mode, + intcgm_vdc_ext.xmin, intcgm_vdc_ext.ymin, intcgm_vdc_ext.xmax, intcgm_vdc_ext.ymax ); + if ( err==CD_ABORT ) return -1; + } + + + if (cdcgmsizecb) + { + int err, w, h; + double w_mm=0., h_mm=0.; + + w = intcgm_view_xmax-intcgm_view_xmin+1; + h = intcgm_view_ymax-intcgm_view_ymin+1; + + if ( intcgm_cgm.vdc_type==INTEGER ) + { + w = (int) (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x); + h = (int) (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y); + if ( intcgm_cgm.scaling_mode.mode==METRIC ) + { + w_mm = w * intcgm_cgm.scaling_mode.scale_factor; + h_mm = h * intcgm_cgm.scaling_mode.scale_factor; + } + } + else + { + if ( intcgm_cgm.scaling_mode.mode==METRIC ) + { + w_mm = (intcgm_cgm.vdc_ext.second.x - intcgm_cgm.vdc_ext.first.x) * intcgm_cgm.scaling_mode.scale_factor; + h_mm = (intcgm_cgm.vdc_ext.second.y - intcgm_cgm.vdc_ext.first.y) * intcgm_cgm.scaling_mode.scale_factor; + } + } + + err = cdcgmsizecb ( intcgm_canvas, w, h, w_mm, h_mm ); + if ( err==CD_ABORT ) return -1; + } + + return cgmt_ter(); +} + +int cgmt_endpic ( void ) /* end picture */ +{ + return cgmt_ter(); +} + +int cgmt_mtfver ( void ) /* metafile version */ +{ + long version; + + if ( cgmt_i ( &version ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_mtfdsc ( void ) /* metafile description */ +{ + char *string=NULL; + + if ( cgmt_s ( &string ) ) return 1; + + free(string); + + return cgmt_ter(); +} + +int cgmt_vdctyp ( void ) /* vdc type */ +{ + const char *options[] = { "integer", "real", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.vdc_type), options ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_intpre ( void ) /* integer precision */ +{ + if ( cgmt_i ( &(intcgm_cgm.int_prec.t_prec.minint) ) ) return 1; + if ( cgmt_i ( &(intcgm_cgm.int_prec.t_prec.maxint) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_realpr ( void ) /* real precision */ +{ + if ( cgmt_r ( &(intcgm_cgm.real_prec.t_prec.minreal) ) ) return 1; + if ( cgmt_r ( &(intcgm_cgm.real_prec.t_prec.maxreal) ) ) return 1; + if ( cgmt_i ( &(intcgm_cgm.real_prec.t_prec.digits) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_indpre ( void ) /* index precision */ +{ + if ( cgmt_i ( &(intcgm_cgm.ix_prec.t_prec.minint) ) ) return 1; + if ( cgmt_i ( &(intcgm_cgm.ix_prec.t_prec.maxint) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_colpre ( void ) /* colour precision */ +{ + if ( cgmt_i ( &(intcgm_cgm.cd_prec) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_colipr ( void ) /* colour index precision */ +{ + if ( cgmt_i ( &(intcgm_cgm.cix_prec) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_maxcoi ( void ) /* maximum colour index */ +{ + if ( cgmt_i ( &(intcgm_cgm.max_cix) ) ) return 1; + + intcgm_color_table = (trgb *) realloc ( intcgm_color_table, sizeof(trgb)*(intcgm_cgm.max_cix+1) ); + + intcgm_color_table[0].red = 255; + intcgm_color_table[0].green = 255; + intcgm_color_table[0].blue = 255; + intcgm_color_table[1].red = 0; + intcgm_color_table[1].green = 0; + intcgm_color_table[1].blue = 0; + + return cgmt_ter(); +} + +int cgmt_covaex ( void ) /* colour value extent */ +{ + if ( cgmt_rgb ( &(intcgm_cgm.color_ext.black.red), &(intcgm_cgm.color_ext.black.green), &(intcgm_cgm.color_ext.black.blue) ) ) return 1; + + if ( cgmt_rgb ( &(intcgm_cgm.color_ext.white.red), &(intcgm_cgm.color_ext.white.green), &(intcgm_cgm.color_ext.white.blue) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_mtfell ( void ) /* metafile element list */ +{ + char *elist=NULL; + + if ( cgmt_s ( &elist ) ) return 1; + + free(elist); + + return cgmt_ter(); +} + +int cgmt_bmtfdf (void ) /* begin metafile defaults */ +{ + return cgmt_ter(); +} + +int cgmt_emtfdf ( void ) /* end metafile defaults */ +{ + return cgmt_ter(); +} + +int cgmt_fntlst ( void ) /* font list */ +{ + char *font=NULL; + + if ( intcgm_text_att.font_list==NULL ) intcgm_text_att.font_list = cgm_NewList(); + + while ( cgmt_ter() ) + { + if ( cgmt_s ( &font ) ) return 1; + cgm_AppendList ( intcgm_text_att.font_list, font ); + } + + return 0; +} + +int cgmt_chslst ( void ) /* character set list */ +{ + const char *options[] = { "std94", "std96", "std94multibyte", "std96multibyte", + "completecode", NULL }; + char *tail; + short code; + + do + { + if ( cgmt_e ( &(code), options ) ) return 1; + + if ( cgmt_s ( &tail ) ) return 1; + + free ( tail ); + + } while ( cgmt_ter() ); + + return 0; +} + +int cgmt_chcdac ( void ) /* character coding announcer */ +{ + const char *options[] = { "basic7bit", "basic8bit", "extd7bit", "extd8bit", NULL }; + short code; + + if ( cgmt_e ( &(code), options ) ) return 1; + + return cgmt_ter (); +} + +int cgmt_sclmde ( void ) /* scaling mode */ +{ + const char *options[] = { "abstract", "metric", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.scaling_mode.mode), options ) ) return 1; + + if ( cgmt_r ( &(intcgm_cgm.scaling_mode.scale_factor) ) ) return 1; + + if ( intcgm_cgm.scaling_mode.mode==ABSTRACT ) intcgm_cgm.scaling_mode.scale_factor=1.; + + intcgm_cgm.drawing_mode = ABSTRACT; + + if (cdcgmsclmdecb) + { + int err; + err = cdcgmsclmdecb ( intcgm_canvas, intcgm_cgm.scaling_mode.mode, &intcgm_cgm.drawing_mode, &intcgm_cgm.scaling_mode.scale_factor ); + if ( err==CD_ABORT ) return -1; + } + + if ( intcgm_cgm.drawing_mode==ABSTRACT ) + { + intcgm_clip_xmin = cgm_canvas2vdcx ( intcgm_view_xmin ); + intcgm_clip_xmax = cgm_canvas2vdcx ( intcgm_view_xmax ); + intcgm_clip_ymin = cgm_canvas2vdcy ( intcgm_view_ymin ); + intcgm_clip_ymax = cgm_canvas2vdcy ( intcgm_view_ymax ); + } + else + { + intcgm_clip_xmin = intcgm_vdc_ext.xmin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_xmax = intcgm_vdc_ext.xmax*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymin = intcgm_vdc_ext.ymin*intcgm_cgm.scaling_mode.scale_factor; + intcgm_clip_ymax = intcgm_vdc_ext.ymax*intcgm_cgm.scaling_mode.scale_factor; + } + + return cgmt_ter(); +} + +int cgmt_clslmd ( void ) /* colour selection mode */ +{ + const char *options[] = { "indexed", "direct", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.clrsm), options ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_lnwdmd ( void ) /* line width specification mode */ +{ + const char *options[] = { "abstract", "scaled", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.lnwsm), options ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_mkszmd ( void ) /* marker size specification mode */ +{ + const char *options[] = { "abstract", "scaled", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.mkssm), options ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_edwdmd ( void ) /* edge width specification mode */ +{ + const char *options[] = { "abstract", "scaled", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.edwsm), options ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_vdcext ( void ) /* vdc extent */ +{ + if ( cgmt_p ( &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y) ) ) return 1; + + if ( cgmt_p ( &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ) ) return 1; + + if (cdcgmvdcextcb) + { + int err; + err = cdcgmvdcextcb( intcgm_canvas, intcgm_cgm.vdc_type, &(intcgm_cgm.vdc_ext.first.x), &(intcgm_cgm.vdc_ext.first.y), + &(intcgm_cgm.vdc_ext.second.x), &(intcgm_cgm.vdc_ext.second.y) ); + if (err==CD_ABORT) return -1; + } + + cgm_do_vdcext ( intcgm_cgm.vdc_ext.first, intcgm_cgm.vdc_ext.second ); + + return cgmt_ter(); +} + +int cgmt_bckcol ( void ) /* backgound colour */ +{ + if ( cgmt_rgb ( &(intcgm_cgm.back_color.red), &(intcgm_cgm.back_color.green), &(intcgm_cgm.back_color.blue) ) ) return 1; + + cgm_do_bckcol ( intcgm_cgm.back_color ); + + return cgmt_ter(); +} + +int cgmt_vdcipr ( void ) /* vdc integer precision */ +{ + if ( cgmt_i ( &(intcgm_cgm.vdc_int.t_prec.minint) ) ) return 1; + if ( cgmt_i ( &(intcgm_cgm.vdc_int.t_prec.maxint) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_vdcrpr ( void ) /* vdc real precision */ +{ + if ( cgmt_r ( &(intcgm_cgm.vdc_real.t_prec.minreal) ) ) return 1; + if ( cgmt_r ( &(intcgm_cgm.vdc_real.t_prec.maxreal) ) ) return 1; + if ( cgmt_i ( &(intcgm_cgm.vdc_real.t_prec.digits) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_auxcol ( void ) /* auxiliary colour */ +{ + if ( cgmt_co ( &(intcgm_cgm.aux_color) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_transp ( void ) /* transparency */ +{ + const char *options[] = { "on", "off", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.transparency), options ) ) return 1; + + cgm_do_transp ( intcgm_cgm.transparency ); + + return cgmt_ter(); +} + +int cgmt_clprec ( void ) /* clip rectangle */ +{ + if ( cgmt_p ( &(intcgm_cgm.clip_rect.first.x), &(intcgm_cgm.clip_rect.first.y) ) ) return 1; + + if ( cgmt_p ( &(intcgm_cgm.clip_rect.second.x), &(intcgm_cgm.clip_rect.second.y) ) ) return 1; + + cgm_do_clprec ( intcgm_cgm.clip_rect.first, intcgm_cgm.clip_rect.second ); + + return cgmt_ter(); +} + +int cgmt_clpind ( void ) /* clip indicator */ +{ + const char *options[] = { "on", "off", NULL }; + + if ( cgmt_e ( &(intcgm_cgm.clip_ind), options ) ) return 1; + + cgm_do_clpind ( intcgm_cgm.clip_ind ); + + return cgmt_ter(); +} + +static tpoint *get_points ( int *np ) +{ + *np=0; + + do + { + if ( cgmt_p ( &(intcgm_point_list[*np].x), &(intcgm_point_list[*np].y) ) ) return NULL; + ++(*np); + if ( *np==intcgm_npoints) + { + intcgm_npoints *= 2; + intcgm_point_list = (tpoint *) realloc ( intcgm_point_list, intcgm_npoints*sizeof(tpoint) ); + } + } while ( cgmt_ter() ); + + return intcgm_point_list; +} + +int cgmt_polyln ( void ) /* polyline */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_polyln ( np, pt ); + + return 0; +} + +int cgmt_incply ( void ) /* incremental polyline */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_incply ( np, pt ); + + return 0; +} + +int cgmt_djtply ( void ) /* disjoint polyline */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_djtply ( np, pt ); + + return 0; +} + +int cgmt_indjpl ( void ) /* incremental disjoint polyline */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_indpl ( np, pt ); + + return 0; +} + +int cgmt_polymk ( void ) /* polymarker */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_polymk ( np, pt ); + + return 0; +} + +int cgmt_incplm ( void ) /* incremental polymarker */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_incplm ( np, pt ); + + return 0; +} + +int cgmt_text ( void ) /* text */ +{ + tpoint pos; + const char *options[] = { "final", "notfinal", NULL }; + short flag; + char *string; + + if ( cgmt_p ( &(pos.x), &(pos.y) ) ) return 1; + + if ( cgmt_e ( &flag, options ) ) return 1; + + if ( cgmt_s ( &string ) ) return 1; + + cgm_do_text ( NORM_TEXT, string, pos ); + + free ( string ); + + return cgmt_ter(); +} + +int cgmt_rsttxt ( void ) /* restricted text */ +{ + double width, height; + tpoint pos; + const char *options[] = { "final", "notfinal", NULL }; + short flag; + char *string; + + if ( cgmt_vdc ( &width ) ) return 1; + + if ( cgmt_vdc ( &height ) ) return 1; + + if ( cgmt_p ( &(pos.x), &(pos.y) ) ) return 1; + + if ( cgmt_e ( &flag, options ) ) return 1; + + if ( cgmt_s ( &string ) ) return 1; + + intcgm_text_att.height = height; + + cgm_do_text ( RESTRICTED_TEXT, string, pos ); + + if ( string!= NULL ) free ( string ); + + return cgmt_ter(); +} + +int cgmt_apdtxt ( void ) /* append text */ +{ + const char *options[] = { "final", "notfinal", NULL }; + short flag; + char *string; + + if ( cgmt_e ( &flag, options ) ) return 1; + + if ( cgmt_s ( &string ) ) return 1; + + free ( string ); + + return cgmt_ter(); +} + +int cgmt_polygn ( void ) /* polygon */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_polygn ( np, pt ); + + return 0; +} + +int cgmt_incplg ( void ) /* incremental polygon */ +{ + tpoint *pt; + int np; + + pt = get_points( &np ); + if ( pt == NULL ) return 1; + + cgm_do_incplg ( np, pt ); + + return 0; +} + +static int get_point_set ( tpoint **pts, short **flags, int *np ) +{ + int intcgm_block=500; + const char *options[] = { "invis", "vis", "closeinvis", "closevis", NULL }; + + *np=0; + *pts = (tpoint *) malloc ( intcgm_block*sizeof(tpoint) ); + *flags = (short *) malloc ( intcgm_block*sizeof(short) ); + + do + { + if ( cgmt_p ( &((*pts)[*np].x), &((*pts)[*np].y) ) ) return 1; + + if ( cgmt_e ( &((*flags)[*np]), options ) ) return 1; + + ++(*np); + if ( *np==intcgm_block) + { + intcgm_block *= 2; + *pts = (tpoint *) realloc ( *pts, intcgm_block*sizeof(tpoint) ); + *flags = (short *) realloc ( *flags, intcgm_block*sizeof(short) ); + } + } while ( cgmt_ter() ); + + return 0; +} + +int cgmt_plgset ( void ) /* polygon set */ +{ + tpoint *pt; + short *flag; + int np; + + if ( get_point_set ( &pt, &flag, &np ) ) return 1; + + cgm_do_plgset( NO, np, pt, flag ); + + free ( pt ); + free ( flag ); + + return 0; +} + +int cgmt_inpgst ( void ) /* incremental polygon set */ +{ + tpoint *pt; + short *flag; + int np; + + if ( get_point_set ( &pt, &flag, &np ) ) return 1; + + cgm_do_plgset( YES, np, pt, flag ); + + free ( pt ); + free ( flag ); + + return 0; +} + +int cgmt_cellar ( void ) /* cell array */ +{ + tpoint corner1; + tpoint corner2; + tpoint corner3; + long nx, ny; + long local_color_prec; + tcolor *cell; + int i,k; + + if ( cgmt_p ( &(corner1.x), &(corner1.y) ) ) return 1; + if ( cgmt_p ( &(corner2.x), &(corner2.y) ) ) return 1; + if ( cgmt_p ( &(corner3.x), &(corner3.y) ) ) return 1; + + if ( cgmt_i ( &nx ) ) return 1; + if ( cgmt_i ( &ny ) ) return 1; + + if ( cgmt_i ( &(local_color_prec) ) ) return 1; + + cell = (tcolor *) malloc ( nx*ny*sizeof(tcolor) ); + + cgmt_getparentheses(); + + for ( k=0; kindex) ) ) return 1; + + if ( cgmt_i ( &(pat->nx) ) ) return 1; + if ( cgmt_i ( &(pat->ny) ) ) return 1; + + if ( cgmt_i ( &(local_color_prec) ) ) return 1; + + pat->pattern = (tcolor *) malloc ( pat->nx*pat->ny*sizeof(tcolor) ); + + cgmt_getparentheses(); + + for ( i=0; i<(pat->nx*pat->ny); i++ ) + if ( cgmt_co ( &(pat->pattern[i]) ) ) return 1; + + cgmt_getparentheses(); + + for ( i=0; (p=(pat_table *)cgm_GetList(intcgm_fill_att.pat_list,i))!=NULL; i++ ) + { + if ( p->index==pat->index ) + { + free(p->pattern); + cgm_DelList(intcgm_fill_att.pat_list,i); + break; + } + } + + cgm_AppendList ( intcgm_fill_att.pat_list, pat ); + + return cgmt_ter(); +} + +int cgmt_patsiz ( void ) /* pattern size */ +{ + if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.height.x) ) ) return 1; + if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.height.y) ) ) return 1; + if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.width.x) ) ) return 1; + if ( cgmt_vdc ( &(intcgm_fill_att.pat_size.width.y) ) ) return 1; + + return cgmt_ter(); +} + +int cgmt_coltab ( void ) /* colour table */ +{ + long starting_index; + + if ( cgmt_i ( &(starting_index) ) ) return 1; + + while ( cgmt_ter() ) + { + if ( cgmt_rgb ( &(intcgm_color_table[starting_index].red), &(intcgm_color_table[starting_index].green), + &(intcgm_color_table[starting_index].blue) ) ) return 1; + starting_index++; + } + + return 0; +} + +int cgmt_asf ( void ) /* asfs */ +{ + const char *asf_value[] = { "bundled", "indiv", NULL }; + const char *asf_type[] = { "linetype" , "linewidth" , "linecolr" , + "markertype" , "markersize", "markercolr", + "textfontindex", "textprec" , "charexp" , + "charspace" , "textcolr" , "intstyle" , + "fillcolr" , "hatchindex", "patindex" , + "edgetype" , "edgewidth" , "edgecolr" , + "all" , "allline" , "allmarker" , + "alltext" , "allfill" , "alledge", NULL }; + tasf *pair; + + if ( intcgm_asf_list==NULL ) intcgm_asf_list = cgm_NewList(); + + while( cgmt_ter() ) + { + pair = (tasf *) malloc ( sizeof (tasf) ); + + if ( cgmt_e ( &(pair->type), asf_type ) ) return 1; + if ( cgmt_e ( &(pair->value), asf_value ) ) return 1; + + cgm_AppendList ( intcgm_asf_list, pair ); + } + + return 0; +} + +int cgmt_escape ( void ) /* escape */ +{ + long identifier; + char *data_rec; + + if ( cgmt_i ( &(identifier) ) ) return 1; + + if ( cgmt_s ( &data_rec ) ) return 1; + + free(data_rec); + + return cgmt_ter(); +} + +int cgmt_messag ( void ) /* message */ +{ + const char *options[] = { "noaction", "action", NULL }; + char *text; + short flag; + + if ( cgmt_e ( &flag, options ) ) return 1; + + if ( cgmt_s ( &text ) ) return 1; + + free(text); + + return cgmt_ter(); +} + +int cgmt_appdta ( void ) /* application data */ +{ + long identifier; + char *data_rec; + + if ( cgmt_i ( &identifier ) ) return 1; + + if ( cgmt_s ( &data_rec ) ) return 1; + + free(data_rec); + + return cgmt_ter(); +} diff --git a/cd/src/intcgm/tparse.h b/cd/src/intcgm/tparse.h new file mode 100755 index 0000000..c1292bc --- /dev/null +++ b/cd/src/intcgm/tparse.h @@ -0,0 +1,101 @@ +#ifndef _TPARSE_H_ +#define _TPARSE_H_ + +int cgmt_begmtf ( void ); +int cgmt_endmtf ( void ); +int cgmt_begpic ( void ); +int cgmt_begpib ( void ); +int cgmt_endpic ( void ); +int cgmt_mtfver ( void ); +int cgmt_mtfdsc ( void ); +int cgmt_vdctyp ( void ); +int cgmt_intpre ( void ); +int cgmt_realpr ( void ); +int cgmt_indpre ( void ); +int cgmt_colpre ( void ); +int cgmt_colipr ( void ); +int cgmt_maxcoi ( void ); +int cgmt_covaex ( void ); +int cgmt_mtfell ( void ); +int cgmt_bmtfdf (void ); +int cgmt_emtfdf ( void ); +int cgmt_fntlst ( void ); +int cgmt_chslst ( void ); +int cgmt_chcdac ( void ); +int cgmt_sclmde ( void ); +int cgmt_clslmd ( void ); +int cgmt_lnwdmd ( void ); +int cgmt_mkszmd ( void ); +int cgmt_edwdmd ( void ); +int cgmt_vdcext ( void ); +int cgmt_bckcol ( void ); +int cgmt_vdcipr ( void ); +int cgmt_vdcrpr ( void ); +int cgmt_auxcol ( void ); +int cgmt_transp ( void ); +int cgmt_clprec ( void ); +int cgmt_clpind ( void ); +int cgmt_polyln ( void ); +int cgmt_incply ( void ); +int cgmt_djtply ( void ); +int cgmt_indjpl ( void ); +int cgmt_polymk ( void ); +int cgmt_incplm ( void ); +int cgmt_text ( void ); +int cgmt_rsttxt ( void ); +int cgmt_apdtxt ( void ); +int cgmt_polygn ( void ); +int cgmt_incplg ( void ); +int cgmt_plgset ( void ); +int cgmt_inpgst ( void ); +int cgmt_cellar ( void ); +int cgmt_gdp ( void ); +int cgmt_rect ( void ); +int cgmt_circle ( void ); +int cgmt_circ3p ( void ); +int cgmt_cir3pc ( void ); +int cgmt_circnt ( void ); +int cgmt_ccntcl ( void ); +int cgmt_ellips ( void ); +int cgmt_ellarc ( void ); +int cgmt_ellacl ( void ); +int cgmt_lnbdin ( void ); +int cgmt_lntype ( void ); +int cgmt_lnwidt ( void ); +int cgmt_lncolr ( void ); +int cgmt_mkbdin ( void ); +int cgmt_mktype ( void ); +int cgmt_mksize ( void ); +int cgmt_mkcolr ( void ); +int cgmt_txbdin ( void ); +int cgmt_txftin ( void ); +int cgmt_txtprc ( void ); +int cgmt_chrexp ( void ); +int cgmt_chrspc ( void ); +int cgmt_txtclr ( void ); +int cgmt_chrhgt ( void ); +int cgmt_chrori ( void ); +int cgmt_txtpat ( void ); +int cgmt_txtali ( void ); +int cgmt_chseti ( void ); +int cgmt_achsti ( void ); +int cgmt_fillin ( void ); +int cgmt_intsty ( void ); +int cgmt_fillco ( void ); +int cgmt_hatind ( void ); +int cgmt_patind ( void ); +int cgmt_edgind ( void ); +int cgmt_edgtyp( void ); +int cgmt_edgwid ( void ); +int cgmt_edgcol ( void ); +int cgmt_edgvis ( void ); +int cgmt_fillrf ( void ); +int cgmt_pattab ( void ); +int cgmt_patsiz ( void ); +int cgmt_coltab ( void ); +int cgmt_asf ( void ); +int cgmt_escape ( void ); +int cgmt_messag ( void ); +int cgmt_appdta ( void ); + +#endif diff --git a/cd/src/intcgm/types.h b/cd/src/intcgm/types.h new file mode 100755 index 0000000..6d6f65c --- /dev/null +++ b/cd/src/intcgm/types.h @@ -0,0 +1,225 @@ +#ifndef _CGM_TYPES_H_ +#define _CGM_TYPES_H_ + +typedef struct { + double xmin; + double xmax; + double ymin; + double ymax; + } tlimit; + +typedef struct { + unsigned long red; + unsigned long green; + unsigned long blue; + } trgb; + +typedef union { + int ind; + trgb rgb; + } tcolor; + +typedef struct { + double x; + double y; + } tpoint; + +typedef struct { + char *dados; + int size; + } tdados; + +typedef struct { + FILE *fp; + + int (*cgmf)(void); + + int file_size; + + int first; + + int mode; /* character, binary, clear text */ + + int len; + + tdados buff; + + short vdc_type; + + union { + long b_prec; /* 8, 16, 24, 32 */ + struct { long minint; long maxint; } t_prec ; + } int_prec; + union { + long b_prec; /* float*32, float*64, fixed*32, fixed*64 */ + struct { double minreal; double maxreal; long digits; } t_prec; + } real_prec; + union { + long b_prec; /* 8, 16, 24, 32 */ + struct { long minint; long maxint; } t_prec; + } ix_prec; + long cd_prec; + long cix_prec; + struct { + trgb black; + trgb white; + } color_ext; + long max_cix; + + struct { + short mode; + double scale_factor; + } scaling_mode; + + short drawing_mode; + + short clrsm; + short lnwsm; + short mkssm; + short edwsm; + + union { + long b_prec; /* 8, 16, 24, 32 */ + struct { long minint; long maxint; } t_prec; + } vdc_int; + union { + long b_prec; /* float*32, float*64, fixed*32, fixed*64 */ + struct { double minreal; double maxreal; long digits; } t_prec; + } vdc_real; + + struct { + tpoint first; + tpoint second; + } vdc_ext; + + trgb back_color; + + tcolor aux_color; + + short transparency; + + struct { + tpoint first; + tpoint second; + } clip_rect; + + short clip_ind; + + int bc; /* byte count */ + int pc; /* pixel count */ + + long bl; /* bytes lidos */ + + int cl; /* coluna para alinhamento */ + + } t_cgm; + +typedef struct { + long index; + long type; + double width; + tcolor color; + } _line_att; + +typedef struct { + long index; + long type; + double size; + tcolor color; + } _marker_att; + +typedef struct { + long index; + long font_index; + TList *font_list; + int font; + int style; + int size; + short prec; + double exp_fact; + double char_spacing; + tcolor color; + double height; + tpoint char_up; + tpoint char_base; + short path; + struct { short hor; + short ver; + double cont_hor; + double cont_ver; + } alignment; + } _text_att; + +typedef struct { + long index; + short int_style; + tcolor color; + long hatch_index; + long pat_index; + tpoint ref_pt; + TList *pat_list; + struct { + tpoint height; + tpoint width; + } pat_size; + } _fill_att; + +typedef struct { + long index; + long type; + double width; + tcolor color; + short visibility; + } _edge_att; + +enum { OFF, ON }; + +enum { YES, NO }; + +enum { INTEGER, REAL }; + +enum { STRING, CHAR, STROKE }; + +enum { ABSOLUTE, SCALED }; + +enum { ABSTRACT, METRIC }; + +enum { INDEXED, DIRECT }; + +enum { MARK_DOT=1, MARK_PLUS=2, MARK_ASTERISK=3, MARK_CIRCLE=4, MARK_CROSS=5 }; + +enum { LINE_SOLID=1, LINE_DASH=2, LINE_DOT=3, LINE_DASH_DOT=4, + LINE_DASH_DOT_DOT=5 }; + +enum { EDGE_SOLID=1, EDGE_DASH=2, EDGE_DOT=3, EDGE_DASH_DOT=4, + EDGE_DASH_DOT_DOT=5 }; + +enum { HOLLOW, SOLID, PATTERN, HATCH, EMPTY }; + +enum { HORIZONTAL=1, VERTICAL=2, POSITIVE_SLOPE=3, NEGATIVE_SLOPE=4, + HV_CROSS=5, SLOPE_CROSS=6 }; + +enum { PATH_RIGHT, PATH_LEFT, PATH_UP, PATH_DOWN }; + +enum { NORMHORIZ, LEFT, CTR, RIGHT, CONTHORIZ }; + +enum { NORMVERT, TOP, CAP, HALF, BASE, BOTTOM, CONTVERT }; + +enum { LINE_TYPE, LINE_WIDTH, LINE_COLOUR, MARKER_TYPE, MARKER_SIZE, + MARKER_COLOUR, TEXT_FONT_INDEX, TEXT_PRECISION, + CHARACTER_EXPANSION_FACTOR, CHARACTER_SPACING, TEXT_COLOUR, + INTERIOR_STYLE, FILL_COLOUR, HATCH_INDEX, PATTERN_INDEX, EDGE_TYPE, + EDGE_WIDTH, EDGE_COLOUR, ALL, ALL_LINE, ALL_MARKER, ALL_TEXT, ALL_FILL, + ALL_EDGE }; + +enum { INDIVIDUAL, BUNDLED }; + +enum { INVISIBLE, VISIBLE, CLOSE_INVISIBLE, CLOSE_VISIBLE }; + +enum { PIE, CHORD }; + +enum { OPEN, CLOSED_PIE, CLOSED_CHORD }; + +enum { NORM_TEXT, RESTRICTED_TEXT }; + +#endif diff --git a/cd/src/lua3/cdlua.c b/cd/src/lua3/cdlua.c new file mode 100755 index 0000000..ea5ac44 --- /dev/null +++ b/cd/src/lua3/cdlua.c @@ -0,0 +1,4366 @@ +/***************************************************************************\ +* CDLUA.C, for LUA 3.1 * +* Diego Fernandes Nehab, Antonio Escano Scuri * +* 01/99 * +* Implements all that TOLUA couldn't handle. * +\***************************************************************************/ + +/***************************************************************************\ +* Included definitions. * +\***************************************************************************/ +#include +#include +#include +#include + +/***************************************************************************\ +* CD Definitions. * +\***************************************************************************/ +#include "cd.h" +#include "wd.h" + +#include "cdirgb.h" /* cdRedImage, cdGreenImage, cdBlueImage */ + +/* error checking when there is no active canvas */ +#include "cdvoid.h" + +/***************************************************************************\ +* LUA Definitions. * +\***************************************************************************/ +#include +#include + +/***************************************************************************\ +* CDLUA Definitions. * +\***************************************************************************/ +#include "cdlua.h" +#include "cdlua3_private.h" + +/***************************************************************************\ +* Globals. * +\***************************************************************************/ +static int color_tag; +static int stipple_tag; +static int pattern_tag; +static int image_tag; +static int bitmap_tag; +static int imagergb_tag; +static int imagergba_tag; +static int palette_tag; +static int imagemap_tag; +static int channel_tag; +static int canvas_tag; +static int state_tag; + +static channel_t channel_info; +static cdCanvas *void_canvas; +static cdContextLUA* cdlua_drivers[50]; +static int cdlua_numdrivers = 0; +static lua_Object cdlua_namespace; + +int luaL_cd_open(void); /* from toluacd.c */ +int luaL_wd_open(void); /* from toluawd.c */ +void cdlua_initdrivers(void); /* to cdluactx.c */ + + +/***************************************************************************\ +* Creation and destruction of types LUA can't handle. * +\***************************************************************************/ + +void cdlua_setnamespace(char* name, char* new_name) +{ + lua_Object obj = lua_getglobal(name); + lua_pushobject(cdlua_namespace); + lua_pushstring(new_name); + lua_pushobject(obj); + lua_settable(); +} + +void cdlua_register(char* name, lua_CFunction func) +{ + lua_register(name, func); + + if (name[0] == 'w') + { + char new_name[100]; + new_name[0] = 'w'; + strcpy(new_name+1, name+2); + cdlua_setnamespace(name, new_name); /* wdXXX */ + } + else + cdlua_setnamespace(name, name+2); /* cdXXX */ +} + +void cdlua_pushnumber(double num, char* name) +{ + lua_pushnumber(num); lua_setglobal(name); + cdlua_setnamespace(name, name+3); /* CD_XXXX */ +} + +static void cdlua_pushcolor(long color, char* name) +{ + lua_pushusertag((void*)color, color_tag); lua_setglobal(name); + cdlua_setnamespace(name, name+3); /* CD_XXXX */ +} + +void cdlua_addcontext(cdContextLUA* luactx) +{ + int i; + luactx->id = cdlua_numdrivers; + cdlua_drivers[cdlua_numdrivers] = luactx; + + cdlua_pushnumber(cdlua_numdrivers, luactx->name); + + /* skip CD_SIZECB, register other callbacks */ + for (i=1; icb_n; i++) + { + cdlua_pushnumber(i, luactx->cb_list[i].name); + } + + cdlua_numdrivers++; +} + +/***************************************************************************\ +* Creates a CD canvas as a canvas_tag usertag lua_Object. * +* If the creation fails, the function returns a nil lua_Object. * +\***************************************************************************/ +static void cdlua_createcanvas(void) +{ + lua_Object driver; + + long int driver_i; + canvas_t *canvas_p; + void *data_p; + + /* if there is not enough memory */ + canvas_p = (canvas_t *) malloc(sizeof(canvas_t)); + if (!canvas_p) { + lua_pushnil(); + return; + } + + /* get driver parameter */ + driver = lua_getparam(1); + if (!lua_isnumber(driver)) + lua_error("cdCreateCanvas: invalid driver parameter!"); + driver_i = (long int) lua_getnumber(driver); + + if (driver_i >= cdlua_numdrivers) + lua_error("cdCreateCanvas: unknown driver!"); + + data_p = cdlua_drivers[driver_i]->checkdata(2); + canvas_p->cd_canvas = cdCreateCanvas(cdlua_drivers[driver_i]->ctx(), data_p); + + /* if creation failed, return nil so that the user can compare */ + /* the result with nil and know that it failed */ + if (!canvas_p->cd_canvas) { + free(canvas_p); + lua_pushnil(); + } + /* else, return a canvas_t structure */ + else + lua_pushusertag((void *) canvas_p, canvas_tag); +} + +static lua_Object wdlua_hardcopy_func_lua = 0; + +static void wdlua_hardcopy_func(void) +{ + lua_callfunction(wdlua_hardcopy_func_lua); +} + +static void wdlua_hardcopy(void) +{ + lua_Object driver; + lua_Object canvas; + + long int driver_i; + canvas_t *canvas_p; + void *data_p; + + /* get driver parameter */ + driver = lua_getparam(1); + if (!lua_isnumber(driver)) + lua_error("wdHardcopy: invalid driver parameter!"); + driver_i = (long int) lua_getnumber(driver); + + canvas = lua_getparam(3); + + if (canvas == LUA_NOOBJECT) + lua_error("wdHardcopy: canvas parameter missing!"); + + /* if the creation failed, canvas can be nil, in which case we */ + /* issue an error */ + if (lua_isnil(canvas)) + lua_error("wdHardcopy: attempt to get a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("wdHardcopy: invalid canvas parameter!"); + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("wdHardcopy: attempt to get a killed canvas!"); + + wdlua_hardcopy_func_lua = lua_getparam(4); + + if (!lua_isfunction(wdlua_hardcopy_func_lua)) + lua_error("wdHardcopy: invalid draw function!"); + + if (lua_getparam(5) != LUA_NOOBJECT) + lua_error("wdHardcopy: too many parameters!"); + + if (driver_i >= cdlua_numdrivers) + lua_error("wdHardcopy: unknown driver!"); + + data_p = cdlua_drivers[driver_i]->checkdata(2); + wdHardcopy(cdlua_drivers[driver_i]->ctx(), data_p, canvas_p->cd_canvas, wdlua_hardcopy_func); +} + +static void cdlua_getcontext(void) +{ + lua_Object canvas; + canvas_t *canvas_p; + cdContext* ctx; + int driver_i = -1, i; + + canvas = lua_getparam(1); + + if (canvas == LUA_NOOBJECT) + lua_error("cdGetContext: canvas parameter missing!"); + + /* if the creation failed, canvas can be nil, in which case we */ + /* issue an error */ + if (lua_isnil(canvas)) + lua_error("cdGetContext: attempt to get a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdGetContext: invalid canvas parameter!"); + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdGetContext: attempt to get a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdGetContext: too many parameters!"); + + ctx = cdGetContext(canvas_p->cd_canvas); + + for (i=0; i < cdlua_numdrivers; i++) + { + if (ctx == cdlua_drivers[i]->ctx()) + { + driver_i = i; + break; + } + } + + if (i == cdlua_numdrivers) + lua_error("cdGetContext: unknown driver!"); + + lua_pushnumber(driver_i); +} + +static void cdlua_contextcaps(void) +{ + lua_Object driver; + long int driver_i; + unsigned long caps; + + /* get driver parameter */ + driver = lua_getparam(1); + if (!lua_isnumber(driver)) + lua_error("cdCreateCanvas: invalid driver parameter!"); + driver_i = (long int) lua_getnumber(driver); + + if (driver_i >= cdlua_numdrivers) + lua_error("cdContextCaps: unknown driver!"); + + caps = cdContextCaps(cdlua_drivers[driver_i]->ctx()); + + lua_pushnumber(caps); +} + +/***************************************************************************\ +* Activates a cd canvas. * +\***************************************************************************/ +static void cdlua_activate(void) +{ + lua_Object canvas; + canvas_t *canvas_p; + + canvas = lua_getparam(1); + + if (canvas == LUA_NOOBJECT) + lua_error("cdActivate: canvas parameter missing!"); + + /* if canvas is nil, activate a void canvas */ + if (lua_isnil(canvas)) { + lua_pushnumber(cdActivate(void_canvas)); + return; + } + + if (lua_tag(canvas) != canvas_tag) { + cdActivate(void_canvas); + lua_error("cdActivate: invalid canvas parameter!"); + } + + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) { + cdActivate(void_canvas); + lua_error("cdActivate: attempt to activate a killed canvas!"); + } + + if (lua_getparam(2) != LUA_NOOBJECT) { + cdActivate(void_canvas); + lua_error("cdActivate: too many parameters!"); + } + + lua_pushnumber(cdActivate(canvas_p->cd_canvas)); +} + +/***************************************************************************\ +* Returns the active canvas. * +\***************************************************************************/ +static void cdlua_activecanvas(void) +{ + canvas_t *canvas_p; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdActiveCanvas: too many parameters!"); + + canvas_p = (canvas_t *) malloc(sizeof(canvas_t)); + if (!canvas_p) { + lua_pushnil(); + return; + } + + canvas_p->cd_canvas = cdActiveCanvas(); + + /* if the active canvas is NULL, return nil so that the user can compare */ + /* the result with nil */ + if (!canvas_p->cd_canvas) { + free(canvas_p); + lua_pushnil(); + } + else + lua_pushusertag((void *) canvas_p, canvas_tag); +} + +cdCanvas* cdlua_checkcanvas(int pos) +{ + lua_Object canvas; + canvas_t *canvas_p; + + canvas = lua_getparam(pos); + + if (canvas == LUA_NOOBJECT) + lua_error("cdlua_getcanvas: canvas parameter missing!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdlua_getcanvas: invalid canvas parameter!"); + + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdlua_getcanvas: attempt to get a killed canvas!"); + + return canvas_p->cd_canvas; +} + +cdCanvas* cdlua_getcanvas(void) +{ + return cdlua_checkcanvas(1); +} + +void cdlua_pushcanvas(cdCanvas* canvas) +{ + canvas_t *canvas_p = (canvas_t *) malloc(sizeof(canvas_t)); + canvas_p->cd_canvas = canvas; + lua_pushusertag((void *)canvas_p, canvas_tag); +} + +static void cdlua_savestate(void) +{ + state_t *state_p; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdSaveState: too many parameters!"); + + state_p = (state_t *) malloc(sizeof(state_t)); + if (!state_p) { + lua_pushnil(); + return; + } + + state_p->state = cdSaveState(); + + /* if the active canvas is NULL, return nil so that the user can compare */ + /* the result with nil */ + if (!state_p->state) { + free(state_p); + lua_pushnil(); + } + else + lua_pushusertag((void *) state_p, state_tag); +} + +static void cdlua_restorestate(void) +{ + lua_Object state; + state_t *state_p; + + state = lua_getparam(1); + if (state == LUA_NOOBJECT) + lua_error("cdRestoreState: state parameter missing!"); + if (lua_isnil(state)) + lua_error("cdRestoreState: attempt to restore a NIL state!"); + + if (lua_tag(state) != state_tag) + lua_error("cdRestoreState: invalid canvas parameter!"); + + state_p = (state_t *) lua_getuserdata(state); + if (!state_p->state) + lua_error("cdRestoreState: attempt to restore a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdRestoreState: too many parameters!"); + + cdRestoreState(state_p->state); +} + +static void cdlua_releasestate(void) +{ + lua_Object state; + state_t *state_p; + + state = lua_getparam(1); + if (state == LUA_NOOBJECT) + lua_error("cdReleaseState: state parameter missing!"); + if (lua_isnil(state)) + lua_error("cdReleaseState: attempt to release a NIL state!"); + + if (lua_tag(state) != state_tag) + lua_error("cdReleaseState: invalid canvas parameter!"); + + state_p = (state_t *) lua_getuserdata(state); + if (!state_p->state) + lua_error("cdReleaseState: attempt to release a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdReleaseState: too many parameters!"); + + cdReleaseState(state_p->state); + state_p->state = NULL; +} + +static void cdlua_LineStyleDashes(void) +{ + lua_Object dashes, count, value; + int *dashes_int, dashes_count, i; + + dashes = lua_getparam(1); + if (dashes == LUA_NOOBJECT) + lua_error("cdLineStyleDashes: dashes parameter missing!"); + if (lua_isnil(dashes)) + lua_error("cdLineStyleDashes: dashes parameter is nil!"); + if (!lua_istable(dashes)) + lua_error("cdLineStyleDashes: invalid dashes parameter!"); + + count = lua_getparam(2); + if (count == LUA_NOOBJECT) + lua_error("cdLineStyleDashes: count parameter missing!"); + if (lua_isnil(count)) + lua_error("cdLineStyleDashes: count parameter is nil!"); + if (!lua_isnumber(dashes)) + lua_error("cdLineStyleDashes: invalid count parameter!"); + + dashes_count = (int)lua_getnumber(count); + dashes_int = malloc(dashes_count*sizeof(int)); + + for (i=0; i < dashes_count; i++) + { + lua_pushobject(dashes); + lua_pushnumber(i+1); + value = lua_gettable(); + + if (!lua_isnumber(value)) + lua_error("cdLineStyleDashes: invalid dash!"); + + dashes_int[i] = (int)lua_getnumber(value); + } + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdLineStyleDashes: too many parameters!"); + + cdLineStyleDashes(dashes_int, dashes_count); + free(dashes_int); +} + +/***************************************************************************\ +* Frees a previously alocated canvas. * +\***************************************************************************/ +static void cdlua_killcanvas(void) +{ + lua_Object canvas; + canvas_t *canvas_p; + cdCanvas *current_canvas; + + canvas = lua_getparam(1); + + if (canvas == LUA_NOOBJECT) + lua_error("cdKillCanvas: canvas parameter missing!"); + + /* if the creation failed, canvas can be nil, in which case we */ + /* issue an error */ + if (lua_isnil(canvas)) + lua_error("cdKillCanvas: attempt to kill a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdKillCanvas: invalid canvas parameter!"); + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdKillCanvas: attempt to kill a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillCanvas: too many parameters!"); + + /* find out about the currently active canvas */ + current_canvas = cdActiveCanvas(); + + /* this should never happen, unless the user did it on purpouse! */ + if (canvas_p->cd_canvas == void_canvas) + lua_error("cdKillCanvas: trying to kill the void canvas???"); + + /* if the user killed the currently active canvas, activate void canvas */ + if (canvas_p->cd_canvas == current_canvas) { + cdActivate(void_canvas); + } + + cdKillCanvas(canvas_p->cd_canvas); + canvas_p->cd_canvas = NULL; +} + +/***************************************************************************\ +* Creates a color as a color_tag usertag lua_Object. The color value is * +* placed in the (void *) value. Not beautiful, but works best. * +\***************************************************************************/ +static void cdlua_encodecolor(void) +{ + lua_Object red, green, blue; + float red_f, green_f, blue_f; + unsigned char red_i, green_i, blue_i; + long int color_i; + + red = lua_getparam(1); + green = lua_getparam(2); + blue = lua_getparam(3); + if (!(lua_isnumber(red) && lua_isnumber(green) && lua_isnumber(blue))) + lua_error("cdEncodeColor: invalid color component parameter!"); + red_f = (float) lua_getnumber(red); + green_f = (float) lua_getnumber(green); + blue_f = (float) lua_getnumber(blue); + if (red_f < 0 || red_f > 255 || green_f < 0 || + green_f > 255 || blue_f < 0 || blue_f > 255) + lua_error("cdEncodeColor: color components values should be in range [0, 255]!"); + red_i = (unsigned char) (red_f); + green_i = (unsigned char) (green_f); + blue_i = (unsigned char) (blue_f); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdEncodeColor: too many parameters!"); + + color_i = cdEncodeColor(red_i, green_i, blue_i); + lua_pushusertag((void *) color_i, color_tag); +} + +static void cdlua_encodealpha(void) +{ + lua_Object color, alpha; + float alpha_f; + unsigned char alpha_i; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdEncodeAlpha: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + alpha = lua_getparam(2); + if (!lua_isnumber(alpha)) + lua_error("cdEncodeAlpha: invalid alpha parameter!"); + alpha_f = (float) lua_getnumber(alpha); + if (alpha_f < 0 || alpha_f > 255) + lua_error("cdEncodeAlpha: alpha components values should be in range [0, 255]!"); + alpha_i = (unsigned char) (alpha_f); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdEncodeAlpha: too many parameters!"); + + color_i = cdEncodeAlpha(color_i, alpha_i); + lua_pushusertag((void *) color_i, color_tag); +} + +/***************************************************************************\ +* Decodes a color previously created. * +\***************************************************************************/ +static void cdlua_decodecolor(void) +{ + lua_Object color; + long int color_i; + unsigned char red_i, green_i, blue_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdDecodeColor: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdDecodeColor: too many parameters!"); + + cdDecodeColor(color_i, &red_i, &green_i, &blue_i); + lua_pushnumber(red_i); + lua_pushnumber(green_i); + lua_pushnumber(blue_i); +} + +static void cdlua_decodealpha(void) +{ + lua_Object color; + long int color_i; + unsigned char alpha_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdDecodeAlpha: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdDecodeAlpha: too many parameters!"); + + alpha_i = cdDecodeAlpha(color_i); + lua_pushnumber(alpha_i); +} + +static void cdlua_alpha(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdRed: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdAlpha: too many parameters!"); + + lua_pushnumber(cdAlpha(color_i)); +} + +static void cdlua_red(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdRed: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdRed: too many parameters!"); + + lua_pushnumber(cdRed(color_i)); +} + +static void cdlua_blue(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdBlue: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdBlue: too many parameters!"); + + lua_pushnumber(cdBlue(color_i)); +} + +static void cdlua_green(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdGreen: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdGreen: too many parameters!"); + + lua_pushnumber(cdGreen(color_i)); +} + +static void cdlua_reserved(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdReserved: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdReserved: too many parameters!"); + + lua_pushnumber(cdReserved(color_i)); +} + +/***************************************************************************\ +* Creates a stipple as a stipple_tag usertag lua_Object. * +\***************************************************************************/ +static void cdlua_createstipple(void) +{ + lua_Object width, height; + long int width_i, height_i; + stipple_t *stipple_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateStipple: invalid dimension parameters!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateStipple: stipple dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreateStipple: too many parameters!"); + + stipple_p = (stipple_t *) malloc(sizeof(stipple_t)); + if (!stipple_p) { + lua_pushnil(); + return; + } + + stipple_p->size = width_i*height_i; + stipple_p->height = height_i; + stipple_p->width = width_i; + stipple_p->value = (unsigned char *) malloc(stipple_p->size); + if (!stipple_p->value) { + free(stipple_p); + lua_pushnil(); + return; + } + + memset(stipple_p->value, '\0', stipple_p->size); + lua_pushusertag((void *) stipple_p, stipple_tag); +} + +static void cdlua_getstipple(void) +{ + int width, height; + unsigned char * stipple; + stipple_t *stipple_p; + + stipple = cdGetStipple(&width, &height); + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdGetStipple: too many parameters!"); + + stipple_p = (stipple_t *) malloc(sizeof(stipple_t)); + if (!stipple_p) { + lua_pushnil(); + return; + } + + stipple_p->size = width*height; + stipple_p->height = height; + stipple_p->width = width; + stipple_p->value = (unsigned char *) malloc(stipple_p->size); + if (!stipple_p->value) { + free(stipple_p); + lua_pushnil(); + return; + } + + memcpy(stipple_p->value, stipple, stipple_p->size); + lua_pushusertag((void *) stipple_p, stipple_tag); +} + +/***************************************************************************\ +* Frees a previously allocated stipple. We don't free stipple_p to prevent * +* a problem if the user called killstipple twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killstipple(void) +{ + lua_Object stipple; + stipple_t *stipple_p; + + stipple = lua_getparam(1); + if (stipple == LUA_NOOBJECT) + lua_error("cdKillStipple: stipple parameter missing!"); + if (lua_isnil(stipple)) + lua_error("cdKillStipple: attempt to kill a NIL stipple!"); + if (lua_tag(stipple) != stipple_tag) + lua_error("cdKillStipple: invalid stipple parameter!"); + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p->value) + lua_error("cdKillStipple: attempt to kill a killed stipple!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillStipple: too many parameters!"); + + free(stipple_p->value); + stipple_p->value = NULL; +} + +/***************************************************************************\ +* Creates a pattern as a pattern_tag usertag lua_Object. A pattern can be * +* considered and treated as a color table. * +\***************************************************************************/ +static void cdlua_createpattern(void) +{ + lua_Object width, height; + long int width_i, height_i; + pattern_t *pattern_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreatePattern: invalid dimension parameters!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreatePattern: pattern dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreatePattern: too many parameters!"); + + pattern_p = (pattern_t *) malloc(sizeof(pattern_t)); + if (!pattern_p) { + lua_pushnil(); + return; + } + + pattern_p->size = width_i*height_i; + pattern_p->width = width_i; + pattern_p->height = height_i; + pattern_p->color = (long int *) malloc(pattern_p->size * sizeof(long int)); + if (!pattern_p->color) { + free(pattern_p); + lua_pushnil(); + return; + } + + memset(pattern_p->color, 255, pattern_p->size * sizeof(long int)); + lua_pushusertag((void *) pattern_p, pattern_tag); +} + +static void cdlua_getpattern(void) +{ + int width, height; + long int * pattern; + pattern_t *pattern_p; + + pattern = cdGetPattern(&width, &height); + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdGetPattern: too many parameters!"); + + pattern_p = (pattern_t *) malloc(sizeof(pattern_t)); + if (!pattern_p) { + lua_pushnil(); + return; + } + + pattern_p->size = width*height; + pattern_p->height = height; + pattern_p->width = width; + pattern_p->color = (long int *) malloc(pattern_p->size * sizeof(long int)); + if (!pattern_p->color) { + free(pattern_p); + lua_pushnil(); + return; + } + + memcpy(pattern_p->color, pattern, pattern_p->size * sizeof(long int)); + lua_pushusertag((void *) pattern_p, pattern_tag); +} + +/***************************************************************************\ +* Frees a previously allocated pattern. We don't free pattern_p to prevent * +* a problem if the user called killpattern twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killpattern(void) +{ + lua_Object pattern; + pattern_t *pattern_p; + + pattern = lua_getparam(1); + + if (pattern == LUA_NOOBJECT) + lua_error("cdKillPattern: pattern parameter missing!"); + if (lua_isnil(pattern)) + lua_error("cdKillPattern: attempt to kill a NIL pattern!"); + if (lua_tag(pattern) != pattern_tag) + lua_error("cdKillPattern: invalid pattern parameter!"); + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p->color) + lua_error("cdKillPattern: attempt to kill a killed pattern!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillPattern: too many parameters!"); + + free(pattern_p->color); + pattern_p->color = NULL; +} + +/***************************************************************************\ +* Creates a palette as a palette_tag usertag lua_Object. A palette can be * +* considered and treated as a color table. * +\***************************************************************************/ +static void cdlua_createpalette(void) +{ + lua_Object size; + long int size_i; + palette_t *palette_p; + + size = lua_getparam(1); + if (!(lua_isnumber(size))) + lua_error("cdCreatePalette: invalid size parameter!"); + size_i = (long int) lua_getnumber(size); + if (size_i < 1) + lua_error("cdCreatePalette: palette size should be a positive integer!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdCreatePalette: too many parameters!"); + + palette_p = (palette_t *) malloc(sizeof(palette_t)); + if (!palette_p) { + lua_pushnil(); + return; + } + + palette_p->size = size_i; + palette_p->color = (long int *) malloc(palette_p->size * sizeof(long int)); + if (!palette_p->color) { + free(palette_p); + lua_pushnil(); + return; + } + + memset(palette_p->color, 255, palette_p->size * sizeof(long int)); + lua_pushusertag((void *) palette_p, palette_tag); +} + +/***************************************************************************\ +* Frees a previously allocated palette. We don't free palette_p to prevent * +* a problem if the user called killpalette twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killpalette(void) +{ + lua_Object palette; + palette_t *palette_p; + + palette = lua_getparam(1); + if (palette == LUA_NOOBJECT) + lua_error("cdKillPalette: palette parameter missing!"); + if (lua_isnil(palette)) + lua_error("cdKillPalette: attempt to kill a NIL palette!"); + if (lua_tag(palette) != palette_tag) + lua_error("cdKillPalette: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("cdKillPalette: attempt to kill a killed palette!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillPalette: too many parameters!"); + + free(palette_p->color); + palette_p->color = NULL; +} + +/***************************************************************************\ +* Image Extended Functions. * +\***************************************************************************/ + +static void cdlua_createbitmap(void) +{ + lua_Object width; + lua_Object height; + lua_Object type; + + long int width_i; + long int height_i; + int type_i; + bitmap_t *image_p; + + width = lua_getparam(1); + height = lua_getparam(2); + type = lua_getparam(3); + if (!(lua_isnumber(type) && lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateBitmap: invalid parameters!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + type_i = (long int) lua_getnumber(type); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateBitmap: imagemap dimensions should be positive integers!"); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdCreateBitmap: too many parameters!"); + + image_p = (bitmap_t *) malloc(sizeof(bitmap_t)); + if (!image_p) { + lua_pushnil(); + return; + } + + image_p->image = cdCreateBitmap(width_i, height_i, type_i); + if (!image_p->image) { + free(image_p); + lua_pushnil(); + } + else + lua_pushusertag((void *) image_p, bitmap_tag); +} + +static void cdlua_killbitmap(void) +{ + lua_Object image; + bitmap_t *image_p; + + image = lua_getparam(1); + if (image == LUA_NOOBJECT) + lua_error("cdKillBitmap: image parameter missing!"); + if (lua_isnil(image)) + lua_error("cdKillBitmap: attempt to kill a NIL image!"); + if (lua_tag(image) != bitmap_tag) + lua_error("cdKillBitmap: invalid image parameter!"); + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p->image) + lua_error("cdKillBitmap: attempt to kill a killed image"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillBitmap: too many parameters!"); + + cdKillBitmap(image_p->image); + image_p->image = NULL; +} + +static void cdlua_getbitmap(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + + bitmap_t *image_p; + int x_i; + int y_i; + + image = lua_getparam(1); + if (image == LUA_NOOBJECT) + lua_error("cdGetBitmap: image parameter missing!"); + if (lua_isnil(image)) + lua_error("cdGetBitmap: attempt to get NIL image"); + if (lua_tag(image) != bitmap_tag) + lua_error("cdGetBitmap: invalid image parameter!"); + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p->image) + lua_error("cdGetBitmap: attempt to get a killed image"); + + x = lua_getparam(2); + y = lua_getparam(3); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("cdGetBitmap: invalid (x, y) parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdGetBitmap: too many parameters!"); + + cdGetBitmap(image_p->image, x_i, y_i); +} + +static void cdlua_putbitmap(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + + bitmap_t *image_p; + int x_i; + int y_i; + int w_i; + int h_i; + + image = lua_getparam(1); + if (image == LUA_NOOBJECT) + lua_error("cdPutBitmap: image parameter missing!"); + if (lua_isnil(image)) + lua_error("cdPutBitmap: attempt to put a NIL image!"); + if (lua_tag(image) != bitmap_tag) + lua_error("cdPutBitmap: invalid image parameter!"); + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p->image) + lua_error("cdPutBitmap: attempt to put a killed image!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h))) + lua_error("cdPutBitmap: invalid (x, y) parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + if (w_i < 0 || h_i < 0) + lua_error("cdPutBitmap: target region dimensions should be positive integers!"); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("cdPutBitmap: too many parameters!"); + + cdPutBitmap(image_p->image, x_i, y_i, w_i, h_i); +} + +static void wdlua_putbitmap(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + + bitmap_t *image_p; + double x_i; + double y_i; + double w_i; + double h_i; + + image = lua_getparam(1); + if (image == LUA_NOOBJECT) + lua_error("wdPutBitmap: image parameter missing!"); + if (lua_isnil(image)) + lua_error("wdPutBitmap: attempt to put a NIL image!"); + if (lua_tag(image) != bitmap_tag) + lua_error("wdPutBitmap: invalid image parameter!"); + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p->image) + lua_error("wdPutBitmap: attempt to put a killed image!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h))) + lua_error("wdPutBitmap: invalid (x, y) parameter!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + w_i = (double) lua_getnumber(w); + h_i = (double) lua_getnumber(h); + if (w_i < 0 || h_i < 0) + lua_error("wdPutBitmap: target region dimensions should be positive integers!"); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("wdPutBitmap: too many parameters!"); + + wdPutBitmap(image_p->image, x_i, y_i, w_i, h_i); +} + +static void cdlua_bitmapsetrect(void) +{ + lua_Object image; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + bitmap_t *image_p; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + image = lua_getparam(1); + if (image == LUA_NOOBJECT) + lua_error("cdBitmapSetRect: image parameter missing!"); + if (lua_isnil(image)) + lua_error("cdBitmapSetRect: attempt to get a NIL image!"); + if (lua_tag(image) != bitmap_tag) + lua_error("cdBitmapSetRect: invalid image parameter!"); + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p->image) + lua_error("cdBitmapSetRect: attempt to get a killed image!"); + + xmin = lua_getparam(2); + xmax = lua_getparam(3); + ymin = lua_getparam(4); + ymax = lua_getparam(5); + if (!(lua_isnumber(xmin) && lua_isnumber(xmax) && + lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("cdBitmapSetRect: invalid parameter!"); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("cdBitmapSetRect: too many parameters!"); + + cdBitmapSetRect(image_p->image, xmin_i, xmax_i, ymin_i, ymax_i); +} + +static void cdlua_rgb2mapex(void) +{ + lua_Object imagemap; + lua_Object imagergb; + + bitmap_t *imagemap_p; + bitmap_t *imagergb_p; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdBitmapRGB2Map: attempt to put a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdBitmapRGB2Map: invalid imagergb parameter!"); + imagergb_p = (bitmap_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->image)) + lua_error("cdBitmapRGB2Map: attempt to put a killed imagergb!"); + + imagemap = lua_getparam(2); + if (lua_isnil(imagemap)) + lua_error("cdBitmapRGB2Map: attempt to put a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("cdBitmapRGB2Map: imagemap invalid parameter!"); + imagemap_p = (bitmap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->image) + lua_error("cdBitmapRGB2Map: attempt to put a killed imagemap!"); + + if (imagergb_p->image->type != CD_RGB || imagemap_p->image->type <= 0) + lua_error("cdBitmapRGB2Map: invalid image type!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdBitmapRGB2Map: too many parameters!"); + + cdBitmapRGB2Map(imagergb_p->image, imagemap_p->image); +} + +/***************************************************************************\ +* Creates a buffer for a RGB image. * +\***************************************************************************/ +static void cdlua_createimagergb(void) +{ + lua_Object width, height; + long int width_i, height_i; + imagergb_t *imagergb_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateImageRGB: invalid imagergb parameter!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateImageRGB: image dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreateImageRGB: too many parameters!"); + + imagergb_p = (imagergb_t *) malloc(sizeof(imagergb_t)); + if (!imagergb_p) { + lua_pushnil(); + return; + } + + imagergb_p->width = width_i; + imagergb_p->height = height_i; + imagergb_p->size = width_i*height_i; + imagergb_p->red = (unsigned char *) malloc(imagergb_p->size); + imagergb_p->green = (unsigned char *) malloc(imagergb_p->size); + imagergb_p->blue = (unsigned char *) malloc(imagergb_p->size); + + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) { + if (imagergb_p->red) free(imagergb_p->red); + if (imagergb_p->green) free(imagergb_p->green); + if (imagergb_p->blue) free(imagergb_p->blue); + free(imagergb_p); + lua_pushnil(); + return; + } + + memset(imagergb_p->red, 255, imagergb_p->size); + memset(imagergb_p->green, 255, imagergb_p->size); + memset(imagergb_p->blue, 255, imagergb_p->size); + + lua_pushusertag((void *) imagergb_p, imagergb_tag); +} + +static void cdlua_imagergb(void) +{ + lua_Object canvas; + canvas_t *canvas_p; + cdCanvas *current_canvas; + int w, h, type = CD_RGB; + + canvas = lua_getparam(1); + + /* if the creation failed, canvas can be nil, in which case we */ + /* issue an error */ + if (lua_isnil(canvas)) + lua_error("cdImageRGB: attempt to get a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdImageRGB: invalid canvas parameter!"); + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdImageRGB: attempt to get a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdImageRGB: too many parameters!"); + + if (cdAlphaImage(canvas_p->cd_canvas)) + type = CD_RGBA; + + current_canvas = cdActiveCanvas(); + cdActivate(canvas_p->cd_canvas); + cdGetCanvasSize(&w, &h, NULL, NULL); + cdActivate(current_canvas); + + if (type == CD_RGBA) + { + imagergba_t *imagergba_p = (imagergba_t *) malloc(sizeof(imagergba_t)); + if (!imagergba_p) { + lua_pushnil(); + return; + } + + imagergba_p->width = w; + imagergba_p->height = h; + imagergba_p->size = w*h; + imagergba_p->red = cdRedImage(canvas_p->cd_canvas); + imagergba_p->green = cdGreenImage(canvas_p->cd_canvas); + imagergba_p->blue = cdBlueImage(canvas_p->cd_canvas); + imagergba_p->blue = cdAlphaImage(canvas_p->cd_canvas); + + lua_pushusertag((void *) imagergba_p, imagergba_tag); + } + else + { + imagergb_t * imagergb_p = (imagergb_t *) malloc(sizeof(imagergb_t)); + if (!imagergb_p) { + lua_pushnil(); + return; + } + + imagergb_p->width = w; + imagergb_p->height = h; + imagergb_p->size = w*h; + imagergb_p->red = cdRedImage(canvas_p->cd_canvas); + imagergb_p->green = cdGreenImage(canvas_p->cd_canvas); + imagergb_p->blue = cdBlueImage(canvas_p->cd_canvas); + + lua_pushusertag((void *) imagergb_p, imagergb_tag); + } +} + +static void cdlua_imagergbbitmap(void) +{ + lua_Object canvas; + canvas_t *canvas_p; + cdCanvas *current_canvas; + bitmap_t *image_p; + int w, h, type = CD_RGB; + + canvas = lua_getparam(1); + + /* if the creation failed, canvas can be nil, in which case we */ + /* issue an error */ + if (lua_isnil(canvas)) + lua_error("cdImageRGBBitmap: attempt to get a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdImageRGBBitmap: invalid canvas parameter!"); + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdImageRGBBitmap: attempt to get a killed canvas!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdImageRGBBitmap: too many parameters!"); + + if (cdAlphaImage(canvas_p->cd_canvas)) + type = CD_RGBA; + + current_canvas = cdActiveCanvas(); + cdActivate(canvas_p->cd_canvas); + cdGetCanvasSize(&w, &h, NULL, NULL); + cdActivate(current_canvas); + + image_p = (bitmap_t *) malloc(sizeof(bitmap_t)); + if (!image_p) { + lua_pushnil(); + return; + } + + image_p->image = cdInitBitmap(w, h, type, + cdRedImage(canvas_p->cd_canvas), + cdGreenImage(canvas_p->cd_canvas), + cdBlueImage(canvas_p->cd_canvas), + cdAlphaImage(canvas_p->cd_canvas)); + + lua_pushusertag((void *)image_p, bitmap_tag); +} + +/***************************************************************************\ +* Frees a previously allocated imagergb. We don't free imagergb_p to avoid * +* problems if the user called killimagergb twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killimagergb(void) +{ + lua_Object imagergb; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdKillImageRGB: attempt to kill a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdKillImageRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdKillImageRGB: attempt to kill a killed imagergb!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillImageRGB: too many parameters!"); + + free(imagergb_p->red); + free(imagergb_p->green); + free(imagergb_p->blue); + imagergb_p->red = NULL; + imagergb_p->green = NULL; + imagergb_p->blue = NULL; +} + +/***************************************************************************\ +* Creates a buffer for a RGBA image. * +\***************************************************************************/ +static void cdlua_createimagergba(void) +{ + lua_Object width, height; + long int width_i, height_i; + imagergba_t *imagergba_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateImageRGBA: invalid imagergba parameter!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateImageRGBA: image dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreateImageRGBA: too many parameters!"); + + imagergba_p = (imagergba_t *) malloc(sizeof(imagergba_t)); + if (!imagergba_p) { + lua_pushnil(); + return; + } + + imagergba_p->width = width_i; + imagergba_p->height = height_i; + imagergba_p->size = width_i*height_i; + imagergba_p->red = (unsigned char *) malloc(imagergba_p->size); + imagergba_p->green = (unsigned char *) malloc(imagergba_p->size); + imagergba_p->blue = (unsigned char *) malloc(imagergba_p->size); + imagergba_p->alpha = (unsigned char *) malloc(imagergba_p->size); + + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) { + if (imagergba_p->red) free(imagergba_p->red); + if (imagergba_p->green) free(imagergba_p->green); + if (imagergba_p->blue) free(imagergba_p->blue); + if (imagergba_p->alpha) free(imagergba_p->alpha); + free(imagergba_p); + lua_pushnil(); + return; + } + + memset(imagergba_p->red, 255, imagergba_p->size); + memset(imagergba_p->green, 255, imagergba_p->size); + memset(imagergba_p->blue, 255, imagergba_p->size); + memset(imagergba_p->alpha, 255, imagergba_p->size); + + lua_pushusertag((void *) imagergba_p, imagergba_tag); +} + +/***************************************************************************\ +* Frees a previously allocated imagergba. Don't free imagergba_p to avoid * +* problems if the user called killimagergba twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killimagergba(void) +{ + lua_Object imagergba; + imagergba_t *imagergba_p; + + imagergba = lua_getparam(1); + if (lua_isnil(imagergba)) + lua_error("cdKillImageRGBA: attempt to kill a NIL imagergba!"); + if (lua_tag(imagergba) != imagergba_tag) + lua_error("cdKillImageRGBA: invalid imagergba parameter!"); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) + lua_error("cdKillImageRGBA: attempt to kill a killed imagergba!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillImageRGBA: too many parameters!"); + + free(imagergba_p->red); + free(imagergba_p->green); + free(imagergba_p->blue); + free(imagergba_p->alpha); + imagergba_p->red = NULL; + imagergba_p->green = NULL; + imagergba_p->blue = NULL; + imagergba_p->alpha = NULL; +} + +/***************************************************************************\ +* Creates a imagemap as a imagemap_tag usertag lua_Object. * +\***************************************************************************/ +static void cdlua_createimagemap(void) +{ + lua_Object width; + lua_Object height; + + long int width_i; + long int height_i; + imagemap_t *imagemap_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateImageMap: invalid imagemap parameter!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateImageMap: imagemap dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreateImageMap: too many parameters!"); + + imagemap_p = (imagemap_t *) malloc(sizeof(imagemap_t)); + if (!imagemap_p) { + lua_pushnil(); + return; + } + + imagemap_p->size = width_i*height_i; + imagemap_p->width = width_i; + imagemap_p->height = height_i; + imagemap_p->index = (unsigned char *) malloc(imagemap_p->size); + if (!imagemap_p->index) { + free(imagemap_p); + lua_pushnil(); + return; + } + + memset(imagemap_p->index, 0, imagemap_p->size); + lua_pushusertag((void *) imagemap_p, imagemap_tag); +} + +/***************************************************************************\ +* Frees a previously allocated imagemap. We don't free imagemap_p to avoid * +* problems if the user called killimagemap twice with the same object. The * +* structure will be freed by a userdata "gc" fallback in LUA 3.0. * +\***************************************************************************/ +static void cdlua_killimagemap(void) +{ + lua_Object imagemap; + imagemap_t *imagemap_p; + + imagemap = lua_getparam(1); + if (lua_isnil(imagemap)) + lua_error("cdKillImageMap: attempt to kill a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("cdKillImageMap: invalid imagemap parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("cdKillImageMap: attempt to kill a killed imagemap!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillImageMap: too many parameters!"); + + free(imagemap_p->index); + imagemap_p->index = NULL; +} + +/***************************************************************************\ +* Creates an image as a image_tag usertag lua_Object. * +\***************************************************************************/ +static void cdlua_createimage(void) +{ + lua_Object width; + lua_Object height; + + long int width_i; + long int height_i; + image_t *image_p; + + width = lua_getparam(1); + height = lua_getparam(2); + if (!(lua_isnumber(width) && lua_isnumber(height))) + lua_error("cdCreateImage: invalid dimension parameters!"); + width_i = (long int) lua_getnumber(width); + height_i = (long int) lua_getnumber(height); + if (width_i < 1 || height_i < 1) + lua_error("cdCreateImage: imagemap dimensions should be positive integers!"); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdCreateImage: too many parameters!"); + + image_p = (image_t *) malloc(sizeof(image_t)); + if (!image_p) { + lua_pushnil(); + return; + } + + image_p->cd_image = cdCreateImage(width_i, height_i); + if (!image_p->cd_image) { + free(image_p); + lua_pushnil(); + } + else + lua_pushusertag((void *) image_p, image_tag); +} + +/***************************************************************************\ +* Frees a previously allocated image. * +\***************************************************************************/ +static void cdlua_killimage(void) +{ + lua_Object image; + image_t *image_p; + + image = lua_getparam(1); + if (lua_isnil(image)) + lua_error("cdKillImage: attempt to kill a NIL image!"); + if (lua_tag(image) != image_tag) + lua_error("cdKillImage: invalid image parameter!"); + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("cdKillImage: attempt to kill a killed image"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdKillImage: too many parameters!"); + + cdKillImage(image_p->cd_image); + image_p->cd_image = NULL; +} + +/***************************************************************************\ +* Fallback definitions. * +\***************************************************************************/ +/***************************************************************************\ +* stipple "settable" fallback. * +\***************************************************************************/ +static void stipplesettable_fb(void) +{ + lua_Object stipple, index, value; + + stipple_t *stipple_p; + long int index_i; + unsigned char value_i; + + stipple = lua_getparam(1); + index = lua_getparam(2); + value = lua_getparam(3); + + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p) { + lua_error("stipple_tag \"settable\": invalid stipple_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("stipple_tag \"settable\": index should be a number!"); + } + + if (!lua_isnumber(value)) { + lua_error("stipple_tag \"settable\": value should be a number!"); + } + + value_i = (unsigned char) lua_getnumber(value); + if ((value_i != 0 && value_i != 1)) + lua_error("stipple_tag \"settable\": value should belong to {0, 1}!"); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= stipple_p->size) + lua_error("stipple_tag \"settable\": index is out of bounds!"); + + stipple_p->value[index_i] = value_i; +} + +/***************************************************************************\ +* imagemap "settable" fallback. * +\***************************************************************************/ +static void imagemapsettable_fb(void) +{ + lua_Object imagemap, index, value; + + imagemap_t *imagemap_p; + long int index_i; + long int value_i; + + imagemap = lua_getparam(1); + index = lua_getparam(2); + value = lua_getparam(3); + + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) { + lua_error("imagemap_tag \"settable\": invalid imagemap_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("imagemap_tag \"settable\": index should be a number!"); + } + + if (!lua_isnumber(value)) { + lua_error("imagemap_tag \"settable\": value should be a number!"); + } + + value_i = (long int) lua_getnumber(value); + if ((value_i < 0 || value_i > 255)) + lua_error("imagemap_tag \"settable\": value should be in range [0, 255]!"); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= imagemap_p->size) + lua_error("imagemap_tag \"settable\": index is out of bounds!"); + + imagemap_p->index[index_i] = (unsigned char) value_i; +} + +/***************************************************************************\ +* pattern "settable" fallback. * +\***************************************************************************/ +static void patternsettable_fb(void) +{ + lua_Object pattern, index, color; + + pattern_t *pattern_p; + long int index_i; + long int color_i; + + pattern = lua_getparam(1); + index = lua_getparam(2); + color = lua_getparam(3); + + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p) { + lua_error("pattern_tag \"settable\": invalid pattern_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("pattern_tag \"settable\": index should be a number!"); + } + + if (lua_tag(color) != color_tag) + lua_error("pattern_tag \"settable\": value should be of type color_tag!"); + + color_i = (long int) lua_getuserdata(color); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= pattern_p->size) + lua_error("pattern_tag \"settable\": index is out of bounds!"); + + pattern_p->color[index_i] = color_i; +} + +/***************************************************************************\ +* palette "settable" fallback. * +\***************************************************************************/ +static void palettesettable_fb(void) +{ + lua_Object palette, index, color; + + palette_t *palette_p; + long int index_i; + long int color_i; + + palette = lua_getparam(1); + index = lua_getparam(2); + color = lua_getparam(3); + + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) { + lua_error("palette_tag \"settable\": invalid palette_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("palette_tag \"settable\": index should be a number!"); + } + + if (lua_tag(color) != color_tag) + lua_error("palette_tag \"settable\": value should be of type color_tag!"); + + color_i = (long int) lua_getuserdata(color); + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= palette_p->size) + lua_error("palette_tag \"settable\": index is out of bounds!"); + + palette_p->color[index_i] = color_i; +} + +/***************************************************************************\ +* channel "settable" fallback. This fallback is called when a LUA line like * +* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the value is assigned where it should. * +\***************************************************************************/ +static void channelsettable_fb(void) +{ + lua_Object channel, index, value; + + channel_t *channel_p; + long int index_i; + long int value_i; + + channel = lua_getparam(1); + index = lua_getparam(2); + value = lua_getparam(3); + + channel_p = (channel_t *) lua_getuserdata(channel); + if (!channel_p) { + lua_error("channel_tag \"settable\": invalid channel_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("channel_tag \"settable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || (channel_p->size > 0 && index_i >= channel_p->size) || + (channel_p->size == -1 && index_i >= 256)) { + lua_error("channel_tag \"settable\": index is out of bounds!"); + } + + if (channel_p->size > 0) + { + if (!lua_isnumber(value)) { + lua_error("channel_tag \"settable\": value should be a number!"); + } + + value_i = (long int) lua_getnumber(value); + if ((value_i < 0 || value_i > 255)) { + lua_error("channel_tag \"settable\": value should be in range [0, 255]!"); + } + + channel_p->value[index_i] = (unsigned char) value_i; + } + else + { + if (lua_tag(value) != color_tag) + lua_error("channel_tag \"settable\": value should be of type color_tag!"); + + value_i = (long int) lua_getuserdata(value); + + ((long int*)channel_p->value)[index_i] = value_i; + } +} + +/***************************************************************************\ +* stipple "gettable" fallback. * +\***************************************************************************/ +static void stipplegettable_fb(void) +{ + lua_Object stipple, index; + + stipple_t *stipple_p; + long int index_i; + + stipple = lua_getparam(1); + index = lua_getparam(2); + + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p) + lua_error("stipple_tag \"gettable\": invalid stipple_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("stipple_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= stipple_p->size) + lua_error("stipple_tag \"gettable\": index is out of bounds!"); + + lua_pushnumber(stipple_p->value[index_i]); +} + +/***************************************************************************\ +* imagemap "gettable" fallback. * +\***************************************************************************/ +static void imagemapgettable_fb(void) +{ + lua_Object imagemap, index; + + imagemap_t *imagemap_p; + long int index_i; + + imagemap = lua_getparam(1); + index = lua_getparam(2); + + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) + lua_error("imagemap_tag \"gettable\": invalid imagemap_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("imagemap_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= imagemap_p->size) + lua_error("imagemap_tag \"gettable\": index is out of bounds!"); + + lua_pushnumber(imagemap_p->index[index_i]); +} + +/***************************************************************************\ +* pattern "gettable" fallback. * +\***************************************************************************/ +static void patterngettable_fb(void) +{ + lua_Object pattern, index; + + pattern_t *pattern_p; + long int index_i; + + pattern = lua_getparam(1); + index = lua_getparam(2); + + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p) + lua_error("pattern_tag \"gettable\": invalid pattern_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("pattern_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= pattern_p->size) + lua_error("pattern_tag \"gettable\": index is out of bounds!"); + + lua_pushusertag((void *) pattern_p->color[index_i], color_tag); +} + +/***************************************************************************\ +* palette "gettable" fallback. * +\***************************************************************************/ +static void palettegettable_fb(void) +{ + lua_Object palette, index; + + palette_t *palette_p; + long int index_i; + + palette = lua_getparam(1); + index = lua_getparam(2); + + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) + lua_error("palette_tag \"gettable\": invalid palette_tag object!"); + + if (!lua_isnumber(index)) { + lua_error("palette_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + if (index_i < 0 || index_i >= palette_p->size) + lua_error("palette_tag \"gettable\": index is out of bounds!"); + + lua_pushusertag((void *) palette_p->color[index_i], color_tag); +} + +/***************************************************************************\ +* channel "gettable" fallback. This fallback is called when a LUA line like * +* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the appropriate value is returned. * +\***************************************************************************/ +static void channelgettable_fb(void) +{ + lua_Object channel, index; + + channel_t *channel_p; + long int index_i; + + channel = lua_getparam(1); + index = lua_getparam(2); + + channel_p = (channel_t *) lua_getuserdata(channel); + if (!channel_p) { + lua_error("channel_tag \"gettable\": invalid channel_tag object!"); + } + + if (!lua_isnumber(index)) { + lua_error("channel_tag \"gettable\": index should be a number!"); + } + + index_i = (long int) lua_getnumber(index); + + if (index_i < 0 || (channel_p->size > 0 && index_i >= channel_p->size) || + (channel_p->size == -1 && index_i >= 256)) { + lua_error("channel_tag \"gettable\": index is out of bounds!"); + } + + if (channel_p->size == -1) + lua_pushusertag((void *) ((long int*)channel_p->value)[index_i], color_tag); + else + lua_pushnumber(channel_p->value[index_i]); +} + +/***************************************************************************\ +* imagergb "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. * +* The channel_info global is filled and its address is returned with a * +* channel_tag usertag lua_Object. The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static void imagergbgettable_fb(void) +{ + lua_Object imagergb, index; + + char *index_s; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + index = lua_getparam(2); + + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!imagergb_p) + lua_error("imagergb_tag \"gettable\": invalid imagergb_tag object!"); + + if (!lua_isstring(index)) { + lua_error("imagergb_tag \"gettable\": index should be a channel name!"); + } + index_s = (char *) lua_getstring(index); + + channel_info.size = imagergb_p->size; + + if (*index_s == 'r' || *index_s == 'R') { + channel_info.value = imagergb_p->red; + } + else if (*index_s == 'g' || *index_s == 'G') { + channel_info.value = imagergb_p->green; + } + else if (*index_s == 'b' || *index_s == 'B') { + channel_info.value = imagergb_p->blue; + } + else { + lua_error("imagergb_tag \"gettable\": index is an invalid channel name!"); + } + + lua_pushusertag((void *) &channel_info, channel_tag); +} + +/***************************************************************************\ +* imagergba "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.* +* The channel_info global is filled and its address is returned with a * +* channel_tag usertag lua_Object. The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static void imagergbagettable_fb(void) +{ + lua_Object imagergba, index; + + char *index_s; + imagergba_t *imagergba_p; + + imagergba = lua_getparam(1); + index = lua_getparam(2); + + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!imagergba_p) + lua_error("imagergba_tag \"gettable\": invalid imagergba_tag object!"); + + if (!lua_isstring(index)) { + lua_error("imagergba_tag \"gettable\": index should be a channel name!"); + } + index_s = (char *) lua_getstring(index); + + channel_info.size = imagergba_p->size; + + if (*index_s == 'r' || *index_s == 'R') { + channel_info.value = imagergba_p->red; + } + else if (*index_s == 'g' || *index_s == 'G') { + channel_info.value = imagergba_p->green; + } + else if (*index_s == 'b' || *index_s == 'B') { + channel_info.value = imagergba_p->blue; + } + else if (*index_s == 'a' || *index_s == 'A') { + channel_info.value = imagergba_p->alpha; + } + else { + lua_error("imagergba_tag \"gettable\": index is an invalid channel name!"); + } + + lua_pushusertag((void *) &channel_info, channel_tag); +} + +/***************************************************************************\ +* bitmap "gettable" fallback. This fallback is called when a LUA line * +* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed.* +* The channel_info global is filled and its address is returned with a * +* channel_tag usertag lua_Object. The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static void bitmapgettable_fb(void) +{ + lua_Object image, index; + + char *index_s; + bitmap_t *image_p; + + image = lua_getparam(1); + index = lua_getparam(2); + + image_p = (bitmap_t *) lua_getuserdata(image); + if (!image_p) + lua_error("bitmap_tag \"gettable\": invalid bitmap_tag object!"); + + if (!lua_isstring(index)) { + lua_error("bitmap_tag \"gettable\": index should be a channel name!"); + } + index_s = (char *) lua_getstring(index); + + channel_info.size = image_p->image->w * image_p->image->h; + + if (*index_s == 'r' || *index_s == 'R') { + channel_info.value = cdBitmapGetData(image_p->image, CD_IRED); + } + else if (*index_s == 'g' || *index_s == 'G') { + channel_info.value = cdBitmapGetData(image_p->image, CD_IGREEN); + } + else if (*index_s == 'b' || *index_s == 'B') { + channel_info.value = cdBitmapGetData(image_p->image, CD_IBLUE); + } + else if (*index_s == 'a' || *index_s == 'A') { + channel_info.value = cdBitmapGetData(image_p->image, CD_IALPHA); + } + else if (*index_s == 'i' || *index_s == 'I') { + channel_info.value = cdBitmapGetData(image_p->image, CD_INDEX); + } + else if (*index_s == 'c' || *index_s == 'C') { + channel_info.value = cdBitmapGetData(image_p->image, CD_COLORS); + channel_info.size = -1; + } + else { + lua_error("imagergba_tag \"gettable\": index is an invalid channel name!"); + } + + lua_pushusertag((void *) &channel_info, channel_tag); +} + +static void stategc_fb(void) +{ + lua_Object state; + + state_t *state_p; + + state = lua_getparam(1); + state_p = (state_t *) lua_getuserdata(state); + if (!state_p) + lua_error("state_tag \"gc\": invalid state_tag object!"); + + if (state_p->state) cdReleaseState(state_p->state); + + /* free the state_t structure */ + free(state_p); +} + +/***************************************************************************\ +* stipple "gc" fallback. * +\***************************************************************************/ +static void stipplegc_fb(void) +{ + lua_Object stipple; + + stipple_t *stipple_p; + + stipple = lua_getparam(1); + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p) + lua_error("stipple_tag \"gc\": invalid stipple_tag object!"); + + /* if the stipple has not been killed, kill it */ + if (stipple_p->value) free(stipple_p->value); + + /* free the stipple_t structure */ + free(stipple_p); +} + +/***************************************************************************\ +* pattern "gc" fallback. * +\***************************************************************************/ +static void patterngc_fb(void) +{ + lua_Object pattern; + + pattern_t *pattern_p; + + pattern = lua_getparam(1); + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p) + lua_error("pattern_tag \"gc\": invalid pattern_tag object!"); + + /* if the pattern has not been killed, kill it */ + if (pattern_p->color) free(pattern_p->color); + + /* free the pattern_t structure */ + free(pattern_p); +} + +/***************************************************************************\ +* palette "gc" fallback. * +\***************************************************************************/ +static void palettegc_fb(void) +{ + lua_Object palette; + + palette_t *palette_p; + + palette = lua_getparam(1); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p) + lua_error("palette_tag \"gc\": invalid palette_tag object!"); + + /* if the palette has not been killed, kill it */ + if (palette_p->color) free(palette_p->color); + + /* free the palette_t structure */ + free(palette_p); +} + +/***************************************************************************\ +* imagergb "gc" fallback. * +\***************************************************************************/ +static void imagergbgc_fb(void) +{ + lua_Object imagergb; + + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!imagergb_p) + lua_error("imagergb_tag \"gc\": invalid imagergb_tag object!"); + + /* if the imagergb has not been killed, kill it */ + if (imagergb_p->red) free(imagergb_p->red); + if (imagergb_p->green) free(imagergb_p->green); + if (imagergb_p->blue) free(imagergb_p->blue); + + /* free the imagergb_t structure */ + free(imagergb_p); +} + +/***************************************************************************\ +* imagergba "gc" fallback. * +\***************************************************************************/ +static void imagergbagc_fb(void) +{ + lua_Object imagergba; + + imagergba_t *imagergba_p; + + imagergba = lua_getparam(1); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!imagergba_p) + lua_error("imagergba_tag \"gc\": invalid imagergba_tag object!"); + + /* if the imagergba has not been killed, kill it */ + if (imagergba_p->red) free(imagergba_p->red); + if (imagergba_p->green) free(imagergba_p->green); + if (imagergba_p->blue) free(imagergba_p->blue); + if (imagergba_p->alpha) free(imagergba_p->alpha); + + /* free the imagergba_t structure */ + free(imagergba_p); +} + +/***************************************************************************\ +* imagemap "gc" fallback. * +\***************************************************************************/ +static void imagemapgc_fb(void) +{ + lua_Object imagemap; + + imagemap_t *imagemap_p; + + imagemap = lua_getparam(1); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p) + lua_error("imagemap_tag \"gc\": invalid imagemap_tag object!"); + + /* if the imagemap has not been killed, kill it */ + if (imagemap_p->index) free(imagemap_p->index); + + /* free the imagemap_t structure */ + free(imagemap_p); +} + +/***************************************************************************\ +* bitmap "gc" fallback. * +\***************************************************************************/ +static void bitmapgc_fb(void) +{ + lua_Object bitmap; + + bitmap_t *bitmap_p; + + bitmap = lua_getparam(1); + bitmap_p = (bitmap_t *) lua_getuserdata(bitmap); + if (!bitmap_p) + lua_error("bitmap_tag \"gc\": invalid bitmap_tag object!"); + + /* if the bitmap has not been killed, kill it */ + if (bitmap_p->image) cdKillBitmap(bitmap_p->image); + + /* free the bitmap_t structure */ + free(bitmap_p); +} + +/***************************************************************************\ +* cdPixel. * +\***************************************************************************/ +static void cdlua_pixel (void) +{ + lua_Object x; + lua_Object y; + lua_Object color; + + int x_i; + int y_i; + long int color_i; + + x = lua_getparam(1); + y = lua_getparam(2); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("cdPixel: pixel coordinates should be integers!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + + color = lua_getparam(3); + if (lua_tag(color) != color_tag) + lua_error("cdPixel: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdPixel: too many parameters!"); + + cdPixel(x_i, y_i, color_i); +} + +static void wdlua_pixel (void) +{ + lua_Object x; + lua_Object y; + lua_Object color; + + double x_i; + double y_i; + long int color_i; + + x = lua_getparam(1); + y = lua_getparam(2); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("wdPixel: pixel coordinates should be numbers!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + + color = lua_getparam(3); + if (lua_tag(color) != color_tag) + lua_error("cdPixel: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdPixel: too many parameters!"); + + wdPixel(x_i, y_i, color_i); +} + +/***************************************************************************\ +* cdGetCanvasSize. * +\***************************************************************************/ +static void cdlua_getcanvassize(void) +{ + int width; + int height; + double mm_width; + double mm_height; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdGetCanvasSize: too many parameters!"); + + cdGetCanvasSize(&width, &height, &mm_width, &mm_height); + lua_pushnumber(width); + lua_pushnumber(height); + lua_pushnumber(mm_width); + lua_pushnumber(mm_height); +} + +/***************************************************************************\ +* Register callback functions. * +\***************************************************************************/ +static void cdlua_registercallback(void) +{ + lua_Object driver, cb, func; + int driver_i, cb_i, func_lock; + cdContextLUA* luactx; + cdCallbackLUA* cdCB; + + driver = lua_getparam(1); + if (!lua_isnumber(driver)) + lua_error("cdRegisterCallback: invalid driver parameter!"); + driver_i = (int) lua_getnumber(driver); + + cb = lua_getparam(2); + if (!lua_isnumber(cb)) + lua_error("cdRegisterCallback: invalid cb parameter!"); + cb_i = (int) lua_getnumber(cb); + + func = lua_getparam(3); + if (lua_isnil(func)) + func_lock = -1; + else if (!lua_isfunction(func)) + { + lua_error("cdRegisterCallback: invalid func parameter!"); + return; + } + else { + lua_pushobject(func); + func_lock = lua_ref(1); + } + + if (driver_i >= cdlua_numdrivers) + lua_error("cdRegisterCallback: invalid driver parameter!"); + + luactx = cdlua_drivers[driver_i]; + + if (cb_i >= luactx->cb_n) + lua_error("cdRegisterCallback: invalid cb parameter!"); + + cdCB = &luactx->cb_list[cb_i]; + + if (cdCB->lock != -1) { + lua_unref(cdCB->lock); + cdCB->lock = func_lock; + if (func_lock == -1) { + cdRegisterCallback(luactx->ctx(), cb_i, NULL); + } + } + else { + if (func_lock != -1) { + cdRegisterCallback(luactx->ctx(), cb_i, (cdCallback)cdCB->func); + cdCB->lock = func_lock; + } + } +} + +/***************************************************************************\ +* cdPlay. * +\***************************************************************************/ +static void cdlua_play(void) +{ + lua_Object driver; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + lua_Object data; + + int driver_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + char *data_s; + + driver = lua_getparam(1); + if (!lua_isnumber(driver)) + lua_error("cdPlay: invalid driver parameter!"); + driver_i = (long int) lua_getnumber(driver); + + xmin = lua_getparam(2); + xmax = lua_getparam(3); + ymin = lua_getparam(4); + ymax = lua_getparam(5); + if (!(lua_isnumber(xmin) && lua_isnumber(xmax) && + lua_isnumber(ymin) && lua_isnumber(ymin))) + lua_error("cdPlay: invalid viewport!"); + xmin_i = (long int) lua_getnumber(xmin); + xmax_i = (long int) lua_getnumber(xmax); + ymin_i = (long int) lua_getnumber(ymin); + ymax_i = (long int) lua_getnumber(ymax); + + data = lua_getparam(6); + if (!lua_isstring(data)) + lua_error("cdPlay: data should be of type string!"); + data_s = lua_getstring(data); + + if (driver_i >= cdlua_numdrivers) + lua_error("cdPlay: unknown driver!"); + + if (lua_getparam(7) != LUA_NOOBJECT) + lua_error("cdPlay: too many parameters!"); + + cdPlay(cdlua_drivers[driver_i]->ctx(), xmin_i, xmax_i, ymin_i, ymax_i, data_s); +} + +/***************************************************************************\ +* cdUpdateYAxis. * +\***************************************************************************/ + +static void cdlua_updateyaxis(void) +{ + lua_Object y; + + int y_i; + + y = lua_getparam(1); + if (!lua_isnumber(y)) + lua_error("cdUpdateYAxis: invalid (y) parameter!"); + y_i = (int) lua_getnumber(y); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdUpdateYAxis: too many parameters!"); + + cdUpdateYAxis(&y_i); + lua_pushnumber(y_i); +} + +/***************************************************************************\ +* cdGetClipArea. * +\***************************************************************************/ +static void cdlua_getcliparea(void) +{ + int xmin; + int xmax; + int ymin; + int ymax; + int status; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdGetClipArea: too many parameters!"); + + status = cdGetClipArea(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); + lua_pushnumber(status); +} + +static void cdlua_RegionBox(void) +{ + int xmin; + int xmax; + int ymin; + int ymax; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdRegionBox: too many parameters!"); + + cdRegionBox(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +static void cdlua_getclippoly(void) +{ + int n, i; + int *pts; + lua_Object points; + + pts = cdGetClipPoly(&n); + lua_pushnumber(n); + + points = lua_createtable(); + + for (i=0; i < 2*n; i++) + { + lua_pushobject(points); + lua_pushnumber(i+1); + lua_pushnumber(pts[i]); + lua_settable(); + } +} + +static void wdlua_getclippoly(void) +{ + int n, i; + double *pts; + lua_Object points; + + pts = wdGetClipPoly(&n); + lua_pushnumber(n); + + points = lua_createtable(); + + for (i=0; i < 2*n; i++) + { + lua_pushobject(points); + lua_pushnumber(i+1); + lua_pushnumber(pts[i]); + lua_settable(); + } +} + +/***************************************************************************\ +* cdMM2Pixel. * +\***************************************************************************/ +static void cdlua_mm2pixel(void) +{ + lua_Object mm_dx; + lua_Object mm_dy; + + double mm_dx_d; + double mm_dy_d; + int dx; + int dy; + + mm_dx = lua_getparam(1); + mm_dy = lua_getparam(2); + if (!(lua_isnumber(mm_dx) && lua_isnumber(mm_dy))) + lua_error("cdMM2Pixel: invalid (mm_dx, mm_dy) parameter!"); + mm_dx_d = (double) lua_getnumber(mm_dx); + mm_dy_d = (double) lua_getnumber(mm_dy); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdMM2Pixel: too many parameters!"); + + cdMM2Pixel(mm_dx, mm_dy, &dx, &dy); + lua_pushnumber(dx); + lua_pushnumber(dy); +} + +/***************************************************************************\ +* cdPixel2MM. * +\***************************************************************************/ +static void cdlua_pixel2mm(void) +{ + lua_Object dx; + lua_Object dy; + int dx_i; + int dy_i; + + double mm_dx; + double mm_dy; + + dx = lua_getparam(1); + dy = lua_getparam(2); + if (!(lua_isnumber(dx) && lua_isnumber(dy))) + lua_error("cdPixel2MM: invalid (dx, dy) parameter!"); + dx_i = (int) lua_getnumber(dx); + dy_i = (int) lua_getnumber(dy); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdPixel2MM: too many parameters!"); + + cdPixel2MM(dx_i, dy_i, &mm_dx, &mm_dy); + lua_pushnumber(mm_dx); + lua_pushnumber(mm_dy); +} + +/***************************************************************************\ +* cdStipple. * +\***************************************************************************/ +static void cdlua_stipple(void) +{ + lua_Object stipple; + stipple_t *stipple_p; + + stipple = lua_getparam(1); + if (lua_isnil(stipple)) + lua_error("cdStipple: attempt to set a NIL stipple!"); + if (lua_tag(stipple) != stipple_tag) + lua_error("cdStipple: invalid stipple parameter!"); + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p->value) + lua_error("cdStipple: attempt to set a killed stipple!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdStipple: too many parameters!"); + + cdStipple(stipple_p->width, stipple_p->height, stipple_p->value); +} + +static void wdlua_stipple(void) +{ + lua_Object stipple; + stipple_t *stipple_p; + double w_mm; + double h_mm; + + stipple = lua_getparam(1); + if (lua_isnil(stipple)) + lua_error("wdStipple: attempt to set a NIL stipple!"); + if (lua_tag(stipple) != stipple_tag) + lua_error("wdStipple: invalid stipple parameter!"); + stipple_p = (stipple_t *) lua_getuserdata(stipple); + if (!stipple_p->value) + lua_error("wdStipple: attempt to set a killed stipple!"); + + w_mm = (double)luaL_check_number(2); + h_mm = (double)luaL_check_number(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdStipple: too many parameters!"); + + wdStipple(stipple_p->width, stipple_p->height, stipple_p->value, w_mm, h_mm); +} + +/***************************************************************************\ +* cdPattern. * +\***************************************************************************/ +static void cdlua_pattern(void) +{ + lua_Object pattern; + pattern_t *pattern_p; + + pattern = lua_getparam(1); + if (lua_isnil(pattern)) + lua_error("cdPattern: attempt to set a NIL pattern!"); + if (lua_tag(pattern) != pattern_tag) + lua_error("cdPattern: invalid pattern parameter!"); + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p->color) + lua_error("cdPattern: attempt to set a killed pattern!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdPattern: too many parameters!"); + + cdPattern(pattern_p->width, pattern_p->height, pattern_p->color); +} + +static void wdlua_pattern(void) +{ + lua_Object pattern; + pattern_t *pattern_p; + double w_mm; + double h_mm; + + pattern = lua_getparam(1); + if (lua_isnil(pattern)) + lua_error("wdPattern: attempt to set a NIL pattern!"); + if (lua_tag(pattern) != pattern_tag) + lua_error("wdPattern: invalid pattern parameter!"); + pattern_p = (pattern_t *) lua_getuserdata(pattern); + if (!pattern_p->color) + lua_error("wdPattern: attempt to set a killed pattern!"); + + w_mm = (double)luaL_check_number(2); + h_mm = (double)luaL_check_number(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdPattern: too many parameters!"); + + wdPattern(pattern_p->width, pattern_p->height, pattern_p->color, w_mm, h_mm); +} + +/***************************************************************************\ +* cdFontDim. * +\***************************************************************************/ +static void cdlua_fontdim(void) +{ + int max_width; + int height; + int ascent; + int descent; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdFontDim: too many parameters!"); + + cdFontDim(&max_width, &height, &ascent, &descent); + lua_pushnumber(max_width); + lua_pushnumber(height); + lua_pushnumber(ascent); + lua_pushnumber(descent); +} + +/***************************************************************************\ +* cdTextSize. * +\***************************************************************************/ +static void cdlua_textsize(void) +{ + lua_Object text; + char* text_s; + + int width; + int height; + + text = lua_getparam(1); + if (!lua_isstring(text)) + lua_error("cdTextSize: text should be of type string!"); + text_s = (char*) lua_getstring(text); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdTextSize: too many parameters!"); + + cdTextSize(text_s, &width, &height); + lua_pushnumber(width); + lua_pushnumber(height); +} + +static void cdlua_textbox(void) +{ + int xmin; + int xmax; + int ymin; + int ymax; + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdTextBox: too many parameters!"); + + cdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +static void wdlua_textbox(void) +{ + double xmin; + double xmax; + double ymin; + double ymax; + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdTextBox: too many parameters!"); + + wdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +static void cdlua_textbounds(void) +{ + int rect[8]; + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdTextBox: too many parameters!"); + + cdTextBounds(x, y, s, rect); + lua_pushnumber(rect[0]); + lua_pushnumber(rect[1]); + lua_pushnumber(rect[2]); + lua_pushnumber(rect[3]); + lua_pushnumber(rect[4]); + lua_pushnumber(rect[5]); + lua_pushnumber(rect[6]); + lua_pushnumber(rect[7]); +} + +static void wdlua_textbounds(void) +{ + double rect[8]; + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdTextBox: too many parameters!"); + + wdTextBounds(x, y, s, rect); + lua_pushnumber(rect[0]); + lua_pushnumber(rect[1]); + lua_pushnumber(rect[2]); + lua_pushnumber(rect[3]); + lua_pushnumber(rect[4]); + lua_pushnumber(rect[5]); + lua_pushnumber(rect[6]); + lua_pushnumber(rect[7]); +} + +static void cdlua_getfont(void) +{ + int type_face, style, size; + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdGetFont: too many parameters!"); + + cdGetFont(&type_face, &style, &size); + lua_pushnumber(type_face); + lua_pushnumber(style); + lua_pushnumber(size); +} + +static void wdlua_getfont(void) +{ + int type_face, style; + double size; + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("wdGetFont: too many parameters!"); + + wdGetFont(&type_face, &style, &size); + lua_pushnumber(type_face); + lua_pushnumber(style); + lua_pushnumber(size); +} + +/***************************************************************************\ +* cdPalette. * +\***************************************************************************/ +static void cdlua_palette(void) +{ + lua_Object palette; + lua_Object mode; + palette_t *palette_p; + int mode_i; + + palette = lua_getparam(1); + if (lua_isnil(palette)) + lua_error("cdPalette: attempt to set a NIL palette!"); + if (lua_tag(palette) != palette_tag) + lua_error("cdPalette: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("cdPalette: attempt to set a killed palette!"); + + mode = lua_getparam(2); + if (!lua_isnumber(mode)) + lua_error("cdPalette: invalid mode parameter!"); + mode_i = (int) lua_getnumber(mode); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("cdPalette: too many parameters!"); + + cdPalette(palette_p->size, palette_p->color, mode_i); +} + +/***************************************************************************\ +* cdBackground. * +\***************************************************************************/ +static void cdlua_background(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdBackground: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdBackground: too many parameters!"); + + color_i = cdBackground(color_i); + lua_pushusertag((void*) color_i, color_tag); +} + +/***************************************************************************\ +* cdForeground. * +\***************************************************************************/ +static void cdlua_foreground(void) +{ + lua_Object color; + long int color_i; + + color = lua_getparam(1); + if (lua_tag(color) != color_tag) + lua_error("cdForeground: invalid color parameter!"); + color_i = (long int) lua_getuserdata(color); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdForeground: too many parameters!"); + + color_i = cdForeground(color_i); + lua_pushusertag((void*) color_i, color_tag); +} + +/***************************************************************************\ +* cdGetImageRGB. * +\***************************************************************************/ +static void cdlua_getimagergb(void) +{ + lua_Object imagergb; + lua_Object x; + lua_Object y; + + imagergb_t *imagergb_p; + int x_i; + int y_i; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdGetImageRGB: attempt to get a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdGetImageRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdGetImageRGB: attempt to get a killed imagergb!"); + + x = lua_getparam(2); + y = lua_getparam(3); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("cdGetImageRGB: invalid (x, y) parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdGetImageRGB: too many parameters!"); + + cdGetImageRGB(imagergb_p->red, imagergb_p->green, imagergb_p->blue, + x_i, y_i, imagergb_p->width, imagergb_p->height); +} +/***************************************************************************\ +* cdPutImageRGB. * +\***************************************************************************/ + +static void cdlua_rgb2map(void) +{ + lua_Object imagemap; + lua_Object palette; + lua_Object imagergb; + + imagemap_t *imagemap_p; + palette_t *palette_p; + imagergb_t *imagergb_p; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdRGB2Map: attempt to put a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdRGB2Map: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdRGB2Map: attempt to put a killed imagergb!"); + + imagemap = lua_getparam(2); + if (lua_isnil(imagemap)) + lua_error("cdRGB2Map: attempt to put a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("cdRGB2Map: imagemap invalid parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("cdRGB2Map: attempt to put a killed imagemap!"); + + palette = lua_getparam(3); + if (lua_isnil(palette)) + lua_error("cdRGB2Map: NIL pallete!"); + if (lua_tag(palette) != palette_tag) + lua_error("cdRGB2Map: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("cdRGB2Map: killed pallete!"); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdRGB2Map: too many parameters!"); + + cdRGB2Map(imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue, + imagemap_p->index, palette_p->size, palette_p->color); +} + +static void cdlua_putimagergb(void) +{ + lua_Object imagergb; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + + imagergb_t *imagergb_p; + int x_i; + int y_i; + int w_i; + int h_i; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdPutImageRGB: attempt to put a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdPutImageRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdPutImageRGB: attempt to put a killed imagergb!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h))) + lua_error("cdPutImageRGB: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageRGB: target region dimensions should be positive integers!"); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("cdPutImageRGB: too many parameters!"); + + cdPutImageRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i); +} + +static void cdlua_putimagerectrgb(void) +{ + lua_Object imagergb; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagergb_t *imagergb_p; + int x_i; + int y_i; + int w_i; + int h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("cdPutImageRectRGB: attempt to put a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("cdPutImageRectRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdPutImageRectRGB: attempt to put a killed imagergb!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + xmin = lua_getparam(6); + xmax = lua_getparam(7); + ymin = lua_getparam(8); + ymax = lua_getparam(9); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("cdPutImageRectRGB: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageRectRGB: target region dimensions should be positive integers!"); + + if (lua_getparam(10) != LUA_NOOBJECT) + lua_error("cdPutImageRectRGB: too many parameters!"); + + cdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +static void wdlua_putimagerectrgb(void) +{ + lua_Object imagergb; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagergb_t *imagergb_p; + double x_i; + double y_i; + double w_i; + double h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagergb = lua_getparam(1); + if (lua_isnil(imagergb)) + lua_error("wdPutImageRectRGB: attempt to put a NIL imagergb!"); + if (lua_tag(imagergb) != imagergb_tag) + lua_error("wdPutImageRectRGB: invalid imagergb parameter!"); + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("wdPutImageRectRGB: attempt to put a killed imagergb!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + xmin = lua_getparam(6); + xmax = lua_getparam(7); + ymin = lua_getparam(8); + ymax = lua_getparam(9); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("wdPutImageRectRGB: invalid parameter!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + w_i = (double) lua_getnumber(w); + h_i = (double) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("wdPutImageRectRGB: target region dimensions should be positive integers!"); + + if (lua_getparam(10) != LUA_NOOBJECT) + lua_error("wdPutImageRectRGB: too many parameters!"); + + wdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +/***************************************************************************\ +* cdPutImageRGBA. * +\***************************************************************************/ +static void cdlua_putimagergba(void) +{ + lua_Object imagergba; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + + imagergba_t *imagergba_p; + int x_i; + int y_i; + int w_i; + int h_i; + + imagergba = lua_getparam(1); + if (lua_isnil(imagergba)) + lua_error("cdPutImageRGBA: attempt to put a NIL imagergba!"); + if (lua_tag(imagergba) != imagergba_tag) + lua_error("cdPutImageRGBA: invalid imagergba parameter!"); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) + lua_error("cdPutImageRGBA: attempt to put a killed imagergba!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h))) + lua_error("cdPutImageRGBA: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageRGBA: target region dimensions should be positive integers!"); + + if (lua_getparam(6) != LUA_NOOBJECT) + lua_error("cdPutImageRGBA: too many parameters!"); + + cdPutImageRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i); +} + +static void cdlua_putimagerectrgba(void) +{ + lua_Object imagergba; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagergba_t *imagergba_p; + int x_i; + int y_i; + int w_i; + int h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagergba = lua_getparam(1); + if (lua_isnil(imagergba)) + lua_error("cdPutImageRectRGBA: attempt to put a NIL imagergba!"); + if (lua_tag(imagergba) != imagergba_tag) + lua_error("cdPutImageRectRGBA: invalid imagergba parameter!"); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) + lua_error("cdPutImageRectRGBA: attempt to put a killed imagergba!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + xmin = lua_getparam(6); + xmax = lua_getparam(7); + ymin = lua_getparam(8); + ymax = lua_getparam(9); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("cdPutImageRectRGBA: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageRectRGBA: target region dimensions should be positive integers!"); + + if (lua_getparam(10) != LUA_NOOBJECT) + lua_error("cdPutImageRectRGBA: too many parameters!"); + + cdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +static void wdlua_putimagerectrgba(void) +{ + lua_Object imagergba; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagergba_t *imagergba_p; + double x_i; + double y_i; + double w_i; + double h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagergba = lua_getparam(1); + if (lua_isnil(imagergba)) + lua_error("wdPutImageRectRGBA: attempt to put a NIL imagergba!"); + if (lua_tag(imagergba) != imagergba_tag) + lua_error("wdPutImageRectRGBA: invalid imagergba parameter!"); + imagergba_p = (imagergba_t *) lua_getuserdata(imagergba); + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue && imagergba_p->alpha)) + lua_error("wdPutImageRectRGBA: attempt to put a killed imagergba!"); + + x = lua_getparam(2); + y = lua_getparam(3); + w = lua_getparam(4); + h = lua_getparam(5); + xmin = lua_getparam(6); + xmax = lua_getparam(7); + ymin = lua_getparam(8); + ymax = lua_getparam(9); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("wdPutImageRectRGBA: invalid parameter!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + w_i = (double) lua_getnumber(w); + h_i = (double) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("wdPutImageRectRGBA: target region dimensions should be positive integers!"); + + if (lua_getparam(10) != LUA_NOOBJECT) + lua_error("wdPutImageRectRGBA: too many parameters!"); + + wdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +/***************************************************************************\ +* cdPutImageMap. * +\***************************************************************************/ +static void cdlua_putimagemap(void) +{ + lua_Object imagemap; + lua_Object palette; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + + imagemap_t *imagemap_p; + palette_t *palette_p; + int x_i; + int y_i; + int w_i; + int h_i; + + imagemap = lua_getparam(1); + if (lua_isnil(imagemap)) + lua_error("cdPutImageMap: attempt to put a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("cdPutImageMap: imagemap invalid parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("cdPutImageMap: attempt to put a killed imagemap!"); + + palette = lua_getparam(2); + if (lua_isnil(palette)) + lua_error("cdPutImageMap: NIL pallete!"); + if (lua_tag(palette) != palette_tag) + lua_error("cdPutImageMap: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("cdPutImageMap: killed pallete!"); + + x = lua_getparam(3); + y = lua_getparam(4); + w = lua_getparam(5); + h = lua_getparam(6); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h))) + lua_error("cdPutImageMap: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageMap: target region dimensions should be positive integers!"); + + if (lua_getparam(7) != LUA_NOOBJECT) + lua_error("cdPutImageMap: too many parameters!"); + + cdPutImageMap(imagemap_p->width, imagemap_p->height, imagemap_p->index, + palette_p->color, x_i, y_i, w_i, h_i); +} + +static void cdlua_putimagerectmap(void) +{ + lua_Object imagemap; + lua_Object palette; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagemap_t *imagemap_p; + palette_t *palette_p; + int x_i; + int y_i; + int w_i; + int h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagemap = lua_getparam(1); + if (lua_isnil(imagemap)) + lua_error("cdPutImageMap: attempt to put a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("cdPutImageMap: imagemap invalid parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("cdPutImageMap: attempt to put a killed imagemap!"); + + palette = lua_getparam(2); + if (lua_isnil(palette)) + lua_error("cdPutImageRectMap: NIL pallete!"); + if (lua_tag(palette) != palette_tag) + lua_error("cdPutImageRectMap: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("cdPutImageRectMap: killed pallete!"); + + x = lua_getparam(3); + y = lua_getparam(4); + w = lua_getparam(5); + h = lua_getparam(6); + xmin = lua_getparam(7); + xmax = lua_getparam(8); + ymin = lua_getparam(9); + ymax = lua_getparam(10); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("cdPutImageRectMap: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + w_i = (int) lua_getnumber(w); + h_i = (int) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("cdPutImageRectMap: target region dimensions should be positive integers!"); + + if (lua_getparam(11) != LUA_NOOBJECT) + lua_error("cdPutImageRectMap: too many parameters!"); + + cdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index, + palette_p->color, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +static void wdlua_putimagerectmap(void) +{ + lua_Object imagemap; + lua_Object palette; + lua_Object x; + lua_Object y; + lua_Object w; + lua_Object h; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + imagemap_t *imagemap_p; + palette_t *palette_p; + double x_i; + double y_i; + double w_i; + double h_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + imagemap = lua_getparam(1); + if (lua_isnil(imagemap)) + lua_error("wdPutImageMap: attempt to put a NIL imagemap!"); + if (lua_tag(imagemap) != imagemap_tag) + lua_error("wdPutImageMap: imagemap invalid parameter!"); + imagemap_p = (imagemap_t *) lua_getuserdata(imagemap); + if (!imagemap_p->index) + lua_error("wdPutImageMap: attempt to put a killed imagemap!"); + + palette = lua_getparam(2); + if (lua_isnil(palette)) + lua_error("wdPutImageRectMap: NIL pallete!"); + if (lua_tag(palette) != palette_tag) + lua_error("wdPutImageRectMap: invalid palette parameter!"); + palette_p = (palette_t *) lua_getuserdata(palette); + if (!palette_p->color) + lua_error("wdPutImageRectMap: killed pallete!"); + + x = lua_getparam(3); + y = lua_getparam(4); + w = lua_getparam(5); + h = lua_getparam(6); + xmin = lua_getparam(7); + xmax = lua_getparam(8); + ymin = lua_getparam(9); + ymax = lua_getparam(10); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(w) && lua_isnumber(h) && + lua_isnumber(xmin) && lua_isnumber(xmax) && lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("wdPutImageRectMap: invalid parameter!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + w_i = (double) lua_getnumber(w); + h_i = (double) lua_getnumber(h); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + if (w_i < 0 || h_i < 0) + lua_error("wdPutImageRectMap: target region dimensions should be positive integers!"); + + if (lua_getparam(11) != LUA_NOOBJECT) + lua_error("wdPutImageRectMap: too many parameters!"); + + wdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index, + palette_p->color, x_i, y_i, w_i, h_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +/***************************************************************************\ +* cdGetImage. * +\***************************************************************************/ +static void cdlua_getimage(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + + image_t *image_p; + int x_i; + int y_i; + + image = lua_getparam(1); + if (lua_isnil(image)) + lua_error("cdGetImage: attempt to get NIL image"); + if (lua_tag(image) != image_tag) + lua_error("cdGetImage: invalid image parameter!"); + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("cdGetImage: attempt to get a killed image"); + + x = lua_getparam(2); + y = lua_getparam(3); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("cdGetImage: invalid (x, y) parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdGetImage: too many parameters!"); + cdGetImage(image_p->cd_image, x_i, y_i); +} + +/***************************************************************************\ +* cdPutImage. * +\***************************************************************************/ +static void cdlua_putimage(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + + image_t *image_p; + int x_i; + int y_i; + + image = lua_getparam(1); + if (lua_isnil(image)) + lua_error("cdPutImage: attempt to put a NIL image!"); + if (lua_tag(image) != image_tag) + lua_error("cdPutImage: invalid image parameter!"); + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("cdPutImage: attempt to put a killed image!"); + + x = lua_getparam(2); + y = lua_getparam(3); + if (!(lua_isnumber(x) && lua_isnumber(y))) + lua_error("cdPutImage: invalid (x, y) parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdPutImage: too many parameters!"); + + cdPutImage(image_p->cd_image, x_i, y_i); +} + +/***************************************************************************\ +* cdPutImageRect. * +\***************************************************************************/ +static void cdlua_putimagerect(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + image_t *image_p; + int x_i; + int y_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + image = lua_getparam(1); + if (lua_isnil(image)) + lua_error("cdPutImageRect: attempt to put a NIL image!"); + if (lua_tag(image) != image_tag) + lua_error("cdPutImageRect: invalid image parameter!"); + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("cdPutImageRect: attempt to put a killed image!"); + + x = lua_getparam(2); + y = lua_getparam(3); + xmin = lua_getparam(4); + xmax = lua_getparam(5); + ymin = lua_getparam(6); + ymax = lua_getparam(7); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(xmin) && lua_isnumber(xmax) && + lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("cdPutImageRect: invalid parameter!"); + x_i = (int) lua_getnumber(x); + y_i = (int) lua_getnumber(y); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + + if (lua_getparam(8) != LUA_NOOBJECT) + lua_error("cdPutImageRect: too many parameters!"); + + cdPutImageRect(image_p->cd_image, x_i, y_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +static void wdlua_putimagerect(void) +{ + lua_Object image; + lua_Object x; + lua_Object y; + lua_Object xmin; + lua_Object xmax; + lua_Object ymin; + lua_Object ymax; + + image_t *image_p; + double x_i; + double y_i; + int xmin_i; + int xmax_i; + int ymin_i; + int ymax_i; + + image = lua_getparam(1); + if (lua_isnil(image)) + lua_error("wdPutImageRect: attempt to put a NIL image!"); + if (lua_tag(image) != image_tag) + lua_error("wdPutImageRect: invalid image parameter!"); + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("wdPutImageRect: attempt to put a killed image!"); + + x = lua_getparam(2); + y = lua_getparam(3); + xmin = lua_getparam(4); + xmax = lua_getparam(5); + ymin = lua_getparam(6); + ymax = lua_getparam(7); + if (!(lua_isnumber(x) && lua_isnumber(y) && lua_isnumber(xmin) && lua_isnumber(xmax) && + lua_isnumber(ymin) && lua_isnumber(ymax))) + lua_error("wdPutImageRect: invalid parameter!"); + x_i = (double) lua_getnumber(x); + y_i = (double) lua_getnumber(y); + xmin_i = (int) lua_getnumber(xmin); + xmax_i = (int) lua_getnumber(xmax); + ymin_i = (int) lua_getnumber(ymin); + ymax_i = (int) lua_getnumber(ymax); + + if (lua_getparam(8) != LUA_NOOBJECT) + lua_error("wdPutImageRect: too many parameters!"); + + wdPutImageRect(image_p->cd_image, x_i, y_i, xmin_i, xmax_i, ymin_i, ymax_i); +} + +/***************************************************************************\ +* cdVersion. * +\***************************************************************************/ + +static void cdlua_version(void) +{ + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdVersion: too many parameters!"); + + lua_pushstring(cdVersion()); +} + +/***************************************************************************\ +* wdGetViewport. * +\***************************************************************************/ +static void wdlua_getviewport(void) +{ + int xmin; + int xmax; + int ymin; + int ymax; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("wdGetViewport: too many parameters!"); + + wdGetViewport(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +/***************************************************************************\ +* wdGetWindow. * +\***************************************************************************/ +static void wdlua_getwindow(void) +{ + double xmin; + double xmax; + double ymin; + double ymax; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("wdGetWindow: too many parameters!"); + + wdGetWindow(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +/***************************************************************************\ +* wdGetClipArea. * +\***************************************************************************/ +static void wdlua_getcliparea(void) +{ + double xmin; + double xmax; + double ymin; + double ymax; + int status; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("wdGetClipArea: too many parameters!"); + + status = wdGetClipArea(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); + lua_pushnumber(status); +} + +static void wdlua_RegionBox(void) +{ + double xmin; + double xmax; + double ymin; + double ymax; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("wdRegionBox: too many parameters!"); + + wdRegionBox(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(xmin); + lua_pushnumber(xmax); + lua_pushnumber(ymin); + lua_pushnumber(ymax); +} + +/***************************************************************************\ +* wdFontDim. * +\***************************************************************************/ +static void wdlua_fontdim(void) +{ + double max_width; + double height; + double ascent; + double descent; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("wdFontDim: too many parameters!"); + + wdFontDim(&max_width, &height, &ascent, &descent); + lua_pushnumber(max_width); + lua_pushnumber(height); + lua_pushnumber(ascent); + lua_pushnumber(descent); +} + +/***************************************************************************\ +* wdTextSize. * +\***************************************************************************/ +static void wdlua_textsize(void) +{ + lua_Object text; + char* text_s; + + double width; + double height; + + text = lua_getparam(1); + if (!lua_isstring(text)) + lua_error("wdTextSize: invalid text parameter!"); + text_s = (char*) lua_getstring(text); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("wdTextSize: too many parameters!"); + + wdTextSize(text_s, &width, &height); + lua_pushnumber(width); + lua_pushnumber(height); +} + +/***************************************************************************\ +* wdGetVectorTextSize. * +\***************************************************************************/ +static void wdlua_getvectortextsize(void) +{ + lua_Object text; + char* text_s; + + double width; + double height; + + text = lua_getparam(1); + if (!lua_isstring(text)) + lua_error("wdGetVectorTextSize: invalid text parameter!"); + text_s = (char*) lua_getstring(text); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("wdGetVectorTextSize: too many parameters!"); + + wdGetVectorTextSize(text_s, &width, &height); + lua_pushnumber(width); + lua_pushnumber(height); +} + +static void cdlua_vectortexttransform(void) +{ + lua_Object old_table, table, value; + double matrix[6], *old_matrix; + int i; + + table = lua_getparam(1); + if (!lua_istable(table)) + lua_error("cdVectorTextTransform: invalid table parameter!"); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdVectorTextTransform: too many parameters!"); + + for (i=0; i < 6; i++) + { + lua_pushobject(table); + lua_pushnumber(i+1); + value = lua_gettable(); + + if (!lua_isnumber(value)) + lua_error("cdVectorTextTransform: invalid value!"); + + matrix[i] = lua_getnumber(value); + } + + old_matrix = cdVectorTextTransform(matrix); + + old_table = lua_createtable(); + + for (i=0; i < 6; i++) + { + lua_pushobject(old_table); + lua_pushnumber(i+1); + lua_pushnumber(old_matrix[i]); + lua_settable(); + } +} + +static void cdlua_vectortextbounds(void) +{ + char* s = (char*)luaL_check_string(1); + int x = (int)luaL_check_number(2); + int y = (int)luaL_check_number(3); + int rect[8], i; + lua_Object lua_rect; + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("cdGetVectorTextBounds: too many parameters!"); + + cdGetVectorTextBounds(s, x, y, rect); + + lua_rect = lua_createtable(); + + for (i=0; i < 8; i++) + { + lua_pushobject(lua_rect); + lua_pushnumber(i+1); + lua_pushnumber(rect[i]); + lua_settable(); + } +} + +static void wdlua_vectortextbounds(void) +{ + char* s = (char*)luaL_check_string(1); + double x = luaL_check_number(2); + double y = luaL_check_number(3); + double rect[8]; + int i; + lua_Object lua_rect; + + if (lua_getparam(4) != LUA_NOOBJECT) + lua_error("wdGetVectorTextBounds: too many parameters!"); + + wdGetVectorTextBounds(s, x, y, rect); + + lua_rect = lua_createtable(); + + for (i=0; i < 8; i++) + { + lua_pushobject(lua_rect); + lua_pushnumber(i+1); + lua_pushnumber(rect[i]); + lua_settable(); + } +} + +static void cdlua_getvectortextsize(void) +{ + lua_Object text; + char* text_s; + + int width; + int height; + + text = lua_getparam(1); + if (!lua_isstring(text)) + lua_error("cdGetVectorTextSize: invalid text parameter!"); + text_s = (char*) lua_getstring(text); + + if (lua_getparam(2) != LUA_NOOBJECT) + lua_error("cdGetTextSize: too many parameters!"); + + cdGetVectorTextSize(text_s, &width, &height); + lua_pushnumber(width); + lua_pushnumber(height); +} +/***************************************************************************\ +* wdWorld2Canvas. * +\***************************************************************************/ +static void wdlua_world2canvas(void) +{ + lua_Object xw; + lua_Object yw; + double xw_d; + double yw_d; + + int xv_i; + int yv_i; + + xw = lua_getparam(1); + yw = lua_getparam(2); + if (!(lua_isnumber(xw) && lua_isnumber(yw))) + lua_error("wdWorld2Canvas: invalid (xw, yw) parameter!"); + xw_d = (double) lua_getnumber(xw); + yw_d = (double) lua_getnumber(yw); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("wdWorld2Canvas: too many parameters!"); + + wdWorld2Canvas(xw_d, yw_d, &xv_i, &yv_i); + lua_pushnumber(xv_i); + lua_pushnumber(yv_i); +} + +/***************************************************************************\ +* wdCanvas2World. * +\***************************************************************************/ +static void wdlua_canvas2world(void) +{ + lua_Object xv; + lua_Object yv; + int xv_i; + int yv_i; + + double xw_d; + double yw_d; + + xv = lua_getparam(1); + yv = lua_getparam(2); + if (!(lua_isnumber(xv) && lua_isnumber(yv))) + lua_error("wdCanvas2World: invalid (xc, yc) parameter!"); + xv_i = (int) lua_getnumber(xv); + yv_i = (int) lua_getnumber(yv); + + if (lua_getparam(3) != LUA_NOOBJECT) + lua_error("wdCanvas2World: too many parameters!"); + + wdCanvas2World(xv_i, yv_i, &xw_d, &yw_d); + lua_pushnumber(xw_d); + lua_pushnumber(yw_d); +} + +/***************************************************************************\ +* Initializes CDLua. * +\***************************************************************************/ +static void cdlua_pushstring(char* str, char* name) +{ + lua_pushstring(str); lua_setglobal(name); + cdlua_setnamespace(name, name+2); /* CD_XXXX = _XXXX */ +} + +static void setinfo(void) +{ + cdlua_pushstring(CD_COPYRIGHT, "CD_COPYRIGHT"); + cdlua_pushstring("A 2D Graphics Library", "CD_DESCRIPTION"); + cdlua_pushstring("CD - Canvas Draw", "CD_NAME"); + cdlua_pushstring("CD "CD_VERSION, "CD_VERSION"); +} + +void cdlua_open(void) +{ + char version[50]; + lua_Object imlua_tag; + + cdlua_namespace = lua_createtable(); + lua_pushobject(cdlua_namespace); lua_setglobal ("cd"); + + sprintf(version, "CDLua %s", cdVersion()); + lua_pushstring(version); lua_setglobal ("CDLUA_VERSION"); + setinfo(); + + /* check if IM has been initialized */ + imlua_tag = lua_getglobal("IMLUA_INSTALLED"); + + /* get IM defined tags, let IM handle with the user tag objects */ + if ((imlua_tag != LUA_NOOBJECT) && (!lua_isnil(imlua_tag))) + { + imlua_tag = lua_getglobal("IMLUA_COLOR_TAG"); + color_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_IMAGERGB_TAG"); + imagergb_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_IMAGERGBA_TAG"); + imagergba_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_PALETTE_TAG"); + palette_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_IMAGEMAP_TAG"); + imagemap_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_CHANNEL_TAG"); + channel_tag = (int) lua_getnumber(imlua_tag); + imlua_tag = lua_getglobal("IMLUA_BITMAP_TAG"); + bitmap_tag = (int) lua_getnumber(imlua_tag); + } + else /* define CD own tags and fallbacks */ + { + /* create user tags */ + color_tag = lua_newtag(); + bitmap_tag = lua_newtag(); + imagergb_tag = lua_newtag(); + imagergba_tag = lua_newtag(); + imagemap_tag = lua_newtag(); + palette_tag = lua_newtag(); + channel_tag = lua_newtag(); + + /* hook "settable" and "gettable" tag methods */ + lua_pushcfunction(palettesettable_fb); lua_settagmethod(palette_tag, "settable"); + lua_pushcfunction(imagemapsettable_fb); lua_settagmethod(imagemap_tag, "settable"); + lua_pushcfunction(channelsettable_fb); lua_settagmethod(channel_tag, "settable"); + + lua_pushcfunction(palettegettable_fb); lua_settagmethod(palette_tag, "gettable"); + lua_pushcfunction(imagemapgettable_fb); lua_settagmethod(imagemap_tag, "gettable"); + lua_pushcfunction(channelgettable_fb); lua_settagmethod(channel_tag, "gettable"); + lua_pushcfunction(imagergbgettable_fb); lua_settagmethod(imagergb_tag, "gettable"); + lua_pushcfunction(imagergbagettable_fb); lua_settagmethod(imagergba_tag, "gettable"); + lua_pushcfunction(bitmapgettable_fb); lua_settagmethod(bitmap_tag, "gettable"); + + lua_pushcfunction(palettegc_fb); lua_settagmethod(palette_tag, "gc"); + lua_pushcfunction(imagemapgc_fb); lua_settagmethod(imagemap_tag, "gc"); + lua_pushcfunction(imagergbgc_fb); lua_settagmethod(imagergb_tag, "gc"); + lua_pushcfunction(imagergbagc_fb); lua_settagmethod(imagergba_tag, "gc"); + lua_pushcfunction(bitmapgc_fb); lua_settagmethod(bitmap_tag, "gc"); + } + + /* these are not handled by IM */ + stipple_tag = lua_newtag(); + pattern_tag = lua_newtag(); + image_tag = lua_newtag(); + canvas_tag = lua_newtag(); + state_tag = lua_newtag(); + + /* hook "settable" and "gettable" tag methods */ + lua_pushcfunction(stipplesettable_fb); lua_settagmethod(stipple_tag, "settable"); + lua_pushcfunction(patternsettable_fb); lua_settagmethod(pattern_tag, "settable"); + lua_pushcfunction(stipplegettable_fb); lua_settagmethod(stipple_tag, "gettable"); + lua_pushcfunction(patterngettable_fb); lua_settagmethod(pattern_tag, "gettable"); + + lua_pushcfunction(stipplegc_fb); lua_settagmethod(stipple_tag, "gc"); + lua_pushcfunction(patterngc_fb); lua_settagmethod(pattern_tag, "gc"); + lua_pushcfunction(stategc_fb); lua_settagmethod(state_tag, "gc"); + + /* register used tags in global context for other libraries use */ + lua_pushnumber(1.0f); lua_setglobal("CDLUA_INSTALLED"); + + lua_pushnumber(color_tag); lua_setglobal(COLOR_TAG); + lua_pushnumber(stipple_tag); lua_setglobal(STIPPLE_TAG); + lua_pushnumber(pattern_tag); lua_setglobal(PATTERN_TAG); + lua_pushnumber(image_tag); lua_setglobal(IMAGE_TAG); + lua_pushnumber(bitmap_tag); lua_setglobal(BITMAP_TAG); + lua_pushnumber(imagergb_tag); lua_setglobal(IMAGERGB_TAG); + lua_pushnumber(imagergba_tag); lua_setglobal(IMAGERGBA_TAG); + lua_pushnumber(imagemap_tag); lua_setglobal(IMAGEMAP_TAG); + lua_pushnumber(palette_tag); lua_setglobal(PALETTE_TAG); + lua_pushnumber(channel_tag); lua_setglobal(CHANNEL_TAG); + lua_pushnumber(canvas_tag); lua_setglobal(CANVAS_TAG); + lua_pushnumber(state_tag); lua_setglobal(STATE_TAG); + + /* registered cd functions */ + cdlua_register("cdSaveState", cdlua_savestate); + cdlua_register("cdRestoreState", cdlua_restorestate); + cdlua_register("cdReleaseState", cdlua_releasestate); + cdlua_register("cdCreateCanvas", cdlua_createcanvas); + cdlua_register("cdContextCaps", cdlua_contextcaps); + cdlua_register("cdGetContext", cdlua_getcontext); + cdlua_register("cdActivate", cdlua_activate); + cdlua_register("cdActiveCanvas", cdlua_activecanvas); + cdlua_register("cdKillCanvas", cdlua_killcanvas); + cdlua_register("cdCreateStipple", cdlua_createstipple); + cdlua_register("cdGetStipple", cdlua_getstipple); + cdlua_register("cdKillStipple", cdlua_killstipple); + cdlua_register("cdCreatePattern", cdlua_createpattern); + cdlua_register("cdGetPattern", cdlua_getpattern); + cdlua_register("cdKillPattern", cdlua_killpattern); + cdlua_register("cdCreatePalette", cdlua_createpalette); + cdlua_register("cdKillPalette", cdlua_killpalette); + cdlua_register("cdCreateImage", cdlua_createimage); + cdlua_register("cdKillImage", cdlua_killimage); + cdlua_register("cdImageRGB", cdlua_imagergb); + cdlua_register("cdImageRGBBitmap", cdlua_imagergbbitmap); + cdlua_register("cdCreateImageRGB", cdlua_createimagergb); + cdlua_register("cdKillImageRGB", cdlua_killimagergb); + cdlua_register("cdCreateImageRGBA", cdlua_createimagergba); + cdlua_register("cdKillImageRGBA", cdlua_killimagergba); + cdlua_register("cdCreateImageMap", cdlua_createimagemap); + cdlua_register("cdKillImageMap", cdlua_killimagemap); + + cdlua_register("cdRegisterCallback", cdlua_registercallback); + cdlua_register("cdEncodeColor", cdlua_encodecolor); + cdlua_register("cdDecodeColor", cdlua_decodecolor); + cdlua_register("cdEncodeAlpha", cdlua_encodealpha); + cdlua_register("cdDecodeAlpha", cdlua_decodealpha); + cdlua_register("cdReserved", cdlua_reserved); + cdlua_register("cdBlue", cdlua_blue); + cdlua_register("cdGreen", cdlua_green); + cdlua_register("cdRed", cdlua_red); + cdlua_register("cdAlpha", cdlua_alpha); + cdlua_register("cdForeground", cdlua_foreground); + cdlua_register("cdBackground", cdlua_background); + cdlua_register("cdUpdateYAxis", cdlua_updateyaxis); + cdlua_register("cdFontDim", cdlua_fontdim); + cdlua_register("cdGetCanvasSize", cdlua_getcanvassize); + cdlua_register("cdGetClipPoly", cdlua_getclippoly); + cdlua_register("cdGetClipArea", cdlua_getcliparea); + cdlua_register("cdRegionBox", cdlua_RegionBox); + cdlua_register("cdGetImage", cdlua_getimage); + cdlua_register("cdGetImageRGB", cdlua_getimagergb); + cdlua_register("cdMM2Pixel", cdlua_mm2pixel); + cdlua_register("cdPalette", cdlua_palette); + cdlua_register("cdPattern", cdlua_pattern); + cdlua_register("cdPixel", cdlua_pixel); + cdlua_register("cdPixel2MM", cdlua_pixel2mm); + cdlua_register("cdPlay", cdlua_play); + cdlua_register("cdPutImage", cdlua_putimage); + cdlua_register("cdRGB2Map", cdlua_rgb2map); + cdlua_register("cdPutImageRGB", cdlua_putimagergb); + cdlua_register("cdPutImageRectRGB", cdlua_putimagerectrgb); + cdlua_register("cdPutImageRGBA", cdlua_putimagergba); + cdlua_register("cdPutImageRectRGBA", cdlua_putimagerectrgba); + cdlua_register("cdPutImageMap", cdlua_putimagemap); + cdlua_register("cdPutImageRectMap", cdlua_putimagerectmap); + cdlua_register("cdPutImageRect", cdlua_putimagerect); + cdlua_register("cdStipple", cdlua_stipple); + cdlua_register("cdTextSize", cdlua_textsize); + cdlua_register("cdTextBox", cdlua_textbox); + cdlua_register("cdTextBounds", cdlua_textbounds); + cdlua_register("cdGetFont", cdlua_getfont); + cdlua_register("cdVersion", cdlua_version); + cdlua_register("cdGetVectorTextSize", cdlua_getvectortextsize); + cdlua_register("cdVectorTextTransform", cdlua_vectortexttransform); + cdlua_register("cdVectorTextBounds", cdlua_vectortextbounds); + cdlua_register("cdCreateBitmap", cdlua_createbitmap); + cdlua_register("cdKillBitmap", cdlua_killbitmap); + cdlua_register("cdBitmapSetRect", cdlua_bitmapsetrect); + cdlua_register("cdPutBitmap", cdlua_putbitmap); + cdlua_register("cdGetBitmap", cdlua_getbitmap); + cdlua_register("cdBitmapRGB2Map", cdlua_rgb2mapex); + cdlua_register("cdLineStyleDashes", cdlua_LineStyleDashes); + + /* registered wd functions */ + cdlua_register("wdHardcopy", wdlua_hardcopy); + cdlua_register("wdPutBitmap", wdlua_putbitmap); + cdlua_register("wdGetWindow", wdlua_getwindow); + cdlua_register("wdGetViewport", wdlua_getviewport); + cdlua_register("wdWorld2Canvas", wdlua_world2canvas); + cdlua_register("wdCanvas2World", wdlua_canvas2world); + cdlua_register("wdGetClipArea", wdlua_getcliparea); + cdlua_register("wdRegionBox", wdlua_RegionBox); + cdlua_register("wdMM2Pixel", cdlua_mm2pixel); + cdlua_register("wdPixel2MM", cdlua_pixel2mm); + cdlua_register("wdFontDim", wdlua_fontdim); + cdlua_register("wdGetFont", wdlua_getfont); + cdlua_register("wdTextSize", wdlua_textsize); + cdlua_register("wdGetVectorTextSize", wdlua_getvectortextsize); + cdlua_register("wdVectorTextBounds", wdlua_vectortextbounds); + cdlua_register("wdPixel", wdlua_pixel); + cdlua_register("wdTextBox", wdlua_textbox); + cdlua_register("wdTextBounds", wdlua_textbounds); + cdlua_register("wdPutImageRectRGB", wdlua_putimagerectrgb); + cdlua_register("wdPutImageRectRGBA", wdlua_putimagerectrgba); + cdlua_register("wdPutImageRectMap", wdlua_putimagerectmap); + cdlua_register("wdPutImageRect", wdlua_putimagerect); + cdlua_register("wdStipple", wdlua_stipple); + cdlua_register("wdPattern", wdlua_pattern); + cdlua_register("wdGetClipPoly", wdlua_getclippoly); + + cdlua_initdrivers(); + + /* color constants */ + cdlua_pushcolor(CD_RED, "CD_RED"); + cdlua_pushcolor(CD_DARK_RED, "CD_DARK_RED"); + cdlua_pushcolor(CD_GREEN, "CD_GREEN"); + cdlua_pushcolor(CD_DARK_GREEN, "CD_DARK_GREEN"); + cdlua_pushcolor(CD_BLUE, "CD_BLUE"); + cdlua_pushcolor(CD_DARK_BLUE, "CD_DARK_BLUE"); + cdlua_pushcolor(CD_YELLOW, "CD_YELLOW"); + cdlua_pushcolor(CD_DARK_YELLOW, "CD_DARK_YELLOW"); + cdlua_pushcolor(CD_MAGENTA, "CD_MAGENTA"); + cdlua_pushcolor(CD_DARK_MAGENTA, "CD_DARK_MAGENTA"); + cdlua_pushcolor(CD_CYAN, "CD_CYAN"); + cdlua_pushcolor(CD_DARK_CYAN, "CD_DARK_CYAN"); + cdlua_pushcolor(CD_WHITE, "CD_WHITE"); + cdlua_pushcolor(CD_BLACK, "CD_BLACK"); + cdlua_pushcolor(CD_DARK_GRAY, "CD_DARK_GRAY"); + cdlua_pushcolor(CD_GRAY, "CD_GRAY"); + + /* cdplay constants */ + cdlua_pushnumber(CD_SIZECB, "CD_SIZECB"); + + /* create void canvas used when there is no active canvas to avoid protection faults */ + void_canvas = cdCreateCanvas(CD_VOID, NULL); + cdActivate(void_canvas); + + /* initialize toLua implementation */ + luaL_cd_open(); + luaL_wd_open(); +} + +void cdlua_close(void) +{ + cdKillCanvas(void_canvas); +} diff --git a/cd/src/lua3/cdlua.def b/cd/src/lua3/cdlua.def new file mode 100755 index 0000000..68b0ee4 --- /dev/null +++ b/cd/src/lua3/cdlua.def @@ -0,0 +1,7 @@ +EXPORTS + cdlua_open + cdlua_close + cdlua_getcanvas + cdlua_addcontext + cdlua_checkcanvas + cdlua_pushcanvas \ No newline at end of file diff --git a/cd/src/lua3/cdluactx.c b/cd/src/lua3/cdluactx.c new file mode 100755 index 0000000..fc09313 --- /dev/null +++ b/cd/src/lua3/cdluactx.c @@ -0,0 +1,950 @@ +/***************************************************************************\ +* CDLUA.C, for LUA 3.1 * +* Diego Fernandes Nehab, Antonio Escano Scuri * +* 01/99 * +\***************************************************************************/ + +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" + +#include "cdimage.h" +#include "cdirgb.h" +#include "cddxf.h" +#include "cddgn.h" +#include "cdcgm.h" +#include "cdwmf.h" +#include "cdemf.h" +#include "cdnative.h" +#include "cdprint.h" +#include "cdclipbd.h" +#include "cdmf.h" +#include "cdps.h" +#include "cddbuf.h" +#include "cdgdiplus.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua3_private.h" + + +/***************************************************************************\ +* CD_CGM. * +\***************************************************************************/ +static void *cdcgm_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_CGM: data should be of type string!"); + + return lua_getstring(data); +} + +static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); +static int cgm_countercb(cdCanvas *canvas, double percent); +static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f); +static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx); +static int cgm_begpictcb(cdCanvas *canvas, char *pict); +static int cgm_begpictbcb(cdCanvas *canvas); +static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx); + +static cdCallbackLUA cdluacgmcb[7] = { +{ + -1, + "CD_SIZECB", + (cdCallback)cgm_sizecb +}, +{ + -1, + "CD_CGMCOUNTERCB", + (cdCallback)cgm_countercb +}, +{ + -1, + "CD_CGMSCLMDECB", + (cdCallback)cgm_sclmdecb +}, +{ + -1, + "CD_CGMVDCEXTCB", + (cdCallback)cgm_vdcextcb +}, +{ + -1, + "CD_CGMBEGPICTCB", + (cdCallback)cgm_begpictcb +}, +{ + -1, + "CD_CGMBEGPICTBCB", + (cdCallback)cgm_begpictbcb +}, +{ + -1, + "CD_CGMBEGMTFCB", + (cdCallback)cgm_begmtfcb +} +}; + +static cdContextLUA cdluacgmctx = +{ + 0, + "CD_CGM", + cdContextCGM, + cdcgm_checkdata, + cdluacgmcb, + 7 +}; + +/***************************************************************************\ +* CGM CD_COUNTERCB. * +\***************************************************************************/ +static int cgm_countercb(cdCanvas *canvas, double percent) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMCOUNTERCB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( percent); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMCOUNTERCB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_BEGPICTCB. * +\***************************************************************************/ +static int cgm_begpictcb(cdCanvas *canvas, char *pict) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMBEGPICTCB].lock); + + cdlua_pushcanvas(canvas); + lua_pushstring(pict); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMBEGPICTCB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx) +{ + lua_Object func, result, xmn_l, ymn_l, xmx_l, ymx_l; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMBEGMTFCB].lock); + + cdlua_pushcanvas(canvas); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMBEGMTFCB: invalid return value!"); + result_i = (int) lua_getnumber(result); + if (result_i == 1) { + lua_endblock(); + return 1; + } + + xmn_l = lua_getresult(2); + if (!lua_isnumber(xmn_l)) + lua_error("cdPlay: CD_CGMBEGMTFCB: invalid xmn return value!"); + *xmn = (int) lua_getnumber(xmn_l); + + ymn_l = lua_getresult(3); + if (!lua_isnumber(ymn_l)) + lua_error("cdPlay: CD_CGMBEGMTFCB: invalid ymn return value!"); + *ymn = (int) lua_getnumber(ymn_l); + + xmx_l = lua_getresult(4); + if (!lua_isnumber(xmx_l)) + lua_error("cdPlay: CD_CGMBEGMTFCB: invalid xmx return value!"); + *xmx = (int) lua_getnumber(xmx_l); + + ymx_l = lua_getresult(5); + if (!lua_isnumber(ymx_l)) + lua_error("cdPlay: CD_CGMBEGMTFCB: invalid ymx return value!"); + *ymx = (int) lua_getnumber(ymx_l); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_BEGPICTBCB. * +\***************************************************************************/ +static int cgm_begpictbcb(cdCanvas *canvas) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMBEGPICTBCB].lock); + + cdlua_pushcanvas(canvas); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMBEGPICTBCB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_SIZECB. * +\***************************************************************************/ +static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_SIZECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( w); + lua_pushnumber( h); + lua_pushnumber( mm_w); + lua_pushnumber( mm_h); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_SIZECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_SCLMDE. * +\***************************************************************************/ +static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f) +{ + lua_Object func, result, draw_mode, factor; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMSCLMDECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( scl_mde); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMSCLMDECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + if (result_i == 1) { + lua_endblock(); + return 1; + } + + draw_mode = lua_getresult(2); + if (!lua_isnumber(draw_mode)) + lua_error("cdPlay: CD_CGMSCLMDECB: invalid draw_mode return value!"); + *draw_mode_i = (short) lua_getnumber(draw_mode); + + factor = lua_getresult(3); + if (!lua_isnumber(factor)) + lua_error("cdPlay: CD_CGMSCLMDECB: invalid factor return value!"); + *factor_f = (double) lua_getnumber(factor); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_VDCEXTCB. * +\***************************************************************************/ +static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx) +{ + lua_Object func, result, xmn_l, ymn_l, xmx_l, ymx_l; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluacgmcb[CD_CGMVDCEXTCB].lock); + + cdlua_pushcanvas(canvas); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_CGMVDCEXTCB: invalid return value!"); + result_i = (int) lua_getnumber(result); + if (result_i == 1) { + lua_endblock(); + return 1; + } + + xmn_l = lua_getresult(2); + if (!lua_isnumber(xmn_l)) + lua_error("cdPlay: CD_CGMVDCEXTCB: invalid xmn return value!"); + if (type == 1) *((float *) xmn) = (float) lua_getnumber(xmn_l); + else *((int *) xmn) = (int) lua_getnumber(xmn_l); + + ymn_l = lua_getresult(3); + if (!lua_isnumber(ymn_l)) + lua_error("cdPlay: CD_CGMVDCEXTCB: invalid ymn return value!"); + if (type == 1) *((float *) ymn) = (float) lua_getnumber(ymn_l); + else *((int *) ymn) = (int) lua_getnumber(ymn_l); + + xmx_l = lua_getresult(4); + if (!lua_isnumber(xmx_l)) + lua_error("cdPlay: CD_CGMVDCEXTCB: invalid xmx return value!"); + if (type == 1) *((float *) xmx) = (float) lua_getnumber(xmx_l); + else *((int *) xmx) = (int) lua_getnumber(xmx_l); + + ymx_l = lua_getresult(5); + if (!lua_isnumber(ymx_l)) + lua_error("cdPlay: CD_CGMVDCEXTCB: invalid ymx return value!"); + if (type == 1) *((float *) ymx) = (float) lua_getnumber(ymx_l); + else *((int *) ymx) = (int) lua_getnumber(ymx_l); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CD_DBUFFER. * +\***************************************************************************/ +static void *cddbuf_checkdata(int param) +{ + canvas_t *canvas_p; + lua_Object canvas; + int canvas_tag = (int)lua_getnumber(lua_getglobal(CANVAS_TAG)); + + canvas = lua_getparam(param); + if (lua_isnil(canvas)) + lua_error("cdCreateCanvas CD_DBUFFER: data is a NIL canvas!"); + + if (lua_tag(canvas) != canvas_tag) + lua_error("cdCreateCanvas CD_DBUFFER: data should be of type canvas_tag!"); + + canvas_p = (canvas_t *) lua_getuserdata(canvas); + if (!canvas_p->cd_canvas) + lua_error("cdCreateCanvas CD_DBUFFER: data is a killed canvas!"); + + return canvas_p->cd_canvas; +} + +static cdContextLUA cdluadbufctx = +{ + 0, + "CD_DBUFFER", + cdContextDBuffer, + cddbuf_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_IMAGE. * +\***************************************************************************/ +static void *cdimage_checkdata(int param) +{ + int image_tag; + image_t *image_p; + lua_Object image = lua_getparam(param); + if (lua_isnil(image)) + lua_error("cdCreateCanvas CD_IMAGE: data is a NIL image!"); + + image_tag = (int)lua_getnumber(lua_getglobal(IMAGE_TAG)); + if (lua_tag(image) != image_tag) + lua_error("cdCreateCanvas CD_IMAGE: data should be of type image_tag!"); + + image_p = (image_t *) lua_getuserdata(image); + if (!image_p->cd_image) + lua_error("cdCreateCanvas CD_IMAGE: data is a killed image!"); + + return image_p->cd_image; +} + +static cdContextLUA cdluaimagectx = +{ + 0, + "CD_IMAGE", + cdContextImage, + cdimage_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_IMAGERGB. * +\***************************************************************************/ +static void *cdimagergb_checkdata(int param) +{ + lua_Object imagergb; + static char data_s[50]; + + imagergb = lua_getparam(param); + if (lua_isnil(imagergb)) + lua_error("cdCreateCanvas CD_IMAGERGB: data is a NIL imagergb!"); + + if (lua_isstring(imagergb)) + { + char* str = lua_getstring(imagergb); + strcpy(data_s, str); + } + else + { + lua_Object res; + int bitmap_tag = (int)lua_getnumber(lua_getglobal(BITMAP_TAG)); + + if (lua_tag(imagergb) == bitmap_tag) + { + bitmap_t *imagergb_p; + + imagergb_p = (bitmap_t *) lua_getuserdata(imagergb); + if (!imagergb_p->image) + lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergb!"); + + if (imagergb_p->image->type != CD_RGB && imagergb_p->image->type != CD_RGBA) + lua_error("cdCreateCanvas CD_IMAGERGB: bitmap should be of type rgb or rgba!"); + + res = lua_getparam(param+1); + if (res == LUA_NOOBJECT || lua_isnil(res)) + { + if (imagergb_p->image->type == CD_RGBA) + sprintf(data_s, "%dx%d %p %p %p %p -a", imagergb_p->image->w, imagergb_p->image->h, + cdBitmapGetData(imagergb_p->image, CD_IRED), + cdBitmapGetData(imagergb_p->image, CD_IGREEN), + cdBitmapGetData(imagergb_p->image, CD_IBLUE), + cdBitmapGetData(imagergb_p->image, CD_IALPHA)); + else + sprintf(data_s, "%dx%d %p %p %p", imagergb_p->image->w, imagergb_p->image->h, + cdBitmapGetData(imagergb_p->image, CD_IRED), + cdBitmapGetData(imagergb_p->image, CD_IGREEN), + cdBitmapGetData(imagergb_p->image, CD_IBLUE)); + } + else + { + double res_f = lua_getnumber(res); + if (imagergb_p->image->type == CD_RGBA) + sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", imagergb_p->image->w, imagergb_p->image->h, + cdBitmapGetData(imagergb_p->image, CD_IRED), + cdBitmapGetData(imagergb_p->image, CD_IGREEN), + cdBitmapGetData(imagergb_p->image, CD_IBLUE), + cdBitmapGetData(imagergb_p->image, CD_IALPHA), + res_f); + else + sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->image->w, imagergb_p->image->h, + cdBitmapGetData(imagergb_p->image, CD_IRED), + cdBitmapGetData(imagergb_p->image, CD_IGREEN), + cdBitmapGetData(imagergb_p->image, CD_IBLUE), + res_f); + } + } + else + { + imagergb_t *imagergb_p; + int imagergb_tag = (int)lua_getnumber(lua_getglobal(IMAGERGB_TAG)); + + if (lua_tag(imagergb) != imagergb_tag) + { + imagergba_t *imagergba_p; + int imagergba_tag = (int)lua_getnumber(lua_getglobal(IMAGERGBA_TAG)); + if (lua_tag(imagergb) != imagergba_tag) + lua_error("cdCreateCanvas CD_IMAGERGB: data should be of type imagergb_tag or imagergba_tag!"); + + imagergba_p = (imagergba_t *) lua_getuserdata(imagergb); + if (!(imagergba_p->red && imagergba_p->green && imagergba_p->blue)) + lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergba!"); + + res = lua_getparam(param+1); + if (res == LUA_NOOBJECT || lua_isnil(res)) + { + sprintf(data_s, "%dx%d %p %p %p", imagergba_p->width, imagergba_p->height, + imagergba_p->red, imagergba_p->green, imagergba_p->blue); + } + else + { + double res_f = lua_getnumber(res); + sprintf(data_s, "%dx%d %p %p %p -r%g", imagergba_p->width, imagergba_p->height, + imagergba_p->red, imagergba_p->green, imagergba_p->blue, res_f); + } + + return data_s; + } + + imagergb_p = (imagergb_t *) lua_getuserdata(imagergb); + if (!(imagergb_p->red && imagergb_p->green && imagergb_p->blue)) + lua_error("cdCreateCanvas CD_IMAGERGB: data is a killed imagergb!"); + + res = lua_getparam(param+1); + if (res == LUA_NOOBJECT || lua_isnil(res)) + { + sprintf(data_s, "%dx%d %p %p %p", imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue); + } + else + { + double res_f = lua_getnumber(res); + sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue, res_f); + } + } + } + + return data_s; +} + +static cdContextLUA cdluaimagergbctx = +{ + 0, + "CD_IMAGERGB", + cdContextImageRGB, + cdimagergb_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_DXF. * +\***************************************************************************/ +static void *cddxf_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_DXF: data should be of type string!"); + + return lua_getstring(data); +} + +static cdContextLUA cdluadxfctx = +{ + 0, + "CD_DXF", + cdContextDXF, + cddxf_checkdata +}; + +/***************************************************************************\ +* CD_DGN. * +\***************************************************************************/ +static void *cddgn_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_DGN: data should be of type string!"); + + return lua_getstring(data); +} + +static cdContextLUA cdluadgnctx = +{ + 0, + "CD_DGN", + cdContextDGN, + cddgn_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_WMF. * +\***************************************************************************/ +static void *cdwmf_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_WMF: data should be of type string!"); + + return lua_getstring(data); +} + +static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdCallbackLUA cdluawmfcb[1] = +{{ + -1, + "CD_SIZECB", + (cdCallback)wmf_sizecb +}}; + +static cdContextLUA cdluawmfctx = +{ + 0, + "CD_WMF", + cdContextWMF, + cdwmf_checkdata, + cdluawmfcb, + 1 +}; + +/***************************************************************************\ +* WMF CD_SIZECB. * +\***************************************************************************/ +static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluawmfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( w); + lua_pushnumber( h); + lua_pushnumber( mm_w); + lua_pushnumber( mm_h); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_SIZECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CD_EMF. * +\***************************************************************************/ +static void *cdemf_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_EMF: data should be of type string!"); + + return lua_getstring(data); +} + +static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdCallbackLUA cdluaemfcb[1] = +{{ + -1, + "CD_SIZECB", + (cdCallback)emf_sizecb +}}; + +static cdContextLUA cdluaemfctx = +{ + 0, + "CD_EMF", + cdContextEMF, + cdemf_checkdata, + cdluaemfcb, + 1 +}; + +/***************************************************************************\ +* EMF CD_SIZECB. * +\***************************************************************************/ +static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluaemfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( w); + lua_pushnumber( h); + lua_pushnumber( mm_w); + lua_pushnumber( mm_h); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_SIZECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CD_METAFILE. * +\***************************************************************************/ +static void *cdmetafile_checkdata(int param) +{ + lua_Object data; + + data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_METAFILE: data should be of type string!"); + + return lua_getstring(data); +} + +static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdCallbackLUA cdluamfcb[1] = +{{ + -1, + "CD_SIZECB", + (cdCallback)metafile_sizecb +}}; + +static cdContextLUA cdluamfctx = +{ + 0, + "CD_METAFILE", + cdContextMetafile, + cdmetafile_checkdata, + cdluamfcb, + 1 +}; + +/***************************************************************************\ +* METAFILE CD_SIZECB. * +\***************************************************************************/ +static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluamfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( w); + lua_pushnumber( h); + lua_pushnumber( mm_w); + lua_pushnumber( mm_h); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_SIZECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CD_PS. * +\***************************************************************************/ +static void *cdps_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_PS: data should be of type string!"); + + return lua_getstring(data); +} + +static cdContextLUA cdluapsctx = +{ + 0, + "CD_PS", + cdContextPS, + cdps_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_PRINTER. * +\***************************************************************************/ +static void *cdprinter_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_PRINTER: data should be of type string!"); + + return lua_getstring(data); +} + +static cdContextLUA cdluaprinterctx = +{ + 0, + "CD_PRINTER", + cdContextPrinter, + cdprinter_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_CLIPBOARD. * +\***************************************************************************/ +static void *cdclipboard_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_CLIPBOARD: data should be of type string!"); + + return lua_getstring(data); +} + +static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdCallbackLUA cdluaclipboardcb[1] = +{{ + -1, + "CD_SIZECB", + (cdCallback)clipboard_sizecb +}}; + +static cdContextLUA cdluaclipboardctx = +{ + 0, + "CD_CLIPBOARD", + cdContextClipboard, + cdclipboard_checkdata, + cdluaclipboardcb, + 1 +}; + +/***************************************************************************\ +* CLIPBOARD CD_SIZECB. * +\***************************************************************************/ +static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + lua_Object func, result; + int result_i; + + lua_beginblock(); + func = lua_getref(cdluaclipboardcb[CD_SIZECB].lock); + + cdlua_pushcanvas(canvas); + lua_pushnumber( w); + lua_pushnumber( h); + lua_pushnumber( mm_w); + lua_pushnumber( mm_h); + lua_callfunction(func); + + result = lua_getresult(1); + if (!lua_isnumber(result)) + lua_error("cdPlay: CD_SIZECB: invalid return value!"); + result_i = (int) lua_getnumber(result); + + lua_endblock(); + + return result_i; +} + +/***************************************************************************\ +* CD_NATIVEWINDOW. * +\***************************************************************************/ +static void *cdnativewindow_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + +#ifdef WIN32 + if (!lua_isuserdata(data)) + lua_error("cdCreateCanvas CD_NATIVEWINDOW: data should be of type userdata!"); + + return lua_getuserdata(data); +#else + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_NATIVEWINDOW: data should be of type string!"); + + return lua_getstring(data); +#endif +} + +static cdContextLUA cdluanativewindowctx = +{ + 0, + "CD_NATIVEWINDOW", + cdContextNativeWindow, + cdnativewindow_checkdata, + NULL, + 0 +}; + +static void cdlua_getscreensize(void) +{ + int width; + int height; + double mm_width; + double mm_height; + + if (lua_getparam(1) != LUA_NOOBJECT) + lua_error("cdGetScreenSize: too many parameters!"); + + cdGetScreenSize(&width, &height, &mm_width, &mm_height); + lua_pushnumber( width); + lua_pushnumber( height); + lua_pushnumber( mm_width); + lua_pushnumber( mm_height); +} + +static void cdlua_getscreencolorplanes(void) +{ + int L_result = cdGetScreenColorPlanes(); + lua_pushnumber(L_result); +} + +static void cdlua_usecontextplus(void) +{ + int use = (int)luaL_check_number(1); + int L_result = cdUseContextPlus(use); + lua_pushnumber(L_result); +} + +/*******************************************************************************/ + +void cdlua_initdrivers(void) +{ + cdlua_register("cdGetScreenColorPlanes",cdlua_getscreencolorplanes); + cdlua_register("cdGetScreenSize",cdlua_getscreensize); + + cdlua_register("cdUseContextPlus",cdlua_usecontextplus); + + /* from GDI+ addicional polygon modes */ + cdlua_pushnumber(CD_SPLINE, "CD_SPLINE"); + cdlua_pushnumber(CD_FILLSPLINE, "CD_FILLSPLINE"); + cdlua_pushnumber(CD_FILLGRADIENT, "CD_FILLGRADIENT"); + + cdlua_addcontext(&cdluaimagectx); + cdlua_addcontext(&cdluaimagergbctx); + cdlua_addcontext(&cdluadxfctx); + cdlua_addcontext(&cdluadgnctx); + cdlua_addcontext(&cdluacgmctx); + cdlua_addcontext(&cdluamfctx); + cdlua_addcontext(&cdluapsctx); + cdlua_addcontext(&cdluaclipboardctx); + cdlua_addcontext(&cdluanativewindowctx); + cdlua_addcontext(&cdluaprinterctx); + cdlua_addcontext(&cdluawmfctx); + cdlua_addcontext(&cdluaemfctx); + cdlua_addcontext(&cdluadbufctx); +} + diff --git a/cd/src/lua3/cdluapdf.c b/cd/src/lua3/cdluapdf.c new file mode 100755 index 0000000..1260b91 --- /dev/null +++ b/cd/src/lua3/cdluapdf.c @@ -0,0 +1,43 @@ +/** \file + * \brief PDF Canvas Lua 3 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cd.h" +#include "cdpdf.h" + +#include +#include + +#include "cdlua.h" +#include "cdluapdf.h" +#include "cdlua3_private.h" + +static void *cdpdf_checkdata(int param) +{ + lua_Object data = lua_getparam(param); + if (!lua_isstring(data)) + lua_error("cdCreateCanvas CD_PDF: data should be of type string!"); + + return lua_getstring(data); +} + +static cdContextLUA cdluapdfctx = +{ + 0, + "CD_PDF", + cdContextPDF, + cdpdf_checkdata, + NULL, + 0 +}; + +void cdluapdf_open(void) +{ + cdlua_addcontext(&cdluapdfctx); +} + diff --git a/cd/src/lua3/cdluapdf.def b/cd/src/lua3/cdluapdf.def new file mode 100755 index 0000000..62a983f --- /dev/null +++ b/cd/src/lua3/cdluapdf.def @@ -0,0 +1,2 @@ +EXPORTS + cdluapdf_open \ No newline at end of file diff --git a/cd/src/lua3/cdvoid.c b/cd/src/lua3/cdvoid.c new file mode 100755 index 0000000..3c78738 --- /dev/null +++ b/cd/src/lua3/cdvoid.c @@ -0,0 +1,126 @@ +/** \file + * \brief CD Void driver for error checking while there is no active canvas + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#ifndef CD_NO_OLD_INTERFACE +#define CD_NO_OLD_INTERFACE +#endif + +#include "cd.h" +#include "cd_private.h" +#include +#include +#include "cdlua3_private.h" + + +struct _cdCtxCanvas +{ + cdCanvas* canvas; +}; + +static void cdcreatecanvas(cdCanvas *canvas, void *data) +{ + cdCtxCanvas *ctxcanvas = (cdCtxCanvas*) malloc(sizeof(cdCtxCanvas)); + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + (void)data; +} + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + free(ctxcanvas); +} + +/***************************************************************************\ +* Echos an error if called. * +\***************************************************************************/ +static void cdvoid_error(void) +{ + lua_error("cdlua: there is no active canvas!"); +} + +/***************************************************************************\ +* Dummy. * +\***************************************************************************/ +static int cdvoid_dummy(void) +{ + return CD_OK; +} + +/***************************************************************************\ +* Driver function table. * +\***************************************************************************/ + +void cdinittable(cdCanvas* canvas) +{ + /* attribute functions can not be set, because of default attributes */ + + canvas->cxClip = (int (*)(cdCtxCanvas*, int))cdvoid_error; + canvas->cxClipArea = (void (*)(cdCtxCanvas*, int, int, int, int))cdvoid_error; + canvas->cxNewRegion = (void (*)(cdCtxCanvas*))cdvoid_error; + canvas->cxIsPointInRegion = (int (*)(cdCtxCanvas*, int, int))cdvoid_error; + canvas->cxOffsetRegion = (void (*)(cdCtxCanvas*, int, int))cdvoid_error; + canvas->cxGetRegionBox = (void (*)(cdCtxCanvas*, int *, int *, int *, int *))cdvoid_error; + canvas->cxFlush = (void ( *)(cdCtxCanvas*))cdvoid_error; + canvas->cxClear = (void ( *)(cdCtxCanvas*))cdvoid_error; + canvas->cxPixel = (void ( *)(cdCtxCanvas*, int ,int ,long ))cdvoid_error; + canvas->cxLine = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxPoly = (void ( *)(cdCtxCanvas*, int ,struct _cdPoint *,int ))cdvoid_error; + canvas->cxRect = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxBox = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxArc = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxSector = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxChord = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxText = (void (*)(cdCtxCanvas*, int ,int ,const char *))cdvoid_error; + canvas->cxGetFontDim = (void (*)(cdCtxCanvas*, int *,int *,int *,int *))cdvoid_error; + canvas->cxGetTextSize = (void (*)(cdCtxCanvas*, const char *,int *,int *))cdvoid_error; + canvas->cxPutImageRectRGB = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxPutImageRectRGBA = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxPutImageRectMap = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const long *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxScrollArea = (void (*)(cdCtxCanvas*, int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxFLine = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFPoly = (void (*)(cdCtxCanvas*, int , cdfPoint*,int ))cdvoid_error; + canvas->cxFRect = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFBox = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFArc = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error; + canvas->cxFSector = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error; + canvas->cxFText = (void (*)(cdCtxCanvas*, double ,double ,const char *))cdvoid_error; + canvas->cxStipple = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *))cdvoid_error; + canvas->cxPattern = (void (*)(cdCtxCanvas*, int ,int , const long *))cdvoid_error; + canvas->cxNativeFont = (int (*)(cdCtxCanvas*, const char*))cdvoid_error; + canvas->cxPalette = (void (*)(cdCtxCanvas*, int ,const long *,int ))cdvoid_error; + canvas->cxGetImageRGB = (void (*)(cdCtxCanvas*, unsigned char *,unsigned char *,unsigned char *,int ,int ,int ,int ))cdvoid_error; + canvas->cxCreateImage = (cdCtxImage* (*)(cdCtxCanvas*, int ,int ))cdvoid_error; + canvas->cxGetImage = (void (*)(cdCtxCanvas*, cdCtxImage*, int ,int ))cdvoid_error; + canvas->cxPutImageRect = (void (*)(cdCtxCanvas*, cdCtxImage*,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxKillImage = (void (*)(cdCtxImage*))cdvoid_error; + canvas->cxFClipArea = (void (*)(cdCtxCanvas*, double,double,double,double))cdvoid_error; + + /* must not be the error callback */ + canvas->cxActivate = (int (*)(cdCtxCanvas*))cdvoid_dummy; + canvas->cxDeactivate = (void (*)(cdCtxCanvas*))cdvoid_dummy; + canvas->cxFont = (int (*)(cdCtxCanvas*, const char *, int, int))cdvoid_dummy; + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdVoidContext = +{ + 0, + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +cdContext* cdContextVoid(void) +{ + return &cdVoidContext; +} + diff --git a/cd/src/lua3/cdvoid.h b/cd/src/lua3/cdvoid.h new file mode 100755 index 0000000..040f604 --- /dev/null +++ b/cd/src/lua3/cdvoid.h @@ -0,0 +1,17 @@ +#ifndef _CD_VOID_ +#define _CD_VOID_ + +#ifdef __cplusplus +extern "C" { +#endif + +cdContext* cdContextVoid(void); + +#define CD_VOID cdContextVoid() + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef _CD_VOID_ */ + diff --git a/cd/src/lua3/toluacd.c b/cd/src/lua3/toluacd.c new file mode 100755 index 0000000..5f29875 --- /dev/null +++ b/cd/src/lua3/toluacd.c @@ -0,0 +1,585 @@ +#include +#include +#include + +#include +#include + +#include "cd.h" +#include "cdps.h" + +#include "cdlua.h" +#include "cdlua3_private.h" + + +static void L_cdFlush(void) +{ + cdFlush(); +} + +static void L_cdClear(void) +{ + cdClear(); +} + +static void L_cdSimulate(void) +{ + int mode = (int)luaL_check_number(1); + int L_result = cdSimulate(mode); + lua_pushnumber(L_result); +} + +static void L_cdOrigin(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + cdOrigin(x,y); +} + +static void L_cdClip(void) +{ + int mode = (int)luaL_check_number(1); + int L_result = cdClip(mode); + lua_pushnumber(L_result); +} + +static void L_cdClipArea(void) +{ + int xmin = (int)luaL_check_number(1); + int xmax = (int)luaL_check_number(2); + int ymin = (int)luaL_check_number(3); + int ymax = (int)luaL_check_number(4); + cdClipArea(xmin,xmax,ymin,ymax); +} + +static void L_cdLine(void) +{ + int x1 = (int)luaL_check_number(1); + int y1 = (int)luaL_check_number(2); + int x2 = (int)luaL_check_number(3); + int y2 = (int)luaL_check_number(4); + cdLine(x1,y1,x2,y2); +} + +static void L_cdBox(void) +{ + int xmin = (int)luaL_check_number(1); + int xmax = (int)luaL_check_number(2); + int ymin = (int)luaL_check_number(3); + int ymax = (int)luaL_check_number(4); + cdBox(xmin,xmax,ymin,ymax); +} + +static void L_cdRect(void) +{ + int xmin = (int)luaL_check_number(1); + int xmax = (int)luaL_check_number(2); + int ymin = (int)luaL_check_number(3); + int ymax = (int)luaL_check_number(4); + cdRect(xmin,xmax,ymin,ymax); +} + +static void L_cdArc(void) +{ + int xc = (int)luaL_check_number(1); + int yc = (int)luaL_check_number(2); + int w = (int)luaL_check_number(3); + int h = (int)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + cdArc(xc,yc,w,h,angle1,angle2); +} + +static void L_cdSector(void) +{ + int xc = (int)luaL_check_number(1); + int yc = (int)luaL_check_number(2); + int w = (int)luaL_check_number(3); + int h = (int)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + cdSector(xc,yc,w,h,angle1,angle2); +} + +static void L_cdChord(void) +{ + int xc = (int)luaL_check_number(1); + int yc = (int)luaL_check_number(2); + int w = (int)luaL_check_number(3); + int h = (int)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + cdChord(xc,yc,w,h,angle1,angle2); +} + +static void L_cdText(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + cdText(x,y,s); +} + +static void L_cdBegin(void) +{ + int mode = (int)luaL_check_number(1); + cdBegin(mode); +} + +static void L_cdVertex(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + cdVertex(x,y); +} + +static void L_cdEnd(void) +{ + cdEnd(); +} + +static void L_cdMark(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + cdMark(x,y); +} + +static void L_cdOffsetRegion(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + cdOffsetRegion(x,y); +} + +static void L_cdPointInRegion(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + int L_result = cdPointInRegion(x,y); + lua_pushnumber((int)L_result); +} + +static void L_cdBackOpacity(void) +{ + int opacity = (int)luaL_check_number(1); + int L_result = cdBackOpacity(opacity); + lua_pushnumber(L_result); +} + +static void L_cdWriteMode(void) +{ + int mode = (int)luaL_check_number(1); + int L_result = cdWriteMode(mode); + lua_pushnumber(L_result); +} + +static void L_cdLineStyle(void) +{ + int style = (int)luaL_check_number(1); + int L_result = cdLineStyle(style); + lua_pushnumber(L_result); +} + +static void L_cdLineWidth(void) +{ + int width = (int)luaL_check_number(1); + int L_result = cdLineWidth(width); + lua_pushnumber(L_result); +} + +static void L_cdRegionCombineMode(void) +{ + int v = (int)luaL_check_number(1); + int L_result = cdRegionCombineMode(v); + lua_pushnumber(L_result); +} + +static void L_cdLineJoin(void) +{ + int v = (int)luaL_check_number(1); + int L_result = cdLineJoin(v); + lua_pushnumber(L_result); +} + +static void L_cdLineCap(void) +{ + int v = (int)luaL_check_number(1); + int L_result = cdLineCap(v); + lua_pushnumber(L_result); +} + +static void L_cdFillMode(void) +{ + int v = (int)luaL_check_number(1); + int L_result = cdFillMode(v); + lua_pushnumber(L_result); +} + +static void L_cdInteriorStyle(void) +{ + int style = (int)luaL_check_number(1); + int L_result = cdInteriorStyle(style); + lua_pushnumber(L_result); +} + +static void L_cdHatch(void) +{ + int style = (int)luaL_check_number(1); + int L_result = cdHatch(style); + lua_pushnumber(L_result); +} + +static void L_cdFont(void) +{ + int type_face = (int)luaL_check_number(1); + int style = (int)luaL_check_number(2); + int size = (int)luaL_check_number(3); + cdFont(type_face,style,size); +} + +static void L_cdNativeFont(void) +{ + char* font = (char*)luaL_check_string(1); + lua_pushstring(cdNativeFont(font)); +} + +static int cdlua_isuserdata(char* name) +{ + if (strcmp(name, "HDC")==0) return 1; + if (strcmp(name, "GC")==0) return 1; + return 0; +} + +static void L_cdSetAttribute(void) +{ + char* name = (char*)luaL_check_string(1); + lua_Object p2 = lua_getparam(2); + + if (p2 == LUA_NOOBJECT) + lua_error("cdSetAttribute: value parameter missing!"); + + /* if p2 is nil */ + if (lua_isnil(p2)) + { + cdSetAttribute(name, NULL); + } + else + { + char* data; + if (cdlua_isuserdata(name)) + data = (char*) lua_getuserdata(p2); + else + data = (char*)luaL_check_string(2); + cdSetAttribute(name, data); + } +} + +static void L_cdGetAttribute(void) +{ + char* name = (char*)luaL_check_string(1); + char* data = cdGetAttribute(name); + if (data) + { + if (cdlua_isuserdata(name)) + lua_pushuserdata(data); + else + lua_pushstring(data); + } + else + lua_pushnil(); +} + +static void L_cdTextAlignment(void) +{ + int alignment = (int)luaL_check_number(1); + int L_result = cdTextAlignment(alignment); + lua_pushnumber(L_result); +} + +static void L_cdTextOrientation(void) +{ + double angle = luaL_check_number(1); + double L_result = cdTextOrientation(angle); + lua_pushnumber(L_result); +} + +static void L_cdMarkType(void) +{ + int type = (int)luaL_check_number(1); + int L_result = cdMarkType(type); + lua_pushnumber(L_result); +} + +static void L_cdMarkSize(void) +{ + int size = (int)luaL_check_number(1); + int L_result = cdMarkSize(size); + lua_pushnumber(L_result); +} + +static void L_cdGetColorPlanes(void) +{ + int L_result = cdGetColorPlanes(); + lua_pushnumber(L_result); +} + +static void L_cdScrollArea(void) +{ + int xmin = (int)luaL_check_number(1); + int xmax = (int)luaL_check_number(2); + int ymin = (int)luaL_check_number(3); + int ymax = (int)luaL_check_number(4); + int dx = (int)luaL_check_number(5); + int dy = (int)luaL_check_number(6); + cdScrollArea(xmin,xmax,ymin,ymax,dx,dy); +} + +static void L_cdVectorFont(void) +{ + char* file = (char*)luaL_check_string(1); + char* L_result = cdVectorFont(file); + lua_pushstring(L_result); +} + +static void L_cdVectorTextDirection(void) +{ + int x1 = (int)luaL_check_number(1); + int y1 = (int)luaL_check_number(2); + int x2 = (int)luaL_check_number(3); + int y2 = (int)luaL_check_number(4); + cdVectorTextDirection(x1,y1,x2,y2); +} + +static void L_cdVectorTextSize(void) +{ + int size_x = (int)luaL_check_number(1); + int size_y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + cdVectorTextSize(size_x,size_y,s); +} + +static void L_cdVectorCharSize(void) +{ + int size = (int)luaL_check_number(1); + int L_result = cdVectorCharSize(size); + lua_pushnumber(L_result); +} + +static void L_cdVectorText(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + cdVectorText(x,y,s); +} + +static void L_cdMultiLineVectorText(void) +{ + int x = (int)luaL_check_number(1); + int y = (int)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + cdMultiLineVectorText(x,y,s); +} + + +/* ---------------------------------------- public interface */ +int luaL_cd_open(void) +{ + cdlua_pushnumber(CD_CAP_NONE, "CD_CAP_NONE"); + cdlua_pushnumber(CD_CAP_FLUSH, "CD_CAP_FLUSH"); + cdlua_pushnumber(CD_CAP_CLEAR, "CD_CAP_CLEAR"); + cdlua_pushnumber(CD_CAP_PLAY, "CD_CAP_PLAY"); + cdlua_pushnumber(CD_CAP_YAXIS, "CD_CAP_YAXIS"); + cdlua_pushnumber(CD_CAP_CLIPAREA, "CD_CAP_CLIPAREA"); + cdlua_pushnumber(CD_CAP_CLIPPOLY, "CD_CAP_CLIPPOLY"); + cdlua_pushnumber(CD_CAP_RECT, "CD_CAP_RECT"); + cdlua_pushnumber(CD_CAP_IMAGERGB, "CD_CAP_IMAGERGB"); + cdlua_pushnumber(CD_CAP_IMAGERGBA, "CD_CAP_IMAGERGBA"); + cdlua_pushnumber(CD_CAP_IMAGEMAP, "CD_CAP_IMAGEMAP"); + cdlua_pushnumber(CD_CAP_GETIMAGERGB, "CD_CAP_GETIMAGERGB"); + cdlua_pushnumber(CD_CAP_IMAGESRV, "CD_CAP_IMAGESRV"); + cdlua_pushnumber(CD_CAP_BACKGROUND, "CD_CAP_BACKGROUND"); + cdlua_pushnumber(CD_CAP_BACKOPACITY, "CD_CAP_BACKOPACITY"); + cdlua_pushnumber(CD_CAP_WRITEMODE, "CD_CAP_WRITEMODE"); + cdlua_pushnumber(CD_CAP_LINESTYLE, "CD_CAP_LINESTYLE"); + cdlua_pushnumber(CD_CAP_LINEWITH, "CD_CAP_LINEWITH"); + cdlua_pushnumber(CD_CAP_FPRIMTIVES, "CD_CAP_FPRIMTIVES"); + cdlua_pushnumber(CD_CAP_HATCH, "CD_CAP_HATCH"); + cdlua_pushnumber(CD_CAP_STIPPLE, "CD_CAP_STIPPLE"); + cdlua_pushnumber(CD_CAP_PATTERN, "CD_CAP_PATTERN"); + cdlua_pushnumber(CD_CAP_FONT, "CD_CAP_FONT"); + cdlua_pushnumber(CD_CAP_FONTDIM, "CD_CAP_FONTDIM"); + cdlua_pushnumber(CD_CAP_TEXTSIZE, "CD_CAP_TEXTSIZE"); + cdlua_pushnumber(CD_CAP_TEXTORIENTATION, "CD_CAP_TEXTORIENTATION"); + cdlua_pushnumber(CD_CAP_PALETTE, "CD_CAP_PALETTE"); + cdlua_pushnumber(CD_CAP_ALL, "CD_CAP_ALL"); + cdlua_pushnumber(CD_CAP_LINECAP, "CD_CAP_LINECAP"); + cdlua_pushnumber(CD_CAP_LINEJOIN, "CD_CAP_LINEJOIN"); + cdlua_pushnumber(CD_CAP_REGION, "CD_CAP_REGION"); + cdlua_pushnumber(CD_CAP_CHORD, "CD_CAP_CHORD"); + cdlua_pushnumber(CD_SIM_FILLS, "CD_SIM_FILLS"); + cdlua_pushnumber(CD_SIM_LINES, "CD_SIM_LINES"); + cdlua_pushnumber(CD_SIM_ALL, "CD_SIM_ALL"); + cdlua_pushnumber(CD_SIM_POLYGON, "CD_SIM_POLYGON"); + cdlua_pushnumber(CD_SIM_SECTOR, "CD_SIM_SECTOR"); + cdlua_pushnumber(CD_SIM_POLYLINE, "CD_SIM_POLYLINE"); + cdlua_pushnumber(CD_SIM_BOX, "CD_SIM_BOX"); + cdlua_pushnumber(CD_SIM_ARC, "CD_SIM_ARC"); + cdlua_pushnumber(CD_SIM_RECT, "CD_SIM_RECT"); + cdlua_pushnumber(CD_SIM_LINE, "CD_SIM_LINE"); + cdlua_pushnumber(CD_SIM_NONE, "CD_SIM_NONE"); + cdlua_pushnumber(CD_SIM_CHORD, "CD_SIM_CHORD"); + cdlua_pushnumber(CD_QUERY, "CD_QUERY"); + cdlua_pushnumber(CD_ERROR, "CD_ERROR"); + cdlua_pushnumber(CD_OK, "CD_OK"); + cdlua_pushnumber(CD_CLIPOFF, "CD_CLIPOFF"); + cdlua_pushnumber(CD_CLIPAREA, "CD_CLIPAREA"); + cdlua_pushnumber(CD_CLIPPOLYGON, "CD_CLIPPOLYGON"); + cdlua_pushnumber(CD_CLIPREGION, "CD_CLIPREGION"); + cdlua_pushnumber(CD_FILL, "CD_FILL"); + cdlua_pushnumber(CD_OPEN_LINES, "CD_OPEN_LINES"); + cdlua_pushnumber(CD_CLOSED_LINES, "CD_CLOSED_LINES"); + cdlua_pushnumber(CD_CLIP, "CD_CLIP"); + cdlua_pushnumber(CD_BEZIER, "CD_BEZIER"); + cdlua_pushnumber(CD_OPAQUE, "CD_OPAQUE"); + cdlua_pushnumber(CD_TRANSPARENT, "CD_TRANSPARENT"); + cdlua_pushnumber(CD_REPLACE, "CD_REPLACE"); + cdlua_pushnumber(CD_XOR, "CD_XOR"); + cdlua_pushnumber(CD_NOT_XOR, "CD_NOT_XOR"); + cdlua_pushnumber(CD_POLITE, "CD_POLITE"); + cdlua_pushnumber(CD_FORCE, "CD_FORCE"); + cdlua_pushnumber(CD_CONTINUOUS, "CD_CONTINUOUS"); + cdlua_pushnumber(CD_DASHED, "CD_DASHED"); + cdlua_pushnumber(CD_DOTTED, "CD_DOTTED"); + cdlua_pushnumber(CD_DASH_DOT, "CD_DASH_DOT"); + cdlua_pushnumber(CD_DASH_DOT_DOT, "CD_DASH_DOT_DOT"); + cdlua_pushnumber(CD_PLUS, "CD_PLUS"); + cdlua_pushnumber(CD_STAR, "CD_STAR"); + cdlua_pushnumber(CD_CIRCLE, "CD_CIRCLE"); + cdlua_pushnumber(CD_X, "CD_X"); + cdlua_pushnumber(CD_BOX, "CD_BOX"); + cdlua_pushnumber(CD_DIAMOND, "CD_DIAMOND"); + cdlua_pushnumber(CD_HOLLOW_CIRCLE, "CD_HOLLOW_CIRCLE"); + cdlua_pushnumber(CD_HOLLOW_BOX, "CD_HOLLOW_BOX"); + cdlua_pushnumber(CD_HOLLOW_DIAMOND, "CD_HOLLOW_DIAMOND"); + cdlua_pushnumber(CD_HORIZONTAL, "CD_HORIZONTAL"); + cdlua_pushnumber(CD_VERTICAL, "CD_VERTICAL"); + cdlua_pushnumber(CD_FDIAGONAL, "CD_FDIAGONAL"); + cdlua_pushnumber(CD_BDIAGONAL, "CD_BDIAGONAL"); + cdlua_pushnumber(CD_CROSS, "CD_CROSS"); + cdlua_pushnumber(CD_DIAGCROSS, "CD_DIAGCROSS"); + cdlua_pushnumber(CD_SOLID, "CD_SOLID"); + cdlua_pushnumber(CD_HATCH, "CD_HATCH"); + cdlua_pushnumber(CD_STIPPLE, "CD_STIPPLE"); + cdlua_pushnumber(CD_PATTERN, "CD_PATTERN"); + cdlua_pushnumber(CD_HOLLOW, "CD_HOLLOW"); + cdlua_pushnumber(CD_NORTH, "CD_NORTH"); + cdlua_pushnumber(CD_SOUTH, "CD_SOUTH"); + cdlua_pushnumber(CD_EAST, "CD_EAST"); + cdlua_pushnumber(CD_WEST, "CD_WEST"); + cdlua_pushnumber(CD_NORTH_EAST, "CD_NORTH_EAST"); + cdlua_pushnumber(CD_NORTH_WEST, "CD_NORTH_WEST"); + cdlua_pushnumber(CD_SOUTH_EAST, "CD_SOUTH_EAST"); + cdlua_pushnumber(CD_SOUTH_WEST, "CD_SOUTH_WEST"); + cdlua_pushnumber(CD_CENTER, "CD_CENTER"); + cdlua_pushnumber(CD_BASE_LEFT, "CD_BASE_LEFT"); + cdlua_pushnumber(CD_BASE_CENTER, "CD_BASE_CENTER"); + cdlua_pushnumber(CD_BASE_RIGHT, "CD_BASE_RIGHT"); + cdlua_pushnumber(CD_SYSTEM, "CD_SYSTEM"); + cdlua_pushnumber(CD_COURIER, "CD_COURIER"); + cdlua_pushnumber(CD_TIMES_ROMAN, "CD_TIMES_ROMAN"); + cdlua_pushnumber(CD_HELVETICA, "CD_HELVETICA"); + cdlua_pushnumber(CD_PLAIN, "CD_PLAIN"); + cdlua_pushnumber(CD_BOLD, "CD_BOLD"); + cdlua_pushnumber(CD_ITALIC, "CD_ITALIC"); + cdlua_pushnumber(CD_BOLD_ITALIC, "CD_BOLD_ITALIC"); + cdlua_pushnumber(CD_SMALL, "CD_SMALL"); + cdlua_pushnumber(CD_STANDARD, "CD_STANDARD"); + cdlua_pushnumber(CD_LARGE, "CD_LARGE"); + cdlua_pushnumber(CD_MM2PT, "CD_MM2PT"); + cdlua_pushnumber(CD_RAD2DEG, "CD_RAD2DEG"); + cdlua_pushnumber(CD_DEG2RAD, "CD_DEG2RAD"); + cdlua_pushnumber(CD_RGBA, "CD_RGBA"); + cdlua_pushnumber(CD_RGB, "CD_RGB"); + cdlua_pushnumber(CD_MAP, "CD_MAP"); + cdlua_pushnumber(CD_IRED, "CD_IRED"); + cdlua_pushnumber(CD_IGREEN, "CD_IGREEN"); + cdlua_pushnumber(CD_IBLUE, "CD_IBLUE"); + cdlua_pushnumber(CD_IALPHA, "CD_IALPHA"); + cdlua_pushnumber(CD_INDEX, "CD_INDEX"); + cdlua_pushnumber(CD_COLORS, "CD_COLORS"); + cdlua_pushnumber(CD_MAP, "CD_MAP"); + cdlua_pushnumber(CD_A0, "CD_A0"); + cdlua_pushnumber(CD_A2, "CD_A2"); + cdlua_pushnumber(CD_A3, "CD_A3"); + cdlua_pushnumber(CD_A1, "CD_A1"); + cdlua_pushnumber(CD_A4, "CD_A4"); + cdlua_pushnumber(CD_A5, "CD_A5"); + cdlua_pushnumber(CD_LETTER, "CD_LETTER"); + cdlua_pushnumber(CD_LEGAL, "CD_LEGAL"); + cdlua_pushnumber(CD_UNION, "CD_UNION"); + cdlua_pushnumber(CD_INTERSECT, "CD_INTERSECT"); + cdlua_pushnumber(CD_DIFFERENCE, "CD_DIFFERENCE"); + cdlua_pushnumber(CD_NOTINTERSECT, "CD_NOTINTERSECT"); + cdlua_pushnumber(CD_REGION, "CD_REGION"); + cdlua_pushnumber(CD_EVENODD, "CD_EVENODD"); + cdlua_pushnumber(CD_WINDING, "CD_WINDING"); + cdlua_pushnumber(CD_BEVEL, "CD_BEVEL"); + cdlua_pushnumber(CD_MITER, "CD_MITER"); + cdlua_pushnumber(CD_ROUND, "CD_ROUND"); + cdlua_pushnumber(CD_CAPROUND, "CD_CAPROUND"); + cdlua_pushnumber(CD_CAPSQUARE, "CD_CAPSQUARE"); + cdlua_pushnumber(CD_CAPFLAT, "CD_CAPFLAT"); + cdlua_pushnumber(CD_CUSTOM, "CD_CUSTOM"); + cdlua_pushnumber(CD_ABORT, "CD_ABORT"); + cdlua_pushnumber(CD_CONTINUE, "CD_CONTINUE"); + + cdlua_register("cdFlush",L_cdFlush); + cdlua_register("cdSimulate",L_cdSimulate); + cdlua_register("cdOrigin",L_cdOrigin); + cdlua_register("cdClear",L_cdClear); + cdlua_register("cdClip",L_cdClip); + cdlua_register("cdClipArea",L_cdClipArea); + cdlua_register("cdLine",L_cdLine); + cdlua_register("cdBox",L_cdBox); + cdlua_register("cdRect",L_cdRect); + cdlua_register("cdArc",L_cdArc); + cdlua_register("cdSector",L_cdSector); + cdlua_register("cdChord",L_cdChord); + cdlua_register("cdText",L_cdText); + cdlua_register("cdBegin",L_cdBegin); + cdlua_register("cdVertex",L_cdVertex); + cdlua_register("cdEnd",L_cdEnd); + cdlua_register("cdOffsetRegion",L_cdOffsetRegion); + cdlua_register("cdPointInRegion",L_cdPointInRegion); + cdlua_register("cdMark",L_cdMark); + cdlua_register("cdBackOpacity",L_cdBackOpacity); + cdlua_register("cdWriteMode",L_cdWriteMode); + cdlua_register("cdRegionCombineMode",L_cdRegionCombineMode); + cdlua_register("cdLineJoin",L_cdLineJoin); + cdlua_register("cdLineCap",L_cdLineCap); + cdlua_register("cdFillMode",L_cdFillMode); + cdlua_register("cdLineStyle",L_cdLineStyle); + cdlua_register("cdLineWidth",L_cdLineWidth); + cdlua_register("cdInteriorStyle",L_cdInteriorStyle); + cdlua_register("cdHatch",L_cdHatch); + cdlua_register("cdFont",L_cdFont); + cdlua_register("cdNativeFont",L_cdNativeFont); + cdlua_register("cdTextAlignment",L_cdTextAlignment); + cdlua_register("cdTextOrientation",L_cdTextOrientation); + cdlua_register("cdMarkType",L_cdMarkType); + cdlua_register("cdMarkSize",L_cdMarkSize); + cdlua_register("cdGetColorPlanes",L_cdGetColorPlanes); + cdlua_register("cdScrollArea",L_cdScrollArea); + cdlua_register("cdVectorFont",L_cdVectorFont); + cdlua_register("cdVectorTextDirection",L_cdVectorTextDirection); + cdlua_register("cdVectorTextSize",L_cdVectorTextSize); + cdlua_register("cdVectorCharSize",L_cdVectorCharSize); + cdlua_register("cdVectorText",L_cdVectorText); + cdlua_register("cdMultiLineVectorText",L_cdMultiLineVectorText); + cdlua_register("cdSetAttribute",L_cdSetAttribute); + cdlua_register("cdGetAttribute",L_cdGetAttribute); + return 1; +} + diff --git a/cd/src/lua3/toluawd.c b/cd/src/lua3/toluawd.c new file mode 100755 index 0000000..2549bcc --- /dev/null +++ b/cd/src/lua3/toluawd.c @@ -0,0 +1,228 @@ +#include +#include + +#include +#include + +#include "cd.h" +#include "wd.h" + +#include "cdlua.h" +#include "cdlua3_private.h" + + +static void L_wdWindow(void) +{ + double xmin = (double)luaL_check_number(1); + double xmax = (double)luaL_check_number(2); + double ymin = (double)luaL_check_number(3); + double ymax = (double)luaL_check_number(4); + wdWindow(xmin,xmax,ymin,ymax); +} + +static void L_wdViewport(void) +{ + int xmin = (int)luaL_check_number(1); + int xmax = (int)luaL_check_number(2); + int ymin = (int)luaL_check_number(3); + int ymax = (int)luaL_check_number(4); + wdViewport(xmin,xmax,ymin,ymax); +} + +static void L_wdClipArea(void) +{ + double xmin = (double)luaL_check_number(1); + double xmax = (double)luaL_check_number(2); + double ymin = (double)luaL_check_number(3); + double ymax = (double)luaL_check_number(4); + wdClipArea(xmin,xmax,ymin,ymax); +} + +static void L_wdLine(void) +{ + double x1 = (double)luaL_check_number(1); + double y1 = (double)luaL_check_number(2); + double x2 = (double)luaL_check_number(3); + double y2 = (double)luaL_check_number(4); + wdLine(x1,y1,x2,y2); +} + +static void L_wdBox(void) +{ + double xmin = (double)luaL_check_number(1); + double xmax = (double)luaL_check_number(2); + double ymin = (double)luaL_check_number(3); + double ymax = (double)luaL_check_number(4); + wdBox(xmin,xmax,ymin,ymax); +} + +static void L_wdRect(void) +{ + double xmin = (double)luaL_check_number(1); + double xmax = (double)luaL_check_number(2); + double ymin = (double)luaL_check_number(3); + double ymax = (double)luaL_check_number(4); + wdRect(xmin,xmax,ymin,ymax); +} + +static void L_wdArc(void) +{ + double xc = (double)luaL_check_number(1); + double yc = (double)luaL_check_number(2); + double w = (double)luaL_check_number(3); + double h = (double)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + wdArc(xc,yc,w,h,angle1,angle2); +} + +static void L_wdSector(void) +{ + double xc = (double)luaL_check_number(1); + double yc = (double)luaL_check_number(2); + double w = (double)luaL_check_number(3); + double h = (double)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + wdSector(xc,yc,w,h,angle1,angle2); +} + +static void L_wdChord(void) +{ + double xc = (double)luaL_check_number(1); + double yc = (double)luaL_check_number(2); + double w = (double)luaL_check_number(3); + double h = (double)luaL_check_number(4); + double angle1 = (double)luaL_check_number(5); + double angle2 = (double)luaL_check_number(6); + wdChord(xc,yc,w,h,angle1,angle2); +} + +static void L_wdText(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + wdText(x,y,s); +} + +static void L_wdVertex(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + wdVertex(x,y); +} + +static void L_wdMark(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + wdMark(x,y); +} + +static void L_wdOffsetRegion(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + wdOffsetRegion(x,y); +} + +static void L_wdPointInRegion(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + int L_result = wdPointInRegion(x,y); + lua_pushnumber((double)L_result); +} + +static void L_wdLineWidth(void) +{ + double width = (double)luaL_check_number(1); + double L_result = wdLineWidth(width); + lua_pushnumber(L_result); +} + +static void L_wdFont(void) +{ + int type_face = (int)luaL_check_number(1); + int style = (int)luaL_check_number(2); + double size = (double)luaL_check_number(3); + wdFont(type_face,style,size); +} + +static void L_wdMarkSize(void) +{ + double size = (double)luaL_check_number(1); + double L_result = wdMarkSize(size); + lua_pushnumber(L_result); +} + +static void L_wdVectorTextDirection(void) +{ + double x1 = (double)luaL_check_number(1); + double y1 = (double)luaL_check_number(2); + double x2 = (double)luaL_check_number(3); + double y2 = (double)luaL_check_number(4); + wdVectorTextDirection(x1,y1,x2,y2); +} + +static void L_wdVectorTextSize(void) +{ + double size_x = (double)luaL_check_number(1); + double size_y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + wdVectorTextSize(size_x,size_y,s); +} + +static void L_wdVectorCharSize(void) +{ + double size = (double)luaL_check_number(1); + double L_result = wdVectorCharSize(size); + lua_pushnumber(L_result); +} + +static void L_wdVectorText(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + wdVectorText(x,y,s); +} + +static void L_wdMultiLineVectorText(void) +{ + double x = (double)luaL_check_number(1); + double y = (double)luaL_check_number(2); + char* s = (char*)luaL_check_string(3); + wdMultiLineVectorText(x,y,s); +} + + +/* ---------------------------------------- public interface */ +int luaL_wd_open(void) +{ + cdlua_register("wdWindow",L_wdWindow); + cdlua_register("wdViewport",L_wdViewport); + cdlua_register("wdClipArea",L_wdClipArea); + cdlua_register("wdLine",L_wdLine); + cdlua_register("wdBox",L_wdBox); + cdlua_register("wdRect",L_wdRect); + cdlua_register("wdArc",L_wdArc); + cdlua_register("wdSector",L_wdSector); + cdlua_register("wdChord",L_wdChord); + cdlua_register("wdText",L_wdText); + cdlua_register("wdVertex",L_wdVertex); + cdlua_register("wdMark",L_wdMark); + cdlua_register("wdOffsetRegion",L_wdOffsetRegion); + cdlua_register("wdPointInRegion",L_wdPointInRegion); + cdlua_register("wdLineWidth",L_wdLineWidth); + cdlua_register("wdFont",L_wdFont); + cdlua_register("wdMarkSize",L_wdMarkSize); + cdlua_register("wdVectorTextDirection",L_wdVectorTextDirection); + cdlua_register("wdVectorTextSize",L_wdVectorTextSize); + cdlua_register("wdVectorCharSize",L_wdVectorCharSize); + cdlua_register("wdVectorText",L_wdVectorText); + cdlua_register("wdMultiLineVectorText",L_wdMultiLineVectorText); + return 1; +} + diff --git a/cd/src/lua5/cdlua5.c b/cd/src/lua5/cdlua5.c new file mode 100755 index 0000000..7e60fbe --- /dev/null +++ b/cd/src/lua5/cdlua5.c @@ -0,0 +1,1823 @@ +/** \file + * \brief Lua Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include + +#include "cd.h" +#include "cdgdiplus.h" +#include "cdnative.h" +#include "cdps.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua5_private.h" + + +/***************************************************************************\ +* Initialization * +\***************************************************************************/ + +static const char* cdlua_key = "cdlua5"; + +static void cdlua_SetState(lua_State * L, cdluaLuaState* cdL) +{ + lua_pushlightuserdata(L, (void*)cdlua_key); + lua_pushlightuserdata(L, (void*)cdL); + lua_settable(L, LUA_REGISTRYINDEX); /* registry[address("cdlua5")]=cdL */ + lua_pop(L, 1); +} + +cdluaLuaState* cdlua_getstate(lua_State * L) +{ + cdluaLuaState* cdL; + lua_pushlightuserdata(L, (void*)cdlua_key); + lua_gettable(L, LUA_REGISTRYINDEX); + cdL = (cdluaLuaState*)lua_touserdata(L, -1); + lua_pop(L, 1); + return cdL; +} + +cdluaContext* cdlua_getcontext(lua_State * L, int param) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + + int driver = luaL_checkint(L, param); + if ((driver < 0) || (driver >= cdL->numdrivers)) + luaL_argerror(L, param, "unknown driver"); + + return cdL->drivers[driver]; +} + +static lua_State* cdlua5_play_luaState = NULL; + +lua_State* cdlua_getplaystate(void) +{ + return cdlua5_play_luaState; +} + +void cdlua_setplaystate(lua_State* L) +{ + cdlua5_play_luaState = L; +} + +static cdluaPalette* cdlua_rawcheckpalette(lua_State *L, int param) +{ + void *p = lua_touserdata(L, param); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, param)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, "cdPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (cdluaPalette*)p; + } + lua_pop(L, 1); /* remove previous metatable */ + + /* check also for IM palette */ + lua_getfield(L, LUA_REGISTRYINDEX, "imPalette"); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return (cdluaPalette*)p; + } + } + } + luaL_typerror(L, param, "cdPalette"); /* else error */ + return NULL; /* to avoid warnings */ +} + +cdluaPalette * cdlua_checkpalette(lua_State * L, int param) +{ + cdluaPalette * pal = cdlua_rawcheckpalette(L, param); + if (!pal->color) + luaL_argerror(L, param, "killed cdPalette"); + return pal; +} + +void cdlua_pushpalette(lua_State* L, long* palette, int size) +{ + cdluaPalette* pal = (cdluaPalette*)lua_newuserdata(L, sizeof(cdluaPalette)); + luaL_getmetatable(L, "cdPalette"); + lua_setmetatable(L, -2); + + pal->count = size; + pal->color = palette; +} + +cdState * cdlua_checkstate(lua_State* L, int param) +{ + cdState** state_p = (cdState**)luaL_checkudata(L, param, "cdState"); + if (!(*state_p)) + luaL_argerror(L, param, "released cdState"); + return *state_p; +} + +void cdlua_pushstate(lua_State* L, cdState* state) +{ + cdState** state_p = (cdState**)lua_newuserdata(L, sizeof(cdState*)); + luaL_getmetatable(L, "cdState"); + lua_setmetatable(L, -2); + + *state_p = state; +} + +cdluaPattern* cdlua_checkpattern(lua_State* L, int param) +{ + cdluaPattern* pattern_p = (cdluaPattern*) luaL_checkudata(L, param, "cdPattern"); + if (!pattern_p->pattern) + luaL_argerror(L, param, "killed cdPattern"); + return pattern_p; +} + +void cdlua_pushpattern(lua_State* L, long int* pattern, int width, int height) +{ + cdluaPattern* pattern_p = (cdluaPattern*)lua_newuserdata(L, sizeof(cdluaPattern)); + luaL_getmetatable(L, "cdPattern"); + lua_setmetatable(L, -2); + + pattern_p->pattern = pattern; + pattern_p->width = width; + pattern_p->height = height; + pattern_p->size = width * height; +} + +cdluaStipple* cdlua_checkstipple(lua_State* L, int param) +{ + cdluaStipple* stipple_p = (cdluaStipple*) luaL_checkudata(L, param, "cdStipple"); + if (!stipple_p->stipple) + luaL_argerror(L, param, "killed cdStipple"); + return stipple_p; +} + +void cdlua_pushstipple(lua_State* L, unsigned char* stipple, int width, int height) +{ + cdluaStipple* stipple_p = (cdluaStipple*)lua_newuserdata(L, sizeof(cdluaStipple)); + luaL_getmetatable(L, "cdStipple"); + lua_setmetatable(L, -2); + + stipple_p->stipple = stipple; + stipple_p->width = width; + stipple_p->height = height; + stipple_p->size = width * height; +} + +cdluaImageRGB* cdlua_checkimagergb(lua_State* L, int param) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB"); + if (!imagergb_p->red) + luaL_argerror(L, param, "killed cdImageRGB"); + return imagergb_p; +} + +void cdlua_pushimagergb(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB)); + luaL_getmetatable(L, "cdImageRGB"); + lua_setmetatable(L, -2); + + imagergb_p->red = red; + imagergb_p->green = green; + imagergb_p->blue = blue; + imagergb_p->width = width; + imagergb_p->height = height; + imagergb_p->size = width * height; + imagergb_p->free = 1; +} + +void cdlua_pushimagergb_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, int width, int height) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)lua_newuserdata(L, sizeof(cdluaImageRGB)); + luaL_getmetatable(L, "cdImageRGB"); + lua_setmetatable(L, -2); + + imagergb_p->red = red; + imagergb_p->green = green; + imagergb_p->blue = blue; + imagergb_p->width = width; + imagergb_p->height = height; + imagergb_p->size = width * height; + imagergb_p->free = 0; +} + +cdluaImageRGBA* cdlua_checkimagergba(lua_State* L, int param) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA"); + if (!imagergba_p->red) + luaL_argerror(L, param, "killed cdImageRGBA"); + return imagergba_p; +} + +void cdlua_pushimagergba(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA)); + luaL_getmetatable(L, "cdImageRGBA"); + lua_setmetatable(L, -2); + + imagergba_p->red = red; + imagergba_p->green = green; + imagergba_p->blue = blue; + imagergba_p->alpha = alpha; + imagergba_p->width = width; + imagergba_p->height = height; + imagergba_p->size = width * height; + imagergba_p->free = 1; +} + +void cdlua_pushimagergba_ex(lua_State* L, unsigned char* red, unsigned char* green, unsigned char* blue, unsigned char* alpha, int width, int height) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)lua_newuserdata(L, sizeof(cdluaImageRGBA)); + luaL_getmetatable(L, "cdImageRGBA"); + lua_setmetatable(L, -2); + + imagergba_p->red = red; + imagergba_p->green = green; + imagergba_p->blue = blue; + imagergba_p->alpha = alpha; + imagergba_p->width = width; + imagergba_p->height = height; + imagergba_p->size = width * height; + imagergba_p->free = 0; +} + +cdluaImageMap* cdlua_checkimagemap(lua_State* L, int param) +{ + cdluaImageMap* imagemap_p = (cdluaImageMap*) luaL_checkudata(L, param, "cdImageMap"); + if (!imagemap_p->index) + luaL_argerror(L, param, "killed cdImageMap"); + return imagemap_p; +} + +void cdlua_pushimagemap(lua_State* L, unsigned char* index, int width, int height) +{ + cdluaImageMap* imagemap_p = (cdluaImageMap*)lua_newuserdata(L, sizeof(cdluaImageMap)); + luaL_getmetatable(L, "cdImageMap"); + lua_setmetatable(L, -2); + + imagemap_p->index = index; + imagemap_p->width = width; + imagemap_p->height = height; + imagemap_p->size = width * height; +} + +cdluaImageChannel* cdlua_checkchannel(lua_State* L, int param) +{ + cdluaImageChannel* channel_p = (cdluaImageChannel*) luaL_checkudata(L, param, "cdImageChannel"); + if (!channel_p->channel) + luaL_argerror(L, param, "killed cdImageChannel"); + return channel_p; +} + +void cdlua_pushchannel(lua_State* L, unsigned char* channel, int size) +{ + cdluaImageChannel* channel_p = (cdluaImageChannel*)lua_newuserdata(L, sizeof(cdluaImageChannel)); + luaL_getmetatable(L, "cdImageChannel"); + lua_setmetatable(L, -2); + + channel_p->channel = channel; + channel_p->size = size; +} + +long cdlua_checkcolor(lua_State* L, int param) +{ + if (!lua_islightuserdata(L, param)) + { + if (lua_isnumber(L, param) && (lua_tointeger(L, param) == CD_QUERY)) + return CD_QUERY; + + luaL_argerror(L, param, "invalid color, must be a light user data"); + } + + return (long int)lua_touserdata(L, param); +} + +cdImage* cdlua_checkimage(lua_State* L, int param) +{ + cdImage** image_p = (cdImage**)luaL_checkudata(L, param, "cdImage"); + if (!(*image_p)) + luaL_argerror(L, param, "killed cdImage"); + return *image_p; +} + +void cdlua_pushimage(lua_State* L, cdImage* image) +{ + cdImage** image_p = (cdImage**)lua_newuserdata(L, sizeof(cdImage*)); + luaL_getmetatable(L, "cdImage"); + lua_setmetatable(L, -2); + + *image_p = image; +} + +cdBitmap * cdlua_checkbitmap(lua_State* L, int param) +{ + cdBitmap** bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap"); + if (!(*bitmap_p)) + luaL_argerror(L, param, "killed cdBitmap"); + return *bitmap_p; +} + +void cdlua_pushbitmap(lua_State* L, cdBitmap* bitmap) +{ + cdBitmap** bitmap_p = (cdBitmap**)lua_newuserdata(L, sizeof(cdBitmap*)); + luaL_getmetatable(L, "cdBitmap"); + lua_setmetatable(L, -2); + + *bitmap_p = bitmap; +} + +/***************************************************************************\ +* cd.ContextCaps(ctx: number) -> (caps: number) * +\***************************************************************************/ +static int cdlua5_contextcaps(lua_State * L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1); + lua_pushnumber(L, cdContextCaps(cdlua_ctx->ctx())); + return 1; +} + +static int cdlua5_releasestate(lua_State * L) +{ + cdState* *state_p = (cdState* *) luaL_checkudata(L, 1, "cdState"); + if (*state_p) + { + cdReleaseState(*state_p); + *state_p = NULL; /* mark as released */ + } + + return 0; +} + +static int cdlua5_createstipple(lua_State *L) +{ + int size; + unsigned char* stipple; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "stipple dimensions should be positive integers"); + + size = width * height; + stipple = (unsigned char *) malloc(size); + memset(stipple, '\0', size); + + cdlua_pushstipple(L, stipple, width, height); + + return 1; +} + +static int cdlua5_killstipple(lua_State *L) +{ + cdluaStipple *stipple_p = (cdluaStipple*)luaL_checkudata(L, 1, "cdStipple"); + if (stipple_p->stipple) + { + free(stipple_p->stipple); + stipple_p->stipple = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* number = stipple[i] * +\***************************************************************************/ +static int cdlua5_indexstipple(lua_State *L) +{ + cdluaStipple* stipple_p = cdlua_checkstipple(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= stipple_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushnumber(L, stipple_p->stipple[index]); + return 1; +} + +/***************************************************************************\ +* stipple[i] = number . * +\***************************************************************************/ +static int cdlua5_newindexstipple(lua_State *L) +{ + unsigned char value; + + cdluaStipple* stipple_p = cdlua_checkstipple(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= stipple_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + value = (unsigned char)luaL_checkint(L, 3); + if ((value != 0 && value != 1)) + luaL_argerror(L, 3, "value must be 0 or 1"); + + stipple_p->stipple[index] = value; + return 0; +} + +static int cdlua5_createpattern(lua_State *L) +{ + int size; + long int *pattern; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "pattern dimensions should be positive integers"); + + size = width * height; + pattern = (long int *) malloc(size * sizeof(long int)); + memset(pattern, 255, size * sizeof(long int)); + + cdlua_pushpattern(L, pattern, width, height); + + return 1; +} + +static int cdlua5_killpattern(lua_State *L) +{ + cdluaPattern *pattern_p = (cdluaPattern *) luaL_checkudata(L, 1, "cdPattern"); + if (pattern_p->pattern) + { + free(pattern_p->pattern); + pattern_p->pattern = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* color = pattern[i] * +\***************************************************************************/ +static int cdlua5_indexpattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pattern_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushlightuserdata(L, (void *) pattern_p->pattern[index]); + return 1; +} + +/***************************************************************************\ +* pattern[i] = color * +\***************************************************************************/ +static int cdlua5_newindexpattern(lua_State *L) +{ + long int color; + + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pattern_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + color = cdlua_checkcolor(L, 3); + + pattern_p->pattern[index] = color; + return 0; +} + +static int cdlua5_rgb2map(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2); + cdluaPalette* pal = cdlua_checkpalette(L, 3); + cdRGB2Map(imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue, + imagemap_p->index, pal->count, pal->color); + return 0; +} + +static int cdlua5_createbitmap(lua_State *L) +{ + cdBitmap *bitmap; + + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + int type = luaL_checkint(L, 3); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "bitmap dimensions should be positive integers"); + + bitmap = cdCreateBitmap(width, height, type); + if (bitmap) + cdlua_pushbitmap(L, bitmap); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killbitmap(lua_State *L) +{ + cdBitmap* *bitmap_p = (cdBitmap* *) luaL_checkudata(L, 1, "cdBitmap"); + if (*bitmap_p) + { + cdKillBitmap(*bitmap_p); + *bitmap_p = NULL; /* mark as killed */ + } + + return 0; +} + +static int cdlua5_bitmapgetdata(lua_State *L) +{ + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + int dataptr = luaL_checkint(L, 2); + + unsigned char *data = cdBitmapGetData(bitmap, dataptr); + if (data) + cdlua_pushchannel(L, data, bitmap->w * bitmap->h); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_bitmapsetrect(lua_State *L) +{ + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + int xmin = (int) luaL_checkint(L, 2); + int xmax = (int) luaL_checkint(L, 3); + int ymin = (int) luaL_checkint(L, 4); + int ymax = (int) luaL_checkint(L, 5); + + cdBitmapSetRect(bitmap, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_bitmaprgb2map(lua_State *L) +{ + cdBitmap* bitmaprgb = cdlua_checkbitmap(L, 1); + cdBitmap* bitmapmap = cdlua_checkbitmap(L, 2); + + if (bitmaprgb->type != CD_RGB) + luaL_argerror(L, 1, "invalid bitmap type, must be RGB"); + if (bitmapmap->type != CD_MAP) + luaL_argerror(L, 2, "invalid bitmap type, must be Map"); + + cdBitmapRGB2Map(bitmaprgb, bitmapmap); + return 0; +} + +static int cdlua5_createimagergb(lua_State * L) +{ + unsigned char *red, *green, *blue; + int size; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "image dimensions should be positive integers"); + + size = width*height; + red = (unsigned char*)malloc(3*size); + + if (red) + { + memset(red, 255, 3*size); /* white */ + green = red + size; + blue = red + 2*size; + cdlua_pushimagergb(L, red, green, blue, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagergb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = (cdluaImageRGB*)luaL_checkudata(L, 1, "cdImageRGB"); + if (imagergb_p->red && imagergb_p->free) + { + free(imagergb_p->red); + imagergb_p->red = NULL; /* mark as killed */ + imagergb_p->green = NULL; + imagergb_p->blue = NULL; + } + + return 0; +} + +static int cdlua5_createimagergba(lua_State * L) +{ + unsigned char *red, *green, *blue, *alpha; + int size; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "image dimensions should be positive integers"); + + size = width*height; + red = (unsigned char*)malloc(4*size); + + if (red) + { + memset(red, 255, 3*size); /* white */ + green = red + size; + blue = red + 2*size; + alpha = red + 3*size; + memset(alpha, 0, size); /* transparent */ + cdlua_pushimagergba(L, red, green, blue, alpha, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagergba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = (cdluaImageRGBA*)luaL_checkudata(L, 1, "cdImageRGBA"); + if (imagergba_p->red && imagergba_p->free) + { + free(imagergba_p->red); + imagergba_p->red = NULL; /* mark as killed */ + imagergba_p->green = NULL; + imagergba_p->blue = NULL; + imagergba_p->alpha = NULL; + } + + return 0; +} + +static int cdlua5_createimagemap(lua_State *L) +{ + int size; + unsigned char *index; + int width = luaL_checkint(L,1); + int height = luaL_checkint(L,2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "imagemap dimensions should be positive integers"); + + size = width * height; + index = (unsigned char *) malloc(size); + + if (index) + { + memset(index, 0, size); + cdlua_pushimagemap(L, index, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killimagemap(lua_State *L) +{ + cdluaImageMap *imagemap_p = (cdluaImageMap *) luaL_checkudata(L, 1, "cdImageMap"); + if (imagemap_p->index) + { + free(imagemap_p->index); + imagemap_p->index = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* number = imagemap[i] * +\***************************************************************************/ +static int cdlua5_indeximagemap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= imagemap_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushnumber(L, imagemap_p->index[index]); + return 1; +} + +/***************************************************************************\ +* imagemap[i] = number * +\***************************************************************************/ +static int cdlua5_newindeximagemap(lua_State *L) +{ + int value; + + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= imagemap_p->size) + luaL_argerror(L, 2, "index is out of bounds"); + + value = luaL_checkint(L, 3); + if ((value < 0 || value > 255)) + luaL_argerror(L, 3, "value should be in range [0, 255]"); + + imagemap_p->index[index] = (unsigned char) value; + return 0; +} + +/***************************************************************************\ +* channel "gettable" fallback. This fallback is called when a LUA line like * +* "c = imagergb.r[y*w + x]" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the appropriate value is returned. * +\***************************************************************************/ +static int cdlua5_indexchannel(lua_State *L) +{ + cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || + (channel_p->size > 0 && index >= channel_p->size) || + (channel_p->size == -1 && index >= 256)) { + luaL_argerror(L, 2, "index is out of bounds"); + } + + if (channel_p->size == -1) /* COLORS */ + lua_pushlightuserdata(L, (void *)((long int*)channel_p->channel)[index]); + else + lua_pushnumber(L, channel_p->channel[index]); + + return 1; +} + +/***************************************************************************\ +* channel "settable" fallback. This fallback is called when a LUA line like * +* "imagergb.r[y*w + x] = c" is executed. The imagergb "gettable" fallback * +* fills and returns a channel structure with info about the buffer. This * +* structure is consulted and the value is assigned where it should. * +\***************************************************************************/ +static int cdlua5_newindexchannel(lua_State *L) +{ + int value; + + cdluaImageChannel* channel_p = cdlua_checkchannel(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || + (channel_p->size > 0 && index >= channel_p->size) || + (channel_p->size == -1 && index >= 256)) { + luaL_argerror(L, 2, "index is out of bounds"); + } + + if (channel_p->size > 0) + { + value = luaL_checkint(L, 3); + if ((value < 0 || value > 255)) + luaL_argerror(L, 3, "value should be in range [0, 255]"); + channel_p->channel[index] = (unsigned char) value; + } + else /* COLORS */ + { + value = (long int) cdlua_checkcolor(L, 3); + ((long int*)channel_p->channel)[index] = value; + } + return 0; +} + +/***************************************************************************\ +* imagergb "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergb.r[y*w + x]" or "imagergb.r[y*w + x] = c" is executed. * +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indeximagergb(lua_State *L) +{ + unsigned char* channel = NULL; + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + if (*index_s == 'r' || *index_s == 'R') + channel = imagergb_p->red; + else if (*index_s == 'g' || *index_s == 'G') + channel = imagergb_p->green; + else if (*index_s == 'b' || *index_s == 'B') + channel = imagergb_p->blue; + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, imagergb_p->size); + + return 1; +} + +/***************************************************************************\ +* imagergba "gettable" fallback. This fallback is called when a LUA line * +* like "c = imagergba.r[y*w + x]" or "imagergba.r[y*w + x] = c" is executed.* +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indeximagergba(lua_State *L) +{ + unsigned char* channel = NULL; + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + if (*index_s == 'r' || *index_s == 'R') + channel = imagergba_p->red; + else if (*index_s == 'g' || *index_s == 'G') + channel = imagergba_p->green; + else if (*index_s == 'b' || *index_s == 'B') + channel = imagergba_p->blue; + else if (*index_s == 'a' || *index_s == 'A') + channel = imagergba_p->alpha; + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, imagergba_p->size); + + return 1; +} + +/***************************************************************************\ +* bitmap "gettable" fallback. This fallback is called when a LUA line * +* like "c = bitmap.r[y*w + x]" or "bitmap.r[y*w + x] = c" is executed. * +* The following "gettable" or "settable" * +* then assigns or returns the appropriate value. * +\***************************************************************************/ +static int cdlua5_indexbitmap(lua_State *L) +{ + unsigned char* channel = NULL; + + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + const char *index_s = luaL_checkstring(L, 2); + + int size = bitmap->w * bitmap->h; + + if (*index_s == 'r' || *index_s == 'R') + channel = cdBitmapGetData(bitmap, CD_IRED); + else if (*index_s == 'g' || *index_s == 'G') + channel = cdBitmapGetData(bitmap, CD_IGREEN); + else if (*index_s == 'b' || *index_s == 'B') + channel = cdBitmapGetData(bitmap, CD_IBLUE); + else if (*index_s == 'a' || *index_s == 'A') + channel = cdBitmapGetData(bitmap, CD_IALPHA); + else if (*index_s == 'i' || *index_s == 'I') + channel = cdBitmapGetData(bitmap, CD_INDEX); + else if (*index_s == 'c' || *index_s == 'C') + { + channel = cdBitmapGetData(bitmap, CD_COLORS); + size = -1; + } + else + luaL_argerror(L, 2, "index is an invalid channel name"); + + cdlua_pushchannel(L, channel, size); + + return 1; +} + +static int cdlua5_killimage(lua_State *L) +{ + cdImage* *image_p = (cdImage* *) luaL_checkudata(L, 1, "cdImage"); + if (*image_p) + { + cdKillImage(*image_p); + *image_p = NULL; /* mark as killed */ + } + return 0; +} + +/***************************************************************************\ +* cd.Version() -> (version: string) * +\***************************************************************************/ +static int cdlua5_version(lua_State *L) +{ + lua_pushstring(L, cdVersion()); + return 1; +} + +/***************************************************************************\ +* Register callback functions. * +* cd.ContextRegisterCallback(ctx, cb: number, func: function) -> (status: number) * +\***************************************************************************/ +static int cdlua5_registercallback(lua_State *L) +{ + int cb_i, func_lock; + cdluaCallback* cdCB; + cdluaContext* cdlua_ctx; + + cdlua_ctx = cdlua_getcontext(L, 1); + + cb_i = luaL_checkint(L, 2); + if (cb_i >= cdlua_ctx->cb_n) + luaL_argerror(L, 2, "invalid callback parameter"); + + if (lua_isnil(L, 3)) + func_lock = -1; + else if (!lua_isfunction(L, 3)) + luaL_argerror(L, 3, "invalid function parameter"); + else + lua_pushvalue(L, 3); + func_lock = lua_ref(L, 1); + + cdCB = &cdlua_ctx->cb_list[cb_i]; + + if (cdCB->lock != -1) + { + lua_unref(L,cdCB->lock); + cdCB->lock = func_lock; + if (func_lock == -1) + { + cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, NULL); + } + } + else + { + if (func_lock != -1) + { + cdContextRegisterCallback(cdlua_ctx->ctx(), cb_i, (cdCallback)cdCB->func); + cdCB->lock = func_lock; + } + } + return 0; +} + + + +/***************************************************************************\ +* Color Coding * +\***************************************************************************/ + +/***************************************************************************\ +* Creates a color as a light userdata. The color value is * +* placed in the (void *) value. Not beautiful, but works best. * +* cd.EncodeColor(r, g, b: number) -> (old_color: color) * +\***************************************************************************/ +static int cdlua5_encodecolor(lua_State *L) +{ + int red_f, green_f, blue_f; + unsigned char red_i, green_i, blue_i; + long int color; + + red_f = luaL_checkint(L, 1); + green_f = luaL_checkint(L, 2); + blue_f = luaL_checkint(L, 3); + + if (red_f < 0 || red_f > 255) + luaL_argerror(L, 1, "color components values should be in range [0, 255]"); + if (green_f < 0 || green_f > 255) + luaL_argerror(L, 2, "color components values should be in range [0, 255]"); + if (blue_f < 0 || blue_f > 255) + luaL_argerror(L, 3, "color components values should be in range [0, 255]"); + + red_i = (unsigned char) (red_f); + green_i = (unsigned char) (green_f); + blue_i = (unsigned char) (blue_f); + + color = cdEncodeColor(red_i, green_i, blue_i); + lua_pushlightuserdata(L, (void *)color); + + return 1; +} + +/***************************************************************************\ +* Decodes a color previously created. * +* cd.DecodeColor(color: color) -> (r, g, b: number) * +\***************************************************************************/ +static int cdlua5_decodecolor(lua_State *L) +{ + unsigned char red_i, green_i, blue_i; + long int color = cdlua_checkcolor(L, 1); + cdDecodeColor(color, &red_i, &green_i, &blue_i); + lua_pushnumber(L, red_i); + lua_pushnumber(L, green_i); + lua_pushnumber(L, blue_i); + + return 3; +} + +/***************************************************************************\ +* cd.EncodeAlpha(color: color_tag, alpha: number) -> (color: color) * +\***************************************************************************/ +static int cdlua5_encodealpha(lua_State *L) +{ + float alpha_f; + unsigned char alpha_i; + long int color; + + color = cdlua_checkcolor(L, 1); + + if (!lua_isnumber(L, 2)) + luaL_argerror(L, 2, "invalid alpha parameter"); + + alpha_f = (float) lua_tonumber(L, 2); + + if (alpha_f < 0 || alpha_f > 255) + luaL_argerror(L, 2, "alpha components values should be in range [0, 255]"); + + alpha_i = (unsigned char) (alpha_f); + + color = cdEncodeAlpha(color, alpha_i); + lua_pushlightuserdata(L, (void *) color); + return 1; +} + +/***************************************************************************\ +* cd.DecodeAlpha(color: color) -> (a: number) * +\***************************************************************************/ +static int cdlua5_decodealpha(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + unsigned char alpha_i = cdDecodeAlpha(color); + lua_pushnumber(L, alpha_i); + return 1; +} + +/***************************************************************************\ +* cd.Alpha(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_alpha(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdAlpha(color)); + return 1; +} + +/***************************************************************************\ +* cd.Red(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_red(lua_State* L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdRed(color)); + return 1; +} + +/***************************************************************************\ +* cd.Blue(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_blue(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdBlue(color)); + return 1; +} + +/***************************************************************************\ +* cd.Green(color: color) -> (r: number) * +\***************************************************************************/ +static int cdlua5_green(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdGreen(color)); + return 1; +} + +static int cdlua5_createpalette(lua_State *L) +{ + int size_i; + long int *palette; + + size_i = luaL_checkint(L, 1); + if (size_i < 1) + luaL_argerror(L, 1, "palette size should be a positive integer"); + + palette = (long int *) malloc(256 * sizeof(long int)); + memset(palette, 0, 256 * sizeof(long int)); + + cdlua_pushpalette(L, palette, size_i); + + return 1; +} + +static int cdlua5_killpalette(lua_State *L) +{ + cdluaPalette* pal = (cdluaPalette *)luaL_checkudata(L, 1, "cdPalette"); + if (pal->color) + { + free(pal->color); + pal->color = NULL; /* mark as killed */ + } + + return 0; +} + +/***************************************************************************\ +* color = palette[i] * +\***************************************************************************/ +static int cdlua5_indexpalette(lua_State *L) +{ + cdluaPalette* pal = cdlua_checkpalette(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + lua_pushlightuserdata(L, (void*) pal->color[index]); + return 1; +} + +/***************************************************************************\ +* palette[i] = color * +\***************************************************************************/ +static int cdlua5_newindexpalette(lua_State *L) +{ + long int color; + cdluaPalette* pal = cdlua_checkpalette(L, 1); + + int index = luaL_checkint(L, 2); + if (index < 0 || index >= pal->count) + luaL_argerror(L, 2, "index is out of bounds"); + + color = cdlua_checkcolor(L, 3); + + pal->color[index] = color; + return 0; +} + +/*****************************************************************************\ + len +\*****************************************************************************/ +static int cdluaPalette_len(lua_State *L) +{ + cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1); + lua_pushinteger(L, pal->count); + return 1; +} + +/*****************************************************************************\ + tostring +\*****************************************************************************/ +static int cdlua5_tostringpalette (lua_State *L) +{ + cdluaPalette *pal = (cdluaPalette*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdPalette(%p)%s", pal, (pal->color)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimage (lua_State *L) +{ + cdImage* *image_p = (cdImage**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImage(%p)%s", image_p, (*image_p)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringbitmap (lua_State *L) +{ + cdBitmap* *bitmap_p = (cdBitmap**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdBitmap(%p)%s", bitmap_p, (*bitmap_p)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringchannel (lua_State *L) +{ + cdluaImageChannel *imagechannel_p = (cdluaImageChannel*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageChannel(%p)%s", imagechannel_p, (imagechannel_p->channel)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringstate (lua_State *L) +{ + cdState* *state_p = (cdState**)lua_touserdata(L, 1); + lua_pushfstring(L, "cdState(%p)%s", state_p, (*state_p)? "": "-released"); + return 1; +} + +static int cdlua5_tostringpattern (lua_State *L) +{ + cdluaPattern *pattern_p = (cdluaPattern*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdPattern(%p)%s", pattern_p, (pattern_p->pattern)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringstipple (lua_State *L) +{ + cdluaStipple *stipple_p = (cdluaStipple*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdStipple(%p)%s", stipple_p, (stipple_p->stipple)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagergba (lua_State *L) +{ + cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageRGBA(%p)%s", imagergba_p, (imagergba_p->red)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagergb (lua_State *L) +{ + cdluaImageRGB *imagergb_p = (cdluaImageRGB*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageRGB(%p)%s", imagergb_p, (imagergb_p->red)? "": "-killed"); + return 1; +} + +static int cdlua5_tostringimagemap (lua_State *L) +{ + cdluaImageMap *imagemap_p = (cdluaImageMap*)lua_touserdata(L, 1); + lua_pushfstring(L, "cdImageMap(%p)%s", imagemap_p, (imagemap_p->index)? "": "-killed"); + return 1; +} + +/***************************************************************************\ +* cd.Reserved * +\***************************************************************************/ +static int cdlua5_reserved(lua_State *L) +{ + long int color = cdlua_checkcolor(L, 1); + lua_pushnumber(L, cdReserved(color)); + return 1; +} + +/***************************************************************************\ +* cd.GetScreenColorPlanes * +\***************************************************************************/ +static int cdlua5_getscreencolorplanes(lua_State *L) +{ + lua_pushnumber(L, cdGetScreenColorPlanes()); + return 1; +} + +/***************************************************************************\ +* cd.GetScreenSize * +\***************************************************************************/ +static int cdlua5_getscreensize(lua_State *L) +{ + int width; + int height; + double mm_width; + double mm_height; + cdGetScreenSize(&width, &height, &mm_width, &mm_height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushnumber(L, mm_width); + lua_pushnumber(L, mm_height); + return 4; +} + +/***************************************************************************\ +* cd.UseContextPlus * +\***************************************************************************/ +static int cdlua5_usecontextplus(lua_State *L) +{ + lua_pushnumber(L, cdUseContextPlus(luaL_checkint(L, 1))); + return 1; +} + + +/********************************************************************************\ +* CDLua Exported functions * +\********************************************************************************/ +static const struct luaL_reg cdlib[] = { + + /* Initialization */ + {"ContextCaps" , cdlua5_contextcaps}, + + /* Control */ + {"ReleaseState" , cdlua5_releasestate}, + + /* Stipple */ + {"CreateStipple", cdlua5_createstipple}, + {"KillStipple" , cdlua5_killstipple}, + + /* Pattern */ + {"CreatePattern", cdlua5_createpattern}, + {"KillPattern" , cdlua5_killpattern}, + + /* Client Images */ + {"RGB2Map" , cdlua5_rgb2map}, + {"CreateBitmap" , cdlua5_createbitmap}, + {"KillBitmap" , cdlua5_killbitmap}, + {"BitmapGetData" , cdlua5_bitmapgetdata}, + {"BitmapSetRect" , cdlua5_bitmapsetrect}, + {"BitmapRGB2Map" , cdlua5_bitmaprgb2map}, + + {"CreateImageRGB" , cdlua5_createimagergb}, + {"KillImageRGB" , cdlua5_killimagergb}, + {"CreateImageRGBA" , cdlua5_createimagergba}, + {"KillImageRGBA" , cdlua5_killimagergba}, + {"CreateImageMap" , cdlua5_createimagemap}, + {"KillImageMap" , cdlua5_killimagemap}, + + /* Server Images */ + {"KillImage" , cdlua5_killimage}, + + /* Other */ + {"Version" , cdlua5_version}, + {"RegisterCallback" , cdlua5_registercallback}, + {"ContextRegisterCallback" , cdlua5_registercallback}, + + /* Color Coding */ + {"EncodeColor" , cdlua5_encodecolor}, + {"DecodeColor" , cdlua5_decodecolor}, + {"EncodeAlpha" , cdlua5_encodealpha}, + {"DecodeAlpha" , cdlua5_decodealpha}, + {"Alpha" , cdlua5_alpha}, + {"Red" , cdlua5_red}, + {"Blue" , cdlua5_blue}, + {"Green" , cdlua5_green}, + {"Reserved" , cdlua5_reserved}, + + /* Palette */ + {"CreatePalette", cdlua5_createpalette}, + {"KillPalette" , cdlua5_killpalette}, + + /* native window functions */ + {"GetScreenColorPlanes" , cdlua5_getscreencolorplanes}, + {"GetScreenSize" , cdlua5_getscreensize}, + + /* gdi+ functions */ + {"UseContextPlus" , cdlua5_usecontextplus}, + + {NULL, NULL}, +}; + +void cdlua_addcontext(lua_State *L, cdluaLuaState* cdL, cdluaContext *cdlua_ctx) +{ + int i; + cdlua_ctx->id = cdL->numdrivers; + cdL->drivers[cdL->numdrivers] = cdlua_ctx; + + lua_pushstring(L, cdlua_ctx->name); + lua_pushnumber(L, cdL->numdrivers); + lua_settable(L, -3); + + /* skip CD_SIZECB, register other callbacks */ + for (i=1; i < cdlua_ctx->cb_n; i++) + { + lua_pushstring(L, cdlua_ctx->cb_list[i].name); + lua_pushnumber(L, i); + lua_settable(L, -3); + } + + cdL->numdrivers++; +} + + +/********************************************************************************\ +* Exports all CD constants * +\********************************************************************************/ +typedef struct cdlua5_constant { + const char *name; + lua_Number value; +} cdlua5_constant; + +typedef struct cdlua5_color { + const char *name; + long int value; +} cdlua5_color; + +static const struct cdlua5_constant cdlibconstant[] = { + /* query value */ + {"QUERY", CD_QUERY}, + + /* these definitions are compatible with the IM library */ + {"RGB" , CD_RGB}, + {"MAP" , CD_MAP}, + {"RGBA", CD_RGBA}, + + {"IRED" , CD_IRED}, + {"IGREEN", CD_IGREEN}, + {"IBLUE" , CD_IBLUE}, + {"IALPHA", CD_IALPHA}, + {"INDEX" , CD_INDEX}, + {"COLORS", CD_COLORS}, + + /* status report */ + {"ERROR", CD_ERROR}, + {"OK" , CD_OK}, + + /* clip mode */ + {"CLIPOFF" , CD_CLIPOFF}, + {"CLIPAREA" , CD_CLIPAREA}, + {"CLIPPOLYGON", CD_CLIPPOLYGON}, + {"CLIPREGION" , CD_CLIPREGION}, + + /* region combine mode */ + {"UNION" , CD_UNION}, + {"INTERSECT" , CD_INTERSECT}, + {"DIFFERENCE" , CD_DIFFERENCE}, + {"NOTINTERSECT", CD_NOTINTERSECT}, + + /* polygon mode (begin...end) */ + {"FILL" , CD_FILL}, + {"OPEN_LINES" , CD_OPEN_LINES}, + {"CLOSED_LINES", CD_CLOSED_LINES}, + {"CLIP" , CD_CLIP}, + {"BEZIER" , CD_BEZIER}, + {"REGION" , CD_REGION}, + {"POLYCUSTOM" , CD_POLYCUSTOM}, + + /* fill mode */ + {"EVENODD", CD_EVENODD}, + {"WINDING", CD_WINDING}, + + /* line join */ + {"MITER", CD_MITER}, + {"BEVEL", CD_BEVEL}, + {"ROUND", CD_ROUND}, + + /* line cap */ + {"CAPFLAT" , CD_CAPFLAT}, + {"CAPSQUARE", CD_CAPSQUARE}, + {"CAPROUND" , CD_CAPROUND}, + + /* background opacity mode */ + {"OPAQUE" , CD_OPAQUE}, + {"TRANSPARENT", CD_TRANSPARENT}, + + /* write mode */ + {"REPLACE", CD_REPLACE}, + {"XOR" , CD_XOR}, + {"NOT_XOR", CD_NOT_XOR}, + + /* color allocation mode (palette) */ + {"POLITE", CD_POLITE}, + {"FORCE" , CD_FORCE}, + + /* line style */ + {"CONTINUOUS" , CD_CONTINUOUS}, + {"DASHED" , CD_DASHED}, + {"DOTTED" , CD_DOTTED}, + {"DASH_DOT" , CD_DASH_DOT}, + {"DASH_DOT_DOT", CD_DASH_DOT_DOT}, + {"CUSTOM" , CD_CUSTOM}, + + /* marker type */ + {"PLUS" , CD_PLUS}, + {"STAR" , CD_STAR}, + {"CIRCLE" , CD_CIRCLE}, + {"X" , CD_X}, + {"BOX" , CD_BOX}, + {"DIAMOND" , CD_DIAMOND}, + {"HOLLOW_CIRCLE" , CD_HOLLOW_CIRCLE}, + {"HOLLOW_BOX" , CD_HOLLOW_BOX}, + {"HOLLOW_DIAMOND", CD_HOLLOW_DIAMOND}, + + /* hatch type */ + {"HORIZONTAL", CD_HORIZONTAL}, + {"VERTICAL" , CD_VERTICAL}, + {"FDIAGONAL" , CD_FDIAGONAL}, + {"BDIAGONAL" , CD_BDIAGONAL}, + {"CROSS" , CD_CROSS}, + {"DIAGCROSS" , CD_DIAGCROSS}, + + /* interior style */ + {"SOLID" , CD_SOLID}, + {"HATCH" , CD_HATCH}, + {"STIPPLE", CD_STIPPLE}, + {"PATTERN", CD_PATTERN}, + {"HOLLOW" , CD_HOLLOW}, + + /* text alignment */ + {"NORTH" , CD_NORTH}, + {"SOUTH" , CD_SOUTH}, + {"EAST" , CD_EAST}, + {"WEST" , CD_WEST}, + {"NORTH_EAST" , CD_NORTH_EAST}, + {"NORTH_WEST" , CD_NORTH_WEST}, + {"SOUTH_EAST" , CD_SOUTH_EAST}, + {"SOUTH_WEST" , CD_SOUTH_WEST}, + {"CENTER" , CD_CENTER}, + {"BASE_LEFT" , CD_BASE_LEFT}, + {"BASE_CENTER", CD_BASE_CENTER}, + {"BASE_RIGHT" , CD_BASE_RIGHT}, + + /* style */ + {"PLAIN" , CD_PLAIN}, + {"BOLD" , CD_BOLD}, + {"ITALIC" , CD_ITALIC}, + {"BOLD_ITALIC", CD_BOLD_ITALIC}, + {"UNDERLINE" , CD_UNDERLINE}, + {"STRIKEOUT" , CD_STRIKEOUT}, + + /* font size */ + {"SMALL" , CD_SMALL}, + {"STANDARD", CD_STANDARD}, + {"LARGE" , CD_LARGE}, + + /* Canvas Capabilities */ + {"CAP_NONE" , CD_CAP_NONE}, + {"CAP_FLUSH" , CD_CAP_FLUSH}, + {"CAP_CLEAR" , CD_CAP_CLEAR}, + {"CAP_PLAY" , CD_CAP_PLAY}, + {"CAP_YAXIS" , CD_CAP_YAXIS}, + {"CAP_CLIPAREA" , CD_CAP_CLIPAREA}, + {"CAP_CLIPPOLY" , CD_CAP_CLIPPOLY}, + {"CAP_RECT" , CD_CAP_RECT}, + {"CAP_IMAGERGB" , CD_CAP_IMAGERGB}, + {"CAP_IMAGERGBA" , CD_CAP_IMAGERGBA}, + {"CAP_IMAGEMAP" , CD_CAP_IMAGEMAP}, + {"CAP_GETIMAGERGB" , CD_CAP_GETIMAGERGB}, + {"CAP_IMAGESRV" , CD_CAP_IMAGESRV}, + {"CAP_BACKGROUND" , CD_CAP_BACKGROUND}, + {"CAP_BACKOPACITY" , CD_CAP_BACKOPACITY}, + {"CAP_WRITEMODE" , CD_CAP_WRITEMODE}, + {"CAP_LINESTYLE" , CD_CAP_LINESTYLE}, + {"CAP_LINEWITH" , CD_CAP_LINEWITH}, + {"CAP_WD" , CD_CAP_FPRIMTIVES}, + {"CAP_HATCH" , CD_CAP_HATCH}, + {"CAP_STIPPLE" , CD_CAP_STIPPLE}, + {"CAP_PATTERN" , CD_CAP_PATTERN}, + {"CAP_FONT" , CD_CAP_FONT}, + {"CAP_FONTDIM" , CD_CAP_FONTDIM}, + {"CAP_TEXTSIZE" , CD_CAP_TEXTSIZE}, + {"CAP_TEXTORIENTATION", CD_CAP_TEXTORIENTATION}, + {"CAP_PALETTE" , CD_CAP_PALETTE}, + {"CAP_LINECAP" , CD_CAP_LINECAP}, + {"CAP_LINEJOIN" , CD_CAP_LINEJOIN}, + {"CAP_REGION" , CD_CAP_REGION}, + {"CAP_CHORD" , CD_CAP_CHORD}, + {"CAP_ALL" , CD_CAP_ALL}, + + /* cdPlay definitions */ + {"SIZECB", CD_SIZECB}, + {"ABORT", CD_ABORT}, + {"CONTINUE", CD_CONTINUE}, + + /* simulation flags */ + {"SIM_NONE" , CD_SIM_NONE}, + {"SIM_LINE" , CD_SIM_LINE}, + {"SIM_RECT" , CD_SIM_RECT}, + {"SIM_ARC" , CD_SIM_ARC}, + {"SIM_POLYLINE" , CD_SIM_POLYLINE}, + {"SIM_BOX" , CD_SIM_BOX}, + {"SIM_SECTOR" , CD_SIM_SECTOR}, + {"SIM_POLYGON" , CD_SIM_POLYGON}, + {"SIM_CHORD" , CD_SIM_CHORD}, + {"SIM_ALL" , CD_SIM_ALL}, + {"SIM_LINES" , CD_SIM_LINES}, + {"SIM_FILLS" , CD_SIM_FILLS}, + + /* some conversion factors */ + {"MM2PT" , CD_MM2PT}, + {"RAD2DEG", CD_RAD2DEG}, + + /* cdcgm.h (the callback names are registered in cdlua_addcontext) */ + + /* cdgdiplus.h */ + {"SPLINE" , CD_SPLINE}, + {"FILLSPLINE" , CD_FILLSPLINE}, + {"FILLGRADIENT", CD_FILLGRADIENT}, + + /* cdps.h */ + {"A0" , CD_A0}, + {"A1" , CD_A1}, + {"A2" , CD_A2}, + {"A3" , CD_A3}, + {"A4" , CD_A4}, + {"A5" , CD_A5}, + {"LETTER", CD_LETTER}, + {"LEGAL" , CD_LEGAL}, + + {NULL, -1}, +}; + +static void initconst(lua_State *L) +{ + const cdlua5_constant *l = cdlibconstant; + for (; l->name; l++) { + lua_pushstring(L, l->name); + lua_pushnumber(L, l->value); + lua_settable(L, -3); + } +} + +/* some predefined colors for convenience */ +static const struct cdlua5_color cdlibcolor[] = { + {"RED" , CD_RED}, + {"DARK_RED" , CD_DARK_RED}, + {"GREEN" , CD_GREEN}, + {"DARK_GREEN" , CD_DARK_GREEN}, + {"BLUE" , CD_BLUE}, + {"DARK_BLUE" , CD_DARK_BLUE}, + {"YELLOW" , CD_YELLOW}, + {"DARK_YELLOW" , CD_DARK_YELLOW}, + {"MAGENTA" , CD_MAGENTA}, + {"DARK_MAGENTA", CD_DARK_MAGENTA}, + {"CYAN" , CD_CYAN}, + {"DARK_CYAN" , CD_DARK_CYAN}, + {"WHITE" , CD_WHITE}, + {"BLACK" , CD_BLACK}, + {"DARK_GRAY" , CD_DARK_GRAY}, + {"GRAY" , CD_GRAY}, + {NULL, -1}, +}; + +static void initcolor(lua_State *L) +{ + const cdlua5_color *l = cdlibcolor; + for (; l->name; l++) + { + lua_pushstring(L, l->name); + lua_pushlightuserdata(L, (void*) l->value); + lua_settable(L, -3); + } +} + +static void initmetatables(lua_State *L) +{ + /* there is no object orientation for these metatables, + only gc and optionaly array access */ + + luaL_newmetatable(L, "cdState"); /* create new metatable for cdState handles */ + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_releasestate); /* register the method */ + lua_settable (L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringstate); + lua_settable(L, -3); + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + luaL_newmetatable(L, "cdImage"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimage); + lua_settable (L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimage); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdBitmap"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killbitmap); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexbitmap); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringbitmap); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageRGB"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimagergb); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagergb); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagergb); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageRGBA"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killimagergba); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagergba); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagergba); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageChannel"); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexchannel); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexchannel); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringchannel); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdStipple"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killstipple); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexstipple); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexstipple); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringstipple); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdPattern"); + lua_pushliteral (L, "__gc"); + lua_pushcfunction (L, cdlua5_killpattern); + lua_settable (L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexpattern); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexpattern); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringpattern); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdPalette"); + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, cdlua5_killpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indexpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindexpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringpalette); + lua_settable(L, -3); + lua_pushliteral(L, "__len"); + lua_pushcfunction(L, cdluaPalette_len); + lua_settable(L, -3); + lua_pop(L, 1); + + luaL_newmetatable(L, "cdImageMap"); + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, cdlua5_killimagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__index"); + lua_pushcfunction(L, cdlua5_indeximagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__newindex"); + lua_pushcfunction(L, cdlua5_newindeximagemap); + lua_settable(L, -3); + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, cdlua5_tostringimagemap); + lua_settable(L, -3); + lua_pop(L, 1); +} + +static void setinfo (lua_State *L) +{ + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, CD_COPYRIGHT); + lua_settable (L, -3); + + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, CD_DESCRIPTION); + lua_settable (L, -3); + + lua_pushliteral (L, "_NAME"); + lua_pushliteral (L, CD_NAME); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION"); + lua_pushstring (L, cdVersion()); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION_DATE"); + lua_pushliteral(L, CD_VERSION_DATE); + lua_settable (L, -3); + + lua_pushliteral (L, "_VERSION_NUMBER"); + lua_pushinteger(L, cdVersionNumber()); + lua_settable (L, -3); +} + + +/********************************************************************************\ +* CDLua OpenLib * +\********************************************************************************/ + + +int cdlua_open (lua_State *L) +{ + cdluaLuaState* cdL = malloc(sizeof(cdluaLuaState)); + memset(cdL, 0, sizeof(cdluaLuaState)); + cdlua_SetState(L, cdL); + + initmetatables(L); + + luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */ + setinfo(L); + + cdlua_open_active(L, cdL); + cdlua_open_canvas(L); + + cdlua_initdrivers(L, cdL); + initconst(L); + initcolor(L); + + return 1; +} + +int cdlua_close(lua_State *L) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + if (cdL) + { + cdKillCanvas(cdL->void_canvas); + free(cdL); + } + return 0; +} + +int luaopen_cdlua(lua_State* L) +{ + return cdlua_open(L); +} + +int luaopen_cdlua51(lua_State* L) +{ + return cdlua_open(L); +} diff --git a/cd/src/lua5/cdlua5.def b/cd/src/lua5/cdlua5.def new file mode 100755 index 0000000..b4811b2 --- /dev/null +++ b/cd/src/lua5/cdlua5.def @@ -0,0 +1,13 @@ +EXPORTS + cdlua_open + cdlua_close + cdlua_getcanvas + cdlua_addcontext + cdlua_getplaystate + cdlua_getstate + cdlua_checkcanvas + cdlua_pushcanvas + luaopen_cdlua + luaopen_cdlua51 + cdlua_pushbitmap + cdlua_checkbitmap \ No newline at end of file diff --git a/cd/src/lua5/cdlua5_active.c b/cd/src/lua5/cdlua5_active.c new file mode 100755 index 0000000..ad4398e --- /dev/null +++ b/cd/src/lua5/cdlua5_active.c @@ -0,0 +1,2163 @@ +/** \file + * \brief Lua Binding of the OLD API that needs an active canvas + * + * See Copyright Notice in cd.h + */ + + +#include +#include +#include + +#ifdef CD_NO_OLD_INTERFACE +#undef CD_NO_OLD_INTERFACE +#endif + +#include "cd.h" +#include "wd.h" +#include "cdirgb.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua5_private.h" +#include "cdvoid5.h" + + +void cdlua_kill_active(lua_State * L, cdCanvas* canvas) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + cdCanvas* void_canvas = cdL->void_canvas; + + /* find out about the currently active canvas */ + cdCanvas *current_canvas = cdActiveCanvas(); + + /* this should never happen, unless the user did it on purpouse! */ + if (canvas == void_canvas) + luaL_error(L, "trying to kill the void canvas"); + + /* if the user killed the currently active canvas, activate void canvas */ + if (canvas == current_canvas) + cdActivate(void_canvas); +} + +/***************************************************************************\ +* Activates a cd canvas. * +\***************************************************************************/ +static int cdlua5_activate(lua_State * L) +{ + cdCanvas* canvas; + + /* if canvas is nil, activate a void canvas */ + if (lua_isnil(L, 1)) + { + cdluaLuaState* cdL = cdlua_getstate(L); + cdCanvas* void_canvas = cdL->void_canvas; + lua_pushnumber(L, cdActivate(void_canvas)); + return 1; + } + + canvas = cdlua_checkcanvas(L, 1); + lua_pushnumber(L, cdActivate(canvas)); + return 1; +} + +/***************************************************************************\ +* Returns the active canvas. * +\***************************************************************************/ +static int cdlua5_activecanvas(lua_State* L) +{ + cdCanvas* canvas = cdActiveCanvas(); + if (canvas) + cdlua_pushcanvas(L, canvas); + else + lua_pushnil(L); + + return 1; +} + +/***************************************************************************\ +* cd.Simulate(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_simulate(lua_State *L) +{ + lua_pushnumber(L, cdSimulate(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* Control * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Clear() * +\***************************************************************************/ +static int cdlua5_clear(lua_State *L) +{ + (void)L; + cdClear(); + return 0; +} + +/***************************************************************************\ +* cd.Flush() * +\***************************************************************************/ +static int cdlua5_flush(lua_State *L) +{ + (void)L; + cdFlush(); + return 0; +} + +static int cdlua5_savestate(lua_State *L) +{ + cdState* state = cdSaveState(); + if (state) + cdlua_pushstate(L, state); + else + lua_pushnil(L); + return 1; +} + +static int cdlua5_restorestate(lua_State * L) +{ + cdRestoreState(cdlua_checkstate(L, 1)); + return 0; +} + +/***************************************************************************\ +* cd.SetAttribute(name, data: string) * +\***************************************************************************/ + +static int cdlua_isuserdata(const char* name) +{ + if (strcmp(name, "HDC")==0) return 1; + if (strcmp(name, "GC")==0) return 1; + return 0; +} + +static int cdlua5_setattribute(lua_State *L) +{ + const char* name = luaL_checkstring(L, 1); + + if (lua_isnil(L, 2)) + { + cdSetAttribute(name, NULL); + } + else + { + char* data; + if (cdlua_isuserdata(name)) + data = (char*) lua_touserdata(L, 2); + else + data = (char*) luaL_checkstring(L, 2); + cdSetAttribute(name, data); + } + return 0; +} + + +/***************************************************************************\ +* cd.SetAttribute(name: string) -> (data: string) * +\***************************************************************************/ +static int cdlua5_getattribute(lua_State *L) +{ + char* name = (char *)luaL_checkstring(L, 1); + char* data = cdGetAttribute(name); + if (data) + { + if (cdlua_isuserdata(name)) + lua_pushlightuserdata(L, data); + else + lua_pushstring(L, data); + } + else + lua_pushnil(L); + return 1; +} + + + +/***************************************************************************\ +* Coordinate System * +\***************************************************************************/ + +/***************************************************************************\ +* cd.GetCanvasSize() -> (width, heigth, mm_width, mm_height: number) * +\***************************************************************************/ +static int cdlua5_getcanvassize(lua_State *L) +{ + int width; + int height; + double mm_width; + double mm_height; + + cdGetCanvasSize(&width, &height, &mm_width, &mm_height); + + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushnumber(L, mm_width); + lua_pushnumber(L, mm_height); + return 4; +} + +/***************************************************************************\ +* cd.UpdateYAxis(yc: number) -> (yr: number) * +\***************************************************************************/ +static int cdlua5_updateyaxis(lua_State *L) +{ + int y = luaL_checkint(L, 1); + cdUpdateYAxis(&y); + lua_pushnumber(L, y); + return 1; +} + +/***************************************************************************\ +* cd.MM2Pixel(mm_dx, mm_dy: number) -> (dx, dy: number) * +\***************************************************************************/ +static int cdlua5_mm2pixel(lua_State *L) +{ + double mm_dx_d, mm_dy_d; + int dx, dy; + + mm_dx_d = luaL_checknumber(L,1); + mm_dy_d = luaL_checknumber(L,2); + + cdMM2Pixel(mm_dx_d, mm_dy_d, &dx, &dy); + lua_pushnumber(L, dx); + lua_pushnumber(L, dy); + return 2; +} + +/***************************************************************************\ +* cd.Pixel2MM(dx, dy: number) -> (mm_dx, mm_dy: number) * +\***************************************************************************/ +static int cdlua5_pixel2mm(lua_State *L) +{ + double mm_dx_d, mm_dy_d; + int dx, dy; + + dx = luaL_checkint(L,1); + dy = luaL_checkint(L,2); + + cdPixel2MM(dx, dy, &mm_dx_d, &mm_dy_d); + lua_pushnumber(L, mm_dx_d); + lua_pushnumber(L, mm_dy_d); + return 2; +} + +/***************************************************************************\ +* cd.Origin(x, y: number) * +\***************************************************************************/ +static int cdlua5_origin(lua_State *L) +{ + cdOrigin(luaL_checkint(L,1), luaL_checkint(L,2)); + return 0; +} + + + +/***************************************************************************\ +* World Coordinates * +\***************************************************************************/ + +/***************************************************************************\ +* wd.Window(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_window(lua_State *L) +{ + double xmin = luaL_checknumber(L, 1); + double xmax = luaL_checknumber(L, 2); + double ymin = luaL_checknumber(L, 3); + double ymax = luaL_checknumber(L, 4); + wdWindow(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* wd.GetWindow() -> (xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_getwindow(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + + wdGetWindow(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* wd.Viewport(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_viewport(lua_State *L) +{ + int xmin = luaL_checkint(L, 1); + int xmax = luaL_checkint(L, 2); + int ymin = luaL_checkint(L, 3); + int ymax = luaL_checkint(L, 4); + wdViewport(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* wd.GetViewport() -> (xmin, xmax, ymin, ymax: number * +\***************************************************************************/ +static int wdlua5_getviewport(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + + wdGetViewport(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* wd.World2Canvas(xw, yw: number) -> (xv, yv: number) * +\***************************************************************************/ +static int wdlua5_world2canvas(lua_State *L) +{ + double xw_d, yw_d; + int xv_i, yv_i; + + xw_d = luaL_checknumber(L, 1); + yw_d = luaL_checknumber(L, 2); + + wdWorld2Canvas(xw_d, yw_d, &xv_i, &yv_i); + lua_pushnumber(L, xv_i); + lua_pushnumber(L, yv_i); + return 2; +} + +/***************************************************************************\ +* wd.Canvas2World(xv, yv: number) -> (xw, yw: number) * +\***************************************************************************/ +static int wdlua5_canvas2world(lua_State *L) +{ + int xv_i, yv_i; + double xw_d, yw_d; + + xv_i = luaL_checkint(L, 1); + yv_i = luaL_checkint(L, 2); + + wdCanvas2World(xv_i, yv_i, &xw_d, &yw_d); + lua_pushnumber(L, xw_d); + lua_pushnumber(L, yw_d); + return 2; +} + + + +/***************************************************************************\ +* General Attributes * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Foreground(color) -> color * +\***************************************************************************/ +static int cdlua5_foreground(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 1); + color_i = cdForeground(color_i); + lua_pushlightuserdata(L, (void*)color_i); + return 1; +} + +/***************************************************************************\ +* cd.Background(color) -> color * +\***************************************************************************/ +static int cdlua5_background(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 1); + color_i = cdBackground(color_i); + lua_pushlightuserdata(L, (void*) color_i); + return 1; +} + +/***************************************************************************\ +* cd.WriteMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_writemode(lua_State *L) +{ + lua_pushnumber(L, cdWriteMode(luaL_checkint(L, 1))); + return 1; +} + + + +/***************************************************************************\ +* Clipping * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Clip(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_clip(lua_State *L) +{ + lua_pushnumber(L, cdClip(luaL_checkint(L,1))); + return 1; +} + +/***************************************************************************\ +* cd.ClipArea(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int cdlua5_cliparea(lua_State *L) +{ + int xmin = luaL_checkint(L, 1); + int xmax = luaL_checkint(L, 2); + int ymin = luaL_checkint(L, 3); + int ymax = luaL_checkint(L, 4); + + cdClipArea(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.wClipArea(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_cliparea(lua_State *L) +{ + double xmin = luaL_checknumber(L, 1); + double xmax = luaL_checknumber(L, 2); + double ymin = luaL_checknumber(L, 3); + double ymax = luaL_checknumber(L, 4); + + wdClipArea(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.GetClipArea() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int cdlua5_getcliparea(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + int status; + + status = cdGetClipArea(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + lua_pushnumber(L, status); + return 5; +} + +/***************************************************************************\ +* cd.wGetClipArea() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int wdlua5_getcliparea(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + int status; + + status = wdGetClipArea(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + lua_pushnumber(L, status); + return 5; +} + +/***************************************************************************\ +* cd.GetClipPoly() -> (n: number, points: table) * +\***************************************************************************/ +static int cdlua5_getclippoly(lua_State *L) +{ + int n, i; + int *pts; + + pts = cdGetClipPoly(&n); + if (pts) + { + lua_pushnumber(L, n); + + lua_newtable(L); + for (i=0; i < 2*n; i++) + { + lua_pushnumber(L, i+1); + lua_pushnumber(L, pts[i]); + lua_settable(L, -3); + } + + return 2; + } + else + { + lua_pushnil(L); + return 1; + } +} + +/***************************************************************************\ +* cd.wGetClipPoly() -> (n: number, points: table) * +\***************************************************************************/ +static int wdlua5_getclippoly(lua_State *L) +{ + int n, i; + double *pts; + + pts = wdGetClipPoly(&n); + if (pts) + { + lua_pushnumber(L, n); + + lua_newtable(L); + for (i=0; i < 2*n; i++) + { + lua_pushnumber(L, i+1); + lua_pushnumber(L, pts[i]); + lua_settable(L,-3); + } + + return 2; + } + else + { + lua_pushnil(L); + return 1; + } +} + + +/***************************************************************************\ +* Regions * +\***************************************************************************/ + +/***************************************************************************\ +* cd.RegionCombineMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_regioncombinemode(lua_State *L) +{ + lua_pushnumber(L, cdRegionCombineMode(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.PointInRegion(x, y: number) -> (status: number) * +\***************************************************************************/ +static int cdlua5_pointinregion(lua_State *L) +{ + lua_pushnumber(L, cdPointInRegion(luaL_checkint(L, 1),luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.wPointInRegion(x, y: number) -> (status: number) * +\***************************************************************************/ +static int wdlua5_pointinregion(lua_State *L) +{ + lua_pushnumber(L, wdPointInRegion(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.OffsetRegion(dx, dy: number) * +\***************************************************************************/ +static int cdlua5_offsetregion(lua_State *L) +{ + cdOffsetRegion(luaL_checkint(L, 1), luaL_checkint(L, 2)); + return 0; +} + +/***************************************************************************\ +* cd.wOffsetRegion(dx, dy: number) * +\***************************************************************************/ +static int wdlua5_offsetregion(lua_State *L) +{ + wdOffsetRegion(luaL_checknumber(L, 1), luaL_checknumber(L, 2)); + return 0; +} + +/***************************************************************************\ +* cd.RegionBox() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int cdlua5_regionbox(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + + cdRegionBox(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* cd.wRegionBox() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int wdlua5_regionbox(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + + wdRegionBox(&xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + + + +/***************************************************************************\ +* Primitives * +\***************************************************************************/ + + + +/***************************************************************************\ +* Marks * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Pixel(x, y: number, color) * +\***************************************************************************/ +static int cdlua5_pixel (lua_State *L) +{ + cdPixel(luaL_checkint(L, 1), luaL_checkint(L, 2), cdlua_checkcolor(L, 3)); + return 0 ; +} + +/***************************************************************************\ +* cd.wPixel(x, y: number, color) * +\***************************************************************************/ +static int wdlua5_pixel (lua_State *L) +{ + wdPixel(luaL_checknumber(L, 1), luaL_checknumber(L, 2), cdlua_checkcolor(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.Mark(x, y: number) * +\***************************************************************************/ +static int cdlua5_mark(lua_State *L) +{ + cdMark(luaL_checkint(L,1), luaL_checkint(L,2)); + return 0; +} + +/***************************************************************************\ +* cd.wMark(x, y: number) * +\***************************************************************************/ +static int wdlua5_mark(lua_State *L) +{ + wdMark(luaL_checknumber(L, 1), luaL_checknumber(L, 2)); + return 0; +} + +/***************************************************************************\ +* cd.MarkType(type: number) -> (old_type: number) * +\***************************************************************************/ +static int cdlua5_marktype(lua_State *L) +{ + lua_pushnumber(L, cdMarkType(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.MarkSize(size: number) -> (old_size: number) * +\***************************************************************************/ +static int cdlua5_marksize(lua_State *L) +{ + lua_pushnumber(L, cdMarkSize(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.wMarkSize(size: number) -> (old_size: number) * +\***************************************************************************/ +static int wdlua5_marksize(lua_State *L) +{ + lua_pushnumber(L, wdMarkSize(luaL_checknumber(L, 1))); + return 1; +} + + + +/***************************************************************************\ +* Lines * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Line(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int cdlua5_line(lua_State *L) +{ + int x1 = luaL_checkint(L,1); + int y1 = luaL_checkint(L,2); + int x2 = luaL_checkint(L,3); + int y2 = luaL_checkint(L,4); + cdLine(x1, y1, x2, y2); + return 0; +} + +/***************************************************************************\ +* cd.wLine(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int wdlua5_line(lua_State *L) +{ + double x1 = luaL_checknumber(L, 1); + double y1 = luaL_checknumber(L, 2); + double x2 = luaL_checknumber(L, 3); + double y2 = luaL_checknumber(L, 4); + wdLine(x1, y1, x2, y2); + return 0; +} + +/***************************************************************************\ +* cd.Rect(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int cdlua5_rect(lua_State *L) +{ + int xmin = luaL_checkint(L,1); + int xmax = luaL_checkint(L,2); + int ymin = luaL_checkint(L,3); + int ymax = luaL_checkint(L,4); + cdRect(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.wRect(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_rect(lua_State *L) +{ + double xmin = luaL_checknumber(L, 1); + double xmax = luaL_checknumber(L, 2); + double ymin = luaL_checknumber(L, 3); + double ymax = luaL_checknumber(L, 4); + wdRect(xmin,xmax,ymin,ymax); + return 0; +} + +/***************************************************************************\ +* cd.Arc(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int cdlua5_arc(lua_State *L) +{ + int xc = luaL_checkint(L,1); + int yc = luaL_checkint(L,2); + int w = luaL_checkint(L,3); + int h = luaL_checkint(L,4); + double angle1 = luaL_checknumber(L,5); + double angle2 = luaL_checknumber(L,6); + cdArc(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.wArc(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int wdlua5_arc(lua_State *L) +{ + double xc = luaL_checknumber(L, 1); + double yc = luaL_checknumber(L, 2); + double w = luaL_checknumber(L, 3); + double h = luaL_checknumber(L, 4); + double angle1 = luaL_checknumber(L, 5); + double angle2 = luaL_checknumber(L, 6); + wdArc(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.LineStyle(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linestyle(lua_State *L) +{ + lua_pushnumber(L, cdLineStyle(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.LineStyleDashes(dashes: table, count: number) * +\***************************************************************************/ +static int cdlua5_linestyledashes(lua_State *L) +{ + int *dashes_int, dashes_count, i; + + if (!lua_istable(L, 1)) + luaL_argerror(L, 1, "invalid dashes, must be a table"); + + dashes_count = luaL_checkint(L, 2); + dashes_int = (int*) malloc(dashes_count * sizeof(int)); + + for (i=0; i < dashes_count; i++) + { + lua_pushnumber(L, i+1); + lua_gettable(L,1); + + dashes_int[i] = luaL_checkint(L,-1); + } + + cdLineStyleDashes(dashes_int, dashes_count); + free(dashes_int); + + return 0; +} + +/***************************************************************************\ +* cd.LineWidth(width: number) -> (old_width: number) * +\***************************************************************************/ +static int cdlua5_linewidth(lua_State *L) +{ + lua_pushnumber(L, cdLineWidth(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.wLineWidth(width: number) -> (old_width: number) * +\***************************************************************************/ +static int wdlua5_linewidth(lua_State *L) +{ + lua_pushnumber(L, wdLineWidth(luaL_checknumber(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.LineJoin(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linejoin(lua_State *L) +{ + lua_pushnumber(L, cdLineJoin(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.LineCap(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linecap(lua_State *L) +{ + lua_pushnumber(L, cdLineCap(luaL_checkint(L, 1))); + return 1; +} + + + +/***************************************************************************\ +* Filled Areas * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Box(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int cdlua5_box(lua_State *L) +{ + int xmin = luaL_checkint(L, 1); + int xmax = luaL_checkint(L, 2); + int ymin = luaL_checkint(L, 3); + int ymax = luaL_checkint(L, 4); + cdBox(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.wBox(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_box(lua_State *L) +{ + double xmin = luaL_checknumber(L, 1); + double xmax = luaL_checknumber(L, 2); + double ymin = luaL_checknumber(L, 3); + double ymax = luaL_checknumber(L, 4); + wdBox(xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.Sector(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int cdlua5_sector(lua_State *L) +{ + int xc = luaL_checkint(L,1); + int yc = luaL_checkint(L,2); + int w = luaL_checkint(L,3); + int h = luaL_checkint(L,4); + double angle1 = luaL_checknumber(L,5); + double angle2 = luaL_checknumber(L,6); + cdSector(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.wSector(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int wdlua5_sector(lua_State *L) +{ + double xc = luaL_checknumber(L, 1); + double yc = luaL_checknumber(L, 2); + double w = luaL_checknumber(L, 3); + double h = luaL_checknumber(L, 4); + double angle1 = luaL_checknumber(L, 5); + double angle2 = luaL_checknumber(L, 6); + wdSector(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.Chord(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int cdlua5_chord(lua_State *L) +{ + int xc = luaL_checkint(L,1); + int yc = luaL_checkint(L,2); + int w = luaL_checkint(L,3); + int h = luaL_checkint(L,4); + double angle1 = luaL_checknumber(L,5); + double angle2 = luaL_checknumber(L,6); + cdChord(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.wChord(xc, yc, w, h, angle1, angle2: number) * +\***************************************************************************/ +static int wdlua5_chord(lua_State *L) +{ + double xc = luaL_checknumber(L, 1); + double yc = luaL_checknumber(L, 2); + double w = luaL_checknumber(L, 3); + double h = luaL_checknumber(L, 4); + double angle1 = luaL_checknumber(L, 5); + double angle2 = luaL_checknumber(L, 6); + wdChord(xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.BackOpacity(opacity: number) -> (old_opacity: number) * +\***************************************************************************/ +static int cdlua5_backopacity(lua_State *L) +{ + lua_pushnumber(L, cdBackOpacity(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.FillMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_fillmode(lua_State *L) +{ + lua_pushnumber(L, cdFillMode(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.InteriorStyle(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_interiorstyle(lua_State *L) +{ + lua_pushnumber(L, cdInteriorStyle(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.Hatch(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_hatch(lua_State *L) +{ + lua_pushnumber(L, cdHatch(luaL_checkint(L, 1))); + return 1; +} + +static int cdlua5_stipple(lua_State *L) +{ + cdluaStipple *stipple_p = cdlua_checkstipple(L, 1); + cdStipple(stipple_p->width, stipple_p->height, stipple_p->stipple); + return 0 ; +} + +static int wdlua5_stipple(lua_State *L) +{ + cdluaStipple *stipple_p = cdlua_checkstipple(L, 1); + double w_mm = luaL_checknumber(L, 2); + double h_mm = luaL_checknumber(L, 3); + wdStipple(stipple_p->width, stipple_p->height, stipple_p->stipple, w_mm, h_mm); + return 0; +} + +static int cdlua5_getstipple(lua_State *L) +{ + int width, height, size; + unsigned char *stipple, *new_stipple = NULL; + + stipple = cdGetStipple(&width, &height); + + size = width * height; + + if (stipple) + new_stipple = (unsigned char *)malloc(size); + + if (new_stipple) + { + memcpy(new_stipple, stipple, size); + cdlua_pushstipple(L, new_stipple, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_pattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + cdPattern(pattern_p->width, pattern_p->height, pattern_p->pattern); + return 0; +} + +static int wdlua5_pattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 1); + double w_mm = luaL_checknumber(L, 2); + double h_mm = luaL_checknumber(L, 3); + wdPattern(pattern_p->width, pattern_p->height, pattern_p->pattern, w_mm, h_mm); + return 0; +} + +static int cdlua5_getpattern(lua_State *L) +{ + int width, height, size; + long int *pattern, *new_pattern = NULL; + + pattern = cdGetPattern(&width, &height); + + size = width * height; + + if (pattern) + new_pattern = (long int *) malloc(size * sizeof(long int)); + + if (new_pattern) + { + memcpy(new_pattern, pattern, size * sizeof(long int)); + cdlua_pushpattern(L, new_pattern, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +/***************************************************************************\ +* Text * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Text(x, y: number, text: string) * +\***************************************************************************/ +static int cdlua5_text(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + cdText(luaL_checkint(L, 1), luaL_checkint(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.wText(x, y: number, text: string) * +\***************************************************************************/ +static int wdlua5_text(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + wdText(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.Font(typeface, style, size: number) * +\***************************************************************************/ +static int cdlua5_font(lua_State *L) +{ + cdFont(luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.wFont(typeface, style, size: number) * +\***************************************************************************/ +static int wdlua5_font(lua_State *L) +{ + wdFont(luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checknumber(L, 3)); + return 0; +} + + +/***************************************************************************\ +* cd.GetFont() -> (typeface, style, size: number) * +\***************************************************************************/ +static int cdlua5_getfont(lua_State *L) +{ + int type_face, style, size; + + cdGetFont(&type_face, &style, &size); + lua_pushnumber(L, type_face); + lua_pushnumber(L, style); + lua_pushnumber(L, size); + return 3; +} + +/***************************************************************************\ +* cd.wGetFont() -> (typeface, style, size: number) * +\***************************************************************************/ +static int wdlua5_getfont(lua_State *L) +{ + int type_face, style; + double size; + + wdGetFont(&type_face, &style, &size); + lua_pushnumber(L, type_face); + lua_pushnumber(L, style); + lua_pushnumber(L, size); + return 3; +} + +/***************************************************************************\ +* cd.NativeFont(font: string) * +\***************************************************************************/ +static int cdlua5_nativefont(lua_State *L) +{ + lua_pushstring(L, cdNativeFont(luaL_checkstring(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.TextAlignment(alignment: number) -> (old_alignment: number) * +\***************************************************************************/ +static int cdlua5_textalignment(lua_State *L) +{ + lua_pushnumber(L, cdTextAlignment(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.TextOrientation(angle: number) -> (old_angle: number) * +\***************************************************************************/ +static int cdlua5_textorientation(lua_State *L) +{ + lua_pushnumber(L, cdTextOrientation(luaL_checknumber(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.FontDim() -> (max_width, max_height, ascent, descent: number) * +\***************************************************************************/ +static int cdlua5_fontdim(lua_State *L) +{ + int max_width; + int height; + int ascent; + int descent; + + cdFontDim(&max_width, &height, &ascent, &descent); + lua_pushnumber(L, max_width); + lua_pushnumber(L, height); + lua_pushnumber(L, ascent); + lua_pushnumber(L, descent); + return 4; +} + +/***************************************************************************\ +* cd.wFontDim() -> (max_width, max_height, ascent, descent: number) * +\***************************************************************************/ +static int wdlua5_fontdim(lua_State *L) +{ + double max_width; + double height; + double ascent; + double descent; + + wdFontDim(&max_width, &height, &ascent, &descent); + lua_pushnumber(L, max_width); + lua_pushnumber(L, height); + lua_pushnumber(L, ascent); + lua_pushnumber(L, descent); + return 4; +} + +/***************************************************************************\ +* cd.TextSize(text: string) -> (width, heigth: number) * +\***************************************************************************/ +static int cdlua5_textsize(lua_State *L) +{ + int width; + int height; + + const char* text_s = luaL_checkstring(L, 1); + + cdTextSize(text_s, &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.wTextSize(text: string) -> (width, heigth: number) * +\***************************************************************************/ +static int wdlua5_textsize(lua_State *L) +{ + double width; + double height; + + const char* text_s = luaL_checkstring(L, 1); + + wdTextSize(text_s, &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/****************************************************************************\ +* cd.TextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\****************************************************************************/ +static int cdlua5_textbox(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + const char* s = luaL_checkstring(L, 3); + + cdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/*****************************************************************************\ +* cd.wTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\*****************************************************************************/ +static int wdlua5_textbox(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + double x = luaL_checknumber(L, 1); + double y = luaL_checknumber(L, 2); + const char* s = luaL_checkstring(L, 3); + + wdTextBox(x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************************************************\ +* cd.TextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) * +\***************************************************************************************************************/ +static int cdlua5_textbounds(lua_State *L) +{ + int rect[8]; + int x = luaL_checkint(L, 1); + int y = luaL_checkint(L, 2); + const char* s = luaL_checkstring(L, 3); + + cdTextBounds(x, y, s, rect); + lua_pushnumber(L, rect[0]); + lua_pushnumber(L, rect[1]); + lua_pushnumber(L, rect[2]); + lua_pushnumber(L, rect[3]); + lua_pushnumber(L, rect[4]); + lua_pushnumber(L, rect[5]); + lua_pushnumber(L, rect[6]); + lua_pushnumber(L, rect[7]); + return 4; +} + +/****************************************************************************************************************\ +* cd.wTextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) * +\****************************************************************************************************************/ +static int wdlua5_textbounds(lua_State *L) +{ + double rect[8]; + double x = luaL_checknumber(L, 1); + double y = luaL_checknumber(L, 2); + const char* s = luaL_checkstring(L, 3); + + wdTextBounds(x, y, s, rect); + lua_pushnumber(L, rect[0]); + lua_pushnumber(L, rect[1]); + lua_pushnumber(L, rect[2]); + lua_pushnumber(L, rect[3]); + lua_pushnumber(L, rect[4]); + lua_pushnumber(L, rect[5]); + lua_pushnumber(L, rect[6]); + lua_pushnumber(L, rect[7]); + return 4; +} + + + +/***************************************************************************\ +* Text * +\***************************************************************************/ + +/***************************************************************************\ +* cd.VectorText(x, y: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L,3); + cdVectorText(luaL_checkint(L, 1), luaL_checkint(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.wVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + wdVectorText(luaL_checknumber(L, 1), luaL_checknumber(L, 2),s); + return 0; +} + +/***************************************************************************\ +* cd.MultiLineVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int cdlua5_multilinevectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + cdMultiLineVectorText(luaL_checkint(L, 1), luaL_checkint(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.wMultiLineVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int wdlua5_multilinevectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + wdMultiLineVectorText(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.VectorTextDirection(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int cdlua5_vectortextdirection(lua_State *L) +{ + int x1 = luaL_checkint(L,1); + int y1 = luaL_checkint(L,2); + int x2 = luaL_checkint(L,3); + int y2 = luaL_checkint(L,4); + cdVectorTextDirection(x1, y1, x2, y2); + return 0; +} + +/***************************************************************************\ +* cd.wVectorTextDirection(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int wdlua5_vectortextdirection(lua_State *L) +{ + double x1 = luaL_checknumber(L, 1); + double y1 = luaL_checknumber(L, 2); + double x2 = luaL_checknumber(L, 3); + double y2 = luaL_checknumber(L, 4); + wdVectorTextDirection(x1, y1, x2, y2); + return 0; +} + + +/***************************************************************************\ +* cd.VectorTextTransform(matrix: table) -> (old_matrix: table) * +\***************************************************************************/ +static int cdlua5_vectortexttransform(lua_State *L) +{ + double matrix[6], *old_matrix; + int i; + + if (!lua_istable(L, 1)) + luaL_argerror(L, 1, "invalid matrix, must be a table"); + + for (i=0; i < 6; i++) + { + lua_rawgeti(L, 1, i+1); + + if (!lua_isnumber(L, -1)) + luaL_argerror(L, 1, "invalid matrix value, must be a number"); + + matrix[i] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + + old_matrix = cdVectorTextTransform(matrix); + lua_newtable(L); + for (i=0; i < 6; i++) + { + lua_pushnumber(L, old_matrix[i]); + lua_rawseti(L, 1, i+1); + } + return 1; +} + +/***************************************************************************\ +* cd.VectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectortextsize(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + cdVectorTextSize(luaL_checkint(L,1), luaL_checkint(L,2), s); + return 0; +} + +/***************************************************************************\ +* cd.wVectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectortextsize(lua_State *L) +{ + const char* s = luaL_checkstring(L, 3); + wdVectorTextSize(luaL_checknumber(L, 1), luaL_checknumber(L, 2), s); + return 0; +} + +/***************************************************************************\ +* cd.VectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectorcharsize(lua_State *L) +{ + lua_pushnumber(L, cdVectorCharSize(luaL_checkint(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.wVectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectorcharsize(lua_State *L) +{ + lua_pushnumber(L, wdVectorCharSize(luaL_checknumber(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.VectorFont(filename: string) -> (font_name: string) * +\***************************************************************************/ +static int cdlua5_vectorfont(lua_State *L) +{ + lua_pushstring(L, cdVectorFont(luaL_checkstring(L, 1))); + return 1; +} + +/***************************************************************************\ +* cd.GetVectorTextSize(text: string) -> (w, h: number) * +\***************************************************************************/ +static int cdlua5_getvectortextsize(lua_State *L) +{ + int width; + int height; + + const char* text_s = luaL_checkstring(L, 1); + + cdGetVectorTextSize(text_s, &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.wGetVectorTextSize(text: string) -> (w, h: number) * +\***************************************************************************/ +static int wdlua5_getvectortextsize(lua_State *L) +{ + double width; + double height; + + const char* text_s = luaL_checkstring(L, 1); + + wdGetVectorTextSize(text_s, &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.GetVectorTextBounds(s: string, px,py: number) -> (rect: table) * +\***************************************************************************/ +static int cdlua5_vectortextbounds(lua_State *L) +{ + const char* s = luaL_checkstring(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int rect[8], i; + + cdGetVectorTextBounds(s, x, y, rect); + lua_newtable(L); + for (i=0; i < 8; i++) + { + lua_pushnumber(L, rect[i]); + lua_rawseti(L, -2, i+1); + } + return 1; +} + +/***************************************************************************\ +* cd.wGetVectorTextBounds(s: string, px,py: number) -> (rect: table) * +\***************************************************************************/ +static int wdlua5_vectortextbounds(lua_State *L) +{ + const char* s = luaL_checkstring(L, 1); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + double rect[8]; + int i; + + wdGetVectorTextBounds(s, x, y, rect); + lua_newtable(L); + for (i=0; i < 8; i++) + { + lua_pushnumber(L, rect[i]); + lua_rawseti(L, -2, i+1); + } + return 1; +} + + + +/***************************************************************************\ +* Client Images. * +\***************************************************************************/ + +static int cdlua5_getimagergb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + + cdGetImageRGB(imagergb_p->red, imagergb_p->green, imagergb_p->blue, + x, y, imagergb_p->width, imagergb_p->height); + return 0; +} + +static int cdlua5_putimagerectrgb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + int xmin = luaL_checkint(L, 6); + int xmax = luaL_checkint(L, 7); + int ymin = luaL_checkint(L, 8); + int ymax = luaL_checkint(L, 9); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + cdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectrgb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 1); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + int xmin = luaL_checkint(L, 6); + int xmax = luaL_checkint(L, 7); + int ymin = luaL_checkint(L, 8); + int ymax = luaL_checkint(L, 9); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + wdPutImageRectRGB(imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putimagerectrgba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + int xmin = luaL_checkint(L, 6); + int xmax = luaL_checkint(L, 7); + int ymin = luaL_checkint(L, 8); + int ymax = luaL_checkint(L, 9); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + cdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectrgba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 1); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + int xmin = luaL_checkint(L, 6); + int xmax = luaL_checkint(L, 7); + int ymin = luaL_checkint(L, 8); + int ymax = luaL_checkint(L, 9); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + wdPutImageRectRGBA(imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putimagerectmap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + cdluaPalette *pal = cdlua_checkpalette(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int w = luaL_checkint(L, 5); + int h = luaL_checkint(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + cdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index, + pal->color, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectmap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 1); + cdluaPalette *pal = cdlua_checkpalette(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double w = luaL_checknumber(L, 5); + double h = luaL_checknumber(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + wdPutImageRectMap(imagemap_p->width, imagemap_p->height, imagemap_p->index, + pal->color, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int w = luaL_checkint(L, 4); + int h = luaL_checkint(L, 5); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + cdPutBitmap(bitmap, x, y, w, h); + return 0; +} + +static int wdlua5_putbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 1); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + + if (w < 0 || h < 0) + luaL_argerror(L, 4, "target region dimensions should be positive integers"); + + wdPutBitmap(bitmap, x, y, w, h); + return 0; +} + +static int cdlua5_getbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + cdGetBitmap(bitmap, x, y); + return 0; +} + +/***************************************************************************\ +* Server Images. * +\***************************************************************************/ + +static int cdlua5_createimage(lua_State *L) +{ + cdImage *image; + int width = luaL_checkint(L, 1); + int height = luaL_checkint(L, 2); + + if (width < 1 || height < 1) + luaL_argerror(L, 1, "image dimensions should be positive integers"); + + image = cdCreateImage(width, height); + if (image) + cdlua_pushimage(L, image); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_getimage(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + cdGetImage(image, x, y); + return 0; +} + +static int cdlua5_putimagerect(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 1); + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + int xmin = luaL_checkint(L, 4); + int xmax = luaL_checkint(L, 5); + int ymin = luaL_checkint(L, 6); + int ymax = luaL_checkint(L, 7); + cdPutImageRect(image, x, y, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerect(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 1); + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + int xmin = luaL_checkint(L, 4); + int xmax = luaL_checkint(L, 5); + int ymin = luaL_checkint(L, 6); + int ymax = luaL_checkint(L, 7); + wdPutImageRect(image, x, y, xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.ScrollArea(xmin, xmax, ymin, ymax, dx, dy: number) * +\***************************************************************************/ +static int cdlua5_scrollarea(lua_State *L) +{ + int xmin = luaL_checkint(L, 1); + int xmax = luaL_checkint(L, 2); + int ymin = luaL_checkint(L, 3); + int ymax = luaL_checkint(L, 4); + int dx = luaL_checkint(L, 5); + int dy = luaL_checkint(L, 6); + cdScrollArea(xmin, xmax, ymin, ymax, dx, dy); + return 0; +} + + + +/***************************************************************************\ +* Other * +\***************************************************************************/ + +/********************************************************************************\ +* cd.Play(ctx, xmin, xmax, ymin, ymax: number, data: string) -> (status: number) * +\********************************************************************************/ + +static int cdlua5_play(lua_State *L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1); + int xmin = luaL_checkint(L,2); + int xmax = luaL_checkint(L,3); + int ymin = luaL_checkint(L,4); + int ymax = luaL_checkint(L,5); + const char *data_s = luaL_checkstring(L,6); + + cdlua_setplaystate(L); + cdPlay(cdlua_ctx->ctx(), xmin, xmax, ymin, ymax, (void*)data_s); + cdlua_setplaystate(NULL); + return 0; +} + +/***************************************************************************\ +* cd.GetColorPlanes() -> (bpp: number) * +\***************************************************************************/ +static int cdlua5_getcolorplanes(lua_State *L) +{ + lua_pushnumber(L, cdGetColorPlanes()); + return 1; +} + +static int cdlua5_palette(lua_State *L) +{ + cdluaPalette *pal = cdlua_checkpalette(L, 1); + int mode_i = luaL_checkint(L, 2); + cdPalette(pal->count, pal->color, mode_i); + return 0; +} + +/***************************************************************************\ +* cd.ImageRGB * +\***************************************************************************/ +static int cdlua5_imagergb(lua_State *L) +{ + cdCanvas *current_canvas; + int w, h, type = CD_RGB; + + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + + if (cdCanvasGetContext(canvas) != CD_IMAGERGB) + luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB"); + + if (cdAlphaImage(canvas)) + type = CD_RGBA; + + current_canvas = cdActiveCanvas(); + cdActivate(canvas); + cdGetCanvasSize(&w, &h, NULL, NULL); + cdActivate(current_canvas); + + /* mark the image NOT to be freed */ + if (type == CD_RGBA) + cdlua_pushimagergba_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), cdAlphaImage(canvas), w, h); + else + cdlua_pushimagergb_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), w, h); + + return 1; +} + +/***************************************************************************\ +* cd.ImageRGBBitmap * +\***************************************************************************/ +static int cdlua5_imagergbbitmap(lua_State *L) +{ + cdCanvas *current_canvas; + int w, h, type = CD_RGB; + + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + + if (cdCanvasGetContext(canvas) != CD_IMAGERGB) + luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB"); + + if (cdAlphaImage(canvas)) + type = CD_RGBA; + + current_canvas = cdActiveCanvas(); + cdActivate(canvas); + cdGetCanvasSize(&w, &h, NULL, NULL); + cdActivate(current_canvas); + + cdlua_pushbitmap(L, cdInitBitmap(w, h, type, + cdRedImage(canvas), + cdGreenImage(canvas), + cdBlueImage(canvas), + cdAlphaImage(canvas))); + + return 1; +} + +/***************************************************************************\ +* Hardcopy * +\***************************************************************************/ +static lua_State* wdlua5_hardcopy_luaState = NULL; + +static void wdlua5_hardcopy_func(void) +{ + lua_State* L = wdlua5_hardcopy_luaState; + lua_pushvalue(L, 4); /* push the function in the stack */ + if(lua_pcall(L, 0, 0, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); +} + +static int wdlua5_hardcopy(lua_State *L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1); + void *data_p = cdlua_ctx->checkdata(L, 2); + cdCanvas* canvas = cdlua_checkcanvas(L, 3); + luaL_argcheck(L, !lua_isfunction(L, 4), 4, "invalid draw function"); + + wdlua5_hardcopy_luaState = L; + wdHardcopy(cdlua_ctx->ctx(), data_p, canvas, wdlua5_hardcopy_func); + + return 0; +} + + +/***************************************************************************\ +* Polygon functions * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Begin(mode: number) * +\***************************************************************************/ +static int cdlua5_begin(lua_State *L) +{ + cdBegin(luaL_checkint(L, 1)); + return 0; +} + +/***************************************************************************\ +* cd.Vertex(x, y: number) * +\***************************************************************************/ +static int cdlua5_vertex(lua_State *L) +{ + cdVertex(luaL_checkint(L, 1), luaL_checkint(L, 2)); + return 0; +} + +/***************************************************************************\ +* cd.wVertex(x, y: number) * +\***************************************************************************/ +static int wdlua5_vertex(lua_State *L) +{ + wdVertex(luaL_checknumber(L, 1), luaL_checknumber(L, 2)); + return 0; +} + +/***************************************************************************\ +* cd.End() * +\***************************************************************************/ +static int cdlua5_end(lua_State *L) +{ + (void)L; + cdEnd(); + return 0; +} + + +/********************************************************************************\ +* CDLua Exported functions * +\********************************************************************************/ +static const struct luaL_reg cdlib_active[] = { + + /* Initialization */ + {"Activate" , cdlua5_activate}, + {"ActiveCanvas" , cdlua5_activecanvas}, + {"Simulate" , cdlua5_simulate}, + + /* Control */ + {"Clear" , cdlua5_clear}, + {"Flush" , cdlua5_flush}, + {"SaveState" , cdlua5_savestate}, + {"RestoreState" , cdlua5_restorestate}, + {"SetAttribute" , cdlua5_setattribute}, + {"GetAttribute" , cdlua5_getattribute}, + + /* Coordinate System */ + {"GetCanvasSize" , cdlua5_getcanvassize}, + {"UpdateYAxis" , cdlua5_updateyaxis}, + {"MM2Pixel" , cdlua5_mm2pixel}, + {"Pixel2MM" , cdlua5_pixel2mm}, + {"Origin" , cdlua5_origin}, + + /* World Coordinates */ + {"wWindow" , wdlua5_window}, + {"wGetWindow" , wdlua5_getwindow}, + {"wViewport" , wdlua5_viewport}, + {"wGetViewport" , wdlua5_getviewport}, + {"wWorld2Canvas" , wdlua5_world2canvas}, + {"wCanvas2World" , wdlua5_canvas2world}, + + {"wHardcopy" , wdlua5_hardcopy}, + + /* General Attributes */ + {"Foreground" , cdlua5_foreground}, + {"Background" , cdlua5_background}, + {"WriteMode" , cdlua5_writemode}, + + /* Clipping */ + {"Clip" , cdlua5_clip}, + {"ClipArea" , cdlua5_cliparea}, + {"wClipArea" , wdlua5_cliparea}, + {"GetClipArea" , cdlua5_getcliparea}, + {"wGetClipArea" , wdlua5_getcliparea}, + {"GetClipPoly" , cdlua5_getclippoly}, + {"wGetClipPoly" , wdlua5_getclippoly}, + + /* Regions */ + {"RegionCombineMode" , cdlua5_regioncombinemode}, + {"PointInRegion" , cdlua5_pointinregion}, + {"wPointInRegion" , wdlua5_pointinregion}, + {"OffsetRegion" , cdlua5_offsetregion}, + {"wOffsetRegion" , wdlua5_offsetregion}, + {"RegionBox" , cdlua5_regionbox}, + {"wRegionBox" , wdlua5_regionbox}, + + /* Marks */ + {"Pixel" , cdlua5_pixel}, + {"wPixel" , wdlua5_pixel}, + {"Mark" , cdlua5_mark}, + {"wMark" , wdlua5_mark}, + {"MarkType" , cdlua5_marktype}, + {"MarkSize" , cdlua5_marksize}, + {"wMarkSize" , wdlua5_marksize}, + + /* Line */ + {"Line" , cdlua5_line}, + {"wLine" , wdlua5_line}, + {"Rect" , cdlua5_rect}, + {"wRect" , wdlua5_rect}, + {"Arc" , cdlua5_arc}, + {"wArc" , wdlua5_arc}, + {"LineStyle" , cdlua5_linestyle}, + {"LineStyleDashes" , cdlua5_linestyledashes}, + {"LineWidth" , cdlua5_linewidth}, + {"wLineWidth" , wdlua5_linewidth}, + {"LineJoin" , cdlua5_linejoin}, + {"LineCap" , cdlua5_linecap}, + + /* Filled Areas */ + {"Box" , cdlua5_box}, + {"wBox" , wdlua5_box}, + {"Sector" , cdlua5_sector}, + {"wSector" , wdlua5_sector}, + {"Chord" , cdlua5_chord}, + {"wChord" , wdlua5_chord}, + {"BackOpacity" , cdlua5_backopacity}, + {"FillMode" , cdlua5_fillmode}, + {"InteriorStyle" , cdlua5_interiorstyle}, + {"Hatch" , cdlua5_hatch}, + + /* Stipple */ + {"Stipple" , cdlua5_stipple}, + {"wStipple" , wdlua5_stipple}, + {"GetStipple" , cdlua5_getstipple}, + + /* Pattern */ + {"Pattern" , cdlua5_pattern}, + {"wPattern" , wdlua5_pattern}, + {"GetPattern" , cdlua5_getpattern}, + + /* Text */ + {"Text" , cdlua5_text}, + {"wText" , wdlua5_text}, + {"Font" , cdlua5_font}, + {"wFont" , wdlua5_font}, + {"GetFont" , cdlua5_getfont}, + {"wGetFont" , wdlua5_getfont}, + {"NativeFont" , cdlua5_nativefont}, + {"TextAlignment" , cdlua5_textalignment}, + {"TextOrientation" , cdlua5_textorientation}, + {"FontDim" , cdlua5_fontdim}, + {"wFontDim" , wdlua5_fontdim}, + {"TextSize" , cdlua5_textsize}, + {"wTextSize" , wdlua5_textsize}, + {"TextBox" , cdlua5_textbox}, + {"wTextBox" , wdlua5_textbox}, + {"TextBounds" , cdlua5_textbounds}, + {"wTextBounds" , wdlua5_textbounds}, + + /* Vector Text */ + {"VectorText" , cdlua5_vectortext}, + {"wVectorText" , wdlua5_vectortext}, + {"MultiLineVectorText" , cdlua5_multilinevectortext}, + {"wMultiLineVectorText" , wdlua5_multilinevectortext}, + {"VectorTextDirection" , cdlua5_vectortextdirection}, + {"wVectorTextDirection" , wdlua5_vectortextdirection}, + {"VectorTextTransform" , cdlua5_vectortexttransform}, + {"VectorTextSize" , cdlua5_vectortextsize}, + {"wVectorTextSize" , wdlua5_vectortextsize}, + {"VectorCharSize" , cdlua5_vectorcharsize}, + {"wVectorCharSize" , wdlua5_vectorcharsize}, + {"VectorFont" , cdlua5_vectorfont}, + {"GetVectorTextSize" , cdlua5_getvectortextsize}, + {"wGetVectorTextSize" , wdlua5_getvectortextsize}, + {"VectorTextBounds" , cdlua5_vectortextbounds}, + {"wVectorTextBounds" , wdlua5_vectortextbounds}, + + /* Client Images */ + {"GetImageRGB" , cdlua5_getimagergb}, + {"PutImageRectRGB" , cdlua5_putimagerectrgb}, + {"wPutImageRectRGB" , wdlua5_putimagerectrgb}, + {"PutImageRectRGBA" , cdlua5_putimagerectrgba}, + {"wPutImageRectRGBA", wdlua5_putimagerectrgba}, + {"PutImageRectMap" , cdlua5_putimagerectmap}, + {"wPutImageRectMap" , wdlua5_putimagerectmap}, + {"GetBitmap" , cdlua5_getbitmap}, + {"PutBitmap" , cdlua5_putbitmap}, + {"wPutBitmap" , wdlua5_putbitmap}, + + {"ImageRGB" , cdlua5_imagergb}, + {"ImageRGBBitmap" , cdlua5_imagergbbitmap}, + + /* Server Images */ + {"CreateImage" , cdlua5_createimage}, + {"GetImage" , cdlua5_getimage}, + {"PutImageRect" , cdlua5_putimagerect}, + {"wPutImageRect" , wdlua5_putimagerect}, + {"ScrollArea" , cdlua5_scrollarea}, + + /* Other */ + {"Play" , cdlua5_play}, + + /* Color Coding */ + {"GetColorPlanes" , cdlua5_getcolorplanes}, + + /* Palette */ + {"Palette" , cdlua5_palette}, + + /* Polygon */ + {"Begin" , cdlua5_begin}, + {"Vertex" , cdlua5_vertex}, + {"wVertex" , wdlua5_vertex}, + {"End" , cdlua5_end}, + + {NULL, NULL}, +}; + +typedef struct cdlua5_constant { + const char *name; + lua_Number value; +} cdlua5_constant; + +/* old backward compatible constants */ +static const struct cdlua5_constant cdlibconstant[] = { + {"SYSTEM", CD_SYSTEM}, + {"COURIER", CD_COURIER}, + {"TIMES_ROMAN", CD_TIMES_ROMAN}, + {"HELVETICA", CD_HELVETICA}, + {"NATIVE", CD_NATIVE}, + {"CLIPON", CD_CLIPON}, + {"CENTER_BASE", CD_CENTER_BASE}, + {"LEFT_BASE", CD_LEFT_BASE}, + {"RIGHT_BASE", CD_RIGHT_BASE}, + {"ITALIC_BOLD", CD_ITALIC_BOLD}, + + {NULL, -1} +}; + +static void initconst(lua_State *L) +{ + const cdlua5_constant *l = cdlibconstant; + for (; l->name; l++) { + lua_pushstring(L, l->name); + lua_pushnumber(L, l->value); + lua_settable(L, -3); + } +} + +void cdlua_open_active (lua_State *L, cdluaLuaState* cdL) +{ + /* "cd" table is at the top of the stack */ + luaL_register(L, NULL, cdlib_active); + initconst(L); + + cdL->void_canvas = cdCreateCanvas(CD_VOID, NULL); + cdlua_setvoidstate(cdL->void_canvas, L); + cdActivate(cdL->void_canvas); +} diff --git a/cd/src/lua5/cdlua5_canvas.c b/cd/src/lua5/cdlua5_canvas.c new file mode 100755 index 0000000..d04f76f --- /dev/null +++ b/cd/src/lua5/cdlua5_canvas.c @@ -0,0 +1,2405 @@ +/** \file + * \brief Lua Binding of the Canvas dependent API + * + * See Copyright Notice in cd.h + */ + + +#include +#include +#include + +#include "cd.h" +#include "wd.h" +#include "cdirgb.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua5_private.h" + +#define _cdCheckCanvas(_canvas) (_canvas!=NULL && ((unsigned char*)_canvas)[0] == 'C' && ((unsigned char*)_canvas)[1] == 'D') + + +void cdlua_pushcanvas(lua_State * L, cdCanvas* canvas) +{ + cdCanvas* *canvas_p = (cdCanvas* *) lua_newuserdata(L, sizeof(cdCanvas*)); + *canvas_p = canvas; + luaL_getmetatable(L, "cdCanvas"); + lua_setmetatable(L, -2); +} + +cdCanvas* cdlua_checkcanvas(lua_State * L, int pos) +{ + cdCanvas* *canvas_p = (cdCanvas**)luaL_checkudata(L, pos, "cdCanvas"); + if (!(*canvas_p)) + luaL_argerror(L, pos, "killed cdCanvas"); + if (!_cdCheckCanvas(*canvas_p)) + luaL_argerror(L, pos, "invalid Lua object, killed cdCanvas in C but not in Lua"); + return *canvas_p; +} + +cdCanvas* cdlua_getcanvas(lua_State * L) +{ + return cdlua_checkcanvas(L, 1); +} + +static int cdlua5_createcanvas(lua_State * L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 1); + void *data_p = cdlua_ctx->checkdata(L, 2); + + cdCanvas* canvas = cdCreateCanvas(cdlua_ctx->ctx(), data_p); + + /* if creation failed, return nil so that the user can compare */ + /* the result with nil and know that it failed */ + if (canvas) + cdlua_pushcanvas(L, canvas); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_killcanvas(lua_State *L) +{ + cdCanvas* *canvas_p = (cdCanvas**) luaL_checkudata(L, 1, "cdCanvas"); + if (!(*canvas_p)) + luaL_argerror(L, 1, "killed cdCanvas"); + if (!_cdCheckCanvas(*canvas_p)) + luaL_argerror(L, 1, "invalid Lua object, killed cdCanvas in C but not in Lua"); + + cdlua_kill_active(L, *canvas_p); + + cdKillCanvas(*canvas_p); + *canvas_p = NULL; /* mark as killed */ + + return 0; +} + +static int cdluaCanvas_eq (lua_State *L) +{ + cdCanvas* canvas1 = cdlua_checkcanvas(L, 1); + cdCanvas* canvas2 = cdlua_checkcanvas(L, 2); + lua_pushboolean(L, canvas1 == canvas2); + return 1; +} + +static int cdluaCanvas_tostring (lua_State *L) +{ + cdCanvas* *canvas_p = (cdCanvas**) luaL_checkudata(L, 1, "cdCanvas"); + if (!(*canvas_p)) + lua_pushfstring(L, "cdCanvas(%p - NULL)-killed", canvas_p); + else if (!_cdCheckCanvas(*canvas_p)) + lua_pushfstring(L, "cdCanvas(%p - INVALID)-killed in C but not in Lua", canvas_p); + else + lua_pushfstring(L, "cdCanvas(%p - %p)", canvas_p, *canvas_p); + return 1; +} + +static int cdlua5_getcontext(lua_State * L) +{ + cdluaLuaState* cdL; + cdContext* ctx; + int i; + int driver = -1; + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + + ctx = cdCanvasGetContext(canvas); + cdL = cdlua_getstate(L); + + for (i=0; i < cdL->numdrivers; i++) + { + if (ctx == cdL->drivers[i]->ctx()) + { + driver = i; + break; + } + } + + if (i == cdL->numdrivers) + luaL_argerror(L, 1, "unknown driver"); + + lua_pushnumber(L, driver); + return 1; +} + +/***************************************************************************\ +* Activates a cd canvas. * +\***************************************************************************/ +static int cdlua5_activate(lua_State * L) +{ + lua_pushnumber(L, cdCanvasActivate(cdlua_checkcanvas(L, 1))); + return 1; +} + +static int cdlua5_deactivate(lua_State * L) +{ + cdCanvasDeactivate(cdlua_checkcanvas(L, 1)); + return 0; +} + +/***************************************************************************\ +* cd.Simulate(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_simulate(lua_State *L) +{ + lua_pushnumber(L, cdCanvasSimulate(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* Control * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Clear() * +\***************************************************************************/ +static int cdlua5_clear(lua_State *L) +{ + cdCanvasClear(cdlua_checkcanvas(L, 1)); + return 0; +} + +/***************************************************************************\ +* cd.Flush() * +\***************************************************************************/ +static int cdlua5_flush(lua_State *L) +{ + cdCanvasFlush(cdlua_checkcanvas(L, 1)); + return 0; +} + +static int cdlua5_savestate(lua_State *L) +{ + cdState* state = cdCanvasSaveState(cdlua_checkcanvas(L, 1)); + if (state) + cdlua_pushstate(L, state); + else + lua_pushnil(L); + return 1; +} + +static int cdlua5_restorestate(lua_State * L) +{ + cdCanvasRestoreState(cdlua_checkcanvas(L, 1), cdlua_checkstate(L, 2)); + return 0; +} + +static int cdlua_isuserdata(const char* name) +{ + if (strcmp(name, "HDC")==0) return 1; + if (strcmp(name, "GC")==0) return 1; + return 0; +} + +/***************************************************************************\ +* cd.SetAttribute(name, data: string) * +\***************************************************************************/ +static int cdlua5_setattribute(lua_State *L) +{ + const char* name = luaL_checkstring(L, 2); + + if (lua_isnil(L, 2)) + { + cdCanvasSetAttribute(cdlua_checkcanvas(L, 1), name, NULL); + } + else + { + char* data; + if (cdlua_isuserdata(name)) + data = (char*) lua_touserdata(L, 3); + else + data = (char*) luaL_checkstring(L, 3); + cdCanvasSetAttribute(cdlua_checkcanvas(L, 1), name, data); + } + return 0; +} + + +/***************************************************************************\ +* cd.SetAttribute(name: string) -> (data: string) * +\***************************************************************************/ +static int cdlua5_getattribute(lua_State *L) +{ + const char* name = luaL_checkstring(L, 2); + char* data = cdCanvasGetAttribute(cdlua_checkcanvas(L, 1), name); + if (data) + { + if (cdlua_isuserdata(name)) + lua_pushlightuserdata(L, data); + else + lua_pushstring(L, data); + } + else + lua_pushnil(L); + return 1; +} + + + +/***************************************************************************\ +* Coordinate System * +\***************************************************************************/ + +/***************************************************************************\ +* cd.GetCanvasSize() -> (width, heigth, mm_width, mm_height: number) * +\***************************************************************************/ +static int cdlua5_getcanvassize(lua_State *L) +{ + int width; + int height; + double mm_width; + double mm_height; + + cdCanvasGetSize(cdlua_checkcanvas(L, 1), &width, &height, &mm_width, &mm_height); + + lua_pushnumber(L, width); + lua_pushnumber(L, height); + lua_pushnumber(L, mm_width); + lua_pushnumber(L, mm_height); + return 4; +} + +/***************************************************************************\ +* cd.UpdateYAxis(yc: number) -> (yr: number) * +\***************************************************************************/ +static int cdlua5_updateyaxis(lua_State *L) +{ + double y = luaL_checknumber(L, 2); + cdfCanvasUpdateYAxis(cdlua_checkcanvas(L, 1), &y); + lua_pushnumber(L, y); + return 1; +} + +static int cdlua5_invertyaxis(lua_State *L) +{ + lua_pushnumber(L, cdfCanvasInvertYAxis(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int cdlua5_mm2pixel(lua_State *L) +{ + double mm_dx, mm_dy; + int dx, dy; + + mm_dx = luaL_checknumber(L,2); + mm_dy = luaL_checknumber(L,3); + + cdCanvasMM2Pixel(cdlua_checkcanvas(L, 1), mm_dx, mm_dy, &dx, &dy); + lua_pushnumber(L, dx); + lua_pushnumber(L, dy); + return 2; +} + +static int cdlua5_pixel2mm(lua_State *L) +{ + double mm_dx_d, mm_dy_d; + int dx, dy; + + dx = luaL_checkint(L,2); + dy = luaL_checkint(L,3); + + cdCanvasPixel2MM(cdlua_checkcanvas(L, 1), dx, dy, &mm_dx_d, &mm_dy_d); + lua_pushnumber(L, mm_dx_d); + lua_pushnumber(L, mm_dy_d); + return 2; +} + +static int cdlua5_fmm2pixel(lua_State *L) +{ + double mm_dx, mm_dy; + double dx, dy; + + mm_dx = luaL_checknumber(L,2); + mm_dy = luaL_checknumber(L,3); + + cdfCanvasMM2Pixel(cdlua_checkcanvas(L, 1), mm_dx, mm_dy, &dx, &dy); + lua_pushnumber(L, dx); + lua_pushnumber(L, dy); + return 2; +} + +static int cdlua5_fpixel2mm(lua_State *L) +{ + double mm_dx_d, mm_dy_d; + double dx, dy; + + dx = luaL_checknumber(L,2); + dy = luaL_checknumber(L,3); + + cdfCanvasPixel2MM(cdlua_checkcanvas(L, 1), dx, dy, &mm_dx_d, &mm_dy_d); + lua_pushnumber(L, mm_dx_d); + lua_pushnumber(L, mm_dy_d); + return 2; +} + +static int cdlua5_origin(lua_State *L) +{ + cdCanvasOrigin(cdlua_checkcanvas(L, 1), luaL_checkint(L,2), luaL_checkint(L,3)); + return 0; +} + +static int cdlua5_getorigin(lua_State *L) +{ + int x, y; + cdCanvasGetOrigin(cdlua_checkcanvas(L, 1), &x, &y); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + return 2; +} + +static int cdlua5_forigin(lua_State *L) +{ + cdfCanvasOrigin(cdlua_checkcanvas(L, 1), luaL_checknumber(L,2), luaL_checknumber(L,3)); + return 0; +} + +static int cdlua5_fgetorigin(lua_State *L) +{ + double x, y; + cdfCanvasGetOrigin(cdlua_checkcanvas(L, 1), &x, &y); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + return 2; +} + +static int cdlua5_transform(lua_State *L) +{ + double matrix[6]; + int i; + + if (!lua_istable(L, 2)) + luaL_argerror(L, 2, "invalid matrix, must be a table"); + + for (i=0; i < 6; i++) + { + lua_rawgeti(L, 2, i+1); + + if (!lua_isnumber(L, -1)) + luaL_argerror(L, 2, "invalid matrix value, must be a number"); + + matrix[i] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + + cdCanvasTransform(cdlua_checkcanvas(L, 1), matrix); + return 0; +} + +static int cdlua5_gettransform(lua_State *L) +{ + int i; + double* matrix = cdCanvasGetTransform(cdlua_checkcanvas(L, 1)); + lua_newtable(L); + for (i=0; i < 6; i++) + { + lua_pushnumber(L, matrix[i]); + lua_rawseti(L, 1, i+1); + } + return 1; +} + +static int cdlua5_transformmultiply(lua_State *L) +{ + double matrix[6]; + int i; + + if (!lua_istable(L, 2)) + luaL_argerror(L, 2, "invalid matrix, must be a table"); + + for (i=0; i < 6; i++) + { + lua_rawgeti(L, 2, i+1); + + if (!lua_isnumber(L, -1)) + luaL_argerror(L, 1, "invalid matrix value, must be a number"); + + matrix[i] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + + cdCanvasTransformMultiply(cdlua_checkcanvas(L, 1), matrix); + return 0; +} + +static int cdlua5_transformrotate(lua_State *L) +{ + cdCanvasTransformRotate(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2)); + return 0; +} + +static int cdlua5_transformscale(lua_State *L) +{ + cdCanvasTransformScale(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +static int cdlua5_transformtranslate(lua_State *L) +{ + cdCanvasTransformTranslate(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +static int cdlua5_transformpoint(lua_State *L) +{ + int x, y; + cdCanvasTransformPoint(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), &x, &y); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + return 2; +} + +static int cdlua5_ftransformpoint(lua_State *L) +{ + double x, y; + cdfCanvasTransformPoint(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), &x, &y); + lua_pushnumber(L, x); + lua_pushnumber(L, y); + return 2; +} + +/***************************************************************************\ +* World Coordinates * +\***************************************************************************/ + +/***************************************************************************\ +* wd.Window(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_window(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + wdCanvasWindow(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* wd.GetWindow() -> (xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_getwindow(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + + wdCanvasGetWindow(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* wd.Viewport(xmin, xmax, ymin, ymax: number) * +\***************************************************************************/ +static int wdlua5_viewport(lua_State *L) +{ + int xmin = luaL_checkint(L, 2); + int xmax = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + int ymax = luaL_checkint(L, 5); + wdCanvasViewport(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* wd.GetViewport() -> (xmin, xmax, ymin, ymax: number * +\***************************************************************************/ +static int wdlua5_getviewport(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + + wdCanvasGetViewport(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* wd.World2Canvas(xw, yw: number) -> (xv, yv: number) * +\***************************************************************************/ +static int wdlua5_world2canvas(lua_State *L) +{ + double xw_d, yw_d; + int xv_i, yv_i; + + xw_d = luaL_checknumber(L, 2); + yw_d = luaL_checknumber(L, 3); + + wdCanvasWorld2Canvas(cdlua_checkcanvas(L, 1), xw_d, yw_d, &xv_i, &yv_i); + lua_pushnumber(L, xv_i); + lua_pushnumber(L, yv_i); + return 2; +} + +/***************************************************************************\ +* wd.Canvas2World(xv, yv: number) -> (xw, yw: number) * +\***************************************************************************/ +static int wdlua5_canvas2world(lua_State *L) +{ + int xv_i, yv_i; + double xw_d, yw_d; + + xv_i = luaL_checkint(L, 2); + yv_i = luaL_checkint(L, 3); + + wdCanvasCanvas2World(cdlua_checkcanvas(L, 1), xv_i, yv_i, &xw_d, &yw_d); + lua_pushnumber(L, xw_d); + lua_pushnumber(L, yw_d); + return 2; +} + + + +/***************************************************************************\ +* General Attributes * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Foreground(color) -> color * +\***************************************************************************/ +static int cdlua5_foreground(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 2); + color_i = cdCanvasForeground(cdlua_checkcanvas(L, 1), color_i); + lua_pushlightuserdata(L, (void*) color_i); + return 1; +} + +static int cdlua5_setforeground(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 2); + cdCanvasSetForeground(cdlua_checkcanvas(L, 1), color_i); + return 0; +} + +/***************************************************************************\ +* cd.Background(color) -> color * +\***************************************************************************/ +static int cdlua5_background(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 2); + color_i = cdCanvasBackground(cdlua_checkcanvas(L, 1), color_i); + lua_pushlightuserdata(L, (void*) color_i); + return 1; +} + +static int cdlua5_setbackground(lua_State *L) +{ + long int color_i = cdlua_checkcolor(L, 2); + cdCanvasSetBackground(cdlua_checkcanvas(L, 1), color_i); + return 0; +} +/***************************************************************************\ +* cd.WriteMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_writemode(lua_State *L) +{ + lua_pushnumber(L, cdCanvasWriteMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +/***************************************************************************\ +* Clipping * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Clip(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_clip(lua_State *L) +{ + lua_pushnumber(L, cdCanvasClip(cdlua_checkcanvas(L, 1), luaL_checkint(L,2))); + return 1; +} + +static int cdlua5_cliparea(lua_State *L) +{ + int xmin = luaL_checkint(L, 2); + int xmax = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + int ymax = luaL_checkint(L, 5); + + cdCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_cliparea(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + + wdCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_fcliparea(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + + cdfCanvasClipArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_getcliparea(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + int status; + + status = cdCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + lua_pushnumber(L, status); + return 5; +} + +static int wdlua5_getcliparea(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + int status; + + status = wdCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + lua_pushnumber(L, status); + return 5; +} + +static int cdlua5_fgetcliparea(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + int status; + + status = cdfCanvasGetClipArea(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + lua_pushnumber(L, status); + return 5; +} + +/***************************************************************************\ +* Regions * +\***************************************************************************/ + +/***************************************************************************\ +* cd.RegionCombineMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_regioncombinemode(lua_State *L) +{ + lua_pushnumber(L, cdCanvasRegionCombineMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.PointInRegion(x, y: number) -> (status: number) * +\***************************************************************************/ +static int cdlua5_pointinregion(lua_State *L) +{ + lua_pushnumber(L, cdCanvasIsPointInRegion(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3))); + return 1; +} + +/***************************************************************************\ +* cd.wPointInRegion(x, y: number) -> (status: number) * +\***************************************************************************/ +static int wdlua5_pointinregion(lua_State *L) +{ + lua_pushnumber(L, wdCanvasIsPointInRegion(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3))); + return 1; +} + +/***************************************************************************\ +* cd.OffsetRegion(dx, dy: number) * +\***************************************************************************/ +static int cdlua5_offsetregion(lua_State *L) +{ + cdCanvasOffsetRegion(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.wOffsetRegion(dx, dy: number) * +\***************************************************************************/ +static int wdlua5_offsetregion(lua_State *L) +{ + wdCanvasOffsetRegion(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.RegionBox() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int cdlua5_regionbox(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + + cdCanvasGetRegionBox(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************\ +* cd.wRegionBox() -> (xmin, xmax, ymin, ymax, status: number) * +\***************************************************************************/ +static int wdlua5_regionbox(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + + wdCanvasGetRegionBox(cdlua_checkcanvas(L, 1), &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + + +/***************************************************************************\ +* Primitives * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Pixel(x, y: number, color) * +\***************************************************************************/ +static int cdlua5_pixel (lua_State *L) +{ + cdCanvasPixel(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), cdlua_checkcolor(L, 4)); + return 0 ; +} + +/***************************************************************************\ +* cd.wPixel(x, y: number, color) * +\***************************************************************************/ +static int wdlua5_pixel (lua_State *L) +{ + wdCanvasPixel(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), cdlua_checkcolor(L, 4)); + return 0; +} + +/***************************************************************************\ +* cd.Mark(x, y: number) * +\***************************************************************************/ +static int cdlua5_mark(lua_State *L) +{ + cdCanvasMark(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.wMark(x, y: number) * +\***************************************************************************/ +static int wdlua5_mark(lua_State *L) +{ + wdCanvasMark(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.MarkType(type: number) -> (old_type: number) * +\***************************************************************************/ +static int cdlua5_marktype(lua_State *L) +{ + lua_pushnumber(L, cdCanvasMarkType(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.MarkSize(size: number) -> (old_size: number) * +\***************************************************************************/ +static int cdlua5_marksize(lua_State *L) +{ + lua_pushnumber(L, cdCanvasMarkSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.wMarkSize(size: number) -> (old_size: number) * +\***************************************************************************/ +static int wdlua5_marksize(lua_State *L) +{ + lua_pushnumber(L, wdCanvasMarkSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2))); + return 1; +} + + + +/***************************************************************************\ +* Lines * +\***************************************************************************/ + +static int cdlua5_line(lua_State *L) +{ + int x1 = luaL_checkint(L,2); + int y1 = luaL_checkint(L,3); + int x2 = luaL_checkint(L,4); + int y2 = luaL_checkint(L,5); + cdCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2); + return 0; +} + +static int wdlua5_line(lua_State *L) +{ + double x1 = luaL_checknumber(L, 2); + double y1 = luaL_checknumber(L, 3); + double x2 = luaL_checknumber(L, 4); + double y2 = luaL_checknumber(L, 5); + wdCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2); + return 0; +} + +static int cdlua5_fline(lua_State *L) +{ + double x1 = luaL_checknumber(L, 2); + double y1 = luaL_checknumber(L, 3); + double x2 = luaL_checknumber(L, 4); + double y2 = luaL_checknumber(L, 5); + cdfCanvasLine(cdlua_checkcanvas(L, 1), x1, y1, x2, y2); + return 0; +} + +static int cdlua5_rect(lua_State *L) +{ + int xmin = luaL_checkint(L,2); + int xmax = luaL_checkint(L,3); + int ymin = luaL_checkint(L,4); + int ymax = luaL_checkint(L,5); + cdCanvasRect(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_rect(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + wdCanvasRect(cdlua_checkcanvas(L, 1), xmin,xmax,ymin,ymax); + return 0; +} + +static int cdlua5_frect(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + cdfCanvasRect(cdlua_checkcanvas(L, 1), xmin,xmax,ymin,ymax); + return 0; +} + +static int cdlua5_arc(lua_State *L) +{ + int xc = luaL_checkint(L,2); + int yc = luaL_checkint(L,3); + int w = luaL_checkint(L,4); + int h = luaL_checkint(L,5); + double angle1 = luaL_checknumber(L,6); + double angle2 = luaL_checknumber(L,7); + cdCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int wdlua5_arc(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + wdCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int cdlua5_farc(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + cdfCanvasArc(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.LineStyle(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linestyle(lua_State *L) +{ + lua_pushnumber(L, cdCanvasLineStyle(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.LineStyleDashes(dashes: table, count: number) * +\***************************************************************************/ +static int cdlua5_linestyledashes(lua_State *L) +{ + int *dashes_int, dashes_count, i; + + if (!lua_istable(L, 2)) + luaL_argerror(L, 2, "invalid dashes, must be a table"); + + dashes_count = luaL_checkint(L, 3); + dashes_int = (int*) malloc(dashes_count * sizeof(int)); + + for (i=0; i < dashes_count; i++) + { + lua_pushnumber(L, i+1); + lua_gettable(L, 2); + + dashes_int[i] = luaL_checkint(L,-1); + } + + cdCanvasLineStyleDashes(cdlua_checkcanvas(L, 1), dashes_int, dashes_count); + free(dashes_int); + + return 0; +} + +/***************************************************************************\ +* cd.LineWidth(width: number) -> (old_width: number) * +\***************************************************************************/ +static int cdlua5_linewidth(lua_State *L) +{ + lua_pushnumber(L, cdCanvasLineWidth(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.wLineWidth(width: number) -> (old_width: number) * +\***************************************************************************/ +static int wdlua5_linewidth(lua_State *L) +{ + lua_pushnumber(L, wdCanvasLineWidth(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.LineJoin(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linejoin(lua_State *L) +{ + lua_pushnumber(L, cdCanvasLineJoin(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.LineCap(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_linecap(lua_State *L) +{ + lua_pushnumber(L, cdCanvasLineCap(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +/***************************************************************************\ +* Filled Areas * +\***************************************************************************/ + +static int cdlua5_box(lua_State *L) +{ + int xmin = luaL_checkint(L, 2); + int xmax = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + int ymax = luaL_checkint(L, 5); + cdCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_box(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + wdCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_fbox(lua_State *L) +{ + double xmin = luaL_checknumber(L, 2); + double xmax = luaL_checknumber(L, 3); + double ymin = luaL_checknumber(L, 4); + double ymax = luaL_checknumber(L, 5); + cdfCanvasBox(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_sector(lua_State *L) +{ + int xc = luaL_checkint(L,2); + int yc = luaL_checkint(L,3); + int w = luaL_checkint(L,4); + int h = luaL_checkint(L,5); + double angle1 = luaL_checknumber(L,6); + double angle2 = luaL_checknumber(L,7); + cdCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int wdlua5_sector(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + wdCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int cdlua5_fsector(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + cdfCanvasSector(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int cdlua5_chord(lua_State *L) +{ + int xc = luaL_checkint(L,2); + int yc = luaL_checkint(L,3); + int w = luaL_checkint(L,4); + int h = luaL_checkint(L,5); + double angle1 = luaL_checknumber(L,6); + double angle2 = luaL_checknumber(L,7); + cdCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int wdlua5_chord(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + wdCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +static int cdlua5_fchord(lua_State *L) +{ + double xc = luaL_checknumber(L, 2); + double yc = luaL_checknumber(L, 3); + double w = luaL_checknumber(L, 4); + double h = luaL_checknumber(L, 5); + double angle1 = luaL_checknumber(L, 6); + double angle2 = luaL_checknumber(L, 7); + cdfCanvasChord(cdlua_checkcanvas(L, 1), xc, yc, w, h, angle1, angle2); + return 0; +} + +/***************************************************************************\ +* cd.BackOpacity(opacity: number) -> (old_opacity: number) * +\***************************************************************************/ +static int cdlua5_backopacity(lua_State *L) +{ + lua_pushnumber(L, cdCanvasBackOpacity(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.FillMode(mode: number) -> (old_mode: number) * +\***************************************************************************/ +static int cdlua5_fillmode(lua_State *L) +{ + lua_pushnumber(L, cdCanvasFillMode(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.InteriorStyle(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_interiorstyle(lua_State *L) +{ + lua_pushnumber(L, cdCanvasInteriorStyle(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.Hatch(style: number) -> (old_style: number) * +\***************************************************************************/ +static int cdlua5_hatch(lua_State *L) +{ + lua_pushnumber(L, cdCanvasHatch(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +static int cdlua5_stipple(lua_State *L) +{ + cdluaStipple *stipple_p = cdlua_checkstipple(L, 2); + cdCanvasStipple(cdlua_checkcanvas(L, 1), stipple_p->width, stipple_p->height, stipple_p->stipple); + return 0 ; +} + +static int wdlua5_stipple(lua_State *L) +{ + cdluaStipple *stipple_p = cdlua_checkstipple(L, 2); + double w_mm = luaL_checknumber(L, 3); + double h_mm = luaL_checknumber(L, 4); + wdCanvasStipple(cdlua_checkcanvas(L, 1), stipple_p->width, stipple_p->height, stipple_p->stipple, w_mm, h_mm); + return 0; +} + +static int cdlua5_getstipple(lua_State *L) +{ + int width, height, size; + unsigned char *stipple, *new_stipple = NULL; + + stipple = cdCanvasGetStipple(cdlua_checkcanvas(L, 1), &width, &height); + + size = width * height; + + if (stipple) + new_stipple = (unsigned char *)malloc(size); + + if (new_stipple) + { + memcpy(new_stipple, stipple, size); + cdlua_pushstipple(L, new_stipple, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_pattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 2); + cdCanvasPattern(cdlua_checkcanvas(L, 1), pattern_p->width, pattern_p->height, pattern_p->pattern); + return 0; +} + +static int wdlua5_pattern(lua_State *L) +{ + cdluaPattern* pattern_p = cdlua_checkpattern(L, 2); + double w_mm = luaL_checknumber(L, 3); + double h_mm = luaL_checknumber(L, 4); + wdCanvasPattern(cdlua_checkcanvas(L, 1), pattern_p->width, pattern_p->height, pattern_p->pattern, w_mm, h_mm); + return 0; +} + +static int cdlua5_getpattern(lua_State *L) +{ + int width, height, size; + long int *pattern, *new_pattern = NULL; + + pattern = cdCanvasGetPattern(cdlua_checkcanvas(L, 1), &width, &height); + + size = width * height; + + if (pattern) + new_pattern = (long int *) malloc(size * sizeof(long int)); + + if (new_pattern) + { + memcpy(new_pattern, pattern, size * sizeof(long int)); + cdlua_pushpattern(L, new_pattern, width, height); + } + else + lua_pushnil(L); + + return 1; +} + +/***************************************************************************\ +* Text * +\***************************************************************************/ + +static int cdlua5_text(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + cdCanvasText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s); + return 0; +} + +static int wdlua5_text(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + wdCanvasText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s); + return 0; +} + +static int cdlua5_ftext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + cdfCanvasText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.Font(typeface, style, size: number) * +\***************************************************************************/ +static int cdlua5_font(lua_State *L) +{ + lua_pushnumber(L, cdCanvasFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), luaL_checkint(L, 3), luaL_checkint(L, 4))); + return 1; +} + +/***************************************************************************\ +* cd.wFont(typeface, style, size: number) * +\***************************************************************************/ +static int wdlua5_font(lua_State *L) +{ + lua_pushnumber(L, wdCanvasFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), luaL_checkint(L, 3), luaL_checknumber(L, 4))); + return 1; +} + + +/***************************************************************************\ +* cd.GetFont() -> (typeface, style, size: number) * +\***************************************************************************/ +static int cdlua5_getfont(lua_State *L) +{ + char type_face[1024]; + int style, size; + + cdCanvasGetFont(cdlua_checkcanvas(L, 1), type_face, &style, &size); + lua_pushstring(L, type_face); + lua_pushnumber(L, style); + lua_pushnumber(L, size); + return 3; +} + +/***************************************************************************\ +* cd.wGetFont() -> (typeface, style, size: number) * +\***************************************************************************/ +static int wdlua5_getfont(lua_State *L) +{ + char type_face[1024]; + int style; + double size; + + wdCanvasGetFont(cdlua_checkcanvas(L, 1), type_face, &style, &size); + lua_pushstring(L, type_face); + lua_pushnumber(L, style); + lua_pushnumber(L, size); + return 3; +} + +/***************************************************************************\ +* cd.NativeFont(font: string) * +\***************************************************************************/ +static int cdlua5_nativefont(lua_State *L) +{ + lua_pushstring(L, cdCanvasNativeFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.TextAlignment(alignment: number) -> (old_alignment: number) * +\***************************************************************************/ +static int cdlua5_textalignment(lua_State *L) +{ + lua_pushnumber(L, cdCanvasTextAlignment(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.TextOrientation(angle: number) -> (old_angle: number) * +\***************************************************************************/ +static int cdlua5_textorientation(lua_State *L) +{ + lua_pushnumber(L, cdCanvasTextOrientation(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.GetFontDim() -> (max_width, max_height, ascent, descent: number) * +\***************************************************************************/ +static int cdlua5_getfontdim(lua_State *L) +{ + int max_width; + int height; + int ascent; + int descent; + + cdCanvasGetFontDim(cdlua_checkcanvas(L, 1), &max_width, &height, &ascent, &descent); + lua_pushnumber(L, max_width); + lua_pushnumber(L, height); + lua_pushnumber(L, ascent); + lua_pushnumber(L, descent); + return 4; +} + +/***************************************************************************\ +* cd.wGetFontDim() -> (max_width, max_height, ascent, descent: number) * +\***************************************************************************/ +static int wdlua5_getfontdim(lua_State *L) +{ + double max_width; + double height; + double ascent; + double descent; + + wdCanvasGetFontDim(cdlua_checkcanvas(L, 1), &max_width, &height, &ascent, &descent); + lua_pushnumber(L, max_width); + lua_pushnumber(L, height); + lua_pushnumber(L, ascent); + lua_pushnumber(L, descent); + return 4; +} + +/***************************************************************************\ +* cd.GetTextSize(text: string) -> (width, heigth: number) * +\***************************************************************************/ +static int cdlua5_gettextsize(lua_State *L) +{ + int width; + int height; + cdCanvasGetTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.wGetTextSize(text: string) -> (width, heigth: number) * +\***************************************************************************/ +static int wdlua5_gettextsize(lua_State *L) +{ + double width; + double height; + wdCanvasGetTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/****************************************************************************\ +* cd.GetTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\****************************************************************************/ +static int cdlua5_gettextbox(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + const char* s = luaL_checkstring(L, 4); + + cdCanvasGetTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/*****************************************************************************\ +* cd.wGetTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\*****************************************************************************/ +static int wdlua5_gettextbox(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + const char* s = luaL_checkstring(L, 4); + + wdCanvasGetTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/***************************************************************************************************************\ +* cd.GetTextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) * +\***************************************************************************************************************/ +static int cdlua5_gettextbounds(lua_State *L) +{ + int rect[8]; + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + const char* s = luaL_checkstring(L, 4); + + cdCanvasGetTextBounds(cdlua_checkcanvas(L, 1), x, y, s, rect); + lua_pushnumber(L, rect[0]); + lua_pushnumber(L, rect[1]); + lua_pushnumber(L, rect[2]); + lua_pushnumber(L, rect[3]); + lua_pushnumber(L, rect[4]); + lua_pushnumber(L, rect[5]); + lua_pushnumber(L, rect[6]); + lua_pushnumber(L, rect[7]); + return 4; +} + +/****************************************************************************************************************\ +* cd.wGetTextBounds(x, y: number, text: string) -> (rect0, rect1, rect2, rect3, rect4, rect5, rect6, rect7: number) * +\****************************************************************************************************************/ +static int wdlua5_gettextbounds(lua_State *L) +{ + double rect[8]; + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + const char* s = luaL_checkstring(L, 4); + + wdCanvasGetTextBounds(cdlua_checkcanvas(L, 1), x, y, s, rect); + lua_pushnumber(L, rect[0]); + lua_pushnumber(L, rect[1]); + lua_pushnumber(L, rect[2]); + lua_pushnumber(L, rect[3]); + lua_pushnumber(L, rect[4]); + lua_pushnumber(L, rect[5]); + lua_pushnumber(L, rect[6]); + lua_pushnumber(L, rect[7]); + return 4; +} + + + +/***************************************************************************\ +* Text * +\***************************************************************************/ + +/***************************************************************************\ +* cd.VectorText(x, y: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L,4); + cdCanvasVectorText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.wVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + wdCanvasVectorText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3),s); + return 0; +} + +/***************************************************************************\ +* cd.MultiLineVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int cdlua5_multilinevectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + cdCanvasMultiLineVectorText(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.wMultiLineVectorText(x, y: number, text: string) * +\***************************************************************************/ +static int wdlua5_multilinevectortext(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + wdCanvasMultiLineVectorText(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.VectorTextDirection(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int cdlua5_vectortextdirection(lua_State *L) +{ + int x1 = luaL_checkint(L,2); + int y1 = luaL_checkint(L,3); + int x2 = luaL_checkint(L,4); + int y2 = luaL_checkint(L,5); + cdCanvasVectorTextDirection(cdlua_checkcanvas(L, 1), x1, y1, x2, y2); + return 0; +} + +/***************************************************************************\ +* cd.wVectorTextDirection(x1, y1, x2, y2: number) * +\***************************************************************************/ +static int wdlua5_vectortextdirection(lua_State *L) +{ + double x1 = luaL_checknumber(L, 2); + double y1 = luaL_checknumber(L, 3); + double x2 = luaL_checknumber(L, 4); + double y2 = luaL_checknumber(L, 5); + wdCanvasVectorTextDirection(cdlua_checkcanvas(L, 1), x1, y1, x2, y2); + return 0; +} + + +/***************************************************************************\ +* cd.VectorTextTransform(matrix: table) -> (old_matrix: table) * +\***************************************************************************/ +static int cdlua5_vectortexttransform(lua_State *L) +{ + double matrix[6], *old_matrix; + int i; + + if (!lua_istable(L, 2)) + luaL_argerror(L, 2, "invalid matrix, must be a table"); + + for (i=0; i < 6; i++) + { + lua_rawgeti(L, 2, i+1); + + if (!lua_isnumber(L, -1)) + luaL_argerror(L, 2, "invalid matrix value, must be a number"); + + matrix[i] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + + old_matrix = cdCanvasVectorTextTransform(cdlua_checkcanvas(L, 1), matrix); + lua_newtable(L); + for (i=0; i < 6; i++) + { + lua_pushnumber(L, old_matrix[i]); + lua_rawseti(L, 1, i+1); + } + return 1; +} + +/***************************************************************************\ +* cd.VectorFontSize(w, h: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectorfontsize(lua_State *L) +{ + cdCanvasVectorFontSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +/***************************************************************************\ +* cd.GetVectorFontSize(text: string) -> (w, h: number) * +\***************************************************************************/ +static int cdlua5_getvectorfontsize(lua_State *L) +{ + double width; + double height; + cdCanvasGetVectorFontSize(cdlua_checkcanvas(L, 1), &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.VectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectortextsize(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + cdCanvasVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.wVectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectortextsize(lua_State *L) +{ + const char* s = luaL_checkstring(L, 4); + wdCanvasVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3), s); + return 0; +} + +/***************************************************************************\ +* cd.VectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int cdlua5_vectorcharsize(lua_State *L) +{ + lua_pushnumber(L, cdCanvasVectorCharSize(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.wVectorTextSize(w, h: number, text: string) * +\***************************************************************************/ +static int wdlua5_vectorcharsize(lua_State *L) +{ + lua_pushnumber(L, wdCanvasVectorCharSize(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.VectorFont(filename: string) -> (font_name: string) * +\***************************************************************************/ +static int cdlua5_vectorfont(lua_State *L) +{ + lua_pushstring(L, cdCanvasVectorFont(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2))); + return 1; +} + +/***************************************************************************\ +* cd.GetVectorTextSize(text: string) -> (w, h: number) * +\***************************************************************************/ +static int cdlua5_getvectortextsize(lua_State *L) +{ + int width; + int height; + cdCanvasGetVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.wGetVectorTextSize(text: string) -> (w, h: number) * +\***************************************************************************/ +static int wdlua5_getvectortextsize(lua_State *L) +{ + double width; + double height; + wdCanvasGetVectorTextSize(cdlua_checkcanvas(L, 1), luaL_checkstring(L, 2), &width, &height); + lua_pushnumber(L, width); + lua_pushnumber(L, height); + return 2; +} + +/***************************************************************************\ +* cd.GetVectorTextBounds(s: string, px,py: number) -> (rect: table) * +\***************************************************************************/ +static int cdlua5_getvectortextbounds(lua_State *L) +{ + const char* s = luaL_checkstring(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int rect[8], i; + + cdCanvasGetVectorTextBounds(cdlua_checkcanvas(L, 1), s, x, y, rect); + lua_newtable(L); + for (i=0; i < 8; i++) + { + lua_pushnumber(L, rect[i]); + lua_rawseti(L, -2, i+1); + } + return 1; +} + +/***************************************************************************\ +* cd.wGetVectorTextBounds(s: string, px,py: number) -> (rect: table) * +\***************************************************************************/ +static int wdlua5_getvectortextbounds(lua_State *L) +{ + const char* s = luaL_checkstring(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double rect[8]; + int i; + + wdCanvasGetVectorTextBounds(cdlua_checkcanvas(L, 1), s, x, y, rect); + lua_newtable(L); + for (i=0; i < 8; i++) + { + lua_pushnumber(L, rect[i]); + lua_rawseti(L, -2, i+1); + } + return 1; +} + +/****************************************************************************\ +* cd.GetVectorTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\****************************************************************************/ +static int cdlua5_getvectortextbox(lua_State *L) +{ + int xmin, xmax, ymin, ymax; + int x = luaL_checkint(L, 2); + int y = luaL_checkint(L, 3); + const char* s = luaL_checkstring(L, 4); + + cdCanvasGetVectorTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + +/*****************************************************************************\ +* cd.wGetVectorTextBox(x, y: number, text: string) -> (xmin, xmax, ymin, ymax: number) * +\*****************************************************************************/ +static int wdlua5_getvectortextbox(lua_State *L) +{ + double xmin, xmax, ymin, ymax; + double x = luaL_checknumber(L, 2); + double y = luaL_checknumber(L, 3); + const char* s = luaL_checkstring(L, 4); + + wdCanvasGetVectorTextBox(cdlua_checkcanvas(L, 1), x, y, s, &xmin, &xmax, &ymin, &ymax); + lua_pushnumber(L, xmin); + lua_pushnumber(L, xmax); + lua_pushnumber(L, ymin); + lua_pushnumber(L, ymax); + return 4; +} + + + +/***************************************************************************\ +* Client Images. * +\***************************************************************************/ + +static int cdlua5_getimagergb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + cdCanvasGetImageRGB(cdlua_checkcanvas(L, 1), imagergb_p->red, imagergb_p->green, imagergb_p->blue, + x, y, imagergb_p->width, imagergb_p->height); + return 0; +} + +static int cdlua5_putimagerectrgb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int w = luaL_checkint(L, 5); + int h = luaL_checkint(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + cdCanvasPutImageRectRGB(cdlua_checkcanvas(L, 1), imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectrgb(lua_State *L) +{ + cdluaImageRGB* imagergb_p = cdlua_checkimagergb(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double w = luaL_checknumber(L, 5); + double h = luaL_checknumber(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + wdCanvasPutImageRectRGB(cdlua_checkcanvas(L, 1), imagergb_p->width, imagergb_p->height, imagergb_p->red, + imagergb_p->green, imagergb_p->blue, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putimagerectrgba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int w = luaL_checkint(L, 5); + int h = luaL_checkint(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + cdCanvasPutImageRectRGBA(cdlua_checkcanvas(L, 1), imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectrgba(lua_State *L) +{ + cdluaImageRGBA* imagergba_p = cdlua_checkimagergba(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double w = luaL_checknumber(L, 5); + double h = luaL_checknumber(L, 6); + int xmin = luaL_checkint(L, 7); + int xmax = luaL_checkint(L, 8); + int ymin = luaL_checkint(L, 9); + int ymax = luaL_checkint(L, 10); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + wdCanvasPutImageRectRGBA(cdlua_checkcanvas(L, 1), imagergba_p->width, imagergba_p->height, imagergba_p->red, + imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putimagerectmap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2); + cdluaPalette *pal = cdlua_checkpalette(L, 3); + int x = luaL_checkint(L, 4); + int y = luaL_checkint(L, 5); + int w = luaL_checkint(L, 6); + int h = luaL_checkint(L, 7); + int xmin = luaL_checkint(L, 8); + int xmax = luaL_checkint(L, 9); + int ymin = luaL_checkint(L, 10); + int ymax = luaL_checkint(L, 11); + + if (w < 0 || h < 0) + luaL_argerror(L, 6, "target region dimensions should be positive integers"); + + cdCanvasPutImageRectMap(cdlua_checkcanvas(L, 1), imagemap_p->width, imagemap_p->height, imagemap_p->index, + pal->color, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerectmap(lua_State *L) +{ + cdluaImageMap* imagemap_p = cdlua_checkimagemap(L, 2); + cdluaPalette *pal = cdlua_checkpalette(L, 3); + double x = luaL_checknumber(L, 4); + double y = luaL_checknumber(L, 5); + double w = luaL_checknumber(L, 6); + double h = luaL_checknumber(L, 7); + int xmin = luaL_checkint(L, 8); + int xmax = luaL_checkint(L, 9); + int ymin = luaL_checkint(L, 10); + int ymax = luaL_checkint(L, 11); + + if (w < 0 || h < 0) + luaL_argerror(L, 6, "target region dimensions should be positive integers"); + + wdCanvasPutImageRectMap(cdlua_checkcanvas(L, 1), imagemap_p->width, imagemap_p->height, imagemap_p->index, + pal->color, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +static int cdlua5_putbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int w = luaL_checkint(L, 5); + int h = luaL_checkint(L, 6); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + cdCanvasPutBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y, w, h); + return 0; +} + +static int wdlua5_putbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double w = luaL_checknumber(L, 5); + double h = luaL_checknumber(L, 6); + + if (w < 0 || h < 0) + luaL_argerror(L, 5, "target region dimensions should be positive integers"); + + wdCanvasPutBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y, w, h); + return 0; +} + +static int cdlua5_getbitmap(lua_State *L) +{ + cdBitmap *bitmap = cdlua_checkbitmap(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + cdCanvasGetBitmap(cdlua_checkcanvas(L, 1), bitmap, x, y); + return 0; +} + +/***************************************************************************\ +* Server Images. * +\***************************************************************************/ + +static int cdlua5_createimage(lua_State *L) +{ + cdImage *image; + int width = luaL_checkint(L, 2); + int height = luaL_checkint(L, 3); + + if (width < 1 || height < 1) + luaL_argerror(L, 2, "image dimensions should be positive integers"); + + image = cdCanvasCreateImage(cdlua_checkcanvas(L, 1), width, height); + if (image) + cdlua_pushimage(L, image); + else + lua_pushnil(L); + + return 1; +} + +static int cdlua5_getimage(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + cdCanvasGetImage(cdlua_checkcanvas(L, 1), image, x, y); + return 0; +} + +static int cdlua5_putimagerect(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int xmin = luaL_checkint(L, 5); + int xmax = luaL_checkint(L, 6); + int ymin = luaL_checkint(L, 7); + int ymax = luaL_checkint(L, 8); + cdCanvasPutImageRect(cdlua_checkcanvas(L, 1), image, x, y, xmin, xmax, ymin, ymax); + return 0; +} + +static int wdlua5_putimagerect(lua_State *L) +{ + cdImage* image = cdlua_checkimage(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + int xmin = luaL_checkint(L, 5); + int xmax = luaL_checkint(L, 6); + int ymin = luaL_checkint(L, 7); + int ymax = luaL_checkint(L, 8); + wdCanvasPutImageRect(cdlua_checkcanvas(L, 1), image, x, y, xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* cd.ScrollArea(xmin, xmax, ymin, ymax, dx, dy: number) * +\***************************************************************************/ +static int cdlua5_scrollarea(lua_State *L) +{ + int xmin = luaL_checkint(L, 2); + int xmax = luaL_checkint(L, 3); + int ymin = luaL_checkint(L, 4); + int ymax = luaL_checkint(L, 5); + int dx = luaL_checkint(L, 6); + int dy = luaL_checkint(L, 7); + cdCanvasScrollArea(cdlua_checkcanvas(L, 1), xmin, xmax, ymin, ymax, dx, dy); + return 0; +} + + + +/***************************************************************************\ +* Other * +\***************************************************************************/ + +/********************************************************************************\ +* cd.Play(ctx, xmin, xmax, ymin, ymax: number, data: string) -> (status: number) * +\********************************************************************************/ + +static int cdlua5_play(lua_State *L) +{ + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 2); + int xmin = luaL_checkint(L,3); + int xmax = luaL_checkint(L,4); + int ymin = luaL_checkint(L,5); + int ymax = luaL_checkint(L,6); + const char *data_s = luaL_checkstring(L,7); + + cdlua_setplaystate(L); + cdCanvasPlay(cdlua_checkcanvas(L, 1), cdlua_ctx->ctx(), xmin, xmax, ymin, ymax, (void*)data_s); + cdlua_setplaystate(NULL); + return 0; +} + +/***************************************************************************\ +* cd.GetColorPlanes() -> (bpp: number) * +\***************************************************************************/ +static int cdlua5_getcolorplanes(lua_State *L) +{ + lua_pushnumber(L, cdCanvasGetColorPlanes(cdlua_checkcanvas(L, 1))); + return 1; +} + +static int cdlua5_palette(lua_State *L) +{ + cdluaPalette *pal = cdlua_checkpalette(L, 2); + int mode_i = luaL_checkint(L, 3); + cdCanvasPalette(cdlua_checkcanvas(L, 1), pal->count, pal->color, mode_i); + return 0; +} + +/***************************************************************************\ +* cd.ImageRGB * +\***************************************************************************/ +static int cdlua5_imagergb(lua_State *L) +{ + int w, h, type = CD_RGB; + + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + + if (cdCanvasGetContext(canvas) != CD_IMAGERGB) + luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB"); + + if (cdAlphaImage(canvas)) + type = CD_RGBA; + + cdCanvasGetSize(canvas, &w, &h, NULL, NULL); + + /* mark the image NOT to be freed */ + if (type == CD_RGBA) + cdlua_pushimagergba_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), cdAlphaImage(canvas), w, h); + else + cdlua_pushimagergb_ex(L, cdRedImage(canvas), cdGreenImage(canvas), cdBlueImage(canvas), w, h); + + return 1; +} + +/***************************************************************************\ +* cd.ImageRGBBitmap * +\***************************************************************************/ +static int cdlua5_imagergbbitmap(lua_State *L) +{ + int w, h, type = CD_RGB; + + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + + if (cdCanvasGetContext(canvas) != CD_IMAGERGB) + luaL_argerror(L, 1, "invalid canvas, must be CD_IMAGERGB"); + + if (cdAlphaImage(canvas)) + type = CD_RGBA; + + cdCanvasGetSize(canvas, &w, &h, NULL, NULL); + + cdlua_pushbitmap(L, cdInitBitmap(w, h, type, + cdRedImage(canvas), + cdGreenImage(canvas), + cdBlueImage(canvas), + cdAlphaImage(canvas))); + + return 1; +} + +/***************************************************************************\ +* Hardcopy * +\***************************************************************************/ +static lua_State* wdlua5_hardcopy_luaState = NULL; + +static void wdlua5_hardcopy_func(cdCanvas* canvas) +{ + lua_State* L = wdlua5_hardcopy_luaState; + lua_pushvalue(L, 4); /* push the function in the stack */ + cdlua_pushcanvas(L, canvas); + if(lua_pcall(L, 1, 0, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); +} + +static int wdlua5_hardcopy(lua_State *L) +{ + cdCanvas* canvas = cdlua_checkcanvas(L, 1); + cdluaContext* cdlua_ctx = cdlua_getcontext(L, 2); + void *data_p = cdlua_ctx->checkdata(L,3); + luaL_argcheck(L, !lua_isfunction(L, 4), 4, "invalid draw function"); + + wdlua5_hardcopy_luaState = L; + wdCanvasHardcopy(canvas, cdlua_ctx->ctx(), data_p, wdlua5_hardcopy_func); + wdlua5_hardcopy_luaState = NULL; + + return 0; +} + + +/***************************************************************************\ +* Polygon functions * +\***************************************************************************/ + +/***************************************************************************\ +* cd.Begin(mode: number) * +\***************************************************************************/ +static int cdlua5_begin(lua_State *L) +{ + cdCanvasBegin(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2)); + return 0; +} + +static int cdlua5_vertex(lua_State *L) +{ + cdCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)); + return 0; +} + +static int wdlua5_vertex(lua_State *L) +{ + wdCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +static int cdlua5_fvertex(lua_State *L) +{ + cdfCanvasVertex(cdlua_checkcanvas(L, 1), luaL_checknumber(L, 2), luaL_checknumber(L, 3)); + return 0; +} + +static int cdlua5_end(lua_State *L) +{ + cdCanvasEnd(cdlua_checkcanvas(L, 1)); + return 0; +} + + +/********************************************************************************\ +* Lua Exported functions * +\********************************************************************************/ + +static const struct luaL_reg cdlib_canvas_meta[] = { + + /* Initialization */ + {"GetContext" , cdlua5_getcontext}, + {"Kill" , cdlua5_killcanvas}, + {"Activate" , cdlua5_activate}, + {"Deactivate" , cdlua5_deactivate}, + {"Simulate" , cdlua5_simulate}, + + /* Control */ + {"Clear" , cdlua5_clear}, + {"Flush" , cdlua5_flush}, + {"SaveState" , cdlua5_savestate}, + {"RestoreState" , cdlua5_restorestate}, + {"SetAttribute" , cdlua5_setattribute}, + {"GetAttribute" , cdlua5_getattribute}, + + /* Coordinate System */ + {"GetSize" , cdlua5_getcanvassize}, + {"UpdateYAxis" , cdlua5_updateyaxis}, + {"InvertYAxis" , cdlua5_invertyaxis}, + {"MM2Pixel" , cdlua5_mm2pixel}, + {"Pixel2MM" , cdlua5_pixel2mm}, + {"Origin" , cdlua5_origin}, + {"GetOrigin" , cdlua5_getorigin}, + {"fMM2Pixel" , cdlua5_fmm2pixel}, + {"fPixel2MM" , cdlua5_fpixel2mm}, + {"fOrigin" , cdlua5_forigin}, + {"fGetOrigin" , cdlua5_fgetorigin}, + {"Transform" , cdlua5_transform}, + {"GetTransform" , cdlua5_gettransform}, + {"TransformMultiply" , cdlua5_transformmultiply}, + {"TransformRotate" , cdlua5_transformrotate}, + {"TransformScale" , cdlua5_transformscale}, + {"TransformTranslate" , cdlua5_transformtranslate}, + {"TransformPoint" , cdlua5_transformpoint}, + {"fTransformPoint" , cdlua5_ftransformpoint}, + + /* World Coordinates */ + {"wWindow" , wdlua5_window}, + {"wGetWindow" , wdlua5_getwindow}, + {"wViewport" , wdlua5_viewport}, + {"wGetViewport" , wdlua5_getviewport}, + {"wWorld2Canvas" , wdlua5_world2canvas}, + {"wCanvas2World" , wdlua5_canvas2world}, + + {"wHardcopy" , wdlua5_hardcopy}, + + /* General Attributes */ + {"Foreground" , cdlua5_foreground}, + {"Background" , cdlua5_background}, + {"SetForeground" , cdlua5_setforeground}, + {"SetBackground" , cdlua5_setbackground}, + {"WriteMode" , cdlua5_writemode}, + + /* Clipping */ + {"Clip" , cdlua5_clip}, + {"ClipArea" , cdlua5_cliparea}, + {"GetClipArea" , cdlua5_getcliparea}, + {"wClipArea" , wdlua5_cliparea}, + {"wGetClipArea" , wdlua5_getcliparea}, + {"fClipArea" , cdlua5_fcliparea}, + {"fGetClipArea" , cdlua5_fgetcliparea}, + + /* Regions */ + {"RegionCombineMode" , cdlua5_regioncombinemode}, + {"IsPointInRegion" , cdlua5_pointinregion}, + {"wIsPointInRegion" , wdlua5_pointinregion}, + {"OffsetRegion" , cdlua5_offsetregion}, + {"wOffsetRegion" , wdlua5_offsetregion}, + {"GetRegionBox" , cdlua5_regionbox}, + {"wGetRegionBox" , wdlua5_regionbox}, + + /* Marks */ + {"Pixel" , cdlua5_pixel}, + {"wPixel" , wdlua5_pixel}, + {"Mark" , cdlua5_mark}, + {"wMark" , wdlua5_mark}, + {"MarkType" , cdlua5_marktype}, + {"MarkSize" , cdlua5_marksize}, + {"wMarkSize" , wdlua5_marksize}, + + /* Line */ + {"Line" , cdlua5_line}, + {"wLine" , wdlua5_line}, + {"fLine" , cdlua5_fline}, + {"Rect" , cdlua5_rect}, + {"wRect" , wdlua5_rect}, + {"fRect" , cdlua5_frect}, + {"Arc" , cdlua5_arc}, + {"wArc" , wdlua5_arc}, + {"fArc" , cdlua5_farc}, + {"LineStyle" , cdlua5_linestyle}, + {"LineStyleDashes" , cdlua5_linestyledashes}, + {"LineWidth" , cdlua5_linewidth}, + {"wLineWidth" , wdlua5_linewidth}, + {"LineJoin" , cdlua5_linejoin}, + {"LineCap" , cdlua5_linecap}, + + /* Filled Areas */ + {"Box" , cdlua5_box}, + {"wBox" , wdlua5_box}, + {"fBox" , cdlua5_fbox}, + {"Sector" , cdlua5_sector}, + {"wSector" , wdlua5_sector}, + {"fSector" , cdlua5_fsector}, + {"Chord" , cdlua5_chord}, + {"wChord" , wdlua5_chord}, + {"fChord" , cdlua5_fchord}, + {"BackOpacity" , cdlua5_backopacity}, + {"FillMode" , cdlua5_fillmode}, + {"InteriorStyle" , cdlua5_interiorstyle}, + {"Hatch" , cdlua5_hatch}, + + /* Stipple */ + {"Stipple" , cdlua5_stipple}, + {"wStipple" , wdlua5_stipple}, + {"GetStipple" , cdlua5_getstipple}, + + /* Pattern */ + {"Pattern" , cdlua5_pattern}, + {"wPattern" , wdlua5_pattern}, + {"GetPattern" , cdlua5_getpattern}, + + /* Text */ + {"Text" , cdlua5_text}, + {"wText" , wdlua5_text}, + {"fText" , cdlua5_ftext}, + {"Font" , cdlua5_font}, + {"wFont" , wdlua5_font}, + {"GetFont" , cdlua5_getfont}, + {"wGetFont" , wdlua5_getfont}, + {"NativeFont" , cdlua5_nativefont}, + {"TextAlignment" , cdlua5_textalignment}, + {"TextOrientation" , cdlua5_textorientation}, + {"GetFontDim" , cdlua5_getfontdim}, + {"wGetFontDim" , wdlua5_getfontdim}, + {"GetTextSize" , cdlua5_gettextsize}, + {"wGetTextSize" , wdlua5_gettextsize}, + {"GetTextBox" , cdlua5_gettextbox}, + {"wGetTextBox" , wdlua5_gettextbox}, + {"GetTextBounds" , cdlua5_gettextbounds}, + {"wGetTextBounds" , wdlua5_gettextbounds}, + + /* Vector Text */ + {"VectorText" , cdlua5_vectortext}, + {"wVectorText" , wdlua5_vectortext}, + {"MultiLineVectorText" , cdlua5_multilinevectortext}, + {"wMultiLineVectorText" , wdlua5_multilinevectortext}, + {"VectorTextDirection" , cdlua5_vectortextdirection}, + {"wVectorTextDirection" , wdlua5_vectortextdirection}, + {"VectorTextTransform" , cdlua5_vectortexttransform}, + {"VectorFontSize" , cdlua5_vectorfontsize}, + {"GetVectorFontSize" , cdlua5_getvectorfontsize}, + {"VectorTextSize" , cdlua5_vectortextsize}, + {"wVectorTextSize" , wdlua5_vectortextsize}, + {"VectorCharSize" , cdlua5_vectorcharsize}, + {"wVectorCharSize" , wdlua5_vectorcharsize}, + {"VectorFont" , cdlua5_vectorfont}, + {"GetVectorTextSize" , cdlua5_getvectortextsize}, + {"wGetVectorTextSize" , wdlua5_getvectortextsize}, + {"GetVectorTextBounds" , cdlua5_getvectortextbounds}, + {"wGetVectorTextBounds" , wdlua5_getvectortextbounds}, + {"GetVectorTextBox" , cdlua5_getvectortextbox}, + {"wGetVectorTextBox" , wdlua5_getvectortextbox}, + + /* Client Images */ + {"GetImageRGB" , cdlua5_getimagergb}, + {"PutImageRectRGB" , cdlua5_putimagerectrgb}, + {"wPutImageRectRGB" , wdlua5_putimagerectrgb}, + {"PutImageRectRGBA" , cdlua5_putimagerectrgba}, + {"wPutImageRectRGBA", wdlua5_putimagerectrgba}, + {"PutImageRectMap" , cdlua5_putimagerectmap}, + {"wPutImageRectMap" , wdlua5_putimagerectmap}, + {"GetBitmap" , cdlua5_getbitmap}, + {"PutBitmap" , cdlua5_putbitmap}, + {"wPutBitmap" , wdlua5_putbitmap}, + + /* Server Images */ + {"CreateImage" , cdlua5_createimage}, + {"GetImage" , cdlua5_getimage}, + {"PutImageRect" , cdlua5_putimagerect}, + {"wPutImageRect" , wdlua5_putimagerect}, + {"ScrollArea" , cdlua5_scrollarea}, + + /* Other */ + {"Play" , cdlua5_play}, + + /* Color Coding */ + {"GetColorPlanes" , cdlua5_getcolorplanes}, + + /* Palette */ + {"Palette" , cdlua5_palette}, + + /* Polygon */ + {"Begin" , cdlua5_begin}, + {"Vertex" , cdlua5_vertex}, + {"wVertex" , wdlua5_vertex}, + {"fVertex" , cdlua5_fvertex}, + {"End" , cdlua5_end}, + + {"__eq", cdluaCanvas_eq}, + {"__tostring", cdluaCanvas_tostring}, + + {NULL, NULL}, +}; + +static const struct luaL_reg cdlib_canvas[] = { + /* Initialization */ + {"CreateCanvas" , cdlua5_createcanvas}, + {"KillCanvas" , cdlua5_killcanvas}, + {"GetContext" , cdlua5_getcontext}, /* compatibility name */ + {"ImageRGB" , cdlua5_imagergb}, + {"ImageRGBBitmap" , cdlua5_imagergbbitmap}, + {NULL, NULL}, +}; + +void cdlua_open_canvas (lua_State *L) +{ + /* "cd" table is at the top of the stack */ + + /* Object Oriented Access */ + luaL_newmetatable(L, "cdCanvas"); /* create new metatable for cdCanvas handles */ + lua_pushliteral(L, "__index"); + lua_pushvalue(L, -2); /* push metatable */ + lua_rawset(L, -3); /* metatable.__index = metatable */ + luaL_register(L, NULL, cdlib_canvas_meta); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + luaL_register(L, NULL, cdlib_canvas); +} diff --git a/cd/src/lua5/cdlua5ctx.c b/cd/src/lua5/cdlua5ctx.c new file mode 100755 index 0000000..e3bd19e --- /dev/null +++ b/cd/src/lua5/cdlua5ctx.c @@ -0,0 +1,802 @@ +/***************************************************************************\ +* $Id: cdlua5ctx.c,v 1.1 2008/10/17 06:10:42 scuri Exp $ +* * +\***************************************************************************/ + +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" + +#include "cdimage.h" +#include "cdirgb.h" +#include "cddxf.h" +#include "cddgn.h" +#include "cdcgm.h" +#include "cdwmf.h" +#include "cdemf.h" +#include "cdnative.h" +#include "cdprint.h" +#include "cdclipbd.h" +#include "cdmf.h" +#include "cdps.h" +#include "cddbuf.h" +#include "cdgdiplus.h" + +#include +#include + +#include "cdlua.h" +#include "cdlua5_private.h" + + +/***************************************************************************\ +* CD_CGM. * +\***************************************************************************/ +static void *cdcgm_checkdata(lua_State * L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); +static int cgm_countercb(cdCanvas *canvas, double percent); +static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f); +static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx); +static int cgm_begpictcb(cdCanvas *canvas, char *pict); +static int cgm_begpictbcb(cdCanvas *canvas); +static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx); + +static cdluaCallback cdluacgmcb[7] = { +{ + -1, + "SIZECB", + (cdCallback)cgm_sizecb +}, +{ + -1, + "CGMCOUNTERCB", + (cdCallback)cgm_countercb +}, +{ + -1, + "CGMSCLMDECB", + (cdCallback)cgm_sclmdecb +}, +{ + -1, + "CGMVDCEXTCB", + (cdCallback)cgm_vdcextcb +}, +{ + -1, + "CGMBEGPICTCB", + (cdCallback)cgm_begpictcb +}, +{ + -1, + "CGMBEGPICTBCB", + (cdCallback)cgm_begpictbcb +}, +{ + -1, + "CGMBEGMTFCB", + (cdCallback)cgm_begmtfcb +} +}; + +static cdluaContext cdluacgmctx = +{ + 0, + "CGM", + cdContextCGM, + cdcgm_checkdata, + cdluacgmcb, + 7 +}; + +/***************************************************************************\ +* CGM CD_COUNTERCB. * +\***************************************************************************/ +static int cgm_countercb(cdCanvas *canvas, double percent) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluacgmcb[CD_CGMCOUNTERCB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, percent); + if(lua_pcall(L, 2, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L,-1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CGM CD_BEGPICTCB. * +\***************************************************************************/ +static int cgm_begpictcb(cdCanvas *canvas, char *pict) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluacgmcb[CD_CGMBEGPICTCB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushstring(L, pict); + if(lua_pcall(L, 2, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L,-1)) + luaL_error(L,"invalid return value"); + + return luaL_checkint(L,-1); +} + +static int cgm_begmtfcb(cdCanvas *canvas, int *xmn, int *ymn, int *xmx, int *ymx) +{ + int result_i; + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluacgmcb[CD_CGMBEGMTFCB].lock); + + cdlua_pushcanvas(L, canvas); + if(lua_pcall(L, 1, 5, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -5)) + luaL_error(L, "invalid return value"); + + result_i = luaL_checkint(L, -5); + if (result_i == 1) + return 1; + + if (!lua_isnumber(L, -4)) + luaL_error(L, "invalid xmn return value"); + *xmn = luaL_checkint(L, -4); + + if (!lua_isnumber(L, -3)) + luaL_error(L, "invalid ymn return value"); + *ymn = luaL_checkint(L, -3); + + if (!lua_isnumber(L, -2)) + luaL_error(L, "invalid xmx return value"); + *xmx = luaL_checkint(L, -2); + + if (!lua_isnumber(L, -1)) + luaL_error(L, "invalid ymx return value"); + *ymx = luaL_checkint(L, -1); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_BEGPICTBCB. * +\***************************************************************************/ +static int cgm_begpictbcb(cdCanvas *canvas) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluacgmcb[CD_CGMBEGPICTBCB].lock); + + cdlua_pushcanvas(L, canvas); + if(lua_pcall(L, 1, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CGM CD_SIZECB. * +\***************************************************************************/ +static int cgm_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L,cdluacgmcb[CD_SIZECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, w ); + lua_pushnumber(L, h ); + lua_pushnumber(L, mm_w ); + lua_pushnumber(L, mm_h ); + if(lua_pcall(L, 5, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CGM CD_SCLMDE. * +\***************************************************************************/ +static int cgm_sclmdecb(cdCanvas *canvas, short scl_mde, short *draw_mode_i, double *factor_f) +{ + int result_i; + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L,cdluacgmcb[CD_CGMSCLMDECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, scl_mde); + if(lua_pcall(L, 2, 3, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -3)) + luaL_error(L, "invalid return value"); + + result_i = luaL_checkint(L, -3); + + if (result_i == 1) + return 1; + + if (!lua_isnumber(L, -2)) + luaL_error(L, "invalid draw mode return value"); + *draw_mode_i = (short) lua_tonumber(L,-2); + + if (!lua_isnumber(L, -1)) + luaL_error(L, "invalid factor return value"); + + *factor_f = (double) lua_tonumber(L, -1); + + return result_i; +} + +/***************************************************************************\ +* CGM CD_VDCEXTCB. * +\***************************************************************************/ +static int cgm_vdcextcb(cdCanvas *canvas, short type, void *xmn, void *ymn, void *xmx, void *ymx) +{ + int result_i; + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluacgmcb[CD_CGMVDCEXTCB].lock); + + cdlua_pushcanvas(L, canvas); + if(lua_pcall(L, 1, 5, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -5)) + luaL_error(L, "invalid return value"); + result_i = luaL_checkint(L,-5); + if (result_i == 1) + return 1; + + if (!lua_isnumber(L, -4)) + luaL_error(L, "invalid xmn return value"); + if (type == 1) *((float *) xmn) = (float) lua_tonumber(L, -4); + else *((int *) xmn) = luaL_checkint(L, -4); + + if (!lua_isnumber(L, -3)) + luaL_error(L, "invalid ymn return value"); + if (type == 1) *((float *) ymn) = (float) lua_tonumber(L, -3); + else *((int *) ymn) = luaL_checkint(L, -3); + + if (!lua_isnumber(L, -2)) + luaL_error(L,"invalid xmx return value"); + if (type == 1) *((float *) xmx) = (float) lua_tonumber(L, -2); + else *((int *) xmx) = luaL_checkint(L, -2); + + if (!lua_isnumber(L, -1)) + luaL_error(L,"invalid ymx return value"); + if (type == 1) *((float *) ymx) = (float) lua_tonumber(L, -1); + else *((int *) ymx) = (int) luaL_checkint(L, -1); + + return result_i; +} + +/***************************************************************************\ +* CD_DBUFFER. * +\***************************************************************************/ +static void *cddbuf_checkdata(lua_State * L, int param) +{ + return cdlua_checkcanvas(L, param); +} + +static cdluaContext cdluadbufctx = +{ + 0, + "DBUFFER", + cdContextDBuffer, + cddbuf_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_IMAGE. * +\***************************************************************************/ +static void *cdimage_checkdata(lua_State *L, int param) +{ + return cdlua_checkimage(L, param); +} + +static cdluaContext cdluaimagectx = +{ + 0, + "IMAGE", + cdContextImage, + cdimage_checkdata, + NULL, + 0 +}; + +static int cdlua_rawchecktype(lua_State *L, int param, const char* type) +{ + if (lua_isuserdata(L, param)) /* value is a userdata? */ + { + if (lua_getmetatable(L, param)) /* does it have a metatable? */ + { + lua_getfield(L, LUA_REGISTRYINDEX, type); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) /* does it have the correct mt? */ + { + lua_pop(L, 2); /* remove both metatables */ + return 1; + } + else + { + lua_pop(L, 2); /* remove both metatables */ + return -1; /* test for other metatables */ + } + } + } + return 0; /* do not continue */ +} + +/***************************************************************************\ +* CD_IMAGERGB. * +\***************************************************************************/ +static void *cdimagergb_checkdata(lua_State* L, int param) +{ + static char data_s[100] = ""; + + if (lua_isstring(L, param)) + { + const char* str = lua_tostring(L, param); + strcpy(data_s, str); + } + else + { + int ret = cdlua_rawchecktype(L, param, "cdBitmap"); + + if (ret == 0) + luaL_typerror(L, param, "cdBitmap"); /* not a user data and not a metatable */ + + if (ret == 1) + { + cdBitmap* *bitmap_p = (cdBitmap**)luaL_checkudata(L, param, "cdBitmap"); + if (!(*bitmap_p)) + luaL_argerror(L, param, "killed cdBitmap"); + + if ((*bitmap_p)->type != CD_RGB && (*bitmap_p)->type != CD_RGBA) + luaL_argerror(L, param, "bitmap should be of type rgb or rgba"); + + if (lua_isnoneornil(L, param+1)) + { + if ((*bitmap_p)->type == CD_RGBA) + sprintf(data_s, "%dx%d %p %p %p %p -a", (*bitmap_p)->w, (*bitmap_p)->h, + cdBitmapGetData(*bitmap_p, CD_IRED), + cdBitmapGetData(*bitmap_p, CD_IGREEN), + cdBitmapGetData(*bitmap_p, CD_IBLUE), + cdBitmapGetData(*bitmap_p, CD_IALPHA)); + else + sprintf(data_s, "%dx%d %p %p %p", (*bitmap_p)->w, (*bitmap_p)->h, + cdBitmapGetData(*bitmap_p, CD_IRED), + cdBitmapGetData(*bitmap_p, CD_IGREEN), + cdBitmapGetData(*bitmap_p, CD_IBLUE)); + } + else + { + double res_f = luaL_checknumber(L, param+1); + if ((*bitmap_p)->type == CD_RGBA) + sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", (*bitmap_p)->w, (*bitmap_p)->h, + cdBitmapGetData(*bitmap_p, CD_IRED), + cdBitmapGetData(*bitmap_p, CD_IGREEN), + cdBitmapGetData(*bitmap_p, CD_IBLUE), + cdBitmapGetData(*bitmap_p, CD_IALPHA), + res_f); + else + sprintf(data_s, "%dx%d %p %p %p -r%g", (*bitmap_p)->w, (*bitmap_p)->h, + cdBitmapGetData(*bitmap_p, CD_IRED), + cdBitmapGetData(*bitmap_p, CD_IGREEN), + cdBitmapGetData(*bitmap_p, CD_IBLUE), + res_f); + } + + return data_s; + } + + ret = cdlua_rawchecktype(L, param, "cdImageRGB"); + if (ret == 1) + { + cdluaImageRGB *imagergb_p = (cdluaImageRGB*) luaL_checkudata(L, param, "cdImageRGB"); + if (!imagergb_p->red) + luaL_argerror(L, param, "killed cdImageRGB"); + + if (lua_isnoneornil(L, param+1)) + { + sprintf(data_s, "%dx%d %p %p %p", imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue); + } + else + { + double res_f = luaL_checknumber(L, param+1); + sprintf(data_s, "%dx%d %p %p %p -r%g", imagergb_p->width, imagergb_p->height, + imagergb_p->red, imagergb_p->green, imagergb_p->blue, res_f); + } + + return data_s; + } + + ret = cdlua_rawchecktype(L, param, "cdImageRGBA"); + if (ret == 1) + { + cdluaImageRGBA *imagergba_p = (cdluaImageRGBA*) luaL_checkudata(L, param, "cdImageRGBA"); + if (!imagergba_p->red) + luaL_argerror(L, param, "killed cdImageRGBA"); + + if (lua_isnoneornil(L, param+1)) + { + sprintf(data_s, "%dx%d %p %p %p %p -a", imagergba_p->width, imagergba_p->height, + imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha); + } + else + { + double res_f = luaL_checknumber(L, param+1); + sprintf(data_s, "%dx%d %p %p %p %p -r%g -a", imagergba_p->width, imagergba_p->height, + imagergba_p->red, imagergba_p->green, imagergba_p->blue, imagergba_p->alpha, res_f); + } + + return data_s; + } + + luaL_typerror(L, param, "cdBitmap"); /* is a metatable but it is not one of the accepted */ + } + + return data_s; +} + +static cdluaContext cdluaimagergbctx = +{ + 0, + "IMAGERGB", + cdContextImageRGB, + cdimagergb_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_DXF. * +\***************************************************************************/ +static void *cddxf_checkdata(lua_State * L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static cdluaContext cdluadxfctx = +{ + 0, + "DXF", + cdContextDXF, + cddxf_checkdata +}; + +/***************************************************************************\ +* CD_DGN. * +\***************************************************************************/ +static void *cddgn_checkdata(lua_State * L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static cdluaContext cdluadgnctx = +{ + 0, + "DGN", + cdContextDGN, + cddgn_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_WMF. * +\***************************************************************************/ +static void *cdwmf_checkdata(lua_State * L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdluaCallback cdluawmfcb[1] = +{{ + -1, + "SIZECB", + (cdCallback)wmf_sizecb +}}; + +static cdluaContext cdluawmfctx = +{ + 0, + "WMF", + cdContextWMF, + cdwmf_checkdata, + cdluawmfcb, + 1 +}; + +/***************************************************************************\ +* WMF CD_SIZECB. * +\***************************************************************************/ +static int wmf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L,cdluawmfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_pushnumber(L, mm_w); + lua_pushnumber(L, mm_h); + if(lua_pcall(L, 5, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -1)) + luaL_error(L,"invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CD_EMF. * +\***************************************************************************/ +static void *cdemf_checkdata(lua_State *L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdluaCallback cdluaemfcb[1] = +{{ + -1, + "SIZECB", + (cdCallback)emf_sizecb +}}; + +static cdluaContext cdluaemfctx = +{ + 0, + "EMF", + cdContextEMF, + cdemf_checkdata, + cdluaemfcb, + 1 +}; + +/***************************************************************************\ +* EMF CD_SIZECB. * +\***************************************************************************/ +static int emf_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L,cdluaemfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_pushnumber(L, mm_w); + lua_pushnumber(L, mm_h); + if(lua_pcall(L, 5, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L,-1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CD_METAFILE. * +\***************************************************************************/ +static void *cdmetafile_checkdata(lua_State *L,int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdluaCallback cdluamfcb[1] = +{{ + -1, + "SIZECB", + (cdCallback)metafile_sizecb +}}; + +static cdluaContext cdluamfctx = +{ + 0, + "METAFILE", + cdContextMetafile, + cdmetafile_checkdata, + cdluamfcb, + 1 +}; + +/***************************************************************************\ +* METAFILE CD_SIZECB. * +\***************************************************************************/ +static int metafile_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + + lua_getref(L, cdluamfcb[CD_SIZECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_pushnumber(L, mm_w); + lua_pushnumber(L, mm_h); + if(lua_pcall(L, 5, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L, -1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CD_PS. * +\***************************************************************************/ +static void *cdps_checkdata( lua_State *L, int param) +{ + return (void *)luaL_checkstring(L, param); +} + +static cdluaContext cdluapsctx = +{ + 0, + "PS", + cdContextPS, + cdps_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_PRINTER. * +\***************************************************************************/ +static void *cdprinter_checkdata(lua_State *L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static cdluaContext cdluaprinterctx = +{ + 0, + "PRINTER", + cdContextPrinter, + cdprinter_checkdata, + NULL, + 0 +}; + +/***************************************************************************\ +* CD_CLIPBOARD. * +\***************************************************************************/ +static void *cdclipboard_checkdata(lua_State *L, int param) +{ + return (void *)luaL_checkstring(L,param); +} + +static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h); + +static cdluaCallback cdluaclipboardcb[1] = +{{ + -1, + "SIZECB", + (cdCallback)clipboard_sizecb +}}; + +static cdluaContext cdluaclipboardctx = +{ + 0, + "CLIPBOARD", + cdContextClipboard, + cdclipboard_checkdata, + cdluaclipboardcb, + 1 +}; + +/***************************************************************************\ +* CLIPBOARD CD_SIZECB. * +\***************************************************************************/ +static int clipboard_sizecb(cdCanvas *canvas, int w, int h, double mm_w, double mm_h) +{ + /* little Wrapper */ + lua_State * L = cdlua_getplaystate(); + lua_getref(L, cdluaclipboardcb[CD_SIZECB].lock); + + cdlua_pushcanvas(L, canvas); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + lua_pushnumber(L, mm_w); + lua_pushnumber(L, mm_h); + if(lua_pcall(L, 5, 1, 0) != 0) + luaL_error(L, "error running function: %s", lua_tostring(L, -1)); + + if (!lua_isnumber(L,-1)) + luaL_error(L, "invalid return value"); + + return luaL_checkint(L,-1); +} + +/***************************************************************************\ +* CD_NATIVEWINDOW. * +\***************************************************************************/ +static void *cdnativewindow_checkdata(lua_State *L, int param) +{ +#ifdef WIN32 + if (!lua_isnil(L,param) && !lua_isuserdata(L,param)) + luaL_argerror(L, param, "data should be of type userdata"); + + return lua_touserdata(L,param); +#else + return (void *)luaL_checkstring(L,param); +#endif +} + +static cdluaContext cdluanativewindowctx = +{ + 0, + "NATIVEWINDOW", + cdContextNativeWindow, + cdnativewindow_checkdata, + NULL, + 0 +}; + + +/*******************************************************************************\ +* Init all CD Drivers * +*********************************************************************************/ +void cdlua_initdrivers(lua_State * L, cdluaLuaState* cdL) +{ + cdlua_addcontext(L, cdL, &cdluaimagectx); + cdlua_addcontext(L, cdL, &cdluaimagergbctx); + cdlua_addcontext(L, cdL, &cdluadxfctx); + cdlua_addcontext(L, cdL, &cdluadgnctx); + cdlua_addcontext(L, cdL, &cdluacgmctx); + cdlua_addcontext(L, cdL, &cdluamfctx); + cdlua_addcontext(L, cdL, &cdluapsctx); + cdlua_addcontext(L, cdL, &cdluaclipboardctx); + cdlua_addcontext(L, cdL, &cdluanativewindowctx); + cdlua_addcontext(L, cdL, &cdluaprinterctx); + cdlua_addcontext(L, cdL, &cdluawmfctx); + cdlua_addcontext(L, cdL, &cdluaemfctx); + cdlua_addcontext(L, cdL, &cdluadbufctx); +} diff --git a/cd/src/lua5/cdluacontextplus5.c b/cd/src/lua5/cdluacontextplus5.c new file mode 100755 index 0000000..de69167 --- /dev/null +++ b/cd/src/lua5/cdluacontextplus5.c @@ -0,0 +1,44 @@ +/** \file + * \brief Context Plus Lua 5 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cd.h" + +#include +#include + + +static int cdlua5_initcontextplus(lua_State *L) +{ + (void)L; + cdInitContextPlus(); + return 0; +} + +static const struct luaL_reg cdlib[] = { + {"InitContextPlus", cdlua5_initcontextplus}, + {NULL, NULL}, +}; + + +static int cdluacontextplus_open (lua_State *L) +{ + cdInitContextPlus(); + luaL_register(L, "cd", cdlib); /* leave "cd" table at the top of the stack */ + return 1; +} + +int luaopen_cdluacontextplus(lua_State* L) +{ + return cdluacontextplus_open(L); +} + +int luaopen_cdluacontextplus51(lua_State* L) +{ + return cdluacontextplus_open(L); +} diff --git a/cd/src/lua5/cdluacontextplus5.def b/cd/src/lua5/cdluacontextplus5.def new file mode 100755 index 0000000..55e478b --- /dev/null +++ b/cd/src/lua5/cdluacontextplus5.def @@ -0,0 +1,4 @@ +EXPORTS + luaopen_cdluacontextplus + luaopen_cdluacontextplus51 + \ No newline at end of file diff --git a/cd/src/lua5/cdluaim5.c b/cd/src/lua5/cdluaim5.c new file mode 100755 index 0000000..77ffc4f --- /dev/null +++ b/cd/src/lua5/cdluaim5.c @@ -0,0 +1,265 @@ +/** \file + * \brief CD+IM Lua 5 Binding + * + * See Copyright Notice in im_lib.h + */ + +#include +#include + +#define CD_NO_OLD_INTERFACE + +#include +#include + +#include "cd.h" +#include "cdirgb.h" +#include "wd.h" + +#include +#include + +#include + +#include "cdlua.h" +#include "cdlua5_private.h" + + +/*****************************************************************************\ + image:cdInitBitmap() -> cdBitmap +\*****************************************************************************/ +static int imlua_cdInitBitmap(lua_State *L) +{ + cdBitmap* bitmap; + imImage *image = imlua_checkimage(L, 1); + + if (!imImageIsBitmap(image)) + luaL_argerror(L, 1, "image is not a bitmap"); + + if (image->color_space == IM_RGB) + bitmap = cdInitBitmap(image->width, image->height, CD_RGB, image->data[0], image->data[1], image->data[2]); + else + bitmap = cdInitBitmap(image->width, image->height, CD_MAP, image->data[0], image->palette); + + if (!bitmap) + luaL_error(L, "insuficient memory to create bitmap"); + + cdlua_pushbitmap(L, bitmap); + return 1; +} + +/*****************************************************************************\ + image:cdCreateBitmap() -> cdBitmap +\*****************************************************************************/ +static int imlua_cdCreateBitmap(lua_State *L) +{ + cdBitmap* bitmap; + imImage *image = imlua_checkimage(L, 1); + + if (!imImageIsBitmap(image)) + luaL_argerror(L, 1, "image is not a bitmap"); + + if (image->color_space == IM_RGB) + bitmap = cdCreateBitmap(image->width, image->height, CD_RGB); + else + bitmap = cdCreateBitmap(image->width, image->height, CD_MAP); + + if (!bitmap) + luaL_error(L, "insuficient memory to create bitmap"); + + if (image->color_space == IM_RGB) + { + memcpy(cdBitmapGetData(bitmap, CD_IRED), image->data[0], image->plane_size); + memcpy(cdBitmapGetData(bitmap, CD_IGREEN), image->data[1], image->plane_size); + memcpy(cdBitmapGetData(bitmap, CD_IBLUE), image->data[2], image->plane_size); + } + else + { + memcpy(cdBitmapGetData(bitmap, CD_INDEX), image->data[0], image->plane_size); + memcpy(cdBitmapGetData(bitmap, CD_COLORS), image->palette, image->palette_count*sizeof(long int)); + } + + cdlua_pushbitmap(L, bitmap); + return 1; +} + +/*****************************************************************************\ + cd:imImageCreate(bitmap: cdBitmap) -> imImage +\*****************************************************************************/ +static int cdlua_imImageCreate(lua_State *L) +{ + imImage *image; + cdBitmap* bitmap = cdlua_checkbitmap(L, 1); + + if (bitmap->type == CD_RGB) + image = imImageCreate(bitmap->w, bitmap->h, IM_RGB, IM_BYTE); + else + image = imImageCreate(bitmap->w, bitmap->h, IM_MAP, IM_BYTE); + + if (!image) + luaL_error(L, "insuficient memory to create image"); + + if (bitmap->type == CD_RGB) + { + memcpy(image->data[0], cdBitmapGetData(bitmap, CD_IRED), image->plane_size); + memcpy(image->data[1], cdBitmapGetData(bitmap, CD_IGREEN), image->plane_size); + memcpy(image->data[2], cdBitmapGetData(bitmap, CD_IBLUE), image->plane_size); + } + else + { + memcpy(image->data[0], cdBitmapGetData(bitmap, CD_INDEX), image->plane_size); + memcpy(image->palette, cdBitmapGetData(bitmap, CD_COLORS), 256*sizeof(long int)); + } + + imlua_pushimage(L, image); + return 1; +} + +/*****************************************************************************\ + image:wdCanvasPutImageRect(_canvas, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax) +\*****************************************************************************/ +static int imlua_wdCanvasPutImageRect(lua_State *L) +{ + int xr, yr, wr, hr; + imImage *image = imlua_checkimage(L, 1); + cdCanvas* canvas = cdlua_checkcanvas(L, 2); + double x = luaL_checknumber(L, 3); + double y = luaL_checknumber(L, 4); + double w = luaL_checknumber(L, 5); + double h = luaL_checknumber(L, 6); + int xmin = luaL_optint(L, 7, 0); + int xmax = luaL_optint(L, 8, 0); + int ymin = luaL_optint(L, 9, 0); + int ymax = luaL_optint(L, 10, 0); + + if (!imImageIsBitmap(image)) + luaL_argerror(L, 1, "image is not a bitmap"); + + wdCanvasWorld2Canvas(canvas, x, y, &xr, &yr); + wdCanvasWorld2CanvasSize(canvas, w, h, &wr, &hr); + + imcdCanvasPutImage(canvas, image, xr, yr, wr, hr, xmin, xmax, ymin, ymax); + return 0; +} + +/*****************************************************************************\ + image:cdCanvasPutImageRect(_canvas, _x, _y, _w, _h, _xmin, _xmax, _ymin, _ymax) +\*****************************************************************************/ +static int imlua_cdCanvasPutImageRect(lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + cdCanvas* canvas = cdlua_checkcanvas(L, 2); + int x = luaL_checkint(L, 3); + int y = luaL_checkint(L, 4); + int w = luaL_checkint(L, 5); + int h = luaL_checkint(L, 6); + int xmin = luaL_optint(L, 7, 0); + int xmax = luaL_optint(L, 8, 0); + int ymin = luaL_optint(L, 9, 0); + int ymax = luaL_optint(L, 10, 0); + + if (!imImageIsBitmap(image)) + luaL_argerror(L, 1, "image is not a bitmap"); + + imcdCanvasPutImage(canvas, image, x, y, w, h, xmin, xmax, ymin, ymax); + return 0; +} + +/***************************************************************************\ +* image:cdCanvasGetImage(_canvas, x, y: number) * +\***************************************************************************/ +static int imlua_cdCanvasGetImage(lua_State *L) +{ + imImage *image = imlua_checkimage(L, 1); + cdCanvas* canvas = cdlua_checkcanvas(L, 2); + int x = luaL_optint(L, 3, 0); + int y = luaL_optint(L, 4, 0); + + if (image->color_space != IM_RGB || image->data_type != IM_BYTE) + luaL_argerror(L, 1, "image is not RGB/byte"); + + cdCanvasGetImageRGB(canvas, image->data[0], image->data[1], image->data[2], x, y, image->width, image->height); + return 0; +} + +/***************************************************************************\ +* image:cdCreateCanvas(res: number) -> cdCanvas * +\***************************************************************************/ +static int imlua_cdCreateCanvas(lua_State * L) +{ + cdCanvas**canvas_p, *canvas; + char data_s[100]; + + imImage *image = imlua_checkimage(L, 1); + + if (lua_isnoneornil(L, 2)) + { + sprintf(data_s, "%dx%d %p %p %p", image->width, image->height, + image->data[0], image->data[1], image->data[2]); + } + else + { + double res_f = luaL_checknumber(L, 2); + sprintf(data_s, "%dx%d %p %p %p -r%g", image->width, image->height, + image->data[0], image->data[1], image->data[2], res_f); + } + + canvas = cdCreateCanvas(CD_IMAGERGB, data_s); + if (!canvas) + { + lua_pushnil(L); + return 1; + } + + canvas_p = (cdCanvas**) lua_newuserdata(L, sizeof(cdCanvas*)); + luaL_getmetatable(L, "cdCanvas"); + lua_setmetatable(L, -2); + *canvas_p = canvas; + + return 1; +} + +static const luaL_reg cdim_metalib[] = { + {"imImageCreate", cdlua_imImageCreate}, + {NULL, NULL} +}; + +static const luaL_reg imcd_metalib[] = { + {"cdCreateBitmap", imlua_cdCreateBitmap}, + {"cdInitBitmap", imlua_cdInitBitmap}, + {"cdCreateCanvas", imlua_cdCreateCanvas}, + {"wdCanvasPutImageRect", imlua_wdCanvasPutImageRect}, + {"cdCanvasPutImageRect", imlua_cdCanvasPutImageRect}, + {"cdCanvasGetImage", imlua_cdCanvasGetImage}, + + {NULL, NULL} +}; + +static void createmeta (lua_State *L) +{ + /* add methods to already created metatables */ + + luaL_getmetatable(L, "imImage"); + luaL_register(L, NULL, imcd_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ + + luaL_getmetatable(L, "cdBitmap"); + luaL_register(L, NULL, cdim_metalib); /* register methods */ + lua_pop(L, 1); /* removes the metatable from the top of the stack */ +} + +int cdluaim_open(lua_State *L) +{ + createmeta(L); + return 0; +} + +int luaopen_cdluaim(lua_State *L) +{ + return cdluaim_open(L); +} + +int luaopen_cdluaim51(lua_State *L) +{ + return cdluaim_open(L); +} diff --git a/cd/src/lua5/cdluaim5.def b/cd/src/lua5/cdluaim5.def new file mode 100755 index 0000000..0b26928 --- /dev/null +++ b/cd/src/lua5/cdluaim5.def @@ -0,0 +1,4 @@ +EXPORTS + cdluaim_open + luaopen_cdluaim + luaopen_cdluaim51 diff --git a/cd/src/lua5/cdluapdf5.c b/cd/src/lua5/cdluapdf5.c new file mode 100755 index 0000000..eb3f221 --- /dev/null +++ b/cd/src/lua5/cdluapdf5.c @@ -0,0 +1,53 @@ +/** \file + * \brief PDF Canvas Lua 5 Binding + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cd.h" +#include "cdpdf.h" + +#include +#include + +#include "cdlua.h" +#include "cdluapdf.h" +#include "cdlua5_private.h" + + +static void *cdpdf_checkdata(lua_State *L, int param) +{ + return (void *)luaL_checkstring(L, param); +} + +static cdluaContext cdluapdfctx = +{ + 0, + "PDF", + cdContextPDF, + cdpdf_checkdata, + NULL, + 0 +}; + +int cdluapdf_open (lua_State *L) +{ + cdluaLuaState* cdL = cdlua_getstate(L); + lua_pushliteral(L, "cd"); + lua_gettable(L, LUA_GLOBALSINDEX); /* leave "cd" table at the top of the stack */ + cdlua_addcontext(L, cdL, &cdluapdfctx); + return 1; +} + +int luaopen_cdluapdf(lua_State* L) +{ + return cdluapdf_open(L); +} + +int luaopen_cdluapdf51(lua_State* L) +{ + return cdluapdf_open(L); +} diff --git a/cd/src/lua5/cdluapdf5.def b/cd/src/lua5/cdluapdf5.def new file mode 100755 index 0000000..bfbc889 --- /dev/null +++ b/cd/src/lua5/cdluapdf5.def @@ -0,0 +1,4 @@ +EXPORTS + cdluapdf_open + luaopen_cdluapdf + luaopen_cdluapdf51 \ No newline at end of file diff --git a/cd/src/lua5/cdvoid5.c b/cd/src/lua5/cdvoid5.c new file mode 100755 index 0000000..2424e1d --- /dev/null +++ b/cd/src/lua5/cdvoid5.c @@ -0,0 +1,130 @@ +/** \file + * \brief CD Void driver for error checking while there is no active canvas + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cd.h" +#include "cd_private.h" + +#include +#include + +#include "cdlua5_private.h" + + +struct _cdCtxCanvas +{ + cdCanvas* canvas; + lua_State * L; +}; + +void cdlua_setvoidstate(cdCanvas* canvas, lua_State * L) +{ + canvas->ctxcanvas->L = L; +} + +static void cdcreatecanvas(cdCanvas *canvas, void *data) +{ + cdCtxCanvas *ctxcanvas = (cdCtxCanvas*) malloc(sizeof(cdCtxCanvas)); + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + (void)data; +} + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + free(ctxcanvas); +} + +/***************************************************************************\ +* Echos an error if called. * +\***************************************************************************/ +static void cdvoid_error(cdCtxCanvas* ctxcanvas) +{ + luaL_error(ctxcanvas->L, "cdlua: there is no active canvas"); +} + +/***************************************************************************\ +* Dummy. * +\***************************************************************************/ +static int cdvoid_dummy(void) +{ + return CD_OK; +} + +/***************************************************************************\ +* Driver function table. * +\***************************************************************************/ + +void cdinittable(cdCanvas* canvas) +{ + /* attribute functions can not be set, because of default attributes */ + + canvas->cxClip = (int (*)(cdCtxCanvas*, int))cdvoid_error; + canvas->cxClipArea = (void (*)(cdCtxCanvas*, int, int, int, int))cdvoid_error; + canvas->cxNewRegion = (void (*)(cdCtxCanvas*))cdvoid_error; + canvas->cxIsPointInRegion = (int (*)(cdCtxCanvas*, int, int))cdvoid_error; + canvas->cxOffsetRegion = (void (*)(cdCtxCanvas*, int, int))cdvoid_error; + canvas->cxGetRegionBox = (void (*)(cdCtxCanvas*, int *, int *, int *, int *))cdvoid_error; + canvas->cxFlush = (void ( *)(cdCtxCanvas*))cdvoid_error; + canvas->cxClear = (void ( *)(cdCtxCanvas*))cdvoid_error; + canvas->cxPixel = (void ( *)(cdCtxCanvas*, int ,int ,long ))cdvoid_error; + canvas->cxLine = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxPoly = (void ( *)(cdCtxCanvas*, int ,struct _cdPoint *,int ))cdvoid_error; + canvas->cxRect = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxBox = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ))cdvoid_error; + canvas->cxArc = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxSector = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxChord = (void ( *)(cdCtxCanvas*, int ,int ,int ,int ,double ,double ))cdvoid_error; + canvas->cxText = (void (*)(cdCtxCanvas*, int ,int ,const char *))cdvoid_error; + canvas->cxGetFontDim = (void (*)(cdCtxCanvas*, int *,int *,int *,int *))cdvoid_error; + canvas->cxGetTextSize = (void (*)(cdCtxCanvas*, const char *,int *,int *))cdvoid_error; + canvas->cxPutImageRectRGB = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxPutImageRectRGBA = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxPutImageRectMap = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *,const long *,int ,int ,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxScrollArea = (void (*)(cdCtxCanvas*, int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxFLine = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFPoly = (void (*)(cdCtxCanvas*, int , cdfPoint*,int ))cdvoid_error; + canvas->cxFRect = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFBox = (void (*)(cdCtxCanvas*, double ,double ,double ,double ))cdvoid_error; + canvas->cxFArc = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error; + canvas->cxFSector = (void (*)(cdCtxCanvas*, double ,double ,double ,double ,double ,double ))cdvoid_error; + canvas->cxFText = (void (*)(cdCtxCanvas*, double ,double ,const char *))cdvoid_error; + canvas->cxStipple = (void (*)(cdCtxCanvas*, int ,int ,const unsigned char *))cdvoid_error; + canvas->cxPattern = (void (*)(cdCtxCanvas*, int ,int , const long *))cdvoid_error; + canvas->cxNativeFont = (int (*)(cdCtxCanvas*, const char*))cdvoid_error; + canvas->cxPalette = (void (*)(cdCtxCanvas*, int ,const long *,int ))cdvoid_error; + canvas->cxGetImageRGB = (void (*)(cdCtxCanvas*, unsigned char *,unsigned char *,unsigned char *,int ,int ,int ,int ))cdvoid_error; + canvas->cxCreateImage = (cdCtxImage* (*)(cdCtxCanvas*, int ,int ))cdvoid_error; + canvas->cxGetImage = (void (*)(cdCtxCanvas*, cdCtxImage*, int ,int ))cdvoid_error; + canvas->cxPutImageRect = (void (*)(cdCtxCanvas*, cdCtxImage*,int ,int ,int ,int ,int ,int ))cdvoid_error; + canvas->cxKillImage = (void (*)(cdCtxImage*))cdvoid_error; + canvas->cxFClipArea = (void (*)(cdCtxCanvas*, double,double,double,double))cdvoid_error; + + /* must not be the error callback */ + canvas->cxActivate = (int (*)(cdCtxCanvas*))cdvoid_dummy; + canvas->cxDeactivate = (void (*)(cdCtxCanvas*))cdvoid_dummy; + canvas->cxFont = (int (*)(cdCtxCanvas*, const char *, int, int))cdvoid_dummy; + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdVoidContext = +{ + 0, + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +cdContext* cdContextVoid(void) +{ + return &cdVoidContext; +} + diff --git a/cd/src/lua5/cdvoid5.h b/cd/src/lua5/cdvoid5.h new file mode 100755 index 0000000..75bf6e7 --- /dev/null +++ b/cd/src/lua5/cdvoid5.h @@ -0,0 +1,18 @@ +#ifndef _CD_VOID_ +#define _CD_VOID_ + +#ifdef __cplusplus +extern "C" { +#endif + +cdContext* cdContextVoid(void); +void cdlua_setvoidstate(cdCanvas* cnv, lua_State * L); + +#define CD_VOID cdContextVoid() + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef _CD_VOID_ */ + diff --git a/cd/src/make_uname b/cd/src/make_uname new file mode 100755 index 0000000..6de18ef --- /dev/null +++ b/cd/src/make_uname @@ -0,0 +1,16 @@ +#This builds all the libraries of the folder for 1 uname + +tecmake $1 MF=cd_freetype $2 $3 $4 $5 $6 $7 $8 +tecmake $1 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cd_pdflib $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cdpdf $2 $3 $4 $5 $6 $7 $8 +#tecmake $1 MF=cdlua3 $2 $3 $4 $5 $6 $7 $8 +#tecmake $1 MF=cdluapdf3 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cdlua5 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cdluaim5 $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cdluapdf5 $2 $3 $4 $5 $6 $7 $8 + +# XRender is NOT available in AIX, IRIX and SunOS +# It is available in Linux, Darwin and FreeBSD +tecmake $1 MF=cdcontextplus $2 $3 $4 $5 $6 $7 $8 +tecmake $1 MF=cdluacontextplus5 $2 $3 $4 $5 $6 $7 $8 diff --git a/cd/src/make_uname.bat b/cd/src/make_uname.bat new file mode 100755 index 0000000..70c3510 --- /dev/null +++ b/cd/src/make_uname.bat @@ -0,0 +1,57 @@ +@echo off +REM This builds all the libraries of the folder for 1 uname + +if "%1"=="VC" goto gdiplus_VC +if "%1"=="vc-all" goto all-vc + +call tecmake %1 "MF=cd_freetype" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=cd_pdflib" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=cdpdf" %2 %3 %4 %5 %6 %7 %8 +REM call tecmake %1 "MF=cdlua3" %2 %3 %4 %5 %6 %7 %8 +REM call tecmake %1 "MF=cdluapdf3" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=cdlua5" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=cdluapdf5" %2 %3 %4 %5 %6 %7 %8 +call tecmake %1 "MF=cdluaim5" %2 %3 %4 %5 %6 %7 %8 + +if "%1"=="vc6" goto gdiplus +if "%1"=="vc7" goto gdiplus +if "%1"=="vc8" goto gdiplus +if "%1"=="vc8_64" goto gdiplus +if "%1"=="vc9" goto gdiplus +if "%1"=="vc9_64" goto gdiplus +if "%1"=="dll" goto gdiplus +if "%1"=="dll7" goto gdiplus +if "%1"=="dll8" goto gdiplus +if "%1"=="dll8_64" goto gdiplus +if "%1"=="dll9" goto gdiplus +if "%1"=="dll9_64" goto gdiplus +if "%1"=="all" goto all-vc +goto end + +:gdiplus +call tecmake %1 "MF=cdcontextplus" %2 %3 %4 %5 %6 +call tecmake %1 "MF=cdluacontextplus5" %2 %3 %4 %5 %6 %7 %8 +goto end + +:gdiplus_VC +call tecmake %2 "MF=cdcontextplus" %3 %4 %5 %6 +call tecmake %2 "MF=cdluacontextplus5" %3 %4 %5 %6 %7 %8 +goto end + +:all-vc +call make_uname VC vc6 %2 %3 %4 %5 %6 +call make_uname VC vc7 %2 %3 %4 %5 %6 +call make_uname VC vc8 %2 %3 %4 %5 %6 +call make_uname VC vc8_64 %2 %3 %4 %5 %6 +call make_uname VC vc9 %2 %3 %4 %5 %6 +call make_uname VC vc9_64 %2 %3 %4 %5 %6 +call make_uname VC dll %2 %3 %4 %5 %6 +call make_uname VC dll7 %2 %3 %4 %5 %6 +call make_uname VC dll8 %2 %3 %4 %5 %6 +call make_uname VC dll8_64 %2 %3 %4 %5 %6 +call make_uname VC dll9 %2 %3 %4 %5 %6 +call make_uname VC dll9_64 %2 %3 %4 %5 %6 +goto end + +:end diff --git a/cd/src/rgb2map.c b/cd/src/rgb2map.c new file mode 100755 index 0000000..fa6a3bd --- /dev/null +++ b/cd/src/rgb2map.c @@ -0,0 +1,976 @@ +/** \file + * \brief RGB2Map Conversion + * + * See Copyright Notice in cd.h + */ + + +#include +#include + +#include "cd.h" + +#define PARM(a) a +typedef unsigned char byte; +/* RANGE forces a to be in the range b..c (inclusive) */ +#define RANGE(a,b,c) { if (a < b) a = b; if (a > c) a = c; } +typedef unsigned long uu_long; +typedef unsigned short uu_short; +#define INT32 int +#define TRUE 1 +#define FALSE 0 + + +static void xvbzero(char *s, size_t len) +{ + for ( ; len>0; len--) *s++ = 0; +} + +static void xvbcopy(char *src, char *dst, size_t len) +{ + /* determine if the regions overlap + * + * 3 cases: src=dst, srcdst + * + * if src=dst, they overlap completely, but nothing needs to be moved + * if srcdst then they overlap + * if src>dst and srcdst) { /* do a backward copy */ + src = src + len - 1; + dst = dst + len - 1; + for ( ; len>0; len--, src--, dst--) *dst = *src; + } + + else { /* they either overlap (src>dst) or they don't overlap */ + /* do a forward copy */ + for ( ; len>0; len--, src++, dst++) *dst = *src; + } +} + +/****************************/ +static int quick_map(const byte *red, const byte *green, const byte *blue, int w, int h, byte *map, byte *rmap, byte *gmap, byte *bmap, int *maxcol) +{ +/* scans picture until it finds more than 'maxcol' different colors. If it +finds more than 'maxcol' colors, it returns '0'. If it DOESN'T, it does +the 24-to-8 conversion by simply sticking the colors it found into +a colormap, and changing instances of a color in pic24 into colormap + indicies (in pic8) */ + + unsigned long colors[256],col; + int i, nc, low, high, mid; + const byte *pred, *pgreen, *pblue; + byte *pix; + + /* put the first color in the table by hand */ + nc = 0; mid = 0; + + for (i=w*h,pred=red,pgreen=green,pblue=blue; i; i--) + { + col = (((uu_long) *pred++) << 16); + col += (((uu_long) *pgreen++) << 8); + col += *pblue++; + + /* binary search the 'colors' array to see if it's in there */ + low = 0; high = nc-1; + while (low <= high) + { + mid = (low+high)/2; + if (col < colors[mid]) high = mid - 1; + else if (col > colors[mid]) low = mid + 1; + else break; + } + + if (high < low) + { /* didn't find color in list, add it. */ + if (nc>=*maxcol) + return 0; + + xvbcopy((char *) &colors[low], (char *) &colors[low+1], (nc - low) * sizeof(uu_long)); + colors[low] = col; + nc++; + } + } + + /* run through the data a second time, this time mapping pixel values in + pic24 into colormap offsets into 'colors' */ + + for (i=w*h,pred=red,pgreen=green,pblue=blue, pix=map; i; i--,pix++) + { + col = (((uu_long) *pred++) << 16); + col += (((uu_long) *pgreen++) << 8); + col += *pblue++; + + /* binary search the 'colors' array. It *IS* in there */ + low = 0; high = nc-1; + while (low <= high) + { + mid = (low+high)/2; + if (col < colors[mid]) high = mid - 1; + else if (col > colors[mid]) low = mid + 1; + else break; + } + + if (high < low) + return 0; + + *pix = (unsigned char)mid; + } + + /* and load up the 'desired colormap' */ + for (i=0; i>16); + gmap[i] = (unsigned char)((colors[i]>>8) & 0xff); + bmap[i] = (unsigned char)( colors[i] & 0xff); + } + + *maxcol = nc; + + return 1; +} + + + +/***************************************************************/ +/* The following is based on jquant2.c from version 5 */ +/* of the IJG JPEG software, which is */ +/* Copyright (C) 1991-1994, Thomas G. Lane. */ +/***************************************************************/ + +#define MAXNUMCOLORS 256 /* maximum size of colormap */ + +#define C0_SCALE 2 /* scale R distances by this much */ +#define C1_SCALE 3 /* scale G distances by this much */ +#define C2_SCALE 1 /* and B by this much */ + +#define HIST_C0_BITS 5 /* bits of precision in R histogram */ +#define HIST_C1_BITS 6 /* bits of precision in G histogram */ +#define HIST_C2_BITS 5 /* bits of precision in B histogram */ + +/* Number of elements along histogram axes. */ +#define HIST_C0_ELEMS (1< 0) + { + /* get pixel value and index into the histogram */ + histp = & histogram[*red >> C0_SHIFT] [*green >> C1_SHIFT] [*blue >> C2_SHIFT]; + + /* increment, check for overflow and undo increment if so. */ + if (++(*histp) <= 0) + (*histp)--; + + red++; + green++; + blue++; + } +} + + +static boxptr find_biggest_color_pop (boxptr boxlist, int numboxes) +{ + register boxptr boxp; + register int i; + register long maxc = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->colorcount > maxc && boxp->volume > 0) { + which = boxp; + maxc = boxp->colorcount; + } + } + return which; +} + + +static boxptr find_biggest_volume (boxptr boxlist, int numboxes) +{ + register boxptr boxp; + register int i; + register INT32 maxv = 0; + boxptr which = NULL; + + for (i = 0, boxp = boxlist; i < numboxes; i++, boxp++) { + if (boxp->volume > maxv) { + which = boxp; + maxv = boxp->volume; + } + } + return which; +} + + +static void update_box (boxptr boxp) +{ + hist2d * histogram = sl_histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + INT32 dist0,dist1,dist2; + long ccount; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + if (c0max > c0min) + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0min = c0min = c0; + goto have_c0min; + } + } +have_c0min: + if (c0max > c0min) + for (c0 = c0max; c0 >= c0min; c0--) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c0max = c0max = c0; + goto have_c0max; + } + } +have_c0max: + if (c1max > c1min) + for (c1 = c1min; c1 <= c1max; c1++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1min = c1min = c1; + goto have_c1min; + } + } +have_c1min: + if (c1max > c1min) + for (c1 = c1max; c1 >= c1min; c1--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) + if (*histp++ != 0) { + boxp->c1max = c1max = c1; + goto have_c1max; + } + } +have_c1max: + if (c2max > c2min) + for (c2 = c2min; c2 <= c2max; c2++) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2min = c2min = c2; + goto have_c2min; + } + } +have_c2min: + if (c2max > c2min) + for (c2 = c2max; c2 >= c2min; c2--) + for (c0 = c0min; c0 <= c0max; c0++) { + histp = & histogram[c0][c1min][c2]; + for (c1 = c1min; c1 <= c1max; c1++, histp += HIST_C2_ELEMS) + if (*histp != 0) { + boxp->c2max = c2max = c2; + goto have_c2max; + } + } +have_c2max: + + dist0 = ((c0max - c0min) << C0_SHIFT) * C0_SCALE; + dist1 = ((c1max - c1min) << C1_SHIFT) * C1_SCALE; + dist2 = ((c2max - c2min) << C2_SHIFT) * C2_SCALE; + boxp->volume = dist0*dist0 + dist1*dist1 + dist2*dist2; + + ccount = 0; + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++, histp++) + if (*histp != 0) { + ccount++; + } + } + boxp->colorcount = ccount; +} + + +static int median_cut (boxptr boxlist, int numboxes, int desired_colors) +{ + int n,lb; + int c0,c1,c2,cmax; + register boxptr b1,b2; + + while (numboxes < desired_colors) { + /* Select box to split. + * Current algorithm: by population for first half, then by volume. + */ + if (numboxes*2 <= desired_colors) { + b1 = find_biggest_color_pop(boxlist, numboxes); + } else { + b1 = find_biggest_volume(boxlist, numboxes); + } + if (b1 == NULL) /* no splittable boxes left! */ + break; + b2 = &boxlist[numboxes]; /* where new box will go */ + /* Copy the color bounds to the new box. */ + b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max; + b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min; + /* Choose which axis to split the box on. + */ + c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE; + c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE; + c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE; + cmax = c1; n = 1; + if (c0 > cmax) { cmax = c0; n = 0; } + if (c2 > cmax) { n = 2; } + switch (n) { + case 0: + lb = (b1->c0max + b1->c0min) / 2; + b1->c0max = lb; + b2->c0min = lb+1; + break; + case 1: + lb = (b1->c1max + b1->c1min) / 2; + b1->c1max = lb; + b2->c1min = lb+1; + break; + case 2: + lb = (b1->c2max + b1->c2min) / 2; + b1->c2max = lb; + b2->c2min = lb+1; + break; + } + /* Update stats for boxes */ + update_box(b1); + update_box(b2); + numboxes++; + } + return numboxes; +} + + +static void compute_color (boxptr boxp, int icolor) +{ + /* Current algorithm: mean weighted by pixels (not colors) */ + /* Note it is important to get the rounding correct! */ + hist2d * histogram = sl_histogram; + histptr histp; + int c0,c1,c2; + int c0min,c0max,c1min,c1max,c2min,c2max; + long count; + long total = 0; + long c0total = 0; + long c1total = 0; + long c2total = 0; + + c0min = boxp->c0min; c0max = boxp->c0max; + c1min = boxp->c1min; c1max = boxp->c1max; + c2min = boxp->c2min; c2max = boxp->c2max; + + for (c0 = c0min; c0 <= c0max; c0++) + for (c1 = c1min; c1 <= c1max; c1++) { + histp = & histogram[c0][c1][c2min]; + for (c2 = c2min; c2 <= c2max; c2++) { + if ((count = *histp++) != 0) { + total += count; + c0total += ((c0 << C0_SHIFT) + ((1<>1)) * count; + c1total += ((c1 << C1_SHIFT) + ((1<>1)) * count; + c2total += ((c2 << C2_SHIFT) + ((1<>1)) * count; + } + } + } + + sl_colormap[0][icolor] = (JSAMPLE) ((c0total + (total>>1)) / total); + sl_colormap[1][icolor] = (JSAMPLE) ((c1total + (total>>1)) / total); + sl_colormap[2][icolor] = (JSAMPLE) ((c2total + (total>>1)) / total); +} + + +static void slow_select_colors (int *descolors) +/* Master routine for color selection */ +{ + box boxlist[MAXNUMCOLORS]; + int numboxes; + int i; + + /* Initialize one box containing whole space */ + numboxes = 1; + boxlist[0].c0min = 0; + boxlist[0].c0max = 255 >> C0_SHIFT; + boxlist[0].c1min = 0; + boxlist[0].c1max = 255 >> C1_SHIFT; + boxlist[0].c2min = 0; + boxlist[0].c2max = 255 >> C2_SHIFT; + /* Shrink it to actually-used volume and set its statistics */ + update_box(& boxlist[0]); + /* Perform median-cut to produce final box list */ + numboxes = median_cut(boxlist, numboxes, *descolors); + /* Compute the representative color for each box, fill colormap */ + for (i = 0; i < numboxes; i++) + compute_color(& boxlist[i], i); + sl_num_colors = numboxes; + + *descolors = sl_num_colors; +} + + +/* log2(histogram cells in update box) for each axis; this can be adjusted */ +#define BOX_C0_LOG (HIST_C0_BITS-3) +#define BOX_C1_LOG (HIST_C1_BITS-3) +#define BOX_C2_LOG (HIST_C2_BITS-3) + +#define BOX_C0_ELEMS (1<> 1; + maxc1 = minc1 + ((1 << BOX_C1_SHIFT) - (1 << C1_SHIFT)); + centerc1 = (minc1 + maxc1) >> 1; + maxc2 = minc2 + ((1 << BOX_C2_SHIFT) - (1 << C2_SHIFT)); + centerc2 = (minc2 + maxc2) >> 1; + + minmaxdist = 0x7FFFFFFFL; + + for (i = 0; i < numcolors; i++) { + /* We compute the squared-c0-distance term, then add in the other two. */ + x = sl_colormap[0][i]; + if (x < minc0) { + tdist = (x - minc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else if (x > maxc0) { + tdist = (x - maxc0) * C0_SCALE; + min_dist = tdist*tdist; + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + min_dist = 0; + if (x <= centerc0) { + tdist = (x - maxc0) * C0_SCALE; + max_dist = tdist*tdist; + } else { + tdist = (x - minc0) * C0_SCALE; + max_dist = tdist*tdist; + } + } + + x = sl_colormap[1][i]; + if (x < minc1) { + tdist = (x - minc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc1) { + tdist = (x - maxc1) * C1_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc1) { + tdist = (x - maxc1) * C1_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc1) * C1_SCALE; + max_dist += tdist*tdist; + } + } + + x = sl_colormap[2][i]; + if (x < minc2) { + tdist = (x - minc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else if (x > maxc2) { + tdist = (x - maxc2) * C2_SCALE; + min_dist += tdist*tdist; + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + /* within cell range so no contribution to min_dist */ + if (x <= centerc2) { + tdist = (x - maxc2) * C2_SCALE; + max_dist += tdist*tdist; + } else { + tdist = (x - minc2) * C2_SCALE; + max_dist += tdist*tdist; + } + } + + mindist[i] = min_dist; /* save away the results */ + if (max_dist < minmaxdist) + minmaxdist = max_dist; + } + + ncolors = 0; + for (i = 0; i < numcolors; i++) { + if (mindist[i] <= minmaxdist) + colorlist[ncolors++] = (JSAMPLE) i; + } + return ncolors; +} + + +static void find_best_colors (int minc0, int minc1, int minc2, int numcolors, + JSAMPLE colorlist[], JSAMPLE bestcolor[]) +{ + int ic0, ic1, ic2; + int i, icolor; + register INT32 * bptr; /* pointer into bestdist[] array */ + JSAMPLE * cptr; /* pointer into bestcolor[] array */ + INT32 dist0, dist1; /* initial distance values */ + register INT32 dist2; /* current distance in inner loop */ + INT32 xx0, xx1; /* distance increments */ + register INT32 xx2; + INT32 inc0, inc1, inc2; /* initial values for increments */ + /* This array holds the distance to the nearest-so-far color for each cell */ + INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Initialize best-distance for each cell of the update box */ + bptr = bestdist; + for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--) + *bptr++ = 0x7FFFFFFFL; + + /* Nominal steps between cell centers ("x" in Thomas article) */ +#define STEP_C0 ((1 << C0_SHIFT) * C0_SCALE) +#define STEP_C1 ((1 << C1_SHIFT) * C1_SCALE) +#define STEP_C2 ((1 << C2_SHIFT) * C2_SCALE) + + for (i = 0; i < numcolors; i++) { + icolor = colorlist[i]; + /* Compute (square of) distance from minc0/c1/c2 to this color */ + inc0 = (minc0 - (int) sl_colormap[0][icolor]) * C0_SCALE; + dist0 = inc0*inc0; + inc1 = (minc1 - (int) sl_colormap[1][icolor]) * C1_SCALE; + dist0 += inc1*inc1; + inc2 = (minc2 - (int) sl_colormap[2][icolor]) * C2_SCALE; + dist0 += inc2*inc2; + /* Form the initial difference increments */ + inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0; + inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1; + inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2; + /* Now loop over all cells in box, updating distance per Thomas method */ + bptr = bestdist; + cptr = bestcolor; + xx0 = inc0; + for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) { + dist1 = dist0; + xx1 = inc1; + for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) { + dist2 = dist1; + xx2 = inc2; + for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) { + if (dist2 < *bptr) { + *bptr = dist2; + *cptr = (JSAMPLE) icolor; + } + dist2 += xx2; + xx2 += 2 * STEP_C2 * STEP_C2; + bptr++; + cptr++; + } + dist1 += xx1; + xx1 += 2 * STEP_C1 * STEP_C1; + } + dist0 += xx0; + xx0 += 2 * STEP_C0 * STEP_C0; + } + } +} + + +static void fill_inverse_cmap (int c0, int c1, int c2) +{ + hist2d * histogram = sl_histogram; + int minc0, minc1, minc2; /* lower left corner of update box */ + int ic0, ic1, ic2; + register JSAMPLE * cptr; /* pointer into bestcolor[] array */ + register histptr cachep; /* pointer into main cache array */ + /* This array lists the candidate colormap indexes. */ + JSAMPLE colorlist[MAXNUMCOLORS]; + int numcolors; /* number of candidate colors */ + /* This array holds the actually closest colormap index for each cell. */ + JSAMPLE bestcolor[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS]; + + /* Convert cell coordinates to update box ID */ + c0 >>= BOX_C0_LOG; + c1 >>= BOX_C1_LOG; + c2 >>= BOX_C2_LOG; + + minc0 = (c0 << BOX_C0_SHIFT) + ((1 << C0_SHIFT) >> 1); + minc1 = (c1 << BOX_C1_SHIFT) + ((1 << C1_SHIFT) >> 1); + minc2 = (c2 << BOX_C2_SHIFT) + ((1 << C2_SHIFT) >> 1); + + numcolors = find_nearby_colors(minc0, minc1, minc2, colorlist); + + /* Determine the actually nearest colors. */ + find_best_colors(minc0, minc1, minc2, numcolors, colorlist, bestcolor); + + /* Save the best color numbers (plus 1) in the main cache array */ + c0 <<= BOX_C0_LOG; /* convert ID back to base cell indexes */ + c1 <<= BOX_C1_LOG; + c2 <<= BOX_C2_LOG; + cptr = bestcolor; + for (ic0 = 0; ic0 < BOX_C0_ELEMS; ic0++) { + for (ic1 = 0; ic1 < BOX_C1_ELEMS; ic1++) { + cachep = & histogram[c0+ic0][c1+ic1][c2]; + for (ic2 = 0; ic2 < BOX_C2_ELEMS; ic2++) { + *cachep++ = (histcell) (*cptr++ + 1); + } + } + } +} + + +static void slow_map_pixels(const byte *red, const byte *green, const byte *blue, int width, int height, byte *map) +{ + register LOCFSERROR cur0, cur1, cur2; /* current error or pixel value */ + LOCFSERROR belowerr0, belowerr1, belowerr2; /* error for pixel below cur */ + LOCFSERROR bpreverr0, bpreverr1, bpreverr2; /* error for below/prev col */ + register FSERRPTR errorptr; /* => fserrors[] at column before current */ + JSAMPROW inRptr, inGptr, inBptr; /* => current input pixel */ + JSAMPROW outptr; /* => current output pixel */ + histptr cachep; + int dir; /* +1 or -1 depending on direction */ + int dir3; /* 3*dir, for advancing errorptr */ + int row, col, offset; + int *error_limit = sl_error_limiter; + JSAMPROW colormap0 = sl_colormap[0]; + JSAMPROW colormap1 = sl_colormap[1]; + JSAMPROW colormap2 = sl_colormap[2]; + hist2d * histogram = sl_histogram; + + for (row = 0; row < height; row++) + { + offset = row * width; + + inRptr = (JSAMPROW)&red[offset]; + inGptr = (JSAMPROW)&green[offset]; + inBptr = (JSAMPROW)&blue[offset]; + outptr = &map[offset]; + + if (sl_on_odd_row) + { + /* work right to left in this row */ + offset = width-1; + + inRptr += offset; /* so point to rightmost pixel */ + inGptr += offset; /* so point to rightmost pixel */ + inBptr += offset; /* so point to rightmost pixel */ + + outptr += offset; + + dir = -1; + dir3 = -3; + errorptr = sl_fserrors + (width+1)*3; /* => entry after last column */ + sl_on_odd_row = FALSE; /* flip for next time */ + } + else + { + /* work left to right in this row */ + dir = 1; + dir3 = 3; + errorptr = sl_fserrors; /* => entry before first real column */ + sl_on_odd_row = TRUE; /* flip for next time */ + } + + /* Preset error values: no error propagated to first pixel from left */ + cur0 = cur1 = cur2 = 0; + /* and no error propagated to row below yet */ + belowerr0 = belowerr1 = belowerr2 = 0; + bpreverr0 = bpreverr1 = bpreverr2 = 0; + + for (col = width; col > 0; col--) + { + cur0 = (cur0 + errorptr[dir3+0] + 8) >> 4; + cur1 = (cur1 + errorptr[dir3+1] + 8) >> 4; + cur2 = (cur2 + errorptr[dir3+2] + 8) >> 4; + + cur0 = error_limit[cur0]; + cur1 = error_limit[cur1]; + cur2 = error_limit[cur2]; + + cur0 += inRptr[0]; + cur1 += inGptr[0]; + cur2 += inBptr[0]; + + RANGE(cur0, 0, 255); + RANGE(cur1, 0, 255); + RANGE(cur2, 0, 255); + + /* Index into the cache with adjusted pixel value */ + cachep = & histogram[cur0>>C0_SHIFT][cur1>>C1_SHIFT][cur2>>C2_SHIFT]; + + /* If we have not seen this color before, find nearest colormap */ + /* entry and update the cache */ + if (*cachep == 0) + fill_inverse_cmap(cur0>>C0_SHIFT, cur1>>C1_SHIFT, cur2>>C2_SHIFT); + + /* Now emit the colormap index for this cell */ + { + register int pixcode = *cachep - 1; + *outptr = (JSAMPLE) pixcode; + /* Compute representation error for this pixel */ + cur0 -= (int) colormap0[pixcode]; + cur1 -= (int) colormap1[pixcode]; + cur2 -= (int) colormap2[pixcode]; + } + + /* Compute error fractions to be propagated to adjacent pixels. + * Add these into the running sums, and simultaneously shift the + * next-line error sums left by 1 column. */ + { + register LOCFSERROR bnexterr, delta; + bnexterr = cur0; /* Process component 0 */ + delta = cur0 * 2; + cur0 += delta; /* form error * 3 */ + errorptr[0] = (FSERROR) (bpreverr0 + cur0); + cur0 += delta; /* form error * 5 */ + bpreverr0 = belowerr0 + cur0; + belowerr0 = bnexterr; + cur0 += delta; /* form error * 7 */ + bnexterr = cur1; /* Process component 1 */ + delta = cur1 * 2; + cur1 += delta; /* form error * 3 */ + errorptr[1] = (FSERROR) (bpreverr1 + cur1); + cur1 += delta; /* form error * 5 */ + bpreverr1 = belowerr1 + cur1; + belowerr1 = bnexterr; + cur1 += delta; /* form error * 7 */ + bnexterr = cur2; /* Process component 2 */ + delta = cur2 * 2; + cur2 += delta; /* form error * 3 */ + errorptr[2] = (FSERROR) (bpreverr2 + cur2); + cur2 += delta; /* form error * 5 */ + bpreverr2 = belowerr2 + cur2; + belowerr2 = bnexterr; + cur2 += delta; /* form error * 7 */ + } + + /* At this point curN contains the 7/16 error value to be propagated + * to the next pixel on the current line, and all the errors for the + * next line have been shifted over. We are therefore ready to move on. + */ + inRptr += dir; /* Advance pixel pointers to next column */ + inGptr += dir; /* Advance pixel pointers to next column */ + inBptr += dir; /* Advance pixel pointers to next column */ + outptr += dir; + errorptr += dir3; /* advance errorptr to current column */ + } + + /* Post-loop cleanup: we must unload the final error values into the + * final fserrors[] entry. Note we need not unload belowerrN because + * it is for the dummy column before or after the actual array. + */ + errorptr[0] = (FSERROR) bpreverr0; /* unload prev errs into array */ + errorptr[1] = (FSERROR) bpreverr1; + errorptr[2] = (FSERROR) bpreverr2; + } +} + + +/* Allocate and fill in the error_limiter table */ +static void init_error_limit (void) +{ + int * table; + int in, out, STEPSIZE; + + table = (int *) malloc((size_t) ((255*2+1) * sizeof(int))); + if (! table) return; + + table += 255; /* so can index -255 .. +255 */ + sl_error_limiter = table; + + STEPSIZE = ((255+1)/16); + + /* Map errors 1:1 up to +- 255/16 */ + out = 0; + for (in = 0; in < STEPSIZE; in++, out++) + { + table[in] = out; + table[-in] = -out; + } + + /* Map errors 1:2 up to +- 3*255/16 */ + for (; in < STEPSIZE*3; in++, out += (in&1) ? 0 : 1) + { + table[in] = out; + table[-in] = -out; + } + + /* Clamp the rest to final out value (which is (255+1)/8) */ + for (; in <= 255; in++) + { + table[in] = out; + table[-in] = -out; + } +} + +void cdRGB2Map(int width, int height, const unsigned char *red, const unsigned char *green, const unsigned char *blue, unsigned char *map, int pal_size, long *colors) +{ + int i, err; + byte rm[256], gm[256], bm[256]; + int num_colors; + + if (pal_size <= 0 || pal_size > 256) + pal_size = 256; + + num_colors = pal_size; + + if (!quick_map(red, green, blue, width, height, map, rm, gm, bm, &num_colors)) + { + err = slow_quant(red, green, blue, width, height, map, rm, gm, bm, &num_colors); + if (err) + return; + } + + for (i=0; i < num_colors; i++) + *colors++ = cdEncodeColor(rm[i], gm[i], bm[i]); + + if (num_colors < pal_size) + { + for (i=num_colors; i < pal_size; i++) + *colors++ = 0; + } +} diff --git a/cd/src/sim/cd_truetype.c b/cd/src/sim/cd_truetype.c new file mode 100755 index 0000000..be0e860 --- /dev/null +++ b/cd/src/sim/cd_truetype.c @@ -0,0 +1,177 @@ +/** \file + * \brief Text and Font Simulation using FreeType library. + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd_truetype.h" + +/******************************************* + Inicializa o Rasterizador +********************************************/ + +#ifdef WIN32 +#include +static int ReadStringKey(HKEY base_key, char* key_name, char* value_name, char* value) +{ + HKEY key; + DWORD max_size = 512; + + if (RegOpenKeyEx(base_key, key_name, 0, KEY_READ, &key) != ERROR_SUCCESS) + return 0; + + if (RegQueryValueEx(key, value_name, NULL, NULL, (LPBYTE)value, &max_size) != ERROR_SUCCESS) + { + RegCloseKey(key); + return 0; + } + + RegCloseKey(key); + return 1; +} + +char* GetFontDir(void) +{ + static char font_dir[512]; + if (!ReadStringKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", "Fonts", font_dir)) + return ""; + else + { + int i, size = (int)strlen(font_dir); + for(i = 0; i < size; i++) + { + if (font_dir[i] == '\\') + font_dir[i] = '/'; + } + return font_dir; + } +} +#endif + +int cdTT_load(cdTT_Text * tt_text, const char *font, int size, double xres, double yres) +{ + char filename[10240]; + FILE *file; /* usado apenas para procurar pelo arquivo */ + FT_Error error; + FT_Face face; + + /* abre arq. no dir. corrente */ + sprintf(filename, "%s.ttf", font); + file = fopen(filename, "r"); + + if (file) + fclose(file); + else + { + /* se nao conseguiu, abre arq. no dir. do cd, */ + char* env = getenv("CDDIR"); + if (env) + { + sprintf(filename, "%s/%s.ttf", env, font); + file = fopen(filename, "r"); + } + + if (file) + fclose(file); + else + { +#ifdef WIN32 + /* no caso do Windows procura no seu diretorio de fontes. */ + sprintf(filename, "%s/%s.ttf", GetFontDir(), font); + file = fopen(filename, "r"); + + if (file) + fclose(file); + else + return 0; +#else + return 0; +#endif + } + } + + error = FT_New_Face(tt_text->library, filename, 0, &face ); + if (error) + return 0; + + /* char_height is 1/64th of points */ + error = FT_Set_Char_Size(face, 0, size*64, (int)(xres*25.4), (int)(yres*25.4)); + if (error) + { + FT_Done_Face(face); + return 0; + } + + if (tt_text->face && tt_text->face != face) + FT_Done_Face(tt_text->face); + + tt_text->face = face; + + tt_text->ascent = face->size->metrics.ascender >> 6; + tt_text->descent = abs(face->size->metrics.descender >> 6); + tt_text->max_height = face->size->metrics.height >> 6; + tt_text->max_width = face->size->metrics.max_advance >> 6; + + if (!face->charmap) + FT_Set_Charmap(face, face->charmaps[0]); + + return 1; +} + +static void cdTT_checkversion(cdTT_Text* tt_text) +{ + FT_Int major, minor, patch; + FT_Library_Version(tt_text->library, &major, &minor, &patch); + if (major != FREETYPE_MAJOR || + minor != FREETYPE_MINOR || + patch != FREETYPE_PATCH) + { + printf("CD - Canvas Draw: Warning - Different FreeType library used!\n" + " Compiled = %d.%d.%d\n" + " RunTime = %d.%d.%d\n", + FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, major, minor, patch); + } +} + +/******************************************* + Inicializaccao +********************************************/ +cdTT_Text* cdTT_create(void) +{ + cdTT_Text * tt_text = malloc(sizeof(cdTT_Text)); + memset(tt_text, 0, sizeof(cdTT_Text)); + + FT_Init_FreeType(&tt_text->library); + + cdTT_checkversion(tt_text); + + return tt_text; +} + +/******************************************* + Desaloca Recursos +********************************************/ +void cdTT_free(cdTT_Text * tt_text) +{ + if (tt_text->rgba_data) + free(tt_text->rgba_data); + + if (tt_text->face) + FT_Done_Face(tt_text->face); + + FT_Done_FreeType(tt_text->library); + + free(tt_text); +} + +#ifdef SunOS_OLD +void *memmove( void *dest, const void *src, size_t count ) +{ + return memcpy(dest, src, count); +} +#endif diff --git a/cd/src/sim/cd_truetype.h b/cd/src/sim/cd_truetype.h new file mode 100755 index 0000000..f29fb82 --- /dev/null +++ b/cd/src/sim/cd_truetype.h @@ -0,0 +1,46 @@ +/** \file + * \brief Text and Font Simulation using FreeType library. + * + * See Copyright Notice in cd.h + */ + +#ifndef __TRUETYPE_H +#define __TRUETYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ft2build.h" +#include FT_FREETYPE_H + +/* + In CD version 4.4 we start to use FreeType 2. + Only TrueType font support is enabled. +*/ + +typedef struct _cdTT_Text +{ + FT_Library library; + FT_Face face; + + unsigned char* rgba_data; /* the image where one character is drawn with the foreground color during text output */ + int rgba_data_size; + + int max_height; + int max_width; + int descent; + int ascent; + +}cdTT_Text; + +cdTT_Text* cdTT_create(void); +void cdTT_free(cdTT_Text * tt_text); +int cdTT_load(cdTT_Text * tt_text, const char *font,int size, double xres, double yres); + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef _CD_TRUETYPE_ */ + diff --git a/cd/src/sim/cdfontex.c b/cd/src/sim/cdfontex.c new file mode 100755 index 0000000..bafa5e7 --- /dev/null +++ b/cd/src/sim/cdfontex.c @@ -0,0 +1,646 @@ +/** \file + * \brief Font Properties Estimation + * + * See Copyright Notice in cd.h + */ + + +#include "cd.h" +#include "cd_private.h" +#include +#include + +typedef struct _cd_font_styles +{ + unsigned char s[4]; +}cd_font_styles; + +static cd_font_styles helv[256] = { +{0, 0, 0, 0}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{30, 30, 30, 30}, +{30, 30, 30, 35}, +{35, 50, 35, 50}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{90, 85, 90, 90}, +{70, 75, 70, 75}, +{20, 25, 20, 25}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{40, 40, 40, 40}, +{60, 60, 60, 60}, +{30, 30, 30, 30}, +{35, 35, 35, 35}, +{30, 30, 30, 30}, +{30, 30, 30, 30}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{30, 35, 30, 35}, +{30, 35, 30, 35}, +{60, 60, 60, 60}, +{60, 60, 60, 60}, +{60, 60, 60, 60}, +{55, 65, 55, 60}, +{100, 100, 100, 100}, +{65, 70, 70, 75}, +{70, 70, 70, 70}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{70, 65, 70, 70}, +{60, 60, 65, 65}, +{80, 80, 80, 80}, +{70, 70, 75, 75}, +{25, 30, 30, 30}, +{50, 55, 55, 55}, +{70, 75, 70, 75}, +{55, 65, 55, 65}, +{80, 85, 85, 90}, +{70, 70, 75, 75}, +{80, 80, 80, 80}, +{65, 70, 70, 70}, +{80, 80, 80, 80}, +{75, 70, 75, 75}, +{70, 70, 70, 70}, +{60, 65, 65, 65}, +{70, 70, 75, 75}, +{65, 70, 70, 70}, +{100, 95, 100, 95}, +{65, 70, 70, 70}, +{65, 65, 70, 65}, +{60, 60, 65, 65}, +{30, 35, 30, 35}, +{30, 30, 30, 30}, +{30, 35, 30, 35}, +{45, 60, 50, 60}, +{55, 55, 55, 55}, +{35, 35, 35, 35}, +{55, 60, 55, 60}, +{55, 65, 60, 65}, +{55, 55, 55, 55}, +{55, 65, 55, 60}, +{55, 60, 55, 55}, +{30, 35, 30, 35}, +{55, 65, 55, 60}, +{55, 65, 55, 65}, +{25, 30, 25, 30}, +{25, 30, 25, 30}, +{50, 60, 55, 60}, +{25, 30, 25, 30}, +{85, 90, 85, 90}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 65, 55, 60}, +{55, 65, 55, 65}, +{35, 40, 35, 40}, +{55, 55, 55, 55}, +{30, 35, 30, 35}, +{55, 65, 55, 60}, +{50, 55, 50, 55}, +{75, 80, 70, 80}, +{50, 60, 50, 55}, +{50, 55, 50, 55}, +{50, 55, 50, 50}, +{35, 40, 35, 40}, +{25, 30, 25, 30}, +{35, 40, 35, 40}, +{60, 60, 60, 60}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{25, 30, 25, 30}, +{55, 55, 55, 55}, +{35, 55, 30, 55}, +{100, 100, 100, 100}, +{55, 55, 55, 55}, +{55, 55, 55, 55}, +{35, 35, 35, 35}, +{100, 105, 100, 100}, +{70, 70, 70, 70}, +{35, 35, 35, 35}, +{100, 105, 100, 100}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{25, 30, 20, 30}, +{25, 30, 20, 30}, +{35, 55, 35, 55}, +{35, 55, 30, 55}, +{35, 35, 35, 35}, +{55, 55, 55, 55}, +{100, 100, 100, 100}, +{30, 35, 30, 35}, +{100, 100, 100, 100}, +{55, 55, 55, 55}, +{35, 35, 35, 35}, +{95, 95, 95, 95}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{65, 65, 70, 65}, +{30, 30, 30, 30}, +{30, 30, 35, 35}, +{55, 55, 55, 60}, +{55, 55, 55, 55}, +{60, 55, 60, 55}, +{55, 55, 55, 55}, +{25, 30, 25, 30}, +{55, 55, 55, 55}, +{35, 35, 35, 35}, +{75, 75, 75, 80}, +{35, 40, 40, 40}, +{55, 55, 55, 55}, +{60, 60, 60, 60}, +{35, 35, 35, 35}, +{75, 75, 75, 80}, +{55, 55, 55, 55}, +{40, 40, 40, 40}, +{55, 55, 55, 60}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{60, 60, 55, 60}, +{55, 55, 55, 55}, +{30, 30, 30, 30}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{40, 40, 40, 40}, +{55, 55, 55, 55}, +{85, 85, 85, 85}, +{85, 85, 85, 85}, +{85, 85, 85, 85}, +{60, 65, 65, 60}, +{65, 70, 70, 75}, +{65, 70, 70, 75}, +{65, 70, 70, 75}, +{65, 70, 70, 75}, +{65, 70, 70, 75}, +{65, 70, 70, 75}, +{100, 100, 100, 100}, +{75, 75, 75, 75}, +{70, 65, 70, 70}, +{70, 65, 70, 70}, +{70, 65, 70, 70}, +{70, 65, 70, 70}, +{25, 30, 30, 30}, +{25, 30, 30, 30}, +{25, 30, 30, 30}, +{25, 30, 30, 30}, +{75, 75, 75, 75}, +{70, 70, 75, 75}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{60, 60, 60, 60}, +{80, 80, 80, 80}, +{70, 70, 75, 75}, +{70, 70, 75, 75}, +{70, 70, 75, 75}, +{70, 70, 75, 75}, +{65, 65, 70, 65}, +{70, 70, 70, 70}, +{65, 65, 65, 65}, +{55, 60, 55, 60}, +{55, 60, 55, 60}, +{55, 60, 55, 60}, +{55, 60, 55, 60}, +{55, 60, 55, 60}, +{55, 60, 55, 60}, +{90, 90, 90, 90}, +{55, 55, 55, 55}, +{55, 60, 55, 55}, +{55, 60, 55, 55}, +{55, 60, 55, 55}, +{55, 60, 55, 55}, +{25, 30, 25, 30}, +{25, 30, 25, 30}, +{25, 30, 25, 30}, +{25, 30, 25, 30}, +{55, 65, 55, 60}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 65, 55, 65}, +{55, 55, 55, 55}, +{60, 65, 65, 60}, +{55, 65, 55, 60}, +{55, 65, 55, 60}, +{55, 65, 55, 60}, +{55, 65, 55, 60}, +{50, 55, 50, 55}, +{55, 65, 55, 65}, +{50, 55, 50, 55} +}; + +static cd_font_styles times[256] = { +{0, 0, 0, 0}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{25, 25, 25, 25}, +{35, 35, 30, 35}, +{40, 55, 45, 55}, +{55, 55, 55, 50}, +{50, 55, 55, 55}, +{85, 100, 85, 85}, +{80, 85, 75, 80}, +{20, 30, 25, 30}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{50, 55, 55, 55}, +{60, 60, 70, 60}, +{25, 25, 25, 25}, +{35, 35, 35, 35}, +{25, 25, 25, 25}, +{30, 30, 30, 30}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{25, 35, 35, 35}, +{30, 35, 35, 35}, +{60, 60, 70, 60}, +{60, 60, 70, 60}, +{60, 60, 70, 60}, +{45, 55, 55, 55}, +{95, 95, 95, 85}, +{70, 70, 60, 70}, +{65, 70, 65, 70}, +{70, 75, 70, 70}, +{75, 75, 75, 75}, +{60, 65, 65, 70}, +{55, 60, 60, 70}, +{70, 80, 75, 75}, +{75, 80, 75, 80}, +{35, 40, 35, 40}, +{40, 55, 45, 50}, +{75, 80, 65, 70}, +{60, 65, 55, 65}, +{90, 95, 85, 90}, +{75, 75, 70, 75}, +{75, 80, 75, 75}, +{60, 65, 60, 65}, +{75, 80, 75, 75}, +{65, 75, 65, 70}, +{55, 60, 55, 55}, +{65, 65, 55, 65}, +{70, 70, 75, 75}, +{70, 70, 60, 65}, +{95, 100, 80, 90}, +{70, 70, 65, 70}, +{70, 70, 55, 65}, +{60, 65, 55, 65}, +{35, 35, 40, 35}, +{30, 30, 30, 30}, +{35, 35, 45, 35}, +{45, 60, 45, 60}, +{55, 55, 55, 55}, +{35, 35, 35, 35}, +{45, 50, 55, 55}, +{50, 55, 55, 50}, +{45, 45, 45, 45}, +{50, 55, 55, 55}, +{45, 50, 45, 45}, +{35, 35, 30, 35}, +{50, 55, 55, 50}, +{50, 55, 55, 55}, +{25, 30, 30, 30}, +{25, 35, 30, 30}, +{50, 55, 50, 55}, +{25, 30, 30, 30}, +{75, 85, 75, 80}, +{50, 55, 55, 55}, +{50, 50, 55, 50}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{35, 45, 40, 40}, +{40, 40, 40, 40}, +{30, 35, 30, 30}, +{50, 55, 55, 55}, +{50, 50, 45, 45}, +{70, 70, 65, 70}, +{50, 50, 45, 55}, +{50, 50, 45, 45}, +{45, 45, 40, 40}, +{50, 40, 40, 35}, +{20, 25, 30, 25}, +{50, 40, 40, 35}, +{55, 55, 55, 60}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{35, 35, 35, 35}, +{50, 55, 50, 55}, +{45, 55, 55, 55}, +{100, 100, 90, 100}, +{50, 50, 55, 55}, +{50, 55, 55, 55}, +{35, 35, 35, 35}, +{100, 100, 100, 105}, +{55, 60, 55, 55}, +{35, 35, 35, 35}, +{90, 100, 95, 95}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{35, 35, 35, 35}, +{35, 35, 35, 35}, +{45, 55, 55, 55}, +{45, 55, 55, 55}, +{35, 40, 35, 35}, +{55, 55, 55, 55}, +{100, 100, 90, 100}, +{35, 35, 35, 35}, +{100, 105, 100, 100}, +{40, 40, 40, 40}, +{35, 35, 35, 35}, +{75, 75, 70, 75}, +{80, 80, 80, 80}, +{80, 80, 80, 80}, +{70, 70, 55, 65}, +{25, 25, 25, 25}, +{35, 30, 40, 35}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{55, 55, 50, 50}, +{55, 55, 55, 55}, +{20, 25, 30, 25}, +{50, 55, 55, 55}, +{35, 40, 30, 35}, +{75, 75, 75, 75}, +{30, 30, 30, 30}, +{50, 55, 55, 55}, +{60, 60, 70, 60}, +{35, 35, 35, 35}, +{75, 75, 80, 75}, +{55, 55, 55, 55}, +{40, 40, 40, 40}, +{55, 55, 55, 55}, +{30, 30, 30, 30}, +{30, 30, 30, 30}, +{30, 35, 35, 35}, +{55, 60, 60, 60}, +{45, 55, 55, 55}, +{25, 25, 25, 25}, +{30, 35, 35, 35}, +{30, 30, 30, 30}, +{30, 35, 35, 30}, +{50, 55, 55, 55}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{75, 75, 75, 75}, +{45, 55, 50, 55}, +{70, 70, 60, 70}, +{70, 70, 60, 70}, +{70, 70, 60, 70}, +{70, 70, 60, 70}, +{70, 70, 60, 70}, +{70, 70, 60, 70}, +{90, 100, 90, 95}, +{70, 75, 70, 70}, +{60, 65, 65, 70}, +{60, 65, 65, 70}, +{60, 65, 65, 70}, +{60, 65, 65, 70}, +{35, 40, 35, 40}, +{35, 40, 35, 40}, +{35, 40, 35, 40}, +{35, 40, 35, 40}, +{75, 75, 75, 75}, +{75, 75, 70, 75}, +{75, 80, 75, 75}, +{75, 80, 75, 75}, +{75, 80, 75, 75}, +{75, 80, 75, 75}, +{75, 80, 75, 75}, +{60, 60, 70, 60}, +{75, 80, 75, 75}, +{75, 70, 75, 75}, +{75, 70, 75, 75}, +{75, 70, 75, 75}, +{75, 70, 75, 75}, +{70, 70, 55, 65}, +{60, 65, 65, 65}, +{50, 55, 55, 55}, +{45, 50, 55, 55}, +{45, 50, 55, 55}, +{45, 50, 55, 55}, +{45, 50, 55, 55}, +{45, 50, 55, 55}, +{45, 50, 55, 55}, +{70, 75, 70, 75}, +{45, 45, 45, 45}, +{45, 50, 45, 45}, +{45, 50, 45, 45}, +{45, 50, 45, 45}, +{45, 50, 45, 45}, +{30, 30, 30, 30}, +{30, 30, 30, 30}, +{30, 30, 30, 30}, +{30, 30, 30, 30}, +{55, 50, 55, 55}, +{50, 55, 55, 55}, +{50, 50, 55, 50}, +{50, 50, 55, 50}, +{50, 50, 55, 50}, +{50, 50, 55, 50}, +{50, 50, 55, 50}, +{55, 55, 55, 55}, +{55, 50, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 55, 55, 55}, +{50, 50, 45, 45}, +{55, 55, 50, 50}, +{50, 50, 45, 45} +}; + + +typedef struct _cdFontType +{ + int max_width, line_height, ascent, descent, style, size; + double sizex; + int (*CharWidth)(char c); +}cdFontType; + + +static cdFontType font; + + +static int CharWidthCourier(char c) +{ + (void)c; + return (int)(0.60 * font.sizex + 0.5); +} + + +static int CharWidthTimesRoman(char c) +{ + return (int)(times[(int)c].s[font.style] * font.sizex / 100 + 0.5); +} + + +static int CharWidthHelvetica(char c) +{ + return (int)(helv[(int)c].s[font.style] * font.sizex / 100 + 0.5); +} + + +static void cdFontEx(cdCanvas* canvas, const char* type_face, int style, int size) +{ + double mm_dx, mm_dy; + double sizey, sizex; + + font.style = style; + + if (size < 0) + { + double size_mm; + cdCanvasPixel2MM(canvas, -size, 0, &size_mm, NULL); + size = (int)(size_mm * CD_MM2PT + 0.5); + } + + font.size = size; + + cdCanvasPixel2MM(canvas, 1, 1, &mm_dx, &mm_dy); + + sizey = ((25.4 / 72) / mm_dy) * size; + sizex = ((25.4 / 72) / mm_dx) * size; + + font.sizex = sizex; + + font.line_height = (int)(1.2 * sizey + 0.5); + font.ascent = (int)(0.75 * font.line_height + 0.5); + font.descent = (int)(0.20 * font.line_height + 0.5); + + if (strcmp(type_face, "Times")==0) + { + if (style == CD_PLAIN || style == CD_BOLD) + font.max_width = (int)(1.05 * sizex + 0.5); + else + font.max_width = (int)(1.15 * sizex + 0.5); + + font.CharWidth = CharWidthTimesRoman; + } + else if (strcmp(type_face, "Helvetica")==0) + { + if (style == CD_PLAIN || style == CD_BOLD) + font.max_width = (int)(1.05 * sizex + 0.5); + else + font.max_width = (int)(1.15 * sizex + 0.5); + + font.CharWidth = CharWidthHelvetica; + } + else + { + if (style == CD_PLAIN || style == CD_ITALIC) + font.max_width = (int)(0.65 * sizex + 0.5); + else + font.max_width = (int)(0.80 * sizex + 0.5); + + font.CharWidth = CharWidthCourier; + } +} + +void cdgetfontdimEX(cdCtxCanvas* ctxcanvas, int *max_width, int *line_height, int *ascent, int *descent) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + cdFontEx(canvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + if (line_height) *line_height = font.line_height; + if (max_width) *max_width = font.max_width; + if (ascent) *ascent = font.ascent; + if (descent) *descent = font.descent; +} + +void cdgettextsizeEX(cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height) +{ + int i = 0, w = 0; + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + cdFontEx(canvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + while (i < len) + { + w += font.CharWidth(s[i]); + i++; + } + + if (height) *height = font.line_height; + if (width) *width = w; +} diff --git a/cd/src/sim/sim.c b/cd/src/sim/sim.c new file mode 100755 index 0000000..349624a --- /dev/null +++ b/cd/src/sim/sim.c @@ -0,0 +1,326 @@ +/** \file + * \brief Simulation Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cd_truetype.h" +#include "sim.h" + + +static unsigned char SimHatchBits[6][8] = { /* [style][y] (8x8) */ + {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */ + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */ + {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */ + {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */ + {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */ + {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */ + +#define CalcYPat(y, h) (canvas->invert_yaxis? h-1-(y%h): y%h) +#define CalcYHatch(y, h) (canvas->invert_yaxis? h-(y&h): y&h) + +void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth) +{ + unsigned char aa_alpha; + long color, aa_color; + + switch(canvas->interior_style) + { + default: /* CD_SOLID */ + { + color = canvas->foreground; + break; + } + case CD_PATTERN: + { + long *pattern = canvas->pattern; + int yp = CalcYPat(y, canvas->pattern_h); + int xp = x % canvas->pattern_w; + color = pattern[canvas->pattern_w*yp + xp]; + break; + } + case CD_HATCH: + { + unsigned char hatch = SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)]; + unsigned char n = (unsigned char)(x&7); + simRotateHatchN(hatch, n); + if (hatch & 0x80) + color = canvas->foreground; + else if (canvas->back_opacity == CD_OPAQUE) + color = canvas->background; + else + return; + break; + } + case CD_STIPPLE: + { + unsigned char *stipple = canvas->stipple; + int yp = CalcYPat(y, canvas->stipple_h); + int xp = x % canvas->stipple_w; + if(stipple[canvas->stipple_w*yp + xp]) + color = canvas->foreground; + else if (canvas->back_opacity == CD_OPAQUE) + color = canvas->background; + else + return; + break; + } + } + + aa_alpha = (unsigned char)((alpha_weigth * cdAlpha(color)) / 255); + aa_color = cdEncodeAlpha(color, aa_alpha); + canvas->cxPixel(canvas->ctxcanvas, x, y, aa_color); +} + +void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax) +{ + cdCanvas* canvas = simulation->canvas; + + if(xmin > xmax) + _cdSwapInt(xmin, xmax); + + switch(canvas->interior_style) + { + case CD_SOLID: + simulation->SolidLine(canvas, xmin,y,xmax); + break; + case CD_PATTERN: + simulation->PatternLine(canvas, xmin,xmax,y,canvas->pattern_w, + canvas->pattern + + canvas->pattern_w*CalcYPat(y, canvas->pattern_h)); + break; + case CD_HATCH: + simulation->HatchLine(canvas, xmin,xmax,y,SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)]); + break; + case CD_STIPPLE: + simulation->StippleLine(canvas, xmin, xmax, y, + canvas->stipple_w, + canvas->stipple + + canvas->stipple_w*CalcYPat(y, canvas->stipple_h)); + } +} + +static void simSolidLine(cdCanvas* canvas, int xmin, int y, int xmax) +{ + /* cdpolySIM and cdboxSIM will set line attributes so this can work */ + canvas->cxLine(canvas->ctxcanvas, xmin, y, xmax, y); +} + +static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern) +{ + cdSimulation* simulation = canvas->simulation; + int x,i; + int xb; + long curColor, old_color; + + i = xmin % pw; + + old_color = canvas->foreground; + + for (x = xmin; x <= xmax;) + { + if (i == pw) + i = 0; + + curColor=pattern[i]; + xb=x; + + while(pattern[i]==curColor && (x <= xmax)) + { + i++; + if (i == pw) + i = 0; + x++; + } + + if(xb==x-1) + canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor); + else + { + cdCanvasSetForeground(canvas, curColor); + simulation->SolidLine(canvas, xb,y,x-1); + } + } + + cdCanvasSetForeground(canvas, old_color); +} + +static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple) +{ + cdSimulation* simulation = canvas->simulation; + int x,xb,i; + long fgColor,bgColor; + int opacity; + int curCase; + + fgColor = canvas->foreground; + opacity=canvas->back_opacity; + + if(opacity==CD_OPAQUE) + { + bgColor=canvas->background; + cdCanvasSetForeground(canvas, fgColor); + for (x = xmin, i=xmin%pw ; x <= xmax;) + { + if(i==pw) + i=0; + xb=x; + curCase=stipple[i]; + while (stipple[i]==curCase && (x<=xmax)) + { + x++; + i++; + if(i==pw) + i=0; + } + if (curCase) + { + if(xb==x-1) + canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor); + else + simulation->SolidLine(canvas, xb,y,x-1); + } + } + cdCanvasSetForeground(canvas, bgColor); + for (x = xmin, i=xmin%pw ; x <= xmax;) + { + if(i==pw) + i=0; + xb=x; + curCase=stipple[i]; + while (stipple[i]==curCase && (x<=xmax)) + { + x++; + i++; + if(i==pw) + i=0; + } + if (!curCase) + { + if(xb==x-1) + canvas->cxPixel(canvas->ctxcanvas, xb,y,bgColor); + else + simulation->SolidLine(canvas, xb,y,x-1); + } + } + } + else + { + cdCanvasSetForeground(canvas, fgColor); + for (x = xmin,i=xmin%pw; x <= xmax;) + { + xb=x; + curCase=stipple[i]; + while (stipple[i]==curCase && (x<=xmax)) + { + i++; + x++; + if(i==pw) + i=0; + } + if(curCase) + { + if(xb==x-1) + canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor); + else + simulation->SolidLine(canvas, xb,y,x-1); + } + } + } + cdCanvasSetForeground(canvas, fgColor); +} + +static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch) +{ + cdSimulation* simulation = canvas->simulation; + int x,xb; + int opacity, mask; + unsigned char startp, n; + long curColor, fgColor, bgColor; + + n = (unsigned char)(xmin&7); + simRotateHatchN(hatch,n); + fgColor=canvas->foreground; + opacity=canvas->back_opacity; + + if(opacity==CD_OPAQUE) + { + bgColor=canvas->background; + for (x = xmin; x <= xmax; x++) + { + curColor=(hatch&0x80)?fgColor:bgColor; + + xb=x; + startp = hatch&0x80? 1: 0; + _cdRotateHatch(hatch); + while (startp == (hatch&0x80? 1: 0) && x <= xmax) + { + x++; + _cdRotateHatch(hatch); + } + + if(xb==x) + canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor); + else + { + cdCanvasSetForeground(canvas, curColor); + simulation->SolidLine(canvas, xb,y,x); + } + } + } + else + { + cdCanvasSetForeground(canvas, fgColor); + for (x = xmin; x <= xmax; x++) + { + mask=(hatch&0x80)?1:0; + + xb=x; + startp = hatch&0x80? 1: 0; + _cdRotateHatch(hatch); + while (startp == (hatch&0x80? 1: 0) && x <= xmax) + { + x++; + _cdRotateHatch(hatch); + } + + if(mask) + { + if(xb==x) + canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor); + else + simulation->SolidLine(canvas, xb,y,x); + } + } + } + + cdCanvasSetForeground(canvas, fgColor); +} + +cdSimulation* cdCreateSimulation(cdCanvas* canvas) +{ + cdSimulation* simulation = (cdSimulation*)malloc(sizeof(cdSimulation)); + memset(simulation, 0, sizeof(cdSimulation)); + + simulation->canvas = canvas; + + simulation->SolidLine = simSolidLine; + simulation->PatternLine = simPatternLine; + simulation->StippleLine = simStippleLine; + simulation->HatchLine = simHatchLine; + + return simulation; +} + +void cdKillSimulation(cdSimulation* simulation) +{ + memset(simulation, 0, sizeof(cdSimulation)); + free(simulation); +} diff --git a/cd/src/sim/sim.h b/cd/src/sim/sim.h new file mode 100755 index 0000000..fec3ce6 --- /dev/null +++ b/cd/src/sim/sim.h @@ -0,0 +1,55 @@ +/** \file + * \brief Simulation Base Driver + * + * See Copyright Notice in cd.h + */ + +#ifndef __SIM_H +#define __SIM_H + + +struct _cdSimulation +{ + int antialias; + + cdCanvas *canvas; + + const char* font_map[100]; + int font_map_n; + + /* horizontal line draw functions */ + void (*SolidLine)(cdCanvas* canvas, int xmin, int y, int xmax); + void (*PatternLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern); + void (*StippleLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple); + void (*HatchLine)(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch); +}; + +#define simRotateHatchN(_x,_n) ((_x) = ((_x) << (_n)) | ((_x) >> (8-(_n)))) + +void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth); +void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax); +int simIsPointInPolyWind(cdPoint* poly, int n, int x, int y); + +/* list of non-horizontal line segments */ +typedef struct _simLineSegment +{ + int x1, y1; /* always y1 < y2 */ + int x2, y2; /* (x2,y2) is not included in the segment to avoid duplicated intersections */ + int x; /* incremental x from x2 to x1 */ + int DeltaX, DeltaY, XDir; + unsigned short ErrorInc, ErrorAcc; +} simLineSegment; + +void simAddSegment(simLineSegment* segment, int x1, int y1, int x2, int y2, int *y_max, int *y_min); +int simSegmentInc(simLineSegment* segment, cdCanvas* canvas, int y); + +void simPolyFill(cdSimulation* simulation, cdPoint* poly, int n); +void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2); +void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2); +void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b); +extern int simLineStyleNoReset; + +int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height); + +#endif + diff --git a/cd/src/sim/sim_linepolyfill.c b/cd/src/sim/sim_linepolyfill.c new file mode 100755 index 0000000..1a20907 --- /dev/null +++ b/cd/src/sim/sim_linepolyfill.c @@ -0,0 +1,1000 @@ +/** \file + * \brief Primitives of the Simulation Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cd_truetype.h" +#include "sim.h" + + +/* para estilos de linha usando rotacao de bits */ +static const unsigned short int simLineStyleBitTable[5]= +{ + 0xFFFF, /* CD_CONTINUOUS */ + 0xFF00, /* CD_DASHED */ + 0x1111, /* CD_DOTTED */ + 0xFE10, /* CD_DASH_DOT */ + 0xFF24, /* CD_DASH_DOT_DOT*/ +}; +int simLineStyleNoReset = 0; +static unsigned short int simLineStyleLastBits = 0; + +#define simRotateLineStyle(_x) (((_x) & 0x8000)? ((_x) << 1)|(0x0001): ((_x) << 1)) + +#define INTENSITYSHIFT 8 /* # of bits by which to shift ErrorAcc to get intensity level */ + + +/* Point in Polygon was obtained from: + www.geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm + + Copyright 2001, softSurfer (www.softsurfer.com) + This code may be freely used and modified for any purpose + providing that this copyright notice is included with it. + SoftSurfer makes no warranty for this code, and cannot be held + liable for any real or imagined damage resulting from its use. +*/ + +#define isLeft( _P0, _P1, _x, _y ) ((_P1.x - _P0.x)*(_y - _P0.y) - (_x - _P0.x)*(_P1.y - _P0.y)) + +int simIsPointInPolyWind(cdPoint* poly, int n, int x, int y) +{ + int i, i1, + wn = 0; /* the winding number counter */ + + for (i = 0; i < n; i++) + { + i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */ + + if (poly[i].y <= y) + { + if (poly[i1].y > y) /* an upward crossing */ + if (isLeft(poly[i], poly[i1], x, y) > 0) /* P left of edge */ + ++wn; /* have a valid up intersect */ + } + else + { + if (poly[i1].y <= y) /* a downward crossing */ + if (isLeft(poly[i], poly[i1], x, y) < 0) /* P right of edge */ + --wn; /* have a valid down intersect */ + } + } + + return wn; +} + +static int compare_int(const int* xx1, const int* xx2) +{ + return *xx1 - *xx2; +} + +void simAddSegment(simLineSegment* segment, int x1, int y1, int x2, int y2, int *y_max, int *y_min) +{ + /* Make sure p2.y > p1.y */ + if (y1 > y2) + { + _cdSwapInt(y1, y2); + _cdSwapInt(x1, x2); + } + + segment->x1 = x1; + segment->y1 = y1; + segment->x2 = x2; + segment->y2 = y2; + + segment->x = x2; /* initial value */ + + segment->DeltaY = y2 - y1; + segment->DeltaX = x2 - x1; + if (segment->DeltaX >= 0) + segment->XDir = -1; /* inverted from simLineThin since here is from p2 to p1 */ + else + { + segment->XDir = 1; + segment->DeltaX = -segment->DeltaX; /* make DeltaX positive */ + } + + segment->ErrorAcc = 0; /* initialize the line error accumulator to 0 */ + + /* Is this an X-major or Y-major line? */ + if (segment->DeltaY > segment->DeltaX) + { + if (segment->DeltaY==0) /* do not compute for horizontal segments */ + return; + + /* Y-major line; calculate 16-bit fixed-point fractional part of a + pixel that X advances each time Y advances 1 pixel, truncating the + result so that we won't overrun the endpoint along the X axis */ + segment->ErrorInc = (unsigned short)(((unsigned long)segment->DeltaX << 16) / (unsigned long)segment->DeltaY); + } + else + { + if (segment->DeltaX==0) /* do not compute for vertical segments */ + return; + + /* It's an X-major line; calculate 16-bit fixed-point fractional part of a + pixel that Y advances each time X advances 1 pixel, truncating the + result to avoid overrunning the endpoint along the X axis */ + segment->ErrorInc = (unsigned short)(((unsigned long)segment->DeltaY << 16) / (unsigned long)segment->DeltaX); + } + + /* also calculates y_max and y_min of the polygon */ + if (y2 > *y_max) + *y_max = y2; + if (y1 < *y_min) + *y_min = y1; +} + +int simSegmentInc(simLineSegment* segment, cdCanvas* canvas, int y) +{ + unsigned short ErrorAccTemp, Weighting; + + if (segment->DeltaY == 0) + { + /* Horizontal line */ + while (segment->DeltaX-- != 0) + segment->x += segment->XDir; + return segment->x; + } + + if (segment->DeltaX == 0) + { + /* Vertical line */ + segment->DeltaY--; + return segment->x; + } + + if (segment->DeltaX == segment->DeltaY) + { + /* Perfect Diagonal line */ + segment->x += segment->XDir; + segment->DeltaY--; + return segment->x; + } + + /* Is this an X-major or Y-major line? */ + if (segment->DeltaY > segment->DeltaX) + { + /* Increment pixels other than the first and last */ + ErrorAccTemp = segment->ErrorAcc; /* remember currrent accumulated error */ + segment->ErrorAcc += segment->ErrorInc; /* calculate error for next pixel */ + if (segment->ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the X coord */ + segment->x += segment->XDir; + } + + Weighting = segment->ErrorAcc >> INTENSITYSHIFT; + + if (Weighting < 128) + return segment->x; + else + return segment->x + segment->XDir; + } + else + { + /* Increment all pixels other than the first and last */ + int hline_end = 0; + while (!hline_end) + { + ErrorAccTemp = segment->ErrorAcc; /* remember currrent accumulated error */ + segment->ErrorAcc += segment->ErrorInc; /* calculate error for next pixel */ + if (segment->ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the Y coord */ + hline_end = 1; + } + + segment->x += segment->XDir; /* X-major, so always advance X */ + } + + return segment->x; + } +} + +typedef struct _simIntervalList +{ + int* xx; + int n, count; +} simIntervalList; + +static int simFillCheckAAPixel(simIntervalList* line_int_list, int x) +{ + int i, *xx = line_int_list->xx; + for (i = 0; i < line_int_list->n; i+=2) + { + if (xx[i] <= x && x <= xx[i+1]) + return 0; /* inside, already drawn, do not draw */ + } + return 1; +} + +static void simPolyAAPixels(cdCanvas *canvas, simIntervalList* line_int_list, int y_min, int y_max, int x1, int y1, int x2, int y2) +{ + unsigned short ErrorInc, ErrorAcc; + unsigned short ErrorAccTemp, Weighting; + int DeltaX, DeltaY, XDir; + int no_antialias = !(canvas->simulation->antialias); + + /* Make sure p2.y > p1.y */ + if (y1 > y2) + { + _cdSwapInt(y1, y2); + _cdSwapInt(x1, x2); + } + + DeltaX = x2 - x1; + if (DeltaX >= 0) + XDir = 1; + else + { + XDir = -1; + DeltaX = -DeltaX; /* make DeltaX positive */ + } + + /* Special-case horizontal, vertical, and diagonal lines, which + require no weighting because they go right through the center of + every pixel */ + DeltaY = y2 - y1; + if (DeltaY == 0 || DeltaX == 0 || DeltaX == DeltaY) return; + + /* Line is not horizontal, diagonal, or vertical */ + + /* start and end pixels are not necessary + since they are always drawn in the previous step. */ + + ErrorAcc = 0; /* initialize the line error accumulator to 0 */ + + /* Is this an X-major or Y-major line? */ + if (DeltaY > DeltaX) + { + ErrorInc = (unsigned short)(((unsigned long)DeltaX << 16) / (unsigned long)DeltaY); + + /* Draw all pixels other than the first and last */ + while (--DeltaY) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorInc; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + x1 += XDir; + + y1++; /* Y-major, so always advance Y */ + + Weighting = ErrorAcc >> INTENSITYSHIFT; + + if (y1 < y_min || y1 > y_max) continue; + + if (no_antialias) + { + if (Weighting < 128) + { + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1, 255); + } + else + { + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1 + XDir)) + simFillDrawAAPixel(canvas, x1 + XDir, y1, 255); + } + } + else + { + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1, 255-Weighting); + + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1 + XDir)) + simFillDrawAAPixel(canvas, x1 + XDir, y1, Weighting); + } + } + } + else + { + ErrorInc = (unsigned short)(((unsigned long)DeltaY << 16) / (unsigned long)DeltaX); + + /* Draw all pixels other than the first and last */ + while (--DeltaX) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorInc; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + y1++; + + x1 += XDir; /* X-major, so always advance X */ + + Weighting = ErrorAcc >> INTENSITYSHIFT; + + if (y1 < y_min || y1 > y_max) continue; + + if (no_antialias) + { + if (Weighting < 128) + { + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1, 255); + } + else + { + if (y1+1 < y_min || y1+1 > y_max) continue; + + if (simFillCheckAAPixel(line_int_list+(y1+1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1+1, 255); + } + } + else + { + if (simFillCheckAAPixel(line_int_list+(y1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1, 255-Weighting); + + if (y1+1 < y_min || y1+1 > y_max) continue; + + if (simFillCheckAAPixel(line_int_list+(y1+1-y_min), x1)) + simFillDrawAAPixel(canvas, x1, y1+1, Weighting); + } + } + } +} + +static void simLineIntervallInit(simIntervalList* line_int_list, int count) +{ + line_int_list->xx = malloc(sizeof(int)*count); + line_int_list->n = 0; + line_int_list->count = count; +} + +static void simLineIntervallAdd(simIntervalList* line_int_list, int x1, int x2) +{ + int i = line_int_list->n; + line_int_list->xx[i] = x1; + line_int_list->xx[i+1] = x2; + line_int_list->n += 2; +} + +void simPolyFill(cdSimulation* simulation, cdPoint* poly, int n) +{ + simLineSegment *seg_i; + simIntervalList* line_int_list, *line_il; + int y_max, y_min, i, y, i1, fill_mode, num_lines, + inter_count, width, height, *xx; + + simLineSegment *segment = (simLineSegment *)malloc(n*sizeof(simLineSegment)); + + width = simulation->canvas->w; + height = simulation->canvas->h; + fill_mode = simulation->canvas->fill_mode; + + y_max = poly[0].y; + y_min = poly[0].y; + for(i = 0; i < n; i++) + { + i1 = (i+1)%n; /* next point(i+1), next of last(n-1) is first(0) */ + simAddSegment(segment+i, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y, &y_max, &y_min); + } + + if (y_min > height-1 || y_max < 0) + { + free(segment); + return; + } + + if (y_min < 0) + y_min = 0; + + if (y_max > height-1) + num_lines = height-y_min; + else + num_lines = y_max-y_min+1; + + line_int_list = malloc(sizeof(simIntervalList)*num_lines); + memset(line_int_list, 0, sizeof(simIntervalList)*num_lines); + + xx = (int*)malloc((n+1)*sizeof(int)); + + /* for all horizontal lines between y_max and y_min */ + for(y = y_max; y >= y_min; y--) + { + inter_count = 0; + + /* for all segments, calculates the intervals to be filled + from the intersection with the horizontal line y. */ + for(i = 0; i < n; i++) + { + seg_i = segment + i; + + /* if the minimum Y coordinate of the segment is greater than the current y, then ignore the segment. */ + /* if it is an horizontal line, then ignore the segment. */ + if (seg_i->y1 > y || + seg_i->y1 == seg_i->y2) + continue; + + if (y == seg_i->y1) /* intersection at the start point (x1,y1) */ + { + int i_next = (i==n-1)? 0: i+1; + int i_prev = (i==0)? n-1: i-1; + simLineSegment *seg_i_next = segment + i_next; + simLineSegment *seg_i_prev = segment + i_prev; + + /* always save at least one intersection point for (y1) */ + + xx[inter_count++] = seg_i->x1; /* save the intersection point */ + + /* check for missing bottom-corner points (|_|), must duplicate the intersection */ + if ((seg_i_next->y1 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */ + (seg_i_prev->y1 == y && seg_i_prev->y2 == seg_i_prev->y1)) /* previous is an horizontal line */ + { + xx[inter_count++] = seg_i->x1; /* save the intersection point */ + } + } + else if ((y > seg_i->y1) && (y < seg_i->y2)) /* intersection inside the segment, do not include y2 */ + { + xx[inter_count++] = simSegmentInc(seg_i, simulation->canvas, y); /* save the intersection point */ + } + else if (y == seg_i->y2) /* intersection at the end point (x2,y2) */ + { + int i_next = (i==n-1)? 0: i+1; + int i_prev = (i==0)? n-1: i-1; + simLineSegment *seg_i_next = segment + i_next; + simLineSegment *seg_i_prev = segment + i_prev; + + /* only save the intersection point for (y2) if not handled by (y1) of another segment */ + + /* check for missing top-corner points (^) or (|¯¯|) */ + if ((seg_i_next->y2 == y && seg_i_next->y2 == seg_i_next->y1) || /* next is an horizontal line */ + (seg_i_prev->y2 == y && seg_i_prev->y2 == seg_i_prev->y1) || /* previous is an horizontal line */ + (seg_i_next->y2 == y && seg_i_next->x2 == seg_i->x2 && seg_i_next->x1 != seg_i->x1) || + (seg_i_prev->y2 == y && seg_i_prev->x2 == seg_i->x2 && seg_i_prev->x1 != seg_i->x1)) + { + xx[inter_count++] = seg_i->x2; /* save the intersection point */ + } + } + } + + /* if outside the canvas, ignore the intervals and */ + /* continue since the segments where updated. */ + if (y > height-1 || inter_count == 0) + continue; + + /* sort the intervals */ + qsort(xx, inter_count, sizeof(int), (int (*)(const void*,const void*))compare_int); + + line_il = line_int_list+(y-y_min); + simLineIntervallInit(line_il, inter_count*2); + + /* for all intervals, fill the interval */ + for(i = 0; i < inter_count; i += 2) /* process only pairs */ + { + if (fill_mode == CD_EVENODD) + { + /* since it fills only pairs of intervals, */ + /* it is the EVENODD fill rule. */ + simFillHorizLine(simulation, xx[i], y, xx[i+1]); + simLineIntervallAdd(line_il, xx[i], xx[i+1]); + } + else + { + simFillHorizLine(simulation, xx[i], y, xx[i+1]); + simLineIntervallAdd(line_il, xx[i], xx[i+1]); + if ((i+2 < inter_count) && (xx[i+1] < xx[i+2])) /* avoid point intervals */ + if (simIsPointInPolyWind(poly, n, (xx[i+1]+xx[i+2])/2, y)) /* if the next interval is inside the polygon then fill it */ + { + simFillHorizLine(simulation, xx[i+1], y, xx[i+2]); + simLineIntervallAdd(line_il, xx[i+1], xx[i+2]); + } + } + } + } + + free(xx); + free(segment); + + /* Once the polygon has been filled, now let's draw the + * antialiased and incomplete pixels at the edges */ + + if (y_max > height-1) + y_max = height-1; + + /* Go through all line segments of the poly */ + for(i = 0; i < n; i++) + { + i1 = (i+1)%n; + simPolyAAPixels(simulation->canvas, line_int_list, y_min, y_max, poly[i].x, poly[i].y, poly[i1].x, poly[i1].y); + } + + for (i = 0; i < num_lines; i++) + { + if (line_int_list[i].xx) + free(line_int_list[i].xx); + } + free(line_int_list); +} + +/*************************************************************************************/ +/*************************************************************************************/ + +#define _cdLineDrawPixel(_canvas, _x1, _y1, _ls, _fgcolor, _bgcolor) \ +{ \ + if (_ls & 1) \ + _canvas->cxPixel(_canvas->ctxcanvas, _x1, _y1, _fgcolor); \ + else if (canvas->back_opacity == CD_OPAQUE) \ + _canvas->cxPixel(_canvas->ctxcanvas, _x1, _y1, _bgcolor); \ +} + +void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2) +{ + const int interior = canvas->interior_style; + const int width = canvas->line_width; + const int style = canvas->line_style; + + const int dx = x2-x1; + const int dy = y2-y1; + + const double len = hypot(dx,dy); + + const double dnx = dx/len; + const double dny = dy/len; + + const int w1 = (int)width/2; + const int w2 = width-w1; + + const int n1x = cdRound( w1*dny); + const int n1y = cdRound(-w1*dnx); + + const int n2x = cdRound(-w2*dny); + const int n2y = cdRound( w2*dnx); + + const int p1x = x1 + n1x; + const int p1y = y1 + n1y; + const int p2x = x1 + n2x; + const int p2y = y1 + n2y; + const int p3x = p2x + dx; + const int p3y = p2y + dy; + const int p4x = p1x + dx; + const int p4y = p1y + dy; + + cdPoint poly[4]; + + cdCanvasLineWidth(canvas, 1); + cdCanvasInteriorStyle(canvas, CD_SOLID); + cdCanvasLineStyle(canvas, CD_CONTINUOUS); + + poly[0].x = p1x; + poly[0].y = p1y; + poly[1].x = p2x; + poly[1].y = p2y; + poly[2].x = p3x; + poly[2].y = p3y; + poly[3].x = p4x; + poly[3].y = p4y; + + simPolyFill(canvas->simulation, poly, 4); + + cdCanvasLineWidth(canvas, width); + cdCanvasInteriorStyle(canvas, interior); + cdCanvasLineStyle(canvas, style); +} + +void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2) +{ + unsigned short ErrorInc, ErrorAcc; + unsigned short ErrorAccTemp, Weighting; + int DeltaX, DeltaY, XDir; + long aa_fgcolor; + unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha; + int no_antialias = !(canvas->simulation->antialias); + unsigned short int ls; + long fgcolor = canvas->foreground; + long bgcolor = canvas->background; + + if (simLineStyleNoReset == 2) + ls = simLineStyleLastBits; + else + { + ls = simLineStyleBitTable[canvas->line_style]; + + if (simLineStyleNoReset == 1) + simLineStyleNoReset = 2; + } + + /* Make sure p2.y > p1.y */ + if (y1 > y2) + { + _cdSwapInt(y1, y2); + _cdSwapInt(x1, x2); + } + + /* Draw the initial pixel, which is always exactly intersected by + the line and so needs no weighting */ + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + + DeltaX = x2 - x1; + if (DeltaX >= 0) + XDir = 1; + else + { + XDir = -1; + DeltaX = -DeltaX; /* make DeltaX positive */ + } + + /* Special-case horizontal, vertical, and diagonal lines, which + require no weighting because they go right through the center of + every pixel */ + DeltaY = y2 - y1; + if (DeltaY == 0) + { + /* Horizontal line */ + while (DeltaX-- != 0) + { + x1 += XDir; + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } + simLineStyleLastBits = ls; + return; + } + + if (DeltaX == 0) + { + /* Vertical line */ + do + { + y1++; + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } while (--DeltaY != 0); + simLineStyleLastBits = ls; + return; + } + + if (DeltaX == DeltaY) + { + /* Perfect Diagonal line */ + do + { + x1 += XDir; + y1++; + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } while (--DeltaY != 0); + simLineStyleLastBits = ls; + return; + } + + /* Line is not horizontal, diagonal, or vertical */ + + ErrorAcc = 0; /* initialize the line error accumulator to 0 */ + + /* Is this an X-major or Y-major line? */ + if (DeltaY > DeltaX) + { + /* Y-major line; calculate 16-bit fixed-point fractional part of a + pixel that X advances each time Y advances 1 pixel, truncating the + result so that we won't overrun the endpoint along the X axis */ + ErrorInc = (unsigned short)(((unsigned long)DeltaX << 16) / (unsigned long)DeltaY); + + /* Draw all pixels other than the first and last */ + while (--DeltaY) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorInc; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the X coord */ + x1 += XDir; + } + + y1++; /* Y-major, so always advance Y */ + + Weighting = ErrorAcc >> INTENSITYSHIFT; + + if (no_antialias) + { + if (Weighting < 128) + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor) + else + _cdLineDrawPixel(canvas, x1 + XDir, y1, ls, fgcolor, bgcolor) + ls = simRotateLineStyle(ls); + } + else + { + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel. + Combine the Weighting with the existing alpha, + When Weighting is zero alpha must be fully preserved. */ + aa_alpha = ((255-Weighting) * alpha) / 255; + + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor, bgcolor); + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, x1 + XDir, y1, ls, aa_fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } + } + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + _cdLineDrawPixel(canvas, x2, y2, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } + else + { + /* It's an X-major line; calculate 16-bit fixed-point fractional part of a + pixel that Y advances each time X advances 1 pixel, truncating the + result to avoid overrunning the endpoint along the X axis */ + ErrorInc = (unsigned short)(((unsigned long)DeltaY << 16) / (unsigned long)DeltaX); + + /* Draw all pixels other than the first and last */ + while (--DeltaX) + { + ErrorAccTemp = ErrorAcc; /* remember currrent accumulated error */ + ErrorAcc += ErrorInc; /* calculate error for next pixel */ + if (ErrorAcc <= ErrorAccTemp) + { + /* The error accumulator turned over, so advance the Y coord */ + y1++; + } + + x1 += XDir; /* X-major, so always advance X */ + + Weighting = ErrorAcc >> INTENSITYSHIFT; + + if (no_antialias) + { + if (Weighting < 128) + _cdLineDrawPixel(canvas, x1, y1, ls, fgcolor, bgcolor) + else + _cdLineDrawPixel(canvas, x1, y1+1, ls, fgcolor, bgcolor) + ls = simRotateLineStyle(ls); + } + else + { + /* The IntensityBits most significant bits of ErrorAcc give us the + intensity weighting for this pixel, and the complement of the + weighting for the paired pixel. + Combine the Weighting with the existing alpha, + When Weighting is zero alpha must be fully preserved. */ + aa_alpha = ((255-Weighting) * alpha) / 255; + + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor, bgcolor); + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, x1, y1+1, ls, aa_fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } + } + + /* Draw the final pixel, which is always exactly intersected by the line + and so needs no weighting */ + _cdLineDrawPixel(canvas, x2, y2, ls, fgcolor, bgcolor); + ls = simRotateLineStyle(ls); + } + + simLineStyleLastBits = ls; +} + +void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b) +{ + double DeltaX, DeltaY, a, b; + long aa_fgcolor; + unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha; + int no_antialias = !(canvas->simulation->antialias); + int yi, xi, update_a = 1, update_b = 1; + unsigned short int ls; + long fgcolor = canvas->foreground; + long bgcolor = canvas->background; + + if (simLineStyleNoReset == 2) + ls = simLineStyleLastBits; + else + { + ls = simLineStyleBitTable[canvas->line_style]; + + if (simLineStyleNoReset == 1) + simLineStyleNoReset = 2; + } + + DeltaX = fabs(x2 - x1); + DeltaY = fabs(y2 - y1); + + if (DeltaX > 0.0001) + { + a = (y1-y2)/(x1-x2); + b = y1 - a*x1; + } + else + { + a = 0; + b = x1; + } + + /* NOTICE: all the complexity of this function + is related to check and update the previous point */ + + /* Is this an X-major or Y-major line? */ + if (DeltaY > DeltaX) + { + /* Increment in Y */ + int y1i = _cdRound(y1), + y2i = _cdRound(y2); + int yi_first = y1i; + int yi_last = y2i, xi_last; + + if (y1i > y2i) + _cdSwapInt(y1i, y2i); + + for (yi = y1i; yi <= y2i; yi++) + { + double x; + if (a) + x = (yi - b)/a; + else + x = b; + + xi = (int)floor(x); + + /* if at the last pixel, store the return value */ + if (yi == yi_last) + xi_last = xi; + + /* Combine the Weighting with the existing alpha, + When Weighting is zero alpha must be fully preserved. */ + aa_alpha = (int)((1.0-(x - xi)) * alpha); + + if (no_antialias) + { + if (aa_alpha > 128) + _cdLineDrawPixel(canvas, xi, yi, ls, fgcolor, bgcolor) + else + _cdLineDrawPixel(canvas, xi+1, yi, ls, fgcolor, bgcolor) + } + else + { + if (yi == yi_first) + { + if (yi == yi_last) /* one pixel only */ + { + update_a = 0; + update_b = 0; + } + + /* if at first, compare with the last two previously drawn */ + /* if the new is equal to the previous, do NOT draw */ + if ((xi != *last_xi_a || yi != *last_yi_a) && + (xi != *last_xi_b || yi != *last_yi_b)) + { + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor); + + if (yi == yi_last) /* one pixel only */ + update_a = 1; + } + + if ((xi+1 != *last_xi_a || yi != *last_yi_a) && + (xi+1 != *last_xi_b || yi != *last_yi_b)) + { + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor, bgcolor); + + if (yi == yi_last) /* one pixel only */ + update_b = 1; + } + } + else + { + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor); + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor, bgcolor); + } + } + + ls = simRotateLineStyle(ls); + } + + if (update_a) + { + *last_xi_a = xi_last; + *last_yi_a = yi_last; + } + if (update_b) + { + *last_xi_b = xi_last+1; + *last_yi_b = yi_last; + } + } + else + { + /* Increment in X */ + int x1i = _cdRound(x1), + x2i = _cdRound(x2); + int xi_first = x1i; + int xi_last = x2i, yi_last; + + if (x1i > x2i) + _cdSwapInt(x1i, x2i); + + for (xi = x1i; xi <= x2i; xi++) + { + double y = a*xi + b; + yi = (int)floor(y); + + /* if at the last pixel, store the return value */ + if (xi == xi_last) + yi_last = yi; + + /* Combine the Weighting with the existing alpha, + When Weighting is zero alpha must be fully preserved. */ + aa_alpha = (int)((1.0-(y - yi)) * alpha); + + if (no_antialias) + { + if (aa_alpha > 128) + _cdLineDrawPixel(canvas, xi, yi, ls, fgcolor, bgcolor) + else + _cdLineDrawPixel(canvas, xi, yi+1, ls, fgcolor, bgcolor) + } + else + { + if (xi == xi_first) + { + if (xi == xi_last) /* one pixel only */ + { + update_a = 0; + update_b = 0; + } + + /* if at first, compare with the last to draw */ + /* if new is equal to the previous, do NOT draw */ + if ((xi != *last_xi_a || yi != *last_yi_a) && + (xi != *last_xi_b || yi != *last_yi_b)) + { + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor); + + if (xi == xi_last) /* one pixel only */ + update_a = 1; + } + + if ((xi != *last_xi_a || yi+1 != *last_yi_a) && + (xi != *last_xi_b || yi+1 != *last_yi_b)) + { + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor, bgcolor); + + if (xi == xi_last) /* one pixel only */ + update_b = 1; + } + } + else + { + aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha); + _cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor, bgcolor); + aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha); + _cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor, bgcolor); + } + } + + ls = simRotateLineStyle(ls); + } + + if (update_a) + { + *last_xi_a = xi_last; + *last_yi_a = yi_last; + } + if (update_b) + { + *last_xi_b = xi_last; + *last_yi_b = yi_last+1; + } + } + + simLineStyleLastBits = ls; +} diff --git a/cd/src/sim/sim_other.c b/cd/src/sim/sim_other.c new file mode 100755 index 0000000..0954406 --- /dev/null +++ b/cd/src/sim/sim_other.c @@ -0,0 +1,411 @@ +/** \file + * \brief Simulation that is independent of the Simulation Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" + + +void cdSimMark(cdCanvas* canvas, int x, int y) +{ + int oldinteriorstyle = canvas->interior_style; + int oldlinestyle = canvas->line_style; + int oldlinewidth = canvas->line_width; + int size = canvas->mark_size; + int half_size = size/2; + int bottom = y-half_size; + int top = y+half_size; + int left = x-half_size; + int right = x+half_size; + + if (canvas->interior_style != CD_SOLID && + (canvas->mark_type == CD_CIRCLE || + canvas->mark_type == CD_BOX || + canvas->mark_type == CD_DIAMOND)) + cdCanvasInteriorStyle(canvas, CD_SOLID); + + if (canvas->line_style != CD_CONTINUOUS && + (canvas->mark_type == CD_STAR || + canvas->mark_type == CD_PLUS || + canvas->mark_type == CD_X || + canvas->mark_type == CD_HOLLOW_BOX || + canvas->mark_type == CD_HOLLOW_CIRCLE || + canvas->mark_type == CD_HOLLOW_DIAMOND)) + cdCanvasLineStyle(canvas, CD_CONTINUOUS); + + if (canvas->line_width != 1 && + (canvas->mark_type == CD_STAR || + canvas->mark_type == CD_PLUS || + canvas->mark_type == CD_X || + canvas->mark_type == CD_HOLLOW_BOX || + canvas->mark_type == CD_HOLLOW_CIRCLE || + canvas->mark_type == CD_HOLLOW_DIAMOND)) + cdCanvasLineWidth(canvas, 1); + + switch (canvas->mark_type) + { + case CD_STAR: + canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top); + canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom); + /* continue */ + case CD_PLUS: + canvas->cxLine(canvas->ctxcanvas, left, y, right, y); + canvas->cxLine(canvas->ctxcanvas, x, bottom, x, top); + break; + case CD_HOLLOW_CIRCLE: + canvas->cxArc(canvas->ctxcanvas, x, y, size, size, 0, 360); + break; + case CD_HOLLOW_BOX: + canvas->cxRect(canvas->ctxcanvas, left, right, bottom, top); + break; + case CD_HOLLOW_DIAMOND: + canvas->cxLine(canvas->ctxcanvas, left, y, x, top); + canvas->cxLine(canvas->ctxcanvas, x, top, right, y); + canvas->cxLine(canvas->ctxcanvas, right, y, x, bottom); + canvas->cxLine(canvas->ctxcanvas, x, bottom, left, y); + break; + case CD_X: + canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top); + canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom); + break; + case CD_CIRCLE: + canvas->cxSector(canvas->ctxcanvas, x, y, size, size, 0, 360); + break; + case CD_BOX: + canvas->cxBox(canvas->ctxcanvas, left, right, bottom, top); + break; + case CD_DIAMOND: + { + cdPoint poly[5]; + poly[0].x = left; + poly[0].y = y; + poly[1].x = x; + poly[1].y = top; + poly[2].x = right; + poly[2].y = y; + poly[3].x = x; + poly[3].y = bottom; + canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4); + } + break; + } + + if (canvas->interior_style != oldinteriorstyle && + (canvas->mark_type == CD_CIRCLE || + canvas->mark_type == CD_BOX || + canvas->mark_type == CD_DIAMOND)) + cdCanvasInteriorStyle(canvas, oldinteriorstyle); + + if (canvas->line_style != oldlinestyle && + (canvas->mark_type == CD_STAR || + canvas->mark_type == CD_PLUS || + canvas->mark_type == CD_X || + canvas->mark_type == CD_HOLLOW_BOX || + canvas->mark_type == CD_HOLLOW_CIRCLE || + canvas->mark_type == CD_HOLLOW_DIAMOND)) + cdCanvasLineStyle(canvas, oldlinestyle); + + if (canvas->line_width != oldlinewidth && + (canvas->mark_type == CD_STAR || + canvas->mark_type == CD_PLUS || + canvas->mark_type == CD_X || + canvas->mark_type == CD_HOLLOW_BOX || + canvas->mark_type == CD_HOLLOW_CIRCLE || + canvas->mark_type == CD_HOLLOW_DIAMOND)) + cdCanvasLineWidth(canvas, oldlinewidth); +} + +/* Setup Bezier coefficient array once for each control polygon. + */ +static void BezierForm(const cdPoint* p, cdfPoint* c) +{ + int k; + static int choose[4] = {1, 3, 3, 1}; + for (k = 0; k < 4; k++) + { + c[k].x = p[k].x * choose[k]; + c[k].y = p[k].y * choose[k]; + } +} + +static void fBezierForm(const cdfPoint* p, cdfPoint* c) +{ + int k; + static int choose[4] = {1, 3, 3, 1}; + for (k = 0; k < 4; k++) + { + c[k].x = p[k].x * choose[k]; + c[k].y = p[k].y * choose[k]; + } +} + +/* Return Point pt(t), t <= 0 <= 1 from C. + * BezierForm must be called once for any given control polygon. + */ +static void BezierCurve(const cdfPoint* c, cdfPoint *pt, double t) +{ + int k; + double t1, tt, u; + cdfPoint b[4]; + + u = t; + + b[0].x = c[0].x; + b[0].y = c[0].y; + for(k = 1; k < 4; k++) + { + b[k].x = c[k].x * u; + b[k].y = c[k].y * u; + u =u*t; + } + + pt->x = b[3].x; + pt->y = b[3].y; + t1 = 1-t; + tt = t1; + for(k = 2; k >= 0; k--) + { + pt->x += b[k].x * tt; + pt->y += b[k].y * tt; + tt =tt*t1; + } +} + +static int BezierNumSegments(cdCanvas* canvas, const cdPoint* p) +{ + int i, K, dx, dy, d, + xmax = p[0].x, + ymax = p[0].y, + xmin = p[0].x, + ymin = p[0].y; + + for (i = 1; i < 4; i++) + { + if (p[i].x > xmax) + xmax = p[i].x; + if (p[i].y > ymax) + ymax = p[i].y; + if (p[i].x < xmin) + xmin = p[i].x; + if (p[i].y < ymin) + ymin = p[i].y; + } + + if (canvas->use_matrix) + { + cdMatrixTransformPoint(canvas->matrix, xmin, ymin, &xmin, &ymin); + cdMatrixTransformPoint(canvas->matrix, xmax, ymax, &xmax, &ymax); + } + + /* diagonal of the bouding box */ + dx = (xmax-xmin); + dy = (ymax-ymin); + d = (int)(sqrt(dx*dx + dy*dy)); + K = d / 8; + if (K < 8) K = 8; + return K; +} + +static int fBezierNumSegments(cdCanvas* canvas, const cdfPoint* p) +{ + int i, K, d; + double dx, dy, + xmax = p[0].x, + ymax = p[0].y, + xmin = p[0].x, + ymin = p[0].y; + + for (i = 1; i < 4; i++) + { + if (p[i].x > xmax) + xmax = p[i].x; + if (p[i].y > ymax) + ymax = p[i].y; + if (p[i].x < xmin) + xmin = p[i].x; + if (p[i].y < ymin) + ymin = p[i].y; + } + + /* diagonal of the bouding box */ + dx = (xmax-xmin); + dy = (ymax-ymin); + d = (int)(sqrt(dx*dx + dy*dy)); + K = d / 8; + if (K < 8) K = 8; + return K; +} + +/* from sim.h */ +void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b); + +/* Quick and Simple Bezier Curve Drawing --- Robert D. Miller + * Graphics GEMS V */ +void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n) +{ + int i = 0, k, K, poly_max = 0; + cdfPoint pt, prev_pt; + cdfPoint bezier_control[4]; + cdPoint* poly = NULL; + int use_poly = 0, + last_xi_a = -65535, + last_yi_a = -65535, + last_xi_b = -65535, + last_yi_b = -65535; + + /* Use special floating point anti-alias line draw when + line_width==1, and NOT using cdlineSIM. */ + if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM) + use_poly = 1; + + n--; /* first n is 4 */ + while (n >= 3) + { + BezierForm(points+i, bezier_control); + K = BezierNumSegments(canvas, points+i); + + if (use_poly && poly_max < K+1) + { + poly = realloc(poly, sizeof(cdPoint)*(K+1)); /* K+1 points */ + if (!poly) return; + poly_max = K+1; + } + + /* first segment */ + BezierCurve(bezier_control, &pt, 0); + if (use_poly) + { + poly[0].x = _cdRound(pt.x); + poly[0].y = _cdRound(pt.y); + } + else + prev_pt = pt; + + for(k = 1; k < K+1; k++) + { + BezierCurve(bezier_control, &pt, (double)k/(double)K); + + if (use_poly) + { + poly[k].x = _cdRound(pt.x); + poly[k].y = _cdRound(pt.y); + } + else + { + int old_use_matrix = canvas->use_matrix; + double x1 = prev_pt.x, + y1 = prev_pt.y, + x2 = pt.x, + y2 = pt.y; + + if (canvas->use_matrix && !canvas->invert_yaxis) + { + cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); + cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); + } + + /* must disable transformation here, because line simulation use cxPixel */ + canvas->use_matrix = 0; + + simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b); + + canvas->use_matrix = old_use_matrix; + prev_pt = pt; + } + } + + if (use_poly) + canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k); + + n -= 3; i += 3; + } + + if (poly) free(poly); +} + +void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n) +{ + int i = 0, k, K, poly_max = 0; + cdfPoint pt; + cdfPoint bezier_control[4]; + cdfPoint* poly = NULL; + + n--; /* first n is 4 */ + while (n >= 3) + { + fBezierForm(points+i, bezier_control); + K = fBezierNumSegments(canvas, points+i); + + if (poly_max < K+1) + { + poly = realloc(poly, sizeof(cdfPoint)*(K+1)); /* K+1 points */ + if (!poly) return; + poly_max = K+1; + } + + /* first segment */ + BezierCurve(bezier_control, &pt, 0); + poly[0].x = _cdRound(pt.x); + poly[0].y = _cdRound(pt.y); + + for(k = 1; k < K+1; k++) + { + BezierCurve(bezier_control, &pt, (double)k/(double)K); + + poly[k].x = _cdRound(pt.x); + poly[k].y = _cdRound(pt.y); + } + + canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k); + n -= 3; i += 3; + } + + if (poly) free(poly); +} + +void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int size, i, j, dst, src, *fx, *fy, rw, rh; + unsigned char *ar, *ag, *ab, al; + + size = w * h; + ar = (unsigned char*)malloc(size*3); + if (!ar) return; + ag = ar + size; + ab = ag + size; + + canvas->cxGetImageRGB(canvas->ctxcanvas, ar, ag, ab, x, y, w, h); + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + fx = cdGetZoomTable(w, rw, xmin); + fy = cdGetZoomTable(h, rh, ymin); + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + dst = j * w + i; + src = fy[j] * iw + fx[i]; + al = a[src]; + ar[dst] = CD_ALPHA_BLEND(r[src], ar[dst], al); + ag[dst] = CD_ALPHA_BLEND(g[src], ag[dst], al); + ab[dst] = CD_ALPHA_BLEND(b[src], ab[dst], al); + } + } + + canvas->cxPutImageRectRGB(canvas->ctxcanvas, w, h, ar, ag, ab, x, y, w, h, 0, 0, 0, 0); + + free(ar); + + free(fx); + free(fy); +} diff --git a/cd/src/sim/sim_primitives.c b/cd/src/sim/sim_primitives.c new file mode 100755 index 0000000..5f5e0a3 --- /dev/null +++ b/cd/src/sim/sim_primitives.c @@ -0,0 +1,524 @@ +/** \file + * \brief Primitives of the Simulation Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cd_truetype.h" +#include "sim.h" + +void cdlineSIM(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + int old_use_matrix = canvas->use_matrix; + + if (canvas->use_matrix && !canvas->invert_yaxis) + { + cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); + cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); + } + + /* must disable transformation here, because line simulation use cxPixel */ + canvas->use_matrix = 0; + + if(canvas->line_width > 1) + simLineThick(canvas, x1, y1, x2, y2); + else + simLineThin(canvas, x1, y1, x2, y2); + + canvas->use_matrix = old_use_matrix; +} + +void cdrectSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + cdPoint poly[5]; /* leave room of one more point */ + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + canvas->cxPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4); +} + +void cdboxSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + + if (canvas->use_matrix) + { + cdPoint poly[5]; /* leave room of one more point */ + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4); + } + else + { + cdSimulation* simulation = canvas->simulation; + int y; + + /* must set line attributes here, because fill simulation use cxLine and cxPixel */ + int old_line_style = cdCanvasLineStyle(canvas, CD_CONTINUOUS); + int old_line_width = cdCanvasLineWidth(canvas, 1); + + for(y=ymin;y<=ymax;y++) + simFillHorizLine(simulation, xmin, y, xmax); + + cdCanvasLineStyle(canvas, old_line_style); + cdCanvasLineWidth(canvas, old_line_width); + } +} + +void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + cdfPoint poly[5]; /* leave room of one more point */ + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4); +} + +void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + cdfPoint poly[5]; /* leave room of one more point */ + poly[0].x = xmin; poly[0].y = ymin; + poly[1].x = xmin; poly[1].y = ymax; + poly[2].x = xmax; poly[2].y = ymax; + poly[3].x = xmax; poly[3].y = ymin; + canvas->cxFPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4); +} + +int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height) +{ + int n, dx, dy, hd; + int w2 = width/2; + int h2 = height/2; + int x1 = xc-w2, + y1 = yc-h2, + x2 = xc+w2, + y2 = yc+h2; + + if (canvas->use_matrix) + { + cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); + cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); + } + + dx = (x1-x2); + dy = (y1-y2); + hd = (int)(sqrt(dx*dx + dy*dy)/2); + + /* Estimation Heuristic: + use half diagonal to estimate the number of segments for 360 degrees. + Use the difference of the half diagonal and its projection to calculate the minimum angle: + cos(min_angle) = hd / (hd + 1) or min_angle = acos(hd / (hd + 1)) + The number of segments will be 360 / min_angle. + */ + + n = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */ + + /* multiple of 4 */ + n = ((n + 3)/4)*4; + + /* minimum number is 4 */ + if (n < 4) n = 4; + + return n; +} + +void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + double c, s, sx, sy, x, y, prev_x, prev_y; + double da; + int i, yc2 = 2*yc, p, + last_xi_a = -65535, + last_yi_a = -65535, + last_xi_b = -65535, + last_yi_b = -65535; + cdPoint* poly = NULL; + + /* number of segments of equivalent poligonal for a full ellipse */ + int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height); + + /* Use special floating point anti-alias line draw when + line_width==1, and NOT using cdlineSIM. */ + if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM) + { + poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+1)); /* n+1 points */ + if (!poly) return; + } + + /* number of segments for the arc */ + n = cdRound((fabs(angle2-angle1)*n)/360); + if (n < 1) n = 1; + + /* converts degrees into radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + + /* generates arc points at origin with axis x and y */ + + da = (angle2-angle1)/n; + c = cos(da); + s = sin(da); + sx = -(width*s)/height; + sy = (height*s)/width; + + x = (width/2.0f)*cos(angle1); + y = (height/2.0f)*sin(angle1); + prev_x = x; + prev_y = y; + if (poly) + { + poly[0].x = _cdRound(x)+xc; + poly[0].y = _cdRound(y)+yc; + + if (canvas->invert_yaxis) /* must invert because of the angle orientation */ + poly[0].y = yc2 - poly[0].y; + + p = 1; + } + else + simLineStyleNoReset = 1; + + for (i = 1; i < n+1; i++) /* n+1 points */ + { + x = c*prev_x + sx*prev_y; + y = sy*prev_x + c*prev_y; + + if (poly) + { + poly[p].x = _cdRound(x)+xc; + poly[p].y = _cdRound(y)+yc; + + if (canvas->invert_yaxis) /* must invert because of the angle orientation */ + poly[p].y = yc2 - poly[p].y; + + if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) + p++; + } + else + { + int old_use_matrix = canvas->use_matrix; + double x1 = prev_x+xc, + y1 = prev_y+yc, + x2 = x+xc, + y2 = y+yc; + + if (canvas->use_matrix && !canvas->invert_yaxis) + { + cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1); + cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2); + } + + /* must disable transformation here, because line simulation use cxPixel */ + canvas->use_matrix = 0; + + if (canvas->invert_yaxis) /* must invert because of the angle orientation */ + { + y1 = yc2 - y1; + y2 = yc2 - y2; + } + + simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b); + + canvas->use_matrix = old_use_matrix; + } + + prev_x = x; + prev_y = y; + } + + if (poly) + { + canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p); + free(poly); + } + else + simLineStyleNoReset = 0; +} + +void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + double c, s, sx, sy, x, y, prev_x, prev_y, da; + int i, p; + cdfPoint* poly = NULL; + + /* number of segments of equivalent poligonal for a full ellipse */ + int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height); + + poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1)); /* n+1 points */ + if (!poly) return; + + /* number of segments for the arc */ + n = cdRound((fabs(angle2-angle1)*n)/360); + if (n < 1) n = 1; + + /* converts degrees into radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + + /* generates arc points at origin with axis x and y */ + + da = (angle2-angle1)/n; + c = cos(da); + s = sin(da); + sx = -(width*s)/height; + sy = (height*s)/width; + + x = (width/2.0f)*cos(angle1); + y = (height/2.0f)*sin(angle1); + prev_x = x; + prev_y = y; + poly[0].x = x+xc; + poly[0].y = y+yc; + + p = 1; + + for (i = 1; i < n+1; i++) /* n+1 points */ + { + x = c*prev_x + sx*prev_y; + y = sy*prev_x + c*prev_y; + + poly[p].x = x+xc; + poly[p].y = y+yc; + + if (poly[p-1].x != poly[p].x || + poly[p-1].y != poly[p].y) + p++; + + prev_x = x; + prev_y = y; + } + + canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p); + free(poly); +} + +void cdfSimElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2, int sector) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + double c, s, sx, sy, x, y, prev_x, prev_y, da; + int i, p; + cdfPoint* poly; + + /* number of segments of equivalent poligonal for a full ellipse */ + int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height); + + /* number of segments for the arc */ + n = cdRound(((angle2-angle1)*n)/360); + if (n < 1) n = 1; + + poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+2+1)); /* n+1 points +1 center */ + + /* converts degrees into radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + + /* generates arc points at origin with axis x and y */ + + da = (angle2-angle1)/n; + c = cos(da); + s = sin(da); + sx = -(width*s)/height; + sy = (height*s)/width; + + x = xc + (width/2.0)*cos(angle1); + y = yc + (height/2.0)*sin(angle1); + prev_x = x; + prev_y = y; + + poly[0].x = x; + poly[0].y = y; + p = 1; + + for (i = 1; i < n+1; i++) /* n+1 points */ + { + x = xc + c*(prev_x-xc) + sx*(prev_y-yc); + y = yc + sy*(prev_x-xc) + c*(prev_y-yc); + + poly[p].x = x; + poly[p].y = y; + + if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) + p++; + + prev_x = x; + prev_y = y; + } + + if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y) + { + if (sector) /* cdSector */ + { + /* add center */ + poly[p].x = xc; + poly[p].y = yc; + } + else /* cdChord */ + { + /* add initial point */ + poly[p].x = poly[0].x; + poly[p].y = poly[0].y; + } + p++; + } + + canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, p); + free(poly); +} + +static void cdSimElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + float c, s, sx, sy, x, y, prev_x, prev_y; + double da; + int i, p, yc2 = 2*yc; + cdPoint* poly; + + /* number of segments of equivalent poligonal for a full ellipse */ + int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height); + + /* number of segments for the arc */ + n = cdRound(((angle2-angle1)*n)/360); + if (n < 1) n = 1; + + poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */ + + /* converts degrees into radians */ + angle1 *= CD_DEG2RAD; + angle2 *= CD_DEG2RAD; + + /* generates arc points at origin with axis x and y */ + + da = (angle2-angle1)/n; + c = (float)cos(da); + s = (float)sin(da); + sx = -(width*s)/height; + sy = (height*s)/width; + + x = xc + (width/2.0f)*(float)cos(angle1); + y = yc + (height/2.0f)*(float)sin(angle1); + prev_x = x; + prev_y = y; + + poly[0].x = _cdRound(x); + poly[0].y = _cdRound(y); + if (canvas->invert_yaxis) + poly[0].y = yc2 - poly[0].y; + p = 1; + + for (i = 1; i < n+1; i++) /* n+1 points */ + { + x = xc + c*(prev_x-xc) + sx*(prev_y-yc); + y = yc + sy*(prev_x-xc) + c*(prev_y-yc); + + poly[p].x = _cdRound(x); + poly[p].y = _cdRound(y); + + if (canvas->invert_yaxis) + poly[p].y = yc2 - poly[p].y; + + if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y) + p++; + + prev_x = x; + prev_y = y; + } + + if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y) + { + if (sector) /* cdSector */ + { + /* add center */ + poly[p].x = xc; + poly[p].y = yc; + } + else /* cdChord */ + { + /* add initial point */ + poly[p].x = poly[0].x; + poly[p].y = poly[0].y; + } + p++; + } + + canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, p); + + free(poly); +} + +void cdsectorSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2) +{ + cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 1); +} + +void cdchordSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2) +{ + cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 0); +} + +void cdpolySIM(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas; + int i, reset = 1; + + switch(mode) + { + case CD_CLOSED_LINES: + poly[n] = poly[0]; + n++; + /* continue */ + case CD_OPEN_LINES: + if (simLineStyleNoReset) /* Bezier simulation use several poly */ + { + reset = 0; + simLineStyleNoReset = 1; + } + for (i = 0; i< n - 1; i++) + canvas->cxLine(canvas->ctxcanvas, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y); + if (reset) simLineStyleNoReset = 0; + break; + case CD_BEZIER: + simLineStyleNoReset = 1; + cdSimPolyBezier(canvas, poly, n); + simLineStyleNoReset = 0; + break; + case CD_FILL: + { + /* must set line attributes here, because fill simulation use cxLine */ + int oldwidth = cdCanvasLineWidth(canvas, 1); + int oldstyle = cdCanvasLineStyle(canvas, CD_CONTINUOUS); + int old_use_matrix = canvas->use_matrix; + + if (canvas->use_matrix && !canvas->invert_yaxis) + { + for(i = 0; i < n; i++) + cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y); + } + + /* must disable transformation here, because line simulation use cxPixel */ + canvas->use_matrix = 0; + + simPolyFill(canvas->simulation, poly, n); + + canvas->use_matrix = old_use_matrix; + cdCanvasLineStyle(canvas, oldstyle); + cdCanvasLineWidth(canvas, oldwidth); + } + break; + } +} diff --git a/cd/src/sim/truetype.h b/cd/src/sim/truetype.h new file mode 100755 index 0000000..5675998 --- /dev/null +++ b/cd/src/sim/truetype.h @@ -0,0 +1,46 @@ +/** \file + * \brief Text and Font Simulation using FreeType library. + * + * See Copyright Notice in cd.h + */ + +#ifndef __TRUETYPE_H +#define __TRUETYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ft2build.h" +#include FT_FREETYPE_H + +/* + In CD version 4.4 we start to use FreeType 2. + Only TrueType font support is enabled. +*/ + +typedef struct _cdTT_Text +{ + FT_Library library; + FT_Face face; + + unsigned char* rgba_data; + int rgba_data_size; + + int max_height; + int max_width; + int descent; + int ascent; + +}cdTT_Text; + +cdTT_Text* cdTT_create(void); +void cdTT_free(cdTT_Text * tt_text); +int cdTT_load(cdTT_Text * tt_text, const char *font,int size, double xres, double yres); + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef _CD_TRUETYPE_ */ + diff --git a/cd/src/tecmake_compact.mak b/cd/src/tecmake_compact.mak new file mode 100755 index 0000000..08e642e --- /dev/null +++ b/cd/src/tecmake_compact.mak @@ -0,0 +1,1172 @@ +#-------------------------------------------------------------------------# +#- Tecmake (Compact Version) -# +#- Generic Makefile to build applications and libraries at TeCGraf -# +#- The user makefile usually has the name "config.mak". -# +#-------------------------------------------------------------------------# + +# Tecmake Version +VERSION = 3.19 + +# First target +.PHONY: build +build: tecmake + + +#---------------------------------# +# System Variables Definitions + +# Base Defintions +TEC_SYSNAME:=$(shell uname -s) +TEC_SYSVERSION:=$(shell uname -r|cut -f1 -d.) +TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.) +TEC_SYSARCH:=$(shell uname -m) + +# Fixes +ifeq ($(TEC_SYSNAME), SunOS) + TEC_SYSARCH:=$(shell uname -p) +endif +ifeq ($(TEC_SYSNAME), IRIX) + TEC_SYSARCH:=$(shell uname -p) +endif +ifeq ($(TEC_SYSNAME), FreeBSD) + TEC_SYSMINOR:=$(shell uname -r|cut -f2 -d.|cut -f1 -d-) +endif +ifeq ($(TEC_SYSNAME), AIX) + TEC_SYSVERSION:=$(shell uname -v) + TEC_SYSMINOR:=$(shell uname -r) + TEC_SYSARCH:=ppc +endif +ifeq ($(TEC_SYSNAME), Darwin) + TEC_SYSARCH:=$(shell uname -p) +endif + +ifeq ($(TEC_SYSARCH), powerpc) + TEC_SYSARCH:=ppc +endif +ifeq ($(TEC_SYSARCH), i686) + TEC_SYSARCH:=x86 +endif +ifeq ($(TEC_SYSARCH), i386) + TEC_SYSARCH:=x86 +endif +ifeq ($(TEC_SYSARCH), x86_64) + TEC_SYSARCH:=x64 +endif + +# Compose +TEC_SYSRELEASE:=$(TEC_SYSVERSION).$(TEC_SYSMINOR) +TEC_UNAME:=$(TEC_SYSNAME)$(TEC_SYSVERSION)$(TEC_SYSMINOR) + +# Linux 2.4 and GCC 3.x +ifeq ($(TEC_UNAME), Linux24) + GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.) + ifeq ($(GCCVER), 3) + TEC_UNAME:=$(TEC_UNAME)g3 + endif +endif + +# Linux 2.6 and GCC 4.x +ifeq ($(TEC_UNAME), Linux26) + GCCVER:=$(shell gcc -dumpversion|cut -f1 -d.) + ifeq ($(GCCVER), 4) + TEC_UNAME:=$(TEC_UNAME)g4 + endif +endif + +# Linux and PowerPC +ifeq ($(TEC_SYSNAME), Linux) + ifeq ($(TEC_SYSARCH), ppc) + TEC_UNAME:=$(TEC_UNAME)ppc + endif +endif + +# 64-bits Linux +ifeq ($(TEC_SYSARCH), x64) + BUILD_64=Yes + TEC_UNAME:=$(TEC_UNAME)_64 +endif + +ifeq ($(TEC_SYSARCH), ia64) + BUILD_64=Yes + TEC_UNAME:=$(TEC_UNAME)_ia64 +endif + +# Solaris and Intel +ifeq ($(TEC_SYSNAME), SunOS) + ifeq ($(TEC_SYSARCH) , x86) + TEC_UNAME:=$(TEC_UNAME)x86 + endif +endif + +# Darwin and Intel +ifeq ($(TEC_SYSNAME), Darwin) +ifeq ($(TEC_SYSARCH), x86) + TEC_UNAME:=$(TEC_UNAME)x86 + endif +endif + +# System Info +.PHONY: sysinfo +sysinfo: + @echo ''; echo 'Tecmake - System Info' + @echo 'TEC_SYSNAME = $(TEC_SYSNAME)' + @echo 'TEC_SYSVERSION = $(TEC_SYSVERSION)' + @echo 'TEC_SYSMINOR = $(TEC_SYSMINOR)' + @echo 'TEC_SYSARCH = $(TEC_SYSARCH)' + @echo 'TEC_UNAME = $(TEC_UNAME)'; echo '' + +#---------------------------------# +# Directories Definitions +PROJDIR = .. +SRCDIR = . +OBJROOT = $(PROJDIR)/obj + + +#---------------------------------# +# Byte Order and Word Size + +ifneq ($(findstring x86, $(TEC_SYSARCH)), ) + TEC_BYTEORDER = TEC_LITTLEENDIAN +else +ifeq ($(TEC_SYSARCH), arm) + TEC_BYTEORDER = TEC_LITTLEENDIAN +else + TEC_BYTEORDER = TEC_LITTLEENDIAN +endif +endif + +ifeq ($(TEC_SYSARCH), x64) + TEC_WORDSIZE = TEC_64 +else +ifdef BUILD_64 + TEC_WORDSIZE = TEC_64 +else + TEC_WORDSIZE = TEC_32 +endif +endif + +# Itanium Exception +ifeq ($(TEC_SYSARCH), ia64) + TEC_BYTEORDER = TEC_LITTLEENDIAN + TEC_WORDSIZE = TEC_64 +endif + + +#---------------------------------# +# Compilation Flags +STDFLAGS := -Wall +STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_SYSNAME)=$(TEC_SYSRELEASE) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15 +STDINCS := +OPTFLAGS := -O3 +STDLFLAGS := r +DEBUGFLAGS := -g +STDLDFLAGS := -shared +DLIBEXT := so + +ifneq ($(findstring Linux, $(TEC_UNAME)), ) + GTK_DEFAULT := +endif +ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + GTK_DEFAULT := +endif +ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + GTK_DEFAULT := +endif +ifneq ($(findstring Linux24, $(TEC_UNAME)), ) + GTK_DEFAULT := +endif + +#---------------------------------# +# Build Tools + +CC := $(TEC_TOOLCHAIN)gcc +CPPC := $(TEC_TOOLCHAIN)g++ +FF := $(TEC_TOOLCHAIN)g77 +RANLIB := $(TEC_TOOLCHAIN)ranlib +AR := $(TEC_TOOLCHAIN)ar +DEBUGGER := $(TEC_TOOLCHAIN)gdb +RCC := $(TEC_TOOLCHAIN)windres +LD := $(TEC_TOOLCHAIN)gcc + +ifeq ($(TEC_UNAME), gcc2) + ifdef USE_GCC_2 + CC := $(CC)-2 + CPPC := $(CPPC)-2 + FF := $(FF)-2 + endif +endif + + +#---------------------------------# +# User Configuration File + +MAKENAME = config.mak + +ifdef MF + MAKENAME = $(MF).mak +endif + +################### +include $(MAKENAME) +################### + + +#---------------------------------# +# Definitions of public variables + +ifdef LIBNAME + TARGETNAME = $(LIBNAME) + MAKETYPE = LIB +else + TARGETNAME = $(APPNAME) + MAKETYPE = APP +endif + +ifndef TARGETNAME + $(error LIBNAME nor APPNAME defined in $(MAKENAME)) +endif + +PROJNAME ?= $(TARGETNAME) + +DEPEND := $(TARGETNAME).dep + +ifdef DEPENDDIR + DEPEND := $(DEPENDDIR)/$(TARGETNAME).dep.$(TEC_UNAME) +endif + +SRCLUADIR ?= $(SRCDIR) +LOHDIR ?= $(SRCLUADIR) + +ifeq ($(MAKETYPE), APP) + TARGETROOT ?= $(PROJDIR)/bin +else + TARGETROOT ?= $(PROJDIR)/lib +endif + +ifneq ($(PROJNAME), $(TARGETNAME)) + OBJROOT := $(OBJROOT)/$(TARGETNAME) +endif + +ifdef DBG + STDFLAGS += $(DEBUGFLAGS) + STDDEFS += -DDEBUG +else + STDDEFS += -DNDEBUG + ifdef OPT + STDFLAGS += $(OPTFLAGS) + ifeq ($(findstring gcc, $(TEC_UNAME)), ) + STRIP ?= Yes + endif + endif +endif + +ifdef BUILD_64 + ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif + ifneq ($(findstring AIX, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif + ifneq ($(findstring IRIX, $(TEC_UNAME)), ) + USE_CC = Yes + BUILD_64_DIR = Yes + endif +endif + +ifdef USE_CC + CC := cc + CPPC := CC + STDFLAGS = + ifdef USE_CC_DIR + TEC_UNAME := $(TEC_UNAME)cc + endif +endif + +ifdef BUILD_64 + ifdef BUILD_64_DIR + TEC_UNAME := $(TEC_UNAME)_64 + endif +endif + +ifneq ($(findstring gcc, $(TEC_UNAME)), ) + ifeq ($(MAKETYPE), APP) + TEC_UNAME_DIR ?= $(TEC_SYSNAME) + endif +endif + +TEC_UNAME_DIR ?= $(TEC_UNAME) +ifdef DBG + ifdef DBG_DIR + TEC_UNAME_DIR := $(TEC_UNAME_DIR)d + endif +endif + +OBJDIR := $(OBJROOT)/$(TEC_UNAME_DIR) +TARGETDIR := $(TARGETROOT)/$(TEC_UNAME_DIR) + +# Change linker if any C++ source +ifndef LINKER + ifneq "$(findstring .cpp, $(SRC))" "" + LINKER := $(CPPC) + else + LINKER := $(CC) + endif +endif + + +#---------------------------------# +# LO and LOH Suffix + +ifeq ($(TEC_BYTEORDER), TEC_BIGENDIAN) + ifeq ($(TEC_WORDSIZE), TEC_64) + LO_SUFFIX ?= _be64 + else + LO_SUFFIX ?= _be32 + endif +else + ifeq ($(TEC_WORDSIZE), TEC_64) + LO_SUFFIX ?= _le64 + else + LO_SUFFIX ?= + endif +endif + + +#---------------------------------# +# Platform specific variables + +# Definicoes para o X11 +X11_LIBS := Xmu Xt Xext X11 +#X11_LIB := +#X11_INC := #include + +# Definicoes para o OpenGL +OPENGL_LIBS := GLU GL +#OPENGL_LIB := +#OPENGL_INC := #include and possibly +MOTIFGL_LIB := GLw #include + +# Definicoes para o Motif +#MOTIF_LIB := +#MOTIF_INC := #include + +# Definicoes para o GLUT +#GLUT_LIB := +#GLUT_INC := + + +ifneq ($(findstring cygw, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + ifdef BUILD_64 + X11_LIB := /usr/X11R6/lib64 + else + X11_LIB := /usr/X11R6/lib + endif + X11_INC := /usr/X11R6/include + MOTIFGL_LIB := +endif + +ifneq ($(findstring Linux, $(TEC_UNAME)), ) + ifdef BUILD_64 + ifeq ($(TEC_SYSARCH), ia64) + STDFLAGS += -fPIC + X11_LIB := /usr/X11R6/lib + else + STDFLAGS += -m64 -fPIC + X11_LIB := /usr/X11R6/lib64 + endif + else + X11_LIB := /usr/X11R6/lib + endif + X11_INC := /usr/X11R6/include + MOTIFGL_LIB := +endif + +ifneq ($(findstring IRIX, $(TEC_UNAME)), ) # any IRIX + LD = ld + STDLDFLAGS := -elf -shared -rdata_shared -soname lib$(TARGETNAME).so + RANLIB := /bin/true + X11_LIBS := Xmu Xt X11 + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -64 -KPIC + STDLDFLAGS += -64 + LINKER += -64 + endif + X11_LIB := /usr/lib64 + MOTIF_LIB := /usr/Motif-2.1/lib64 + else + X11_LIB := /usr/lib32 + MOTIF_LIB := /usr/Motif-2.1/lib32 + endif + MOTIF_INC = /usr/Motif-2.1/include +endif + +ifneq ($(findstring AIX, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -q64 # to compilers C and C++ + STDLFLAGS := -X64 $(STDLFLAGS) # to librarian + STDLDFLAGS += -64 + LINKER += -q64 # to linker + endif + endif +endif + +ifneq ($(findstring HP-UX, $(TEC_UNAME)), ) + NO_DYNAMIC ?= Yes + MOTIF_INC := /usr/include/Motif2.1 + X11_LIBS := Xt Xext X11 + OPENGL_LIB := /opt/graphics/OpenGL/lib + OPENGL_INC := /opt/graphics/OpenGL/include + STDDEFS := -DTEC_UNAME=$(TEC_UNAME) -DTEC_SYSNAME=$(TEC_SYSNAME) -D$(TEC_BYTEORDER) -D$(TEC_WORDSIZE) -DFUNCPROTO=15 + CC := aCC + CPPC := aCC + LINKER := aCC +endif + +ifneq ($(findstring SunOS, $(TEC_UNAME)), ) + LD = ld + STDLDFLAGS := -G + X11_INC := /usr/openwin/share/include + X11_LIB := /usr/openwin/lib + MOTIF_INC := /usr/dt/share/include + MOTIF_LIB := /usr/dt/lib + OPENGL_INC := /usr/openwin/share/include/X11 + GLUT_LIB := /usr/local/glut-3.7/lib/glut + GLUT_INC := /usr/local/glut-3.7/include + ifdef BUILD_64 + ifdef USE_CC + STDFLAGS += -xarch=v9 -KPIC + # have to force these PATHs because of a conflict with standard PATHs + STDLDFLAGS += -64 -L/usr/lib/64 -L/usr/ucblib/sparcv9 + LINKER += -xarch=v9 + endif + endif +endif + +ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + X11_LIBS := Xmu Xp Xt Xext X11 + X11_LIB := /usr/X11R6/lib + X11_INC := /usr/X11R6/include + MOTIF_INC := /usr/OpenMotif/include + MOTIF_LIB := /usr/OpenMotif/lib + ifdef BUILD_DYLIB + STDLDFLAGS := -dynamiclib -install_name lib$(TARGETNAME).dylib + DLIBEXT := dylib + else + STDLDFLAGS := -bundle -undefined dynamic_lookup + endif +endif + +ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + X11_LIB := /usr/X11R6/lib + X11_INC := /usr/X11R6/include +endif + + +################################ +# Allows an extra configuration file. +ifdef EXTRA_CONFIG +include $(EXTRA_CONFIG) +endif +################################ + + +#---------------------------------# +# Tecgraf Libraries Location +TECTOOLS_HOME ?= ../.. + +IUP ?= $(TECTOOLS_HOME)/iup +CD ?= $(TECTOOLS_HOME)/cd +IM ?= $(TECTOOLS_HOME)/im +LUA ?= $(TECTOOLS_HOME)/lua +LUA51 ?= $(TECTOOLS_HOME)/lua5.1 + + +#---------------------------------# +# Pre-defined libraries + +# Library order: +# user + iupcd + cd + iup + motif + X +# Library path order is the oposite + +USE_MOTIF = Yes + +ifdef USE_LUA + LUASUFX := + LIBLUASUFX := 3 +endif + +ifdef USE_LUA4 + LUASUFX := 4 + LIBLUASUFX := 4 + override USE_LUA = Yes + LUA := $(LUA4) +endif + +ifdef USE_LUA5 + LUASUFX := 5 + LIBLUASUFX := 5 + override USE_LUA = Yes + LUA := $(LUA5) +endif + +ifdef USE_LUA50 + LUASUFX := 50 + LIBLUASUFX := 5 + override USE_LUA = Yes + LUA := $(LUA50) + NO_LUALIB := Yes +endif + +ifdef USE_LUA51 + LUASUFX := 5.1 + LIBLUASUFX := 51 + override USE_LUA = Yes + LUA := $(LUA51) + NO_LUALIB := Yes +endif + +ifdef USE_IUP3 + override USE_IUP = Yes +endif + +ifdef USE_IUP3BETA + IUP := $(IUP)3 +endif + +ifdef USE_IUPBETA + IUP := $(IUP)/beta +endif + +ifdef USE_CDBETA + CD := $(CD)/beta +endif + +ifdef USE_IMBETA + IM := $(IM)/beta +endif + +ifdef USE_GLUT + override USE_OPENGL = Yes +endif + +ifdef USE_IUPCONTROLS + override USE_CD = Yes + override USE_IUP = Yes + ifdef USE_IUPLUA + ifdef USE_STATIC + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacontrols$(LIBLUASUFX).a + else + LIBS += iupluacontrols$(LIBLUASUFX) + endif + override USE_CDLUA = Yes + endif + ifdef USE_STATIC + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcontrols.a + else + LIBS += iupcontrols + endif +endif + +ifdef USE_IMLUA + override USE_IM = Yes + ifdef USE_STATIC + SLIB += $(IM)/lib/$(TEC_UNAME)/libimlua$(LIBLUASUFX).a + else + LIBS += imlua$(LIBLUASUFX) + endif +endif + +ifdef USE_CDLUA + override USE_CD = Yes + ifdef USE_STATIC + ifdef USE_IUP + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdluaiup$(LIBLUASUFX).a + endif + endif + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdlua$(LIBLUASUFX).a + else + ifdef USE_IUP + ifdef USE_OLDNAMES + LIBS += cdluaiup$(LIBLUASUFX) + endif + endif + LIBS += cdlua$(LIBLUASUFX) + endif +endif + +ifdef USE_IUPLUA + override USE_IUP = Yes + ifdef USE_STATIC + ifdef USE_CD + ifndef USE_OLDNAMES + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluacd$(LIBLUASUFX).a + endif + endif + ifdef USE_OPENGL + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupluagl$(LIBLUASUFX).a + endif + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiuplua$(LIBLUASUFX).a + else + ifdef USE_CD + ifndef USE_OLDNAMES + LIBS += iupluacd$(LIBLUASUFX) + endif + endif + ifdef USE_OPENGL + LIBS += iupluagl$(LIBLUASUFX) + endif + LIBS += iuplua$(LIBLUASUFX) + endif +endif + +ifdef USE_LUA + LUA_LIB ?= $(LUA)/lib/$(TEC_UNAME) + ifdef USE_STATIC + ifndef NO_LUALIB + SLIB += $(LUA_LIB)/liblualib$(LUASUFX).a + endif + SLIB += $(LUA_LIB)/liblua$(LUASUFX).a + else + ifndef NO_LUALIB + LIBS += lualib$(LUASUFX) + endif + ifndef NO_LUALINK + LIBS += lua$(LUASUFX) + LDIR += $(LUA_LIB) + endif + endif + + LUA_INC ?= $(LUA)/include + INCLUDES += $(LUA_INC) + + LUA_BIN ?= $(LUA)/bin/$(TEC_UNAME) + BIN2C := $(LUA_BIN)/bin2c$(LUASUFX) + LUAC := $(LUA_BIN)/luac$(LUASUFX) + LUABIN := $(LUA_BIN)/lua$(LUASUFX) +endif + +ifdef USE_IUP + IUPSUFX := + ifdef USE_IUP3 + ifdef GTK_DEFAULT + ifdef USE_MOTIF + IUPSUFX := mot + else + override USE_GTK = Yes + endif + else + ifdef USE_GTK + IUPSUFX := gtk + else + override USE_MOTIF = Yes + endif + endif + else + override USE_MOTIF = Yes + endif + ifdef USE_STATIC + ifdef USE_CD + ifndef USE_OLDNAMES + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupcd.a + endif + endif + ifdef USE_OPENGL + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiupgl.a + endif + SLIB += $(IUP)/lib/$(TEC_UNAME)/libiup$(IUPSUFX).a + else + ifdef USE_CD + ifndef USE_OLDNAMES + LIBS += iupcd + endif + endif + ifdef USE_OPENGL + LIBS += iupgl + endif + LIBS += iup$(IUPSUFX) + LDIR += $(IUP)/lib/$(TEC_UNAME) + endif + INCLUDES += $(IUP)/include +endif + +ifdef USE_CD + override USE_X11 = Yes + ifdef USE_STATIC + ifdef USE_IUP + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdiup.a + endif + endif + ifdef USE_XRENDER + ifdef USE_OLDNAMES + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdxrender.a + else + SLIB += $(CD)/lib/$(TEC_UNAME)/libcdcontextplus.a + endif + endif + SLIB += $(CD)/lib/$(TEC_UNAME)/libcd.a + ifdef USE_XRENDER + LIBS += Xrender Xft + else + ifndef USE_GTK + ifndef USE_OLDNAMES + # Freetype is included in GTK +# SLIB += $(CD)/lib/$(TEC_UNAME)/libfreetype.a + endif + endif + endif + else + ifdef USE_XRENDER + ifdef USE_OLDNAMES + LIBS += cdxrender + else + LIBS += cdcontextplus + endif + endif + LIBS += cd + LDIR += $(CD)/lib/$(TEC_UNAME) + ifdef USE_XRENDER + LIBS += Xrender Xft + else + ifndef USE_GTK + ifndef USE_OLDNAMES + # Freetype is included in GTK + LIBS += freetype + endif + endif + endif + endif + INCLUDES += $(CD)/include +endif + +ifdef USE_IM + ifdef USE_STATIC + SLIB += $(IM)/lib/$(TEC_UNAME)/libim.a + else + LIBS += im + LDIR += $(IM)/lib/$(TEC_UNAME) + endif + INCLUDES += $(IM)/include +endif + +# All except gcc in Windows (Cygwin) +ifeq ($(findstring gcc, $(TEC_UNAME)), ) + +ifdef USE_GLUT + LIBS += glut + LDIR += $(GLUT_LIB) + STDINCS += $(GLUT_INC) +endif + +ifdef USE_OPENGL + override USE_X11 = Yes + ifdef USE_MOTIF + LIBS += $(MOTIFGL_LIB) + endif + LIBS += $(OPENGL_LIBS) + LDIR += $(OPENGL_LIB) + STDINCS += $(OPENGL_INC) +endif + +ifdef USE_MOTIF + override USE_X11 = Yes + LIBS += Xm + LDIR += $(MOTIF_LIB) + STDINCS += $(MOTIF_INC) + ifneq ($(findstring Linux, $(TEC_UNAME)), ) + X11_LIBS := Xpm $(X11_LIBS) + endif + ifneq ($(findstring cygw, $(TEC_UNAME)), ) + X11_LIBS := Xpm $(X11_LIBS) + endif +endif + +ifdef USE_GTK +# ifneq ($(findstring Darwin, $(TEC_UNAME)), ) +# STDINCS += /Library/Frameworks/Gtk.framework/Headers +# STDINCS += /Library/Frameworks/GLib.framework/Headers +# STDINCS += /Library/Frameworks/Cairo.framework/Headers +# LFLAGS += -framework Gtk +# else + ifneq ($(findstring Darwin, $(TEC_UNAME)), ) + GTK_BASE := /sw + LDIR += /sw/lib + LIBS += freetype + else + GTK_BASE := /usr + endif + override USE_X11 = Yes + LIBS += gtk-x11-2.0 gdk-x11-2.0 gdk_pixbuf-2.0 pango-1.0 pangox-1.0 gobject-2.0 gmodule-2.0 glib-2.0 + STDINCS += $(GTK_BASE)/include/atk-1.0 $(GTK_BASE)/include/gtk-2.0 $(GTK_BASE)/include/cairo $(GTK_BASE)/include/pango-1.0 $(GTK_BASE)/include/glib-2.0 + ifeq ($(TEC_SYSARCH), x64) + STDINCS += $(GTK_BASE)/lib64/glib-2.0/include $(GTK_BASE)/lib64/gtk-2.0/include + else + ifeq ($(TEC_SYSARCH), ia64) + STDINCS += $(GTK_BASE)/lib64/glib-2.0/include $(GTK_BASE)/lib64/gtk-2.0/include + else + STDINCS += $(GTK_BASE)/lib/glib-2.0/include $(GTK_BASE)/lib/gtk-2.0/include + endif + endif + ifneq ($(findstring FreeBSD, $(TEC_UNAME)), ) + STDINCS += /lib/X11R6/include/gtk-2.0 + endif +# endif +endif + +ifdef USE_QT + override USE_X11 = Yes + LIBS += QtGui QtCore + QT_BASE_INC := /usr/include/qt4 + STDINCS += $(QT_BASE_INC) $(QT_BASE_INC)/QtCore $(QT_BASE_INC)/QtGui + STDDEFS += -DQT_DLL -DQT_QT3SUPPORT_LIB -DQT3_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_THREAD_SUPPORT +endif + +ifdef USE_X11 + LIBS += $(X11_LIBS) + LDIR += $(X11_LIB) + STDINCS += $(X11_INC) +endif + +LIBS += m + +else + # gcc in Windows + NO_DYNAMIC ?= Yes + STDDEFS += -DWIN32 + + ifdef USE_NOCYGWIN + STDFLAGS += -mno-cygwin + endif + + ifdef USE_GLUT + LIBS += glut32 + endif + + ifdef USE_OPENGL + LIBS += opengl32 glu32 glaux + endif + + LIBS += gdi32 winspool comdlg32 comctl32 ole32 + + ifdef USE_GTK + LIBS += gtk-win32-2.0 gdk-win32-2.0 gdk_pixbuf-2.0 pango-1.0 pangowin32-1.0 gobject-2.0 gmodule-2.0 glib-2.0 + #LDIR += $(GTK)/lib + GTK_INC = /usr + STDINCS += $(GTK_INC)/include/atk-1.0 $(GTK_INC)/include/gtk-2.0 $(GTK_INC)/include/cairo $(GTK_INC)/include/pango-1.0 $(GTK_INC)/include/glib-2.0 $(GTK_INC)/lib/glib-2.0/include $(GTK_INC)/lib/gtk-2.0/include + endif + + APPTYPE ?= windows + + ifeq ($(APPTYPE), windows) + LFLAGS += -mwindows + + ifdef USE_NOCYGWIN + LFLAGS += -mno-cygwin + endif + endif +endif + + +#---------------------------------# +# Building compilation flags that are sets + +INCLUDES := $(addprefix -I, $(INCLUDES)) +STDINCS := $(addprefix -I, $(STDINCS)) +EXTRAINCS := $(addprefix -I, $(EXTRAINCS)) +DEFINES := $(addprefix -D, $(DEFINES)) + +LIBS := $(addprefix -l, $(LIBS)) +ifdef LDIR + LDIR := $(addprefix -L, $(LDIR)) +endif + + +#---------------------------------# +# Definitions of private variables + +# Library flags for application and dynamic library linker +LFLAGS += $(LDIR) $(LIBS) +# C compiler flags +CFLAGS = $(FLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS) +# C++ compiler flags +CXXFLAGS = $(CPPFLAGS) $(STDFLAGS) $(INCLUDES) $(STDINCS) $(EXTRAINCS) $(DEFINES) $(STDDEFS) + +# Sources with relative path +SOURCES := $(addprefix $(SRCDIR)/, $(SRC)) + +# Target for applications or libraries +ifeq ($(MAKETYPE), APP) + TARGET := $(TARGETDIR)/$(TARGETNAME) +else + ifeq ($(NO_DYNAMIC), Yes) + TARGET := $(TARGETDIR)/lib$(TARGETNAME).a + else + TARGET := $(TARGETDIR)/lib$(TARGETNAME).a $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) + endif +endif + +# OBJ: list of .o, without path +# OBJS: list of .o with relative path +OBJ = $(notdir $(SRC)) +OBJ := $(OBJ:.c=.o) +OBJ := $(OBJ:.cpp=.o) +OBJ := $(OBJ:.cxx=.o) +OBJ := $(OBJ:.cc=.o) +OBJ := $(OBJ:.f=.o) +OBJ := $(OBJ:.for=.o) +OBJ := $(OBJ:.rc=.ro) +OBJS = $(addprefix $(OBJDIR)/, $(OBJ)) + +# LOH: list of .loh, without path +# LOHS: list of .loh, with relative path +LO = $(notdir $(SRCLUA)) +LO := $(LO:.lua=$(LO_SUFFIX).lo) +LOS = $(addprefix $(OBJROOT)/, $(LO)) + +LOH = $(notdir $(SRCLUA)) +LOH := $(LOH:.lua=$(LO_SUFFIX).loh) +LOHS = $(addprefix $(LOHDIR)/, $(LOH)) + +# Construct VPATH variable +P-SRC = $(dir $(SRC)) +P-SRC += $(dir $(SRCLUA)) +VPATH = .:$(foreach dir,$(P-SRC),$(if $(dir)="./",:$(dir))) + + +#---------------------------------# +# Main Rule - Build Everything that it is necessary + +.PHONY: tecmake +ifeq ($(MAKETYPE), APP) + tecmake: print-start directories application scripts +else + ifeq ($(NO_DYNAMIC), Yes) + tecmake: print-start directories static-lib + else + tecmake: print-start directories static-lib dynamic-lib + endif +endif + +.PHONY: print-start +print-start: + @echo ''; echo 'Tecmake - Starting [ $(TARGETNAME):$(TEC_UNAME) ]' + + +#---------------------------------# +# Dynamic Library Build + +.PHONY: dynamic-lib +dynamic-lib: $(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) + +$(TARGETDIR)/lib$(TARGETNAME).$(DLIBEXT) : $(LOHS) $(OBJS) $(EXTRADEPS) + $(LD) $(STDLDFLAGS) -o $@ $(OBJS) $(SLIB) $(LFLAGS) + @echo 'Tecmake - Dynamic Library ($@) Done.'; echo '' + + +#---------------------------------# +# Static Library Build + +.PHONY: static-lib +static-lib: $(TARGETDIR)/lib$(TARGETNAME).a + +$(TARGETDIR)/lib$(TARGETNAME).a : $(LOHS) $(OBJS) $(EXTRADEPS) + $(AR) $(STDLFLAGS) $@ $(OBJS) $(SLIB) $(LCFLAGS) + -$(RANLIB) $@ + @echo 'Tecmake - Static Library ($@) Done.'; echo '' + + +#---------------------------------# +# Application Build + +.PHONY: application +application: $(TARGETDIR)/$(TARGETNAME) + +$(TARGETDIR)/$(TARGETNAME) : $(LOHS) $(OBJS) $(EXTRADEPS) + $(LINKER) -o $@ $(OBJS) $(SLIB) $(LFLAGS) + @if [ ! -z "$(STRIP)" ]; then \ + echo "Striping debug information" ;\ + strip $@ ;\ + fi + @echo 'Tecmake - Application ($@) Done.'; echo '' + + +#---------------------------------# +# Application Scripts + +# Script name +SRELEASE := $(SRCDIR)/$(TARGETNAME) + +.PHONY: scripts +ifdef NO_SCRIPTS + scripts: ; +else + scripts: $(SRELEASE) ; +endif + +$(SRELEASE): $(MAKENAME) + @echo 'Building script $(@F)' + @echo "#!/bin/csh" > $@ + @echo "# Script generated automatically by tecmake v$(VERSION)" >> $@ + @echo "# Remove the comment bellow to set the LD_LIBRARY_PATH if needed." >> $@ + @echo '#setenv LD_LIBRARY_PATH $(MYLIB1)/lib/$${TEC_UNAME}:$(MYLIB2)/lib/$${TEC_UNAME}:$$LD_LIBRARY_PATH' >> $@ + @echo 'if ( -r app.env ) source app.env' >> $@ + @echo 'exec $(TARGETROOT)/$$TEC_UNAME/$(TARGETNAME) $$*' >> $@ + @chmod a+x $@ + + +#---------------------------------# +# Directories Creation + +.PHONY: directories +directories: $(OBJDIR) $(TARGETDIR) $(EXTRADIR) $(LOHDIR) + +$(OBJDIR) $(TARGETDIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi + +ifdef EXTRADIR + $(EXTRADIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi +else + $(EXTRADIR): ; +endif + +ifdef LOHDIR + $(LOHDIR): + if [ ! -d $@ ] ; then mkdir -p $@ ; fi +else + $(LOHDIR): ; +endif + + +#---------------------------------# +# Compilation Rules + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + @echo Compiling $( $@ + +$(OBJROOT)/%$(LO_SUFFIX).lo: $(SRCLUADIR)/%.lua + @echo Compiling $( $(DEPEND) + @which $(CPPC) 2> /dev/null 1>&2 ;\ + if [ $$? -eq 0 ]; then \ + echo "Building dependencies... (can be slow)" ;\ + $(CPPC) $(INCLUDES) $(DEFINES) $(STDDEFS) -MM $(SOURCES) | \ + sed -e '1,$$s/^\([^ ]\)/$$(OBJDIR)\/\1/' > $(DEPEND) ;\ + else \ + echo "" ;\ + echo "$(CPPC) not found. Dependencies can not be built." ;\ + echo "Must set USE_NODEPEND=Yes." ;\ + echo "" ;\ + exit 1 ;\ + fi + endif + +################### +ifndef USE_NODEPEND +include $(DEPEND) +endif +################### + + +#---------------------------------# +# Management Rules + +# make clean-extra +# Remove extra files +.PHONY: clean-extra +clean-extra: + rm -f $(DEPEND) $(SRELEASE) so_locations + +# make clean-lohs +# Remove Lua object inclusion files +.PHONY: clean-lohs +clean-lohs: + rm -f $(LOS) $(LOHS) + +# make clean-obj +# Remove object files +.PHONY: clean-obj +clean-obj: + rm -f $(OBJS) + +# make clean-target +# Remove target +.PHONY: clean-target +clean-target: + rm -f $(TARGET) + +# make clean +# Remove target and object files +.PHONY: clean +clean: clean-target clean-obj + +# make rebuild +# Remove symbols from executables +.PHONY: strip +strip: + test -r $(TARGETDIR)/$(TARGETNAME) && strip $(TARGETDIR)/$(TARGETNAME) + +# make rebuild +# Rebuild target and object files +.PHONY: rebuild +rebuild: clean-extra clean-lohs clean-obj clean-target tecmake + +# make relink +# Rebuild target without rebuilding object files +.PHONY: relink +relink: clean-target tecmake + +.PHONY: version +version: + @echo "Tecmake Compact Version $(VERSION)" + +#---------------------------------# diff --git a/cd/src/wd.c b/cd/src/wd.c new file mode 100755 index 0000000..85e01dd --- /dev/null +++ b/cd/src/wd.c @@ -0,0 +1,473 @@ +/** \file + * \brief World Coordinate Functions + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cd.h" +#include "wd.h" + +#include "cd_private.h" + + +static void wdUpdateTransformation(cdCanvas* canvas) +{ + if (canvas->window.xmax != canvas->window.xmin) + canvas->sx = (canvas->viewport.xmax - canvas->viewport.xmin)/(canvas->window.xmax - canvas->window.xmin); + else + canvas->sx = 0; + canvas->tx = canvas->viewport.xmin - canvas->window.xmin*canvas->sx; + + if (canvas->window.ymax != canvas->window.ymin) + canvas->sy = (canvas->viewport.ymax - canvas->viewport.ymin)/(canvas->window.ymax - canvas->window.ymin); + else + canvas->sy = 0; + canvas->ty = canvas->viewport.ymin - canvas->window.ymin*canvas->sy; + + canvas->s = sqrt(canvas->sx * canvas->sx + canvas->sy * canvas->sy); +} + +void wdSetDefaults(cdCanvas* canvas) +{ + canvas->window.xmin = 0; + canvas->window.xmax = canvas->w_mm; + canvas->window.ymin = 0; + canvas->window.ymax = canvas->h_mm; + + canvas->viewport.xmin = 0; + canvas->viewport.xmax = canvas->w-1; + canvas->viewport.ymin = 0; + canvas->viewport.ymax = canvas->h-1; + + wdUpdateTransformation(canvas); +} + +void wdCanvasWindow(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + canvas->window.xmin = xmin; + canvas->window.xmax = xmax; + canvas->window.ymin = ymin; + canvas->window.ymax = ymax; + + wdUpdateTransformation(canvas); +} + +void wdCanvasGetWindow (cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax) +{ + if (xmin) *xmin = canvas->window.xmin; + if (xmax) *xmax = canvas->window.xmax; + if (ymin) *ymin = canvas->window.ymin; + if (ymax) *ymax = canvas->window.ymax; +} + +void wdCanvasViewport(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax) +{ + canvas->viewport.xmin = xmin; + canvas->viewport.xmax = xmax; + canvas->viewport.ymin = ymin; + canvas->viewport.ymax = ymax; + + wdUpdateTransformation(canvas); +} + +void wdCanvasGetViewport(cdCanvas* canvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + if (xmin) *xmin = canvas->viewport.xmin; + if (xmax) *xmax = canvas->viewport.xmax; + if (ymin) *ymin = canvas->viewport.ymin; + if (ymax) *ymax = canvas->viewport.ymax; +} + +#define _wWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \ +{ \ + _xv = cdRound(_canvas->sx*(_xw) + _canvas->tx); \ + _yv = cdRound(_canvas->sy*(_yw) + _canvas->ty); \ +} + +#define _wfWorld2Canvas(_canvas, _xw, _yw, _xv, _yv) \ +{ \ + _xv = (_canvas->sx*(_xw) + _canvas->tx); \ + _yv = (_canvas->sy*(_yw) + _canvas->ty); \ +} + +void wdCanvasWorld2Canvas(cdCanvas* canvas, double xw, double yw, int *xv, int *yv) +{ + if (xv) *xv = cdRound(canvas->sx*xw + canvas->tx); + if (yv) *yv = cdRound(canvas->sy*yw + canvas->ty); +} + +#define _wWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \ +{ \ + _Wv = cdRound(_canvas->sx*(_Ww)); \ + _Hv = cdRound(_canvas->sy*(_Hw)); \ +} + +#define _wfWorld2CanvasSize(_canvas, _Ww, _Hw, _Wv, _Hv) \ +{ \ + _Wv = (_canvas->sx*(_Ww)); \ + _Hv = (_canvas->sy*(_Hw)); \ +} + +void wdCanvasWorld2CanvasSize(cdCanvas* canvas, double hw, double vw, int *hv, int *vv) +{ + if (hv) *hv = cdRound(canvas->sx*hw); + if (vv) *vv = cdRound(canvas->sy*vw); +} + +#define _wCanvas2World(_canvas, _xv, _yv, _xw, _yw) \ +{ \ + _xw = ((double)(_xv) - _canvas->tx)/_canvas->sx; \ + _yw = ((double)(_yv) - _canvas->ty)/_canvas->sy; \ +} + +void wdCanvasCanvas2World(cdCanvas* canvas, int xv, int yv, double *xw, double *yw) +{ + if (xw) *xw = ((double)xv - canvas->tx)/canvas->sx; + if (yw) *yw = ((double)yv - canvas->ty)/canvas->sy; +} + +void wdCanvasClipArea(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + int xminr, xmaxr, yminr, ymaxr; + + _wWorld2Canvas(canvas, xmin, ymin, xminr, yminr); + _wWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr); + + cdCanvasClipArea(canvas, xminr, xmaxr, yminr, ymaxr); +} + +int wdCanvasIsPointInRegion(cdCanvas* canvas, double x, double y) +{ + int xr, yr; + _wWorld2Canvas(canvas, x, y, xr, yr); + return cdCanvasIsPointInRegion(canvas, xr, yr); +} + +void wdCanvasOffsetRegion(cdCanvas* canvas, double x, double y) +{ + int xr, yr; + _wWorld2Canvas(canvas, x, y, xr, yr); + cdCanvasOffsetRegion(canvas, xr, yr); +} + +void wdCanvasGetRegionBox(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax) +{ + int xminr, xmaxr, yminr, ymaxr; + cdCanvasGetRegionBox(canvas, &xminr, &xmaxr, &yminr, &ymaxr); + _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin); + _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax); +} + +int wdCanvasGetClipArea(cdCanvas* canvas, double *xmin, double *xmax, double *ymin, double *ymax) +{ + int xminr, xmaxr, yminr, ymaxr; + int clip = cdCanvasGetClipArea(canvas, &xminr, &xmaxr, &yminr, &ymaxr); + _wCanvas2World(canvas, xminr, yminr, *xmin, *ymin); + _wCanvas2World(canvas, xmaxr, ymaxr, *xmax, *ymax); + return clip; +} + +void wdCanvasLine(cdCanvas* canvas, double x1, double y1, double x2, double y2) +{ + double xr1, xr2, yr1, yr2; + _wfWorld2Canvas(canvas, x1, y1, xr1, yr1); + _wfWorld2Canvas(canvas, x2, y2, xr2, yr2); + cdfCanvasLine(canvas, xr1, yr1, xr2, yr2); +} + +void wdCanvasBox(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + double xminr, xmaxr, yminr, ymaxr; + _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr); + _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr); + cdfCanvasBox(canvas, xminr, xmaxr, yminr, ymaxr); +} + +void wdCanvasRect(cdCanvas* canvas, double xmin, double xmax, double ymin, double ymax) +{ + double xminr, xmaxr, yminr, ymaxr; + _wfWorld2Canvas(canvas, xmin, ymin, xminr, yminr); + _wfWorld2Canvas(canvas, xmax, ymax, xmaxr, ymaxr); + cdfCanvasRect(canvas, xminr, xmaxr, yminr, ymaxr); +} + +void wdCanvasArc(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + double xcr, ycr, wr, hr; + _wfWorld2Canvas(canvas, xc, yc, xcr, ycr); + _wfWorld2CanvasSize(canvas, w, h, wr, hr); + cdfCanvasArc(canvas, xcr, ycr, wr, hr, angle1, angle2); +} + +void wdCanvasSector(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + double xcr, ycr, wr, hr; + _wfWorld2Canvas(canvas, xc, yc, xcr, ycr); + _wfWorld2CanvasSize(canvas, w, h, wr, hr); + cdfCanvasSector(canvas, xcr, ycr, wr, hr, angle1, angle2); +} + +void wdCanvasChord(cdCanvas* canvas, double xc, double yc, double w, double h, double angle1, double angle2) +{ + double xcr, ycr, wr, hr; + _wfWorld2Canvas(canvas, xc, yc, xcr, ycr); + _wfWorld2CanvasSize(canvas, w, h, wr, hr); + cdfCanvasChord(canvas, xcr, ycr, wr, hr, angle1, angle2); +} + +void wdCanvasText(cdCanvas* canvas, double x, double y, const char *s) +{ + double xr, yr; + _wfWorld2Canvas(canvas, x, y, xr, yr); + cdfCanvasText(canvas, xr, yr, s); +} + +void wdCanvasVertex(cdCanvas* canvas, double x, double y) +{ + double xr, yr; + _wfWorld2Canvas(canvas, x, y, xr, yr); + cdfCanvasVertex(canvas, xr, yr); +} + +void wdCanvasMark(cdCanvas* canvas, double x, double y) +{ + int xr, yr; + _wWorld2Canvas(canvas, x, y, xr, yr); + cdCanvasMark(canvas, xr, yr); +} + +void wdCanvasPixel(cdCanvas* canvas, double x, double y, long color) +{ + int xr, yr; + _wWorld2Canvas(canvas, x, y, xr, yr); + cdCanvasPixel(canvas, xr, yr, color); +} + +void wdCanvasPutImageRect(cdCanvas* canvas, cdImage* image, double x, double y, int xmin, int xmax, int ymin, int ymax) +{ + int xr, yr; + _wWorld2Canvas(canvas, x, y, xr, yr); + cdCanvasPutImageRect(canvas, image, xr, yr, xmin, xmax, ymin, ymax); +} + +void wdCanvasPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + int xr, yr, wr, hr; + _wWorld2Canvas(canvas, x, y, xr, yr); + _wWorld2CanvasSize(canvas, w, h, wr, hr); + cdCanvasPutImageRectRGB(canvas, iw, ih, r, g, b, xr, yr, wr, hr, xmin, xmax, ymin, ymax); +} + +void wdCanvasPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + int xr, yr, wr, hr; + _wWorld2Canvas(canvas, x, y, xr, yr); + _wWorld2CanvasSize(canvas, w, h, wr, hr); + cdCanvasPutImageRectRGBA(canvas, iw, ih, r, g, b, a, xr, yr, wr, hr, xmin, xmax, ymin, ymax); +} + +void wdCanvasPutImageRectMap(cdCanvas* canvas, int iw, int ih, const unsigned char *index, const long *colors, double x, double y, double w, double h, int xmin, int xmax, int ymin, int ymax) +{ + int xr, yr, wr, hr; + _wWorld2Canvas(canvas, x, y, xr, yr); + _wWorld2CanvasSize(canvas, w, h, wr, hr); + cdCanvasPutImageRectMap(canvas, iw, ih, index, colors, xr, yr, wr, hr, xmin, xmax, ymin, ymax); +} + +void wdCanvasPutBitmap(cdCanvas* canvas, cdBitmap* image, double x, double y, double w, double h) +{ + int xr, yr, wr, hr; + _wWorld2Canvas(canvas, x, y, xr, yr); + _wWorld2CanvasSize(canvas, w, h, wr, hr); + cdCanvasPutBitmap(canvas, image, xr, yr, wr, hr); +} + +double wdCanvasLineWidth(cdCanvas* canvas, double width_mm) +{ + int width; + double line_width_mm = canvas->line_width/canvas->xres; + + if (width_mm == CD_QUERY) + return line_width_mm; + + width = cdRound(width_mm*canvas->xres); + if (width < 1) width = 1; + + cdCanvasLineWidth(canvas, width); + + return line_width_mm; +} + +int wdCanvasFont(cdCanvas* canvas, const char* type_face, int style, double size_mm) +{ + return cdCanvasFont(canvas, type_face, style, cdRound(size_mm*CD_MM2PT)); +} + +void wdCanvasGetFont(cdCanvas* canvas, char *type_face, int *style, double *size) +{ + int point_size; + cdCanvasGetFont(canvas, type_face, style, &point_size); + if (point_size<0) + { + if (size) cdCanvasPixel2MM(canvas, -point_size, 0, size, NULL); + } + else + { + if (size) *size = ((double)point_size) / CD_MM2PT; + } +} + +double wdCanvasMarkSize(cdCanvas* canvas, double size_mm) +{ + int size; + double mark_size_mm = canvas->mark_size/canvas->xres; + + if (size_mm == CD_QUERY) + return mark_size_mm; + + size = cdRound(size_mm*canvas->xres); + if (size < 1) size = 1; + + canvas->mark_size = size; + + return mark_size_mm; +} + +void wdCanvasGetFontDim(cdCanvas* canvas, double *max_width, double *height, double *ascent, double *descent) +{ + double origin_x, origin_y, tmp = 0; + double distance_x, distance_y; + int font_max_width, font_height, font_ascent, font_descent; + cdCanvasGetFontDim(canvas, &font_max_width, &font_height, &font_ascent, &font_descent); + _wCanvas2World(canvas, 0, 0, origin_x, origin_y); + _wCanvas2World(canvas, font_max_width, font_height, distance_x, distance_y); + if (max_width) *max_width = fabs(distance_x - origin_x); + if (height) *height = fabs(distance_y - origin_y); + _wCanvas2World(canvas, tmp, font_ascent, tmp, distance_y); + if (ascent) *ascent = fabs(distance_y - origin_y); + _wCanvas2World(canvas, tmp, font_descent, tmp, distance_y); + if (descent) *descent = fabs(distance_y - origin_y); +} + +void wdCanvasGetTextSize(cdCanvas* canvas, const char *s, double *width, double *height) +{ + int text_width, text_height; + double origin_x, origin_y; + double text_x, text_y; + _wCanvas2World(canvas, 0, 0, origin_x, origin_y); + cdCanvasGetTextSize(canvas, s, &text_width, &text_height); + _wCanvas2World(canvas, text_width, text_height, text_x, text_y); + if (width) *width = fabs(text_x - origin_x); + if (height) *height = fabs(text_y - origin_y); +} + +void wdCanvasGetTextBox(cdCanvas* canvas, double x, double y, const char *s, double *xmin, double *xmax, double *ymin, double *ymax) +{ + int rx, ry, rxmin, rxmax, rymin, rymax; + + _wWorld2Canvas(canvas, x, y, rx, ry); + cdCanvasGetTextBox(canvas, rx, ry, s, &rxmin, &rxmax, &rymin, &rymax); + + _wCanvas2World(canvas, rxmin, rymin, *xmin, *ymin); + _wCanvas2World(canvas, rxmax, rymax, *xmax, *ymax); +} + +void wdCanvasGetTextBounds(cdCanvas* canvas, double x, double y, const char *s, double *rect) +{ + int rx, ry, rrect[8]; + + _wWorld2Canvas(canvas, x, y, rx, ry); + cdCanvasGetTextBounds(canvas, rx, ry, s, rrect); + + _wCanvas2World(canvas, rrect[0], rrect[1], rect[0], rect[1]); + _wCanvas2World(canvas, rrect[2], rrect[3], rect[2], rect[3]); + _wCanvas2World(canvas, rrect[4], rrect[5], rect[4], rect[5]); + _wCanvas2World(canvas, rrect[6], rrect[7], rect[6], rect[7]); +} + +void wdCanvasPattern(cdCanvas* canvas, int w, int h, const long *color, double w_mm, double h_mm) +{ + long *pattern = 0; + int w_pxl, h_pxl, x, y, cx, cy; + int wratio, hratio; + int *XTab, *YTab; + + cdCanvasMM2Pixel(canvas, w_mm, h_mm, &w_pxl, &h_pxl); + + wratio = cdRound((double)w_pxl/(double)w); + hratio = cdRound((double)h_pxl/(double)h); + + wratio = (wratio <= 0)? 1: wratio; + hratio = (hratio <= 0)? 1: hratio; + + w_pxl = wratio * w; + h_pxl = hratio * h; + + pattern = (long*)malloc(w_pxl*h_pxl*sizeof(long)); + + XTab = cdGetZoomTable(w_pxl, w, 0); + YTab = cdGetZoomTable(h_pxl, h, 0); + + for (y=0; y +#include + +#include "cd.h" +#include "wd.h" + +/* from cd_private.h */ +int cdRound(double x); + +/* re-declared here to ignore CD_NO_OLD_INTERFACE definition */ +int cdActivate(cdCanvas* canvas); +cdCanvas* cdActiveCanvas(void); + +/* +** --------------------------------------------------------------- +** Private functions: +*/ + +static void _wdHdcpyDoit(cdCanvas *canvas, cdCanvas *canvas_copy, void (*draw_func)(cdCanvas *canvas_copy)) +{ + cdCanvas *old_active; + double left, right, bottom, top; /* canvas visualization window */ + int canvas_hsize, canvas_vsize; /* canvas sizes in pixels */ + int hdcpy_hsize, hdcpy_vsize; /* paper sizes in points */ + double canvas_vpr; /* canvas viewport distortion ratio */ + double hdcpy_vpr; /* paper viewport distortion ratio */ + int xc, yc; /* paper center in pixels */ + int xmin, xmax, ymin, ymax; /* paper viewport */ + + /* Activate canvas visualization surface. */ + if (cdCanvasActivate(canvas) != CD_OK) return; + + /* Get current canvas window parameters and sizes. */ + wdCanvasGetWindow(canvas, &left, &right, &bottom, &top); + cdCanvasGetSize(canvas, &canvas_hsize, &canvas_vsize, 0L, 0L); + + /* Activate hardcopy visualization surface. */ + if (cdCanvasActivate(canvas_copy) != CD_OK) return; + + /* Set window parameters on hardcopy surface. */ + wdCanvasWindow(canvas_copy, left, right, bottom, top); + + /* Adjust paper viewport, centralized, matching canvas viewport. */ + canvas_vpr = (double)canvas_vsize / (double)canvas_hsize; + cdCanvasGetSize(canvas_copy, &hdcpy_hsize, &hdcpy_vsize, 0L, 0L); + hdcpy_vpr = (double)hdcpy_vsize / (double)hdcpy_hsize; + xc = (int)((double)hdcpy_hsize/2.0); + yc = (int)((double)hdcpy_vsize/2.0); + + if (canvas_vpr < hdcpy_vpr) + { + xmin = 0; + xmax = hdcpy_hsize; + ymin = yc - (int)((double)hdcpy_hsize*(double)canvas_vpr/2.0); + ymax = yc + (int)((double)hdcpy_hsize*(double)canvas_vpr/2.0); + } + else + { + xmin = xc - (int)((double)hdcpy_vsize/(double)canvas_vpr/2.0); + xmax = xc + (int)((double)hdcpy_vsize/(double)canvas_vpr/2.0); + ymin = 0; + ymax = hdcpy_vsize; + } + + cdCanvasClipArea(canvas_copy, xmin, xmax, ymin, ymax); + cdCanvasClip(canvas_copy, CD_CLIPAREA); + wdCanvasViewport(canvas_copy, xmin, xmax, ymin, ymax); + + /* for backward compatibility */ + old_active = cdActiveCanvas(); + cdActivate(canvas_copy); + + /* Draw on hardcopy surface. */ + draw_func(canvas_copy); + + if (old_active) cdActivate(old_active); +} + +/* +** --------------------------------------------------------------- +** Entry points begin here: +*/ + +void wdCanvasHardcopy(cdCanvas *canvas, cdContext* ctx, void *data, void(*draw_func)(cdCanvas *canvas_copy)) +{ + /* Create a visualization surface. */ + cdCanvas *canvas_copy = cdCreateCanvas(ctx, data); + if (!canvas_copy) return; + + /* Do hardcopy. */ + _wdHdcpyDoit(canvas, canvas_copy, draw_func); + + /* Destroy visualization surface. */ + cdKillCanvas(canvas_copy); +} diff --git a/cd/src/win32/cdwclp.c b/cd/src/win32/cdwclp.c new file mode 100755 index 0000000..a62e9e8 --- /dev/null +++ b/cd/src/win32/cdwclp.c @@ -0,0 +1,552 @@ +/** \file + * \brief Windows Clipboard Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include + +#include "cdwin.h" +#include "cdclipbd.h" +#include "cdmf.h" +#include "cdemf.h" +#include "cdwmf.h" +#include "cdmf_private.h" + + +static cdSizeCB cdsizecb = NULL; + +static int cdregistercallback(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdsizecb = (cdSizeCB)func; + return CD_OK; + } + + return CD_ERROR; +} + +/* +%F cdPlay para Clipboard. +Interpreta os dados do clipboard, seja metafile ou bitmap. +*/ +static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + char tmpPath[512]; + char filename[1024]; + HANDLE hFile; + DWORD dwSize, nBytesWrite; + int err; + unsigned char* buffer; + (void)data; + + if (IsClipboardFormatAvailable(CF_TEXT)) + { + HANDLE Handle; + + GetTempPath(512, tmpPath); + GetTempFileName(tmpPath, "~cd", 0, filename); + + OpenClipboard(NULL); + Handle = GetClipboardData(CF_TEXT); + if (Handle == NULL) + { + CloseClipboard(); + return CD_ERROR; + } + + buffer = (unsigned char*)GlobalLock(Handle); + dwSize = (DWORD)GlobalSize(Handle); + + hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL); + CloseHandle(hFile); + + GlobalUnlock(Handle); + + CloseClipboard(); + + err = cdCanvasPlay(canvas, CD_METAFILE, xmin, xmax, ymin, ymax, filename); + + DeleteFile(filename); + + if (err == CD_OK) + return err; + } + + if (IsClipboardFormatAvailable(CF_ENHMETAFILE)) + { + HENHMETAFILE Handle; + + GetTempPath(512, tmpPath); + GetTempFileName(tmpPath, "~cd", 0, filename); + + OpenClipboard(NULL); + Handle = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE); + if (Handle == NULL) + { + CloseClipboard(); + return CD_ERROR; + } + + dwSize = GetEnhMetaFileBits(Handle, 0, NULL); + + buffer = (unsigned char*)malloc(dwSize); + + GetEnhMetaFileBits(Handle, dwSize, buffer); + + hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL); + CloseHandle(hFile); + + free(buffer); + + CloseClipboard(); + + err = cdCanvasPlay(canvas, CD_EMF, xmin, xmax, ymin, ymax, filename); + + DeleteFile(filename); + + return err; + } + + if (IsClipboardFormatAvailable(CF_METAFILEPICT)) + { + HANDLE Handle; + METAFILEPICT* lpMFP; + + GetTempPath(512, tmpPath); + GetTempFileName(tmpPath, "~cd", 0, filename); + + OpenClipboard(NULL); + Handle = GetClipboardData(CF_METAFILEPICT); + if (Handle == NULL) + { + CloseClipboard(); + return CD_ERROR; + } + + lpMFP = (METAFILEPICT*) GlobalLock(Handle); + + dwSize = GetMetaFileBitsEx(lpMFP->hMF, 0, NULL); + buffer = (unsigned char*)malloc(dwSize); + + GetMetaFileBitsEx(lpMFP->hMF, dwSize, buffer); + + hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); + wmfWritePlacebleFile(hFile, buffer, dwSize, lpMFP->mm, lpMFP->xExt, lpMFP->yExt); + CloseHandle(hFile); + + GlobalUnlock(Handle); + free(buffer); + + CloseClipboard(); + + err = cdCanvasPlay(canvas, CD_WMF, xmin, xmax, ymin, ymax, filename); + + DeleteFile(filename); + + return err; + } + + if (IsClipboardFormatAvailable(CF_DIB)) + { + HANDLE Handle; + int size; + cdwDIB dib; + + OpenClipboard(NULL); + Handle = GetClipboardData(CF_DIB); + if (Handle == NULL) + { + CloseClipboard(); + return CD_ERROR; + } + + cdwDIBReference(&dib, (BYTE*) GlobalLock(Handle), NULL); + + if (dib.type == -1) + { + GlobalUnlock(Handle); + CloseClipboard(); + return CD_ERROR; + } + + if (cdsizecb) + { + int err; + err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h); + if (err) + { + GlobalUnlock(Handle); + CloseClipboard(); + return CD_ERROR; + } + } + + size = dib.w*dib.h; + + if (xmax == 0) xmax = dib.w + xmin - 1; + if (ymax == 0) ymax = dib.h + ymin - 1; + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, xmin, ymin, xmax - xmin + 1, ymax - ymin + 1, 0, 0, 0, 0); + + free(index); + free(colors); + } + + GlobalUnlock(Handle); + + CloseClipboard(); + + return CD_ERROR; + } + + if (IsClipboardFormatAvailable(CF_BITMAP)) + { + HBITMAP Handle; + int size, type; + cdwDIB dib; + HDC ScreenDC; + SIZE sz; + + OpenClipboard(NULL); + Handle = GetClipboardData(CF_BITMAP); + if (Handle == NULL) + { + CloseClipboard(); + return CD_ERROR; + } + + GetBitmapDimensionEx(Handle, &sz); + + ScreenDC = GetDC(NULL); + if (GetDeviceCaps(ScreenDC, BITSPIXEL) > 8) + type = 0; + else + type = 1; + + dib.w = sz.cx; + dib.h = sz.cy; + dib.type = type; + + if (cdsizecb) + { + int err; + err = cdsizecb(canvas, dib.w, dib.h, dib.w, dib.h); + if (err) + { + ReleaseDC(NULL, ScreenDC); + CloseClipboard(); + return CD_ERROR; + } + } + + cdwCreateDIB(&dib); + + GetDIBits(ScreenDC, Handle, 0, sz.cy, dib.bits, dib.bmi, DIB_RGB_COLORS); + ReleaseDC(NULL, ScreenDC); + + size = dib.w*dib.h; + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, dib.h, r, g, b, 0, 0, dib.w, dib.h, 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, dib.h, index, colors, 0, 0, dib.w, dib.h, 0, 0, 0, 0); + + free(index); + free(colors); + } + + cdwKillDIB(&dib); + + CloseClipboard(); + + return CD_ERROR; + } + + return CD_ERROR; +} + +static void cdkillcanvasCLIPBDMF (cdCtxCanvas *ctxcanvas) +{ + HANDLE Handle, hFile; + char* buffer; + DWORD dwSize, nBytesRead; + char filename[10240]; + cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas; + + /* guardar antes de remover o canvas */ + strcpy(filename, mfcanvas->filename); + + OpenClipboard(NULL); + EmptyClipboard(); + + cdkillcanvasMF(mfcanvas); /* this will close the file */ + + hFile = CreateFile(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + dwSize = GetFileSize (hFile, NULL) ; + + Handle = GlobalAlloc(GMEM_MOVEABLE, dwSize+1); + buffer = (char*)GlobalLock(Handle); + ReadFile(hFile, buffer, dwSize, &nBytesRead, NULL); + buffer[dwSize] = 0; + GlobalUnlock(Handle); + + CloseHandle(hFile); + + SetClipboardData(CF_TEXT, Handle); + + CloseClipboard(); +} + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ + cdwKillCanvas(ctxcanvas); + + OpenClipboard(NULL); + EmptyClipboard(); + + if (ctxcanvas->wtype == CDW_WMF) + { + HMETAFILE hmf = CloseMetaFile(ctxcanvas->hDC); + + HANDLE hMemG; + METAFILEPICT* lpMFP; + + hMemG = GlobalAlloc(GHND|GMEM_DDESHARE, (DWORD)sizeof(METAFILEPICT)); + lpMFP = (METAFILEPICT*) GlobalLock(hMemG); + + lpMFP->mm = MM_ANISOTROPIC; + lpMFP->xExt = (long)(100 * ctxcanvas->canvas->w_mm); + lpMFP->yExt = (long)(100 * ctxcanvas->canvas->h_mm); + + lpMFP->hMF = hmf; + + GlobalUnlock(hMemG); + SetClipboardData(CF_METAFILEPICT, hMemG); + } + else if (ctxcanvas->wtype == CDW_EMF) + { + HENHMETAFILE hmf = CloseEnhMetaFile(ctxcanvas->hDC); + SetClipboardData(CF_ENHMETAFILE, hmf); + } + else + { + HANDLE hDib; + + GdiFlush(); + + hDib = cdwCreateCopyHDIB(&ctxcanvas->bmiClip, ctxcanvas->bitsClip); + + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBitmapClip); + DeleteObject(ctxcanvas->hBitmapClip); + DeleteDC(ctxcanvas->hDC); + + SetClipboardData(CF_DIB, hDib); + } + + CloseClipboard(); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char* strsize = (char*)data; + int w = 0, h = 0, wtype = CDW_EMF; /* default clipboard type */ + double xres=0, yres=0; + HDC hDC; + BITMAPINFO bmi; + BYTE* bits; + HBITMAP hBitmapClip, hOldBitmapClip; + + /* Inicializa parametros */ + if (strsize == NULL) + return; + + if (strstr(strsize, "-b") != NULL) + wtype = CDW_BMP; + else if (strstr(strsize, "-m") != NULL) + wtype = -1; /* CD METAFILE */ + + if (wtype != -1) + { + sscanf(strsize,"%dx%d",&w, &h); + if (w == 0 || h == 0) + return; + } + + if (wtype == CDW_EMF) + { + HDC ScreenDC = GetDC(NULL); + RECT rect; + /* LOGPIXELS can not be used for EMF */ + xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + rect.left = 0; + rect.top = 0; + rect.right = (int)(100. * w / xres); + rect.bottom = (int)(100. * h / yres); + hDC = CreateEnhMetaFile(ScreenDC,NULL,&rect,NULL); + ReleaseDC(NULL, ScreenDC); + } + else if (wtype == CDW_BMP) + { + HDC ScreenDC = GetDC(NULL); + hDC = CreateCompatibleDC(ScreenDC); + xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = w; + bmi.bmiHeader.biHeight = h; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 24; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biSizeImage = 0; + bmi.bmiHeader.biXPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSX) / 0.0254); + bmi.bmiHeader.biYPelsPerMeter = (long)(GetDeviceCaps(ScreenDC, LOGPIXELSY) / 0.0254); + bmi.bmiHeader.biClrUsed = 0; + bmi.bmiHeader.biClrImportant = 0; + + hBitmapClip = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, &bits, NULL, 0); + + ReleaseDC(NULL, ScreenDC); + + if (!hBitmapClip) + return; + + hOldBitmapClip = SelectObject(hDC, hBitmapClip); + } + + if (wtype == -1) + { + char filename[1024]; + char tmpPath[512]; + char str[1024]; + + GetTempPath(512, tmpPath); + GetTempFileName(tmpPath, "~cd", 0, filename); + + sprintf(str, "%s %s", filename, strsize); + cdcreatecanvasMF(canvas, str); + } + else + { + cdCtxCanvas* ctxcanvas; + + /* Inicializa driver WIN32 */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype); + + canvas->w = w; + canvas->h = h; + canvas->xres = xres; + canvas->yres = yres; + canvas->w_mm = ((double)w) / xres; + canvas->h_mm = ((double)h) / yres; + canvas->bpp = 24; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; + + if (wtype == CDW_BMP) + { + ctxcanvas->hBitmapClip = hBitmapClip; + ctxcanvas->hOldBitmapClip = hOldBitmapClip; + ctxcanvas->bmiClip = bmi; + ctxcanvas->bitsClip = bits; + } + } +} + +static void cdinittable(cdCanvas* canvas) +{ + if (canvas->invert_yaxis == 0) /* a simple way to distinguish MF from WIN */ + { + cdinittableMF(canvas); + canvas->cxKillCanvas = cdkillcanvasCLIPBDMF; + } + else + { + cdwInitTable(canvas); + canvas->cxKillCanvas = cdkillcanvas; + } +} + +static cdContext cdClipboardContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + cdplay, + cdregistercallback +}; + +cdContext* cdContextClipboard(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_CLIPBOARD); + if (ctx != NULL) + return ctx; + } + + return &cdClipboardContext; +} diff --git a/cd/src/win32/cdwdbuf.c b/cd/src/win32/cdwdbuf.c new file mode 100755 index 0000000..85af87c --- /dev/null +++ b/cd/src/win32/cdwdbuf.c @@ -0,0 +1,181 @@ +/** \file + * \brief Windows Double Buffer + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cdwin.h" +#include "cddbuf.h" + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + cdKillImage(ctxcanvas->image_dbuffer); + cdwKillCanvas(ctxcanvas); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cddeactivate(cdCtxCanvas* ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + /* this is done in the canvas_dbuffer context */ + cdCanvasDeactivate(canvas_dbuffer); +} + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + int old_writemode; + cdImage* image_dbuffer = ctxcanvas->image_dbuffer; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + GdiFlush(); + + /* this is done in the canvas_dbuffer context */ + /* Flush can be affected by Origin and Clipping, but not WriteMode */ + old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE); + cdCanvasPutImageRect(canvas_dbuffer, image_dbuffer, 0, 0, 0, 0, 0, 0); + cdCanvasWriteMode(canvas_dbuffer, old_writemode); +} + +static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer) +{ + int w, h; + cdCtxCanvas* ctxcanvas; + cdImage* image_dbuffer; + cdCtxImage* ctximage; + + cdCanvasActivate(canvas_dbuffer); + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + /* this is done in the canvas_dbuffer context */ + image_dbuffer = cdCanvasCreateImage(canvas_dbuffer, w, h); + if (!image_dbuffer) + return; + + ctximage = image_dbuffer->ctximage; + + /* Inicializa driver DBuffer */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, ctximage->hDC, CDW_BMP); + + ctxcanvas->image_dbuffer = image_dbuffer; + ctxcanvas->canvas_dbuffer = canvas_dbuffer; + + canvas->w = ctximage->w; + canvas->h = ctximage->h; + canvas->w_mm = ctximage->w_mm; + canvas->h_mm = ctximage->h_mm; + canvas->bpp = ctximage->bpp; + canvas->xres = ctximage->xres; + canvas->yres = ctximage->yres; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = ctximage->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = ctximage->h - 1; +} + +static int cdactivate(cdCtxCanvas *ctxcanvas) +{ + int w, h; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* this is done in the canvas_dbuffer context */ + /* this will update canvas size */ + cdCanvasActivate(canvas_dbuffer); + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + /* check if the size changed */ + if (w != ctxcanvas->image_dbuffer->w || + h != ctxcanvas->image_dbuffer->h) + { + cdCanvas* canvas = ctxcanvas->canvas; + /* save the current, if the rebuild fail */ + cdImage* old_image_dbuffer = ctxcanvas->image_dbuffer; + cdCtxCanvas* old_ctxcanvas = ctxcanvas; + + /* if the image is rebuild, the canvas that uses the image must be also rebuild */ + + /* rebuild the image and the canvas */ + canvas->ctxcanvas = NULL; + cdcreatecanvas(canvas, canvas_dbuffer); + if (!canvas->ctxcanvas) + { + canvas->ctxcanvas = old_ctxcanvas; + return CD_ERROR; + } + + /* remove the old image and canvas */ + cdKillImage(old_image_dbuffer); + cdwKillCanvas(old_ctxcanvas); + free(old_ctxcanvas); + + ctxcanvas = canvas->ctxcanvas; + + /* update canvas attributes */ + canvas->cxBackground(ctxcanvas, canvas->background); + canvas->cxForeground(ctxcanvas, canvas->foreground); + canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity); + canvas->cxWriteMode(ctxcanvas, canvas->write_mode); + canvas->cxLineStyle(ctxcanvas, canvas->line_style); + canvas->cxLineWidth(ctxcanvas, canvas->line_width); + canvas->cxLineCap(ctxcanvas, canvas->line_cap); + canvas->cxLineJoin(ctxcanvas, canvas->line_join); + canvas->cxHatch(ctxcanvas, canvas->hatch_style); + if (canvas->stipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple); + if (canvas->pattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern); + canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style); + if (canvas->native_font[0] == 0) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + else canvas->cxNativeFont(ctxcanvas, canvas->native_font); + canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment); + canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation); + if (canvas->use_matrix && canvas->cxTransform) canvas->cxTransform(ctxcanvas, canvas->matrix); + if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax); +/* if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); */ + if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n); +/* if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); */ + if (canvas->clip_mode != CD_CLIPOFF) canvas->cxClip(ctxcanvas, canvas->clip_mode); + } + + return CD_OK; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxActivate = cdactivate; + canvas->cxDeactivate = cddeactivate; + canvas->cxFlush = cdflush; + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdDBufferContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextDBuffer(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_DBUFFER); + if (ctx != NULL) + return ctx; + } + + return &cdDBufferContext; +} diff --git a/cd/src/win32/cdwdib.c b/cd/src/win32/cdwdib.c new file mode 100755 index 0000000..aff3f64 --- /dev/null +++ b/cd/src/win32/cdwdib.c @@ -0,0 +1,662 @@ +/** \file + * \brief Windows DIB Utilities + * + * See Copyright Notice in cd.h + */ + +#include "cdwin.h" + + +/* +%F Calcula o tamanho de uma linha. O DIB existe em uma "long boundary", +ou seja cada linha e' um multiplo de quatro bytes ou 32 bits. +*/ +static int cdwDIBLineSize(int width, int bpp) +{ + return ((width * bpp + 31L) / 32L) * 4L; +} + + +/* +%F Alloca memoria para o DIB com os par^ametros do cdwDIB. +*/ +int cdwCreateDIB(cdwDIB* dib) +{ + int dibSize, pal_size; + BITMAPINFOHEADER* bmih; + + pal_size = dib->type? 256: 0; + dibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size + cdwDIBLineSize(dib->w, dib->type? 8: 24) * dib->h; + + dib->dib = (BYTE*) calloc(dibSize, 1); + if (dib->dib == NULL) + return 0; + + dib->bmi = (BITMAPINFO*)dib->dib; + dib->bmih = (BITMAPINFOHEADER*)dib->dib; + dib->bmic = (RGBQUAD*)(dib->dib + sizeof(BITMAPINFOHEADER)); + dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size; + + bmih = dib->bmih; + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = dib->w; + bmih->biHeight = dib->h; + bmih->biPlanes = 1; + bmih->biBitCount = dib->type? 8: 24; + bmih->biCompression = 0; + bmih->biSizeImage = 0; + bmih->biXPelsPerMeter = 0; + bmih->biYPelsPerMeter = 0; + bmih->biClrUsed = dib->type? 256: 0; + bmih->biClrImportant = dib->type? 256: 0; + + return 1; +} + +HANDLE cdwCreateCopyHDIB(BITMAPINFO* bmi, BYTE* bits) +{ + int dibSize, pal_size, headerSize; + HANDLE hDib; unsigned char* pDib; + + if (bmi->bmiHeader.biBitCount > 8) + { + pal_size = 0; + + if (bmi->bmiHeader.biCompression == BI_BITFIELDS) + pal_size = 3; + } + else + { + if (bmi->bmiHeader.biClrUsed != 0) + pal_size = bmi->bmiHeader.biClrUsed; + else + pal_size = 1 << bmi->bmiHeader.biBitCount; + } + + /* calc size */ + headerSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size; + dibSize = headerSize + cdwDIBLineSize(bmi->bmiHeader.biWidth, bmi->bmiHeader.biBitCount) * bmi->bmiHeader.biHeight; + + hDib = GlobalAlloc(GHND, dibSize); + if (!hDib) + return NULL; + + /* Get a pointer to the memory block */ + pDib = (LPBYTE)GlobalLock(hDib); + + /* copy struct data */ + CopyMemory(pDib, bmi, headerSize); + + /* copy dib data */ + CopyMemory(pDib + headerSize, bits, dibSize - headerSize); + + GlobalUnlock(hDib); + + return hDib; +} + +int cdwCreateDIBRefBuffer(cdwDIB* dib, unsigned char* *bits, int *size) +{ + int dibSize, pal_size; + BITMAPINFOHEADER* bmih; + + pal_size = dib->type? 256: 0; + dibSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size + cdwDIBLineSize(dib->w, dib->type? 8: 24) * dib->h; + + /* bits may contains an allocated buffer, but no dib */ + if (*bits && *size >= dibSize) + dib->dib = *bits; + else + { + *size = dibSize; + + if (*bits) + *bits = realloc(*bits, *size); + else + *bits = malloc(*size); + + dib->dib = *bits; + } + + if (dib->dib == NULL) + return 0; + + dib->bmi = (BITMAPINFO*)dib->dib; + dib->bmih = (BITMAPINFOHEADER*)dib->dib; + dib->bmic = (RGBQUAD*)(dib->dib + sizeof(BITMAPINFOHEADER)); + dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size; + + bmih = dib->bmih; + bmih->biSize = sizeof(BITMAPINFOHEADER); + bmih->biWidth = dib->w; + bmih->biHeight = dib->h; + bmih->biPlanes = 1; + bmih->biBitCount = dib->type? 8: 24; + bmih->biCompression = 0; + bmih->biSizeImage = 0; + bmih->biXPelsPerMeter = 0; + bmih->biYPelsPerMeter = 0; + bmih->biClrUsed = dib->type? 256: 0; + bmih->biClrImportant = dib->type? 256: 0; + + return 1; +} + +void cdwCreateDIBRefBits(cdwDIB* dib, unsigned char *bits) +{ + BITMAPINFO* bmi = malloc(sizeof(BITMAPINFO)); + + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi->bmiHeader.biWidth = dib->w; + bmi->bmiHeader.biHeight = dib->h; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = dib->type==0? 24: 32; + bmi->bmiHeader.biCompression = BI_RGB; + bmi->bmiHeader.biXPelsPerMeter = 0; + bmi->bmiHeader.biYPelsPerMeter = 0; + bmi->bmiHeader.biSizeImage = 0; + bmi->bmiHeader.biClrUsed = 0; + bmi->bmiHeader.biClrImportant = 0; + + cdwDIBReference(dib, (BYTE*)bmi, bits); + + /* restore correct type */ + if (bmi->bmiHeader.biBitCount == 32) + dib->type = 2; +} + +HBITMAP cdwCreateDIBSection(cdwDIB* dib, HDC hDC) +{ + HBITMAP hbitmap; + BYTE *pvBits; + BITMAPINFO* bmi = malloc(sizeof(BITMAPINFO)); + + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi->bmiHeader.biWidth = dib->w; + bmi->bmiHeader.biHeight = dib->h; + bmi->bmiHeader.biPlanes = 1; + bmi->bmiHeader.biBitCount = dib->type==0? 24: 32; + bmi->bmiHeader.biCompression = BI_RGB; + bmi->bmiHeader.biXPelsPerMeter = (long)(GetDeviceCaps(hDC, LOGPIXELSX) / 0.0254); + bmi->bmiHeader.biYPelsPerMeter = (long)(GetDeviceCaps(hDC, LOGPIXELSY) / 0.0254); + bmi->bmiHeader.biSizeImage = 0; + bmi->bmiHeader.biClrUsed = 0; + bmi->bmiHeader.biClrImportant = 0; + + hbitmap = CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, &pvBits, NULL, 0x0); + + if (hbitmap) + { + cdwDIBReference(dib, (BYTE*)bmi, pvBits); + + /* restore correct type */ + if (bmi->bmiHeader.biBitCount == 32) + dib->type = 2; + } + else + free(bmi); + + return hbitmap; +} + +void cdwDIBReference(cdwDIB* dib, BYTE* bmi, BYTE* bits) +{ + int pal_size; + + dib->dib = bmi; + + dib->bmi = (BITMAPINFO*)bmi; + dib->bmih = &dib->bmi->bmiHeader; + dib->bmic = dib->bmi->bmiColors; + + if (dib->bmih->biBitCount > 8) + { + dib->type = 0; + pal_size = 0; + + if (dib->bmih->biCompression == BI_BITFIELDS) + pal_size = 3; + } + else + { + dib->type = 1; + + if (dib->bmih->biClrUsed != 0) + pal_size = dib->bmih->biClrUsed; + else + pal_size = 1 << dib->bmih->biBitCount; + } + + if (bits == NULL) + dib->bits = dib->dib + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * pal_size; + else + dib->bits = bits; + + dib->w = dib->bmih->biWidth; + dib->h = dib->bmih->biHeight; +} + + +/* %F Libera a memoria alocada para o DIB. */ +void cdwKillDIB(cdwDIB* dib) +{ + free(dib->dib); +} + +/* %F Converte cor de CD para DIB. */ +static RGBQUAD sColorToDIB(long cd_color) +{ + RGBQUAD color; + color.rgbRed = cdRed(cd_color); + color.rgbGreen = cdGreen(cd_color); + color.rgbBlue = cdBlue(cd_color); + return color; +} + +void cdwDIBEncodeRGBRect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, int xi, int yi, int wi, int hi) +{ + int x,y, resto1, resto2, offset; + BYTE* bits; + + bits = dib->bits; + resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3; + resto2 = wi - dib->w; + + offset = wi * yi + xi; + + red = red + offset; + green = green + offset; + blue = blue + offset; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + *bits++ = *blue++; + *bits++ = *green++; + *bits++ = *red++; + } + + bits += resto1; + + red += resto2; + green += resto2; + blue += resto2; + } +} + +/* RGB in RGBA DIBs are pre-multiplied by alpha to AlphaBlend usage. */ +#define CD_ALPHAPRE(_src, _alpha) (((_src)*(_alpha))/255) + +void cdwDIBEncodeRGBARect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int xi, int yi, int wi, int hi) +{ + int x,y, resto1, resto2, offset; + BYTE* bits; + + bits = dib->bits; + resto1 = cdwDIBLineSize(dib->w, 32) - dib->w * 4; + resto2 = wi - dib->w; + + offset = wi * yi + xi; + + red = red + offset; + green = green + offset; + blue = blue + offset; + alpha = alpha + offset; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + *bits++ = CD_ALPHAPRE(*blue, *alpha); blue++; + *bits++ = CD_ALPHAPRE(*green, *alpha); green++; + *bits++ = CD_ALPHAPRE(*red, *alpha); red++; + *bits++ = *alpha++; + } + + bits += resto1; + + red += resto2; + green += resto2; + blue += resto2; + alpha += resto2; + } +} + +void cdwDIBEncodeAlphaRect(cdwDIB* dib, const unsigned char *alpha, int xi, int yi, int wi, int hi) +{ + int x,y, resto1, resto2, offset; + BYTE* bits; + + bits = dib->bits; + resto1 = cdwDIBLineSize(dib->w, 32) - dib->w * 4; + resto2 = wi - dib->w; + + offset = wi * yi + xi; + + alpha = alpha + offset; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + *bits++ = CD_ALPHAPRE(*bits, *alpha); + *bits++ = CD_ALPHAPRE(*bits, *alpha); + *bits++ = CD_ALPHAPRE(*bits, *alpha); + *bits++ = *alpha++; + } + + bits += resto1; + alpha += resto2; + } +} + +void cdwDIBEncodeRGBARectZoom(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int w, int h, int xi, int yi, int wi, int hi) +{ + int x,y, resto1, resto2, offset; + BYTE* bits; + const unsigned char *_red, *_green, *_blue, *_alpha; + unsigned char a; + + bits = dib->bits; + resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3; + + if (dib->w != wi || dib->h != hi) + { + int* XTab = cdGetZoomTable(dib->w, wi, xi); + int* YTab = cdGetZoomTable(dib->h, hi, yi); + + for (y = 0; y < dib->h; y++) + { + offset = YTab[y] * w; + _red = red + offset; + _green = green + offset; + _blue = blue + offset; + _alpha = alpha + offset; + + for (x = 0; x < dib->w; x++) + { + offset = XTab[x]; + a = _alpha[offset]; + *bits++ = CD_ALPHA_BLEND(_blue[offset], *bits, a); + *bits++ = CD_ALPHA_BLEND(_green[offset], *bits, a); + *bits++ = CD_ALPHA_BLEND(_red[offset], *bits, a); + } + + bits += resto1; + } + + free(XTab); + free(YTab); + } + else + { + resto2 = w - wi; + + offset = w * yi + xi; + red = red + offset; + green = green + offset; + blue = blue + offset; + alpha = alpha + offset; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + a = *alpha++; + *bits++ = CD_ALPHA_BLEND(*blue++, *bits, a); + *bits++ = CD_ALPHA_BLEND(*green++, *bits, a); + *bits++ = CD_ALPHA_BLEND(*red++, *bits, a); + } + + bits += resto1; + + red += resto2; + green += resto2; + blue += resto2; + alpha += resto2; + } + } +} + +/* +%F Copia os pixels de um DIB em 3 matrizes red, green e +blue, respectivamente. As matrizes, armazenadas num vetor de bytes devem +ter a mesma dimens~ao da imagem. +*/ +void cdwDIBDecodeRGB(cdwDIB* dib, unsigned char *red, unsigned char *green, unsigned char *blue) +{ + int x,y, offset; + unsigned short color; + BYTE* bits; + unsigned long rmask=0, gmask=0, bmask=0, + roff = 0, goff = 0, boff = 0; /* pixel bit mask control when reading 16 and 32 bpp images */ + + bits = dib->bits; + + if (dib->bmih->biBitCount == 16) + offset = cdwDIBLineSize(dib->w, dib->bmih->biBitCount); + else + offset = cdwDIBLineSize(dib->w, dib->bmih->biBitCount) - dib->w * (dib->bmih->biBitCount == 24?3:4); + + if (dib->bmih->biCompression == BI_BITFIELDS) + { + unsigned long Mask; + unsigned long* palette = (unsigned long*)dib->bmic; + + rmask = Mask = palette[0]; + while (!(Mask & 0x01)) + {Mask >>= 1; roff++;} + + gmask = Mask = palette[1]; + while (!(Mask & 0x01)) + {Mask >>= 1; goff++;} + + bmask = Mask = palette[2]; + while (!(Mask & 0x01)) + {Mask >>= 1; boff++;} + } + else if (dib->bmih->biBitCount == 16) + { + bmask = 0x001F; + gmask = 0x03E0; + rmask = 0x7C00; + boff = 0; + goff = 5; + roff = 10; + } + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + if (dib->bmih->biBitCount != 16) + { + *blue++ = *bits++; + *green++ = *bits++; + *red++ = *bits++; + + if (dib->bmih->biBitCount == 32) + bits++; + } + else + { + color = ((unsigned short*)bits)[x]; + *red++ = (unsigned char)((((rmask & color) >> roff) * 255) / (rmask >> roff)); + *green++ = (unsigned char)((((gmask & color) >> goff) * 255) / (gmask >> goff)); + *blue++ = (unsigned char)((((bmask & color) >> boff) * 255) / (bmask >> boff)); + } + } + + bits += offset; + } +} + +void cdwDIBDecodeMap(cdwDIB* dib, unsigned char *index, long *colors) +{ + int x,y, line_size,c,pal_size; + BYTE* bits; + RGBQUAD* bmic; + + bmic = dib->bmic; + bits = dib->bits; + line_size = cdwDIBLineSize(dib->w, dib->bmih->biBitCount); + pal_size = dib->bmih->biClrUsed != 0? dib->bmih->biClrUsed: 1 << dib->bmih->biBitCount; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + switch (dib->bmih->biBitCount) + { + case 1: + *index++ = (unsigned char)((bits[x / 8] >> (7 - x % 8)) & 0x01); + break; + case 4: + *index++ = (unsigned char)((bits[x / 2] >> ((1 - x % 2) * 4)) & 0x0F); + break; + case 8: + *index++ = bits[x]; + break; + } + } + + bits += line_size; + } + + for (c = 0; c < pal_size; c++) + { + colors[c] = cdEncodeColor(bmic->rgbRed, bmic->rgbGreen, bmic->rgbBlue); + bmic++; + } +} + +/* +%F Cria uma Logical palette a partir da palette do DIB. +*/ +HPALETTE cdwDIBLogicalPalette(cdwDIB* dib) +{ + LOGPALETTE* pLogPal; + PALETTEENTRY* pPalEntry; + HPALETTE hPal; + RGBQUAD* bmic; + int c; + + pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)); + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = 256; + + bmic = dib->bmic; + pPalEntry = pLogPal->palPalEntry; + + for (c = 0; c < 256; c++) + { + pPalEntry->peRed = bmic->rgbRed; + pPalEntry->peGreen = bmic->rgbGreen; + pPalEntry->peBlue = bmic->rgbBlue; + pPalEntry->peFlags = PC_NOCOLLAPSE; + + pPalEntry++; + bmic++; + } + + hPal = CreatePalette(pLogPal); + free(pLogPal); + + return hPal; +} + +/* +%F Copia os pixels definidos por uma matriz de indices e palheta de +de cores num DIB de mesma dimens~ao. +*/ +void cdwDIBEncodeMap(cdwDIB* dib, unsigned char *index, long int *colors) +{ + int x,y, pal_size, resto, c; + BYTE* bits; + RGBQUAD* bmic; + + bits = dib->bits; + bmic = dib->bmic; + resto = cdwDIBLineSize(dib->w, 8) - dib->w; + + /* Como nao sabemos o tamanho da palette a priori, + teremos que ver qual o maior indice usado na imagem. */ + pal_size = *index; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + if (*index > pal_size) + pal_size = *index; + + *bits++ = *index++; + } + + bits += resto; + } + + pal_size++; + + for (c = 0; c < pal_size; c++) + *bmic++ = sColorToDIB(colors[c]); +} + +void cdwDIBEncodeMapRect(cdwDIB* dib, const unsigned char *index, const long int *colors, int xi, int yi, int wi, int hi) +{ + int x,y, pal_size, resto1, resto2, c; + BYTE* bits; + RGBQUAD* bmic; + + bits = dib->bits; + bmic = dib->bmic; + resto1 = cdwDIBLineSize(dib->w, 8) - dib->w; + resto2 = wi - dib->w; + + index = index + (wi * yi + xi); + + /* Como nao sabemos o tamanho da palette a priori, + teremos que ver qual o maior indice usado na imagem. */ + pal_size = *index; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + if (*index > pal_size) + pal_size = *index; + + *bits++ = *index++; + } + + bits += resto1; + index += resto2; + } + + pal_size++; + + for (c = 0; c < pal_size; c++) + *bmic++ = sColorToDIB(colors[c]); +} + +void cdwDIBEncodePattern(cdwDIB* dib, const long int *colors) +{ + int x,y, resto1; + BYTE* bits; + + bits = dib->bits; + resto1 = cdwDIBLineSize(dib->w, 24) - dib->w * 3; + + for (y = 0; y < dib->h; y++) + { + for (x = 0; x < dib->w; x++) + { + *bits++ = cdBlue(*colors); + *bits++ = cdGreen(*colors); + *bits++ = cdRed(*colors); + colors++; + } + bits += resto1; + } +} diff --git a/cd/src/win32/cdwemf.c b/cd/src/win32/cdwemf.c new file mode 100755 index 0000000..ad037c9 --- /dev/null +++ b/cd/src/win32/cdwemf.c @@ -0,0 +1,117 @@ +/** \file + * \brief Windows EMF Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cdwin.h" +#include "cdemf.h" + + + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + HENHMETAFILE hmf; + + cdwKillCanvas(ctxcanvas); + + hmf = CloseEnhMetaFile(ctxcanvas->hDC); + DeleteEnhMetaFile(hmf); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +/* +%F cdCreateCanvas para EMF. +O DC é um EMF em memoria. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ + cdCtxCanvas* ctxcanvas; + char* strdata = (char*)data; + int w = 0, h = 0; + double xres, yres; + FILE* file; + char filename[10240] = ""; + HDC ScreenDC, hDC; + RECT rect; + + /* Inicializa parametros */ + if (strdata == NULL) + return; + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata,"%dx%d", &w, &h); + if (w == 0 || h == 0) + return; + + /* Verifica se o arquivo pode ser aberto para escrita */ + file = fopen(filename, "wb"); + if (file == NULL) return; + fclose(file); + + ScreenDC = GetDC(NULL); + /* LOGPIXELS can not be used for EMF */ + xres = (double)GetDeviceCaps(ScreenDC, HORZRES) / (double)GetDeviceCaps(ScreenDC, HORZSIZE); + yres = (double)GetDeviceCaps(ScreenDC, VERTRES) / (double)GetDeviceCaps(ScreenDC, VERTSIZE); + rect.left = 0; + rect.top = 0; + rect.right = (int)(100. * w / xres); + rect.bottom = (int)(100. * h / yres); + hDC = CreateEnhMetaFile(ScreenDC,filename,&rect,NULL); + ReleaseDC(NULL, ScreenDC); + + if(!hDC) + return; + + /* Inicializa driver WIN32 */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, CDW_EMF); + + canvas->w = w; + canvas->h = h; + canvas->xres = xres; + canvas->yres = yres; + canvas->w_mm = ((double)w) / xres; + canvas->h_mm = ((double)h) / yres; + canvas->bpp = 24; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdEMFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + cdplayEMF, + cdregistercallbackEMF +}; + +cdContext* cdContextEMF(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_EMF); + if (ctx != NULL) + return ctx; + } + + return &cdEMFContext; +} diff --git a/cd/src/win32/cdwimg.c b/cd/src/win32/cdwimg.c new file mode 100755 index 0000000..47d99f9 --- /dev/null +++ b/cd/src/win32/cdwimg.c @@ -0,0 +1,83 @@ +/** \file + * \brief Windows Image Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cdwin.h" +#include "cdimage.h" + + + +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ + cdwKillCanvas(ctxcanvas); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +/* +%F cdCreateCanvas para Image. +O DC é um BITMAP em memoria. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas* ctxcanvas; + cdCtxImage* ctximage; + + if (data == NULL) + return; + + ctximage = ((cdImage*)data)->ctximage; + + /* Inicializa parametros */ + if (ctximage == NULL) + return; + + /* Inicializa driver Image */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, ctximage->hDC, CDW_BMP); + + canvas->w = ctximage->w; + canvas->h = ctximage->h; + canvas->w_mm = ctximage->w_mm; + canvas->h_mm = ctximage->h_mm; + canvas->bpp = ctximage->bpp; + canvas->xres = ctximage->xres; + canvas->yres = ctximage->yres; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdImageContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextImage(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_IMAGE); + if (ctx != NULL) + return ctx; + } + + return &cdImageContext; +} diff --git a/cd/src/win32/cdwin.c b/cd/src/win32/cdwin.c new file mode 100755 index 0000000..371bb6d --- /dev/null +++ b/cd/src/win32/cdwin.c @@ -0,0 +1,2368 @@ +/** \file + * \brief Windows Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include + +#include "cdwin.h" + +#ifndef AC_SRC_ALPHA +#define AC_SRC_ALPHA 0x01 +#endif + +/* CD region combine to WIN32 region combine */ +static int sCombineRegion2win [] ={RGN_OR, RGN_AND, RGN_DIFF, RGN_XOR}; + +typedef BOOL (CALLBACK* AlphaBlendFunc)( HDC hdcDest, + int xoriginDest, int yoriginDest, + int wDest, int hDest, HDC hdcSrc, + int xoriginSrc, int yoriginSrc, + int wSrc, int hSrc, + BLENDFUNCTION ftn); +static AlphaBlendFunc cdwAlphaBlend = NULL; + +static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height); + +/* +%F Libera memoria e handles alocados pelo driver Windows. +*/ +void cdwKillCanvas(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->clip_pnt != NULL) + free(ctxcanvas->clip_pnt); + + if (ctxcanvas->dib_bits != NULL) + free(ctxcanvas->dib_bits); + + /* apaga as areas de memoria do windows para os padroes */ + + if (ctxcanvas->clip_hrgn) DeleteObject(ctxcanvas->clip_hrgn); + if (ctxcanvas->new_rgn) DeleteObject(ctxcanvas->new_rgn); + + if (ctxcanvas->hOldBitmapPat) SelectObject(ctxcanvas->hDCMemPat, ctxcanvas->hOldBitmapPat); + if (ctxcanvas->hBitmapPat) DeleteObject(ctxcanvas->hBitmapPat); + if (ctxcanvas->hDCMemPat) DeleteDC(ctxcanvas->hDCMemPat); + + if (ctxcanvas->hOldBitmapStip) SelectObject(ctxcanvas->hDCMemStip, ctxcanvas->hOldBitmapStip); + if (ctxcanvas->hBitmapStip) DeleteObject(ctxcanvas->hBitmapStip); + if (ctxcanvas->hDCMemStip) DeleteDC(ctxcanvas->hDCMemStip); + + if (ctxcanvas->img_mask) DeleteObject(ctxcanvas->img_mask); + + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont); + DeleteObject(ctxcanvas->hFont); /* Fonte */ + + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen); /* restaura os objetos */ + DeleteObject(ctxcanvas->hPen); /* Pen corrente */ + + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); /* default do canvas */ + DeleteObject(ctxcanvas->hBrush); /* Brush corrente */ + + DeleteObject(ctxcanvas->hNullPen); /* Pen para tirar borda */ + DeleteObject(ctxcanvas->hBkBrush); /* Brush para o background */ + + /* ctxcanvas e ctxcanvas->hDC sao liberados em cada driver */ +} + +/* +Restaura os atributos do CD que sao guardados no DC do Windows quando +ha uma troca de DC. Usado pelos drivers Native Window e Printer. +*/ +void cdwRestoreDC(cdCtxCanvas *ctxcanvas) +{ + /* cdClipArea */ + SelectClipRgn(ctxcanvas->hDC, ctxcanvas->clip_hrgn); + + /* cdForeground */ + SetTextColor(ctxcanvas->hDC, ctxcanvas->fg); + + /* cdBackground */ + SetBkColor(ctxcanvas->hDC, ctxcanvas->bg); + + /* cdBackOpacity */ + switch (ctxcanvas->canvas->back_opacity) + { + case CD_TRANSPARENT: + SetBkMode(ctxcanvas->hDC, TRANSPARENT); + break; + case CD_OPAQUE: + SetBkMode(ctxcanvas->hDC, OPAQUE); + break; + } + + /* cdWriteMode */ + switch (ctxcanvas->canvas->write_mode) + { + case CD_REPLACE: + SetROP2(ctxcanvas->hDC, R2_COPYPEN); + break; + case CD_XOR: + SetROP2(ctxcanvas->hDC, R2_XORPEN); + break; + case CD_NOT_XOR: + SetROP2(ctxcanvas->hDC, R2_NOTXORPEN); + break; + } + + /* Text Alignment is calculated from this state */ + SetTextAlign(ctxcanvas->hDC,TA_LEFT|TA_BASELINE); + + /* cdLineStyle e cdLineWidth */ + ctxcanvas->hOldPen = SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); + + /* cdInteriorStyle */ + ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); + + /* cdFont */ + ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont); +} + + +/*********************************************************************/ +/* +%S Cor +*/ +/*********************************************************************/ + +static long int sColorFromWindows(COLORREF color) +{ + return cdEncodeColor(GetRValue(color),GetGValue(color),GetBValue(color)); +} + +static COLORREF sColorToWindows(cdCtxCanvas* ctxcanvas, long int cd_color) +{ + unsigned char red,green,blue; + COLORREF color; + + cdDecodeColor(cd_color,&red,&green,&blue); + + if (ctxcanvas->canvas->bpp <= 8) + color=PALETTERGB((BYTE)red,(BYTE)green,(BYTE)blue); + else + color=RGB((BYTE)red,(BYTE)green,(BYTE)blue); + + return color; +} + +static long int cdforeground (cdCtxCanvas* ctxcanvas, long int color) +{ + ctxcanvas->fg = sColorToWindows(ctxcanvas, color); + SetTextColor(ctxcanvas->hDC, ctxcanvas->fg); + ctxcanvas->rebuild_pen = 1; + return color; +} + +static void sCreatePen(cdCtxCanvas* ctxcanvas) +{ + int cd2win_cap[] = {PS_ENDCAP_FLAT, PS_ENDCAP_SQUARE, PS_ENDCAP_ROUND}; + int cd2win_join[] = {PS_JOIN_MITER, PS_JOIN_BEVEL, PS_JOIN_ROUND}; + + ctxcanvas->logPen.lopnColor = ctxcanvas->fg; + + if (ctxcanvas->hOldPen) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen); + if (ctxcanvas->hPen) DeleteObject(ctxcanvas->hPen); + + if (ctxcanvas->logPen.lopnWidth.x == 1) + { + LOGBRUSH LogBrush; + LogBrush.lbStyle = BS_SOLID; + LogBrush.lbColor = ctxcanvas->logPen.lopnColor; + LogBrush.lbHatch = 0; + + if (ctxcanvas->canvas->line_style == CD_CUSTOM) + { + ctxcanvas->hPen = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE, + 1, &LogBrush, + ctxcanvas->canvas->line_dashes_count, (DWORD*)ctxcanvas->canvas->line_dashes); + } + else + { + ctxcanvas->hPen = ExtCreatePen(PS_COSMETIC | ctxcanvas->logPen.lopnStyle, + 1, &LogBrush, + 0, NULL); + } + } + else + { + int style = PS_GEOMETRIC; + LOGBRUSH LogBrush; + LogBrush.lbStyle = BS_SOLID; + LogBrush.lbColor = ctxcanvas->logPen.lopnColor; + LogBrush.lbHatch = 0; + + style |= cd2win_cap[ctxcanvas->canvas->line_cap]; + style |= cd2win_join[ctxcanvas->canvas->line_join]; + + if (ctxcanvas->canvas->line_style == CD_CUSTOM) + { + ctxcanvas->hPen = ExtCreatePen( PS_USERSTYLE | style, + ctxcanvas->logPen.lopnWidth.x, &LogBrush, + ctxcanvas->canvas->line_dashes_count, (DWORD*)ctxcanvas->canvas->line_dashes); + } + else + ctxcanvas->hPen = ExtCreatePen( ctxcanvas->logPen.lopnStyle | style, + ctxcanvas->logPen.lopnWidth.x, &LogBrush, + 0, NULL); + } + + ctxcanvas->hOldPen = SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); + ctxcanvas->rebuild_pen = 0; +} + +static int cdbackopacity (cdCtxCanvas* ctxcanvas, int opacity) +{ + switch (opacity) + { + case CD_TRANSPARENT: + SetBkMode(ctxcanvas->hDC, TRANSPARENT); + break; + case CD_OPAQUE: + SetBkMode(ctxcanvas->hDC, OPAQUE); + break; + } + + return opacity; +} + +static int cdwritemode (cdCtxCanvas* ctxcanvas, int mode) +{ + switch (mode) + { + case CD_REPLACE: + SetROP2(ctxcanvas->hDC, R2_COPYPEN); + ctxcanvas->RopBlt = SRCCOPY; + break; + case CD_XOR: + SetROP2(ctxcanvas->hDC, R2_XORPEN); + ctxcanvas->RopBlt = SRCINVERT; + break; + case CD_NOT_XOR: + SetROP2(ctxcanvas->hDC, R2_NOTXORPEN); + ctxcanvas->RopBlt = SRCINVERT; + break; + } + + return mode; +} + +static long int cdbackground (cdCtxCanvas* ctxcanvas, long int color) +{ + ctxcanvas->bg = sColorToWindows(ctxcanvas, color); + SetBkColor(ctxcanvas->hDC, ctxcanvas->bg); + + if (ctxcanvas->hBkBrush) DeleteObject(ctxcanvas->hBkBrush); + ctxcanvas->hBkBrush = CreateSolidBrush(ctxcanvas->bg); + + return color; +} + +static void cdpalette(cdCtxCanvas* ctxcanvas, int n, const long int *palette, int mode) +{ + LOGPALETTE* pLogPal; + unsigned char red,green,blue; + int k, np = n; + (void)mode; + + if (ctxcanvas->canvas->bpp > 8) /* se o sistema for true color */ + return; + + if (n < 246) + np += 10; + + pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + np * sizeof(PALETTEENTRY)); + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = (WORD)np; + + if (n < 246) + { + k = 10; + GetSystemPaletteEntries(ctxcanvas->hDC, 0, 10, pLogPal->palPalEntry); + } + else + k=0; + + for (; k < np; k++) + { + cdDecodeColor(palette[k],&red,&green,&blue); + + pLogPal->palPalEntry[k].peRed = (BYTE)red; + pLogPal->palPalEntry[k].peGreen = (BYTE)green; + pLogPal->palPalEntry[k].peBlue = (BYTE)blue; + pLogPal->palPalEntry[k].peFlags = PC_NOCOLLAPSE; + } + + if (ctxcanvas->hPal) + { + if (ctxcanvas->hOldPal) SelectPalette(ctxcanvas->hDC, ctxcanvas->hOldPal, FALSE); + DeleteObject(ctxcanvas->hPal); + } + + ctxcanvas->hPal = CreatePalette(pLogPal); + ctxcanvas->hOldPal = SelectPalette(ctxcanvas->hDC, ctxcanvas->hPal, FALSE); + + RealizePalette(ctxcanvas->hDC); + + free(pLogPal); +} + + +/*********************************************************************/ +/* +%S Canvas e clipping +*/ +/*********************************************************************/ + +static HRGN sClipRect(cdCtxCanvas* ctxcanvas) +{ + HRGN clip_hrgn; + + if (ctxcanvas->clip_hrgn) + DeleteObject(ctxcanvas->clip_hrgn); + + clip_hrgn = CreateRectRgn(ctxcanvas->canvas->clip_rect.xmin, ctxcanvas->canvas->clip_rect.ymin, + ctxcanvas->canvas->clip_rect.xmax+1, ctxcanvas->canvas->clip_rect.ymax+1); + + SelectClipRgn(ctxcanvas->hDC, clip_hrgn); + return clip_hrgn; +} + +static HRGN sClipPoly(cdCtxCanvas* ctxcanvas) +{ + HRGN clip_hrgn; + + if (ctxcanvas->clip_hrgn) + DeleteObject(ctxcanvas->clip_hrgn); + + clip_hrgn = CreatePolygonRgn(ctxcanvas->clip_pnt, + ctxcanvas->clip_pnt_n, + ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + SelectClipRgn(ctxcanvas->hDC, clip_hrgn); + return clip_hrgn; +} + +static int cdclip (cdCtxCanvas* ctxcanvas, int clip_mode) +{ + if (ctxcanvas->wtype == CDW_WMF) + return clip_mode; + + switch (clip_mode) + { + case CD_CLIPOFF: + SelectClipRgn(ctxcanvas->hDC, NULL); /* toda 'area do canvas */ + if (ctxcanvas->clip_hrgn) + DeleteObject(ctxcanvas->clip_hrgn); + ctxcanvas->clip_hrgn = NULL; + break; + case CD_CLIPAREA: + ctxcanvas->clip_hrgn = sClipRect(ctxcanvas); + break; + case CD_CLIPPOLYGON: + ctxcanvas->clip_hrgn = sClipPoly(ctxcanvas); + break; + case CD_CLIPREGION: + if (ctxcanvas->clip_hrgn) + DeleteObject(ctxcanvas->clip_hrgn); + ctxcanvas->clip_hrgn = CreateRectRgn(0,0,0,0); + CombineRgn(ctxcanvas->clip_hrgn, ctxcanvas->new_rgn, NULL, RGN_COPY); + SelectClipRgn(ctxcanvas->hDC, ctxcanvas->clip_hrgn); + break; + } + + return clip_mode; +} + +static void cdcliparea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->wtype == CDW_WMF) + return; + + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_rect.xmin = xmin; + ctxcanvas->canvas->clip_rect.xmax = xmax; + ctxcanvas->canvas->clip_rect.ymin = ymin; + ctxcanvas->canvas->clip_rect.ymax = ymax; + ctxcanvas->clip_hrgn = sClipRect(ctxcanvas); + } +} + +static void cdnewregion(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->new_rgn) + DeleteObject(ctxcanvas->new_rgn); + ctxcanvas->new_rgn = CreateRectRgn(0, 0, 0, 0); +} + +static int cdispointinregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_rgn) + return 0; + + if (PtInRegion(ctxcanvas->new_rgn, x, y)) + return 1; + + return 0; +} + +static void cdoffsetregion(cdCtxCanvas* ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_rgn) + return; + + OffsetRgn(ctxcanvas->new_rgn, x, y); +} + +static void cdgetregionbox(cdCtxCanvas* ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + RECT rect; + + if (!ctxcanvas->new_rgn) + return; + + GetRgnBox(ctxcanvas->new_rgn, &rect); + + /* RECT in Windows does not includes the right, bottom. */ + *xmin = rect.left; + *xmax = rect.right-1; + *ymin = rect.top; + *ymax = rect.bottom-1; +} + +/******************************************************************/ +/* +%S Primitivas e seus atributos +*/ +/******************************************************************/ + +static int cdlinestyle (cdCtxCanvas* ctxcanvas, int style) +{ + switch (style) + { + case CD_CONTINUOUS: + ctxcanvas->logPen.lopnStyle = PS_SOLID; + break; + case CD_DASHED: + ctxcanvas->logPen.lopnStyle = PS_DASH; + break; + case CD_DOTTED: + ctxcanvas->logPen.lopnStyle = PS_DOT; + break; + case CD_DASH_DOT: + ctxcanvas->logPen.lopnStyle = PS_DASHDOT; + break; + case CD_DASH_DOT_DOT: + ctxcanvas->logPen.lopnStyle = PS_DASHDOTDOT; + break; + } + + ctxcanvas->rebuild_pen = 1; + + return style; +} + +static int cdlinewidth (cdCtxCanvas* ctxcanvas, int width) +{ + ctxcanvas->logPen.lopnWidth.x = width; + ctxcanvas->rebuild_pen = 1; + return width; +} + +static int cdlinecap (cdCtxCanvas* ctxcanvas, int cap) +{ + ctxcanvas->rebuild_pen = 1; + return cap; +} + +static int cdlinejoin (cdCtxCanvas* ctxcanvas, int join) +{ + ctxcanvas->rebuild_pen = 1; + return join; +} + +static int cdhatch (cdCtxCanvas* ctxcanvas, int hatch_style) +{ + switch (hatch_style) + { + case CD_HORIZONTAL: + ctxcanvas->logBrush.lbHatch = HS_HORIZONTAL; + break; + case CD_VERTICAL: + ctxcanvas->logBrush.lbHatch = HS_VERTICAL; + break; + case CD_FDIAGONAL: + ctxcanvas->logBrush.lbHatch = HS_FDIAGONAL; + break; + case CD_BDIAGONAL: + ctxcanvas->logBrush.lbHatch = HS_BDIAGONAL; + break; + case CD_CROSS: + ctxcanvas->logBrush.lbHatch = HS_CROSS; + break; + case CD_DIAGCROSS: + ctxcanvas->logBrush.lbHatch = HS_DIAGCROSS; + break; + } + + ctxcanvas->logBrush.lbColor=ctxcanvas->fg; + ctxcanvas->logBrush.lbStyle=BS_HATCHED; + + if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); + if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush); + + ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush); + ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); + + return hatch_style; +} + +static HBITMAP Stipple2Bitmap(int w, int h, const unsigned char *index, int negative) +{ + HBITMAP hBitmap; + BYTE *buffer; + + int nb; /* number of bytes per line */ + int x,y,k,offset; + + /* Cria um bitmap com os indices dados */ + nb = ((w + 15) / 16) * 2; /* Must be in a word boundary. */ + buffer = (BYTE *) malloc (nb*h); + memset(buffer, 0xff, nb*h); + + for (y=0; yhOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); + if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush); + + ctxcanvas->hBrush = CreatePatternBrush(hBitmap); + ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); + + DeleteObject(hBitmap); +} + +static void cdpattern(cdCtxCanvas* ctxcanvas, int w, int h, const long int *colors) +{ + cdwDIB dib; + HBRUSH hBrush; + + if (ctxcanvas->wtype == CDW_WMF) + return; + + dib.w = w; + dib.h = h; + dib.type = 0; + if (!cdwCreateDIB(&dib)) + return; + + cdwDIBEncodePattern(&dib, colors); + hBrush = CreateDIBPatternBrushPt(dib.dib, DIB_RGB_COLORS); + cdwKillDIB(&dib); + + if (hBrush) + { + if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); + if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush); + + ctxcanvas->hBrush = hBrush; + ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); + } +} + +static int cdinteriorstyle (cdCtxCanvas* ctxcanvas, int style) +{ + switch (style) + { + case CD_SOLID: + ctxcanvas->logBrush.lbStyle=BS_SOLID; + ctxcanvas->logBrush.lbColor=ctxcanvas->fg; + + if (ctxcanvas->hOldBrush) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); + if (ctxcanvas->hBrush) DeleteObject(ctxcanvas->hBrush); + + ctxcanvas->hBrush = CreateBrushIndirect(&ctxcanvas->logBrush); + ctxcanvas->hOldBrush = SelectObject(ctxcanvas->hDC, ctxcanvas->hBrush); + break; + case CD_HATCH: + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + break; + case CD_STIPPLE: + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + break; + case CD_PATTERN: + if (ctxcanvas->wtype == CDW_WMF) + return style; + cdpattern(ctxcanvas, ctxcanvas->canvas->pattern_w, ctxcanvas->canvas->pattern_h, ctxcanvas->canvas->pattern); + break; + } + + return style; +} + +static void cdline (cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2) +{ + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + + MoveToEx( ctxcanvas->hDC, x1, y1, NULL ); + LineTo( ctxcanvas->hDC, x2, y2 ); + SetPixelV(ctxcanvas->hDC, x2, y2, ctxcanvas->fg); +} + +static void cdrect (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + HBRUSH oldBrush; + + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + + oldBrush = SelectObject(ctxcanvas->hDC, GetStockObject(NULL_BRUSH)); /* tira o desenho do interior */ + Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+1, ymax+1); /* +1 porque nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, oldBrush); /* restaura o brush corrente */ +} + +static void cdbox (cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN) ) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + if (ctxcanvas->canvas->new_region) + { + HRGN rgn = CreateRectRgn(xmin, ymin, xmax+1, ymax+1); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + else + { + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + Rectangle(ctxcanvas->hDC, xmin, ymin, xmax+2, ymax+2); /* +2 porque a pena e' NULL NULL e o nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + } +} + +typedef struct _winArcParam +{ + int LeftRect, /* x-coordinate of upper-left corner of bounding rectangle */ + TopRect, /* y-coordinate of upper-left corner of bounding rectangle */ + RightRect, /* x-coordinate of lower-right corner of bounding rectangle */ + BottomRect, /* y-coordinate of lower-right corner of bounding rectangle */ + XStartArc, /* first radial ending point */ + YStartArc, /* first radial ending point */ + XEndArc, /* second radial ending point */ + YEndArc; /* second radial ending point */ +} winArcParam; + +static void calcArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2, winArcParam* arc) +{ + arc->LeftRect = xc - w/2; + arc->RightRect = xc + w/2 + 1; + arc->XStartArc = xc + cdRound(w * cos(CD_DEG2RAD * angle1) / 2.0); + arc->XEndArc = xc + cdRound(w * cos(CD_DEG2RAD * angle2) / 2.0); + + if (ctxcanvas->canvas->invert_yaxis) + { + arc->TopRect = yc - h/2; + arc->BottomRect = yc + h/2 + 1; + arc->YStartArc = yc - cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); + arc->YEndArc = yc - cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); + } + else + { + arc->BottomRect = yc - h/2; + arc->TopRect = yc + h/2 + 1; + arc->YStartArc = yc + cdRound(h * sin(CD_DEG2RAD * angle1) / 2.0); + arc->YEndArc = yc + cdRound(h * sin(CD_DEG2RAD * angle2) / 2.0); + + /* it is clock-wise when axis inverted */ + _cdSwapInt(arc->XStartArc, arc->XEndArc); + _cdSwapInt(arc->YStartArc, arc->YEndArc); + } +} + +static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + winArcParam arc; + calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + + Arc(ctxcanvas->hDC, arc.LeftRect, arc.TopRect, arc.RightRect, arc.BottomRect, arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); +} + +static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + winArcParam arc; + calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN) ) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + if (angle1==0 && angle2==360) + { + if (ctxcanvas->canvas->new_region) + { + HRGN rgn = CreateEllipticRgn(arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + else + { + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + Ellipse(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + } + } + else + { + if (ctxcanvas->canvas->new_region) + BeginPath(ctxcanvas->hDC); + + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + Pie(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1,arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + + if (ctxcanvas->canvas->new_region) + { + HRGN rgn; + EndPath(ctxcanvas->hDC); + rgn = PathToRegion(ctxcanvas->hDC); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + } +} + +static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2) +{ + winArcParam arc; + calcArc(ctxcanvas, xc, yc, w, h, angle1, angle2, &arc); + + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN) ) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + if (angle1==0 && angle2==360) + { + if (ctxcanvas->canvas->new_region) + { + HRGN rgn = CreateEllipticRgn(arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + else + { + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + Ellipse(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1); /* +1 porque a pena e' NULL e +1 porque nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + } + } + else + { + if (ctxcanvas->canvas->new_region) + BeginPath(ctxcanvas->hDC); + + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + Chord(ctxcanvas->hDC,arc.LeftRect, arc.TopRect, arc.RightRect+1, arc.BottomRect+1,arc.XStartArc, arc.YStartArc, arc.XEndArc, arc.YEndArc); /* +2 porque a pena e' NULL e o nao inclue right/bottom */ + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + + if (ctxcanvas->canvas->new_region) + { + HRGN rgn; + EndPath(ctxcanvas->hDC); + rgn = PathToRegion(ctxcanvas->hDC); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + } +} + +static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i, t, nc; + POINT* pnt; + HPEN oldPen = NULL, Pen = NULL; + + switch( mode ) + { + case CD_CLOSED_LINES: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + /* continua */ + case CD_OPEN_LINES: + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + Polyline(ctxcanvas->hDC, (POINT*)poly, n); + break; + case CD_BEZIER: + if (ctxcanvas->rebuild_pen) + sCreatePen(ctxcanvas); + PolyBezier(ctxcanvas->hDC, (POINT*)poly, n); + break; + case CD_FILL: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + if (ctxcanvas->canvas->new_region) + { + HRGN rgn = CreatePolygonRgn((POINT*)poly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + else + { + if ((ctxcanvas->logBrush.lbColor != ctxcanvas->fg) && + (ctxcanvas->canvas->interior_style != CD_PATTERN)) + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + + if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') + { + SelectObject(ctxcanvas->hDC, ctxcanvas->hNullPen); /* tira o desenho da borda */ + } + else + { + Pen = CreatePen(PS_SOLID, 1, ctxcanvas->fg); + oldPen = SelectObject(ctxcanvas->hDC, Pen); + } + + SetPolyFillMode(ctxcanvas->hDC, ctxcanvas->canvas->fill_mode==CD_EVENODD?ALTERNATE:WINDING); + Polygon(ctxcanvas->hDC, (POINT*)poly, n); + + if (ctxcanvas->canvas->interior_style != CD_SOLID || ctxcanvas->fill_attrib[0] == '0') + { + SelectObject(ctxcanvas->hDC, ctxcanvas->hPen); /* restaura a Pen corrente */ + } + else + { + SelectObject(ctxcanvas->hDC, oldPen); + DeleteObject(Pen); + } + } + break; + case CD_CLIP: + poly[n].x = poly[0].x; + poly[n].y = poly[0].y; + n++; + + if (ctxcanvas->wtype == CDW_WMF) + return; + + if (ctxcanvas->clip_pnt) + free(ctxcanvas->clip_pnt); + + ctxcanvas->clip_pnt = (POINT*)malloc(n*sizeof(POINT)); + + pnt = (POINT*)poly; + t = n; + nc = 1; + + ctxcanvas->clip_pnt[0] = *pnt; + pnt++; + + for (i = 1; i < t-1; i++, pnt++) + { + if (!((pnt->x == ctxcanvas->clip_pnt[nc-1].x && pnt->x == (pnt + 1)->x) || + (pnt->y == ctxcanvas->clip_pnt[nc-1].y && pnt->y == (pnt + 1)->y))) + { + ctxcanvas->clip_pnt[nc] = *pnt; + nc++; + } + } + + ctxcanvas->clip_pnt_n = nc; + + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + ctxcanvas->clip_hrgn = sClipPoly(ctxcanvas); + + break; + } +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + { + XFORM xForm; + SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + + /* configure a bottom-up coordinate system */ + + /* Equivalent of: + SetMapMode(ctxcanvas->hDC, MM_ISOTROPIC); + SetWindowExtEx(ctxcanvas->hDC, ctxcanvas->canvas->w-1, ctxcanvas->canvas->h-1, NULL); + SetWindowOrgEx(ctxcanvas->hDC, 0, 0, NULL); + SetViewportExtEx(ctxcanvas->hDC, ctxcanvas->canvas->w-1, -(ctxcanvas->canvas->h-1), NULL); + SetViewportOrgEx(ctxcanvas->hDC, 0, ctxcanvas->canvas->h-1, NULL); + */ + + xForm.eM11 = (FLOAT)1; + xForm.eM12 = (FLOAT)0; + xForm.eM21 = (FLOAT)0; + xForm.eM22 = (FLOAT)-1; + xForm.eDx = (FLOAT)0; + xForm.eDy = (FLOAT)(ctxcanvas->canvas->h-1); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + ctxcanvas->canvas->invert_yaxis = 0; + + xForm.eM11 = (FLOAT)matrix[0]; + xForm.eM12 = (FLOAT)matrix[1]; + xForm.eM21 = (FLOAT)matrix[2]; + xForm.eM22 = (FLOAT)matrix[3]; + xForm.eDx = (FLOAT)matrix[4]; + xForm.eDy = (FLOAT)matrix[5]; + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + } + else + { + ctxcanvas->canvas->invert_yaxis = 1; + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); + } +} + +static void sTextOutBlt(cdCtxCanvas* ctxcanvas, int px, int py, const char* s, int len) +{ + HDC hBitmapDC; + HBITMAP hBitmap, hOldBitmap; + HFONT hOldFont; + int w, h, wt, ht, x, y, off, px_off = 0, py_off = 0; + double teta = ctxcanvas->canvas->text_orientation*CD_DEG2RAD; + double cos_teta = cos(teta); + double sin_teta = sin(teta); + + cdgettextsize(ctxcanvas, s, len, &w, &h); + wt = w; + ht = h; + + if (ctxcanvas->canvas->text_orientation != 0) + { + /* novo tamanho da imagem */ + w = (int)(w * cos_teta + h * sin_teta); + h = (int)(h * cos_teta + w * sin_teta); + } + + /* coloca no centro da imagem */ + y = h/2; + x = w/2; + + /* corrige alinhamento do centro */ + off = ht/2 - ctxcanvas->font.descent; + if (ctxcanvas->canvas->text_orientation != 0) + { + y += (int)(off * cos_teta); + x += (int)(off * sin_teta); + } + else + y += off; + + /* calcula o alinhamento da imagem no canvas */ + if (ctxcanvas->canvas->text_orientation != 0) + { + double d = sqrt(wt*wt + ht*ht); + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_CENTER: + py_off = 0; + px_off = 0; + break; + case CD_BASE_LEFT: + py_off = - (int)(off * cos_teta + w/2 * sin_teta); + px_off = (int)(w/2 * cos_teta - off * sin_teta); + break; + case CD_BASE_CENTER: + py_off = - (int)(off * cos_teta); + px_off = - (int)(off * sin_teta); + break; + case CD_BASE_RIGHT: + py_off = - (int)(off * cos_teta - w/2 * sin_teta); + px_off = - (int)(w/2 * cos_teta + off * sin_teta); + break; + case CD_NORTH: + py_off = (int)(ht/2 * cos_teta); + px_off = (int)(ht/2 * sin_teta); + break; + case CD_SOUTH: + py_off = - (int)(ht/2 * cos_teta); + px_off = - (int)(ht/2 * sin_teta); + break; + case CD_EAST: + py_off = (int)(wt/2 * sin_teta); + px_off = - (int)(wt/2 * cos_teta); + break; + case CD_WEST: + py_off = - (int)(wt/2 * sin_teta); + px_off = (int)(wt/2 * cos_teta); + break; + case CD_NORTH_EAST: + py_off = (int)(h/2); + px_off = - (int)(sqrt(d*d - h*h)/2); + break; + case CD_NORTH_WEST: + py_off = (int)(sqrt(d*d - w*w)/2); + px_off = - (int)(w/2); + break; + case CD_SOUTH_WEST: + py_off = - (int)(h/2); + px_off = (int)(sqrt(d*d - h*h)/2); + break; + case CD_SOUTH_EAST: + py_off = - (int)(sqrt(d*d - w*w)/2); + px_off = (int)(w/2); + break; + } + } + else + { + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + px_off = - w/2; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + px_off = 0; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + px_off = w/2; + break; + } + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + py_off = - off; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + py_off = - h/2; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + py_off = + h/2; + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + py_off = py; + break; + } + } + + /* move do centro da imagem para o canto superior esquerdo da imagem */ + px_off -= w/2; + py_off -= h/2; + + /* desloca o ponto dado */ + if (ctxcanvas->canvas->invert_yaxis) + { + px += px_off; + py += py_off; + } + else + { + px += px_off; + py -= py_off; + } + + hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, w, h); + hBitmapDC = CreateCompatibleDC(ctxcanvas->hDC); + + hOldBitmap = SelectObject(hBitmapDC, hBitmap); + + /* copia a area do canvas para o bitmap */ + BitBlt(hBitmapDC, 0, 0, w, h, ctxcanvas->hDC, px, py, SRCCOPY); + + /* compensa a ROP antes de desenhar */ + BitBlt(hBitmapDC, 0, 0, w, h, ctxcanvas->hDC, px, py, ctxcanvas->RopBlt); + + SetBkMode(hBitmapDC, TRANSPARENT); + SetBkColor(hBitmapDC, ctxcanvas->bg); + SetTextColor(hBitmapDC, ctxcanvas->fg); + SetTextAlign(hBitmapDC, TA_CENTER | TA_BASELINE); + hOldFont = SelectObject(hBitmapDC, ctxcanvas->hFont); + + TextOut(hBitmapDC, x, y, s, len); + + if (ctxcanvas->canvas->invert_yaxis) + BitBlt(ctxcanvas->hDC, px, py, w, h, hBitmapDC, 0, 0, ctxcanvas->RopBlt); + else + StretchBlt(ctxcanvas->hDC, px, py, w, -h, hBitmapDC, 0, 0, w, h, ctxcanvas->RopBlt); + + SelectObject(hBitmapDC, hOldFont); + SelectObject(hBitmapDC, hOldBitmap); + + DeleteObject(hBitmap); + DeleteDC(hBitmapDC); +} + +static void cdgettextsize (cdCtxCanvas* ctxcanvas, const char *s, int len, int *width, int *height) +{ + SIZE size; + + GetTextExtentPoint32(ctxcanvas->hDC, s, len, &size); + + if (width) + *width = size.cx; + + if (height) + *height = size.cy; +} + +static void cdwCanvasGetTextHeight(cdCanvas* canvas, int x, int y, const char *s, int len, int *hbox, int *hoff) +{ + int w, h, ascent, height, baseline; + int xmin, xmax, ymin, ymax; + + cdgettextsize(canvas->ctxcanvas, s, len, &w, &h); + cdCanvasGetFontDim(canvas, NULL, &height, &ascent, NULL); + baseline = height - ascent; + + /* move to bottom-left */ + cdTextTranslatePoint(canvas, x, y, w, h, baseline, &xmin, &ymin); + + *hoff = y - ymin; + + xmax = xmin + w-1; + ymax = ymin + h-1; + + if (canvas->text_orientation) + { + double cos_theta = cos(canvas->text_orientation*CD_DEG2RAD); + double sin_theta = sin(canvas->text_orientation*CD_DEG2RAD); + int rectY[4]; + + *hoff = (int)(*hoff * cos_theta); + + cdRotatePointY(canvas, xmin, ymin, x, y, &rectY[0], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymin, x, y, &rectY[1], sin_theta, cos_theta); + cdRotatePointY(canvas, xmax, ymax, x, y, &rectY[2], sin_theta, cos_theta); + cdRotatePointY(canvas, xmin, ymax, x, y, &rectY[3], sin_theta, cos_theta); + + ymin = ymax = rectY[0]; + if (rectY[1] < ymin) ymin = rectY[1]; + if (rectY[2] < ymin) ymin = rectY[2]; + if (rectY[3] < ymin) ymin = rectY[3]; + if (rectY[1] > ymax) ymax = rectY[1]; + if (rectY[2] > ymax) ymax = rectY[2]; + if (rectY[3] > ymax) ymax = rectY[3]; + } + + *hbox = ymax-ymin+1; +} + +static void cdwTextTransform(cdCtxCanvas* ctxcanvas, const char* s, int len, int *x, int *y) +{ + XFORM xForm; + int hoff, h; + + cdwCanvasGetTextHeight(ctxcanvas->canvas, *x, *y, s, len, &h, &hoff); + + /* move to (x,y) and remove a vertical offset since text reference point is top-left */ + xForm.eM11 = (FLOAT)1; + xForm.eM12 = (FLOAT)0; + xForm.eM21 = (FLOAT)0; + xForm.eM22 = (FLOAT)1; + xForm.eDx = (FLOAT)*x; + xForm.eDy = (FLOAT)(*y - (h-1) - hoff); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + /* invert the text vertical orientation, relative to itself */ + xForm.eM11 = (FLOAT)1; + xForm.eM12 = (FLOAT)0; + xForm.eM21 = (FLOAT)0; + xForm.eM22 = (FLOAT)-1; + xForm.eDx = (FLOAT)0; + xForm.eDy = (FLOAT)(h-1); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + *x = 0; + *y = 0; +} + +static void cdtext(cdCtxCanvas* ctxcanvas, int x, int y, const char *s, int len) +{ + if (ctxcanvas->canvas->write_mode == CD_REPLACE || + ctxcanvas->wtype == CDW_EMF || + ctxcanvas->wtype == CDW_WMF || + ctxcanvas->canvas->new_region) + { + int h = -1; + + if ((ctxcanvas->canvas->text_alignment == CD_CENTER || + ctxcanvas->canvas->text_alignment == CD_EAST || + ctxcanvas->canvas->text_alignment == CD_WEST) && + ctxcanvas->wtype != CDW_WMF) + { + /* compensa deficiencia do alinhamento no windows */ + int off; + cdgettextsize(ctxcanvas, s, len, NULL, &h); + off = h/2 - ctxcanvas->font.descent; + + if (ctxcanvas->canvas->text_orientation != 0) + { + y += (int)(off * cos(ctxcanvas->canvas->text_orientation*CD_DEG2RAD)); + x += (int)(off * sin(ctxcanvas->canvas->text_orientation*CD_DEG2RAD)); + } + else + y += off; + } + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + SetBkMode(ctxcanvas->hDC, TRANSPARENT); + + if (ctxcanvas->canvas->new_region) + BeginPath(ctxcanvas->hDC); + + if (ctxcanvas->canvas->use_matrix) + cdwTextTransform(ctxcanvas, s, len, &x, &y); + + TextOut(ctxcanvas->hDC, x, y+1, s, len); /* compensa erro de desenho com +1 */ + + if (ctxcanvas->canvas->use_matrix) + cdtransform(ctxcanvas, ctxcanvas->canvas->matrix); + + if (ctxcanvas->canvas->new_region) + { + HRGN rgn; + EndPath(ctxcanvas->hDC); + rgn = PathToRegion(ctxcanvas->hDC); + CombineRgn(ctxcanvas->new_rgn, ctxcanvas->new_rgn, rgn, sCombineRegion2win[ctxcanvas->canvas->combine_mode]); + DeleteObject(rgn); + } + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + SetBkMode(ctxcanvas->hDC, OPAQUE); + } + else + sTextOutBlt(ctxcanvas, x, y+1, s, len); +} + +static int cdtextalignment(cdCtxCanvas* ctxcanvas, int text_align) +{ + int align = TA_NOUPDATECP; + + switch (text_align) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + align |= TA_RIGHT; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + align |= TA_CENTER; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + align |= TA_LEFT; + break; + } + + switch (text_align) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + align |= TA_BASELINE; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + align |= TA_BOTTOM; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + align |= TA_TOP; + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + align |= TA_BASELINE; /* tem que compensar ao desenhar o texto */ + break; + } + + SetTextAlign(ctxcanvas->hDC, align); + + return text_align; +} + +static int cdfont(cdCtxCanvas* ctxcanvas, const char *type_face, int style, int size) +{ + TEXTMETRIC tm; + DWORD bold, italic = 0, underline = 0, strikeout = 0; + int angle, size_pixel; + HFONT hFont; + + if (style&CD_BOLD) + bold = FW_BOLD; + else + bold = FW_NORMAL; + + if (style&CD_ITALIC) + italic = 1; + + if (style&CD_UNDERLINE) + underline = 1; + + if (style&CD_STRIKEOUT) + strikeout = 1; + + angle = ctxcanvas->font_angle; + + if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Monospace")) + type_face = "Courier New"; + else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Serif")) + type_face = "Times New Roman"; + else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Sans")) + type_face = "Arial"; + + size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size); + hFont = CreateFont(-size_pixel, 0, angle, angle, bold, italic, underline, strikeout, + DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH, + type_face); + if (!hFont) return 0; + + if (ctxcanvas->hOldFont) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont); + if (ctxcanvas->hFont) DeleteObject(ctxcanvas->hFont); + ctxcanvas->hFont = hFont; + ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont); + + GetTextMetrics (ctxcanvas->hDC, &tm); + ctxcanvas->font.max_width = tm.tmMaxCharWidth; + ctxcanvas->font.height = tm.tmHeight + tm.tmExternalLeading ; + ctxcanvas->font.ascent = tm.tmAscent; + ctxcanvas->font.descent = tm.tmDescent; + + return 1; +} + +static int cdnativefont (cdCtxCanvas* ctxcanvas, const char* nativefont) +{ + TEXTMETRIC tm; + HFONT hFont; + int size = 12, bold = FW_NORMAL, italic = 0, + style = CD_PLAIN, underline = 0, strikeout = 0, + size_pixel; + char type_face[1024]; + + if (nativefont[0] == '-' && nativefont[1] == 'd') + { + COLORREF rgbColors; + CHOOSEFONT cf; + LOGFONT lf; + + ZeroMemory(&cf, sizeof(CHOOSEFONT)); + + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = GetForegroundWindow(); + cf.lpLogFont = &lf; + cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT; + rgbColors = cf.rgbColors = ctxcanvas->fg; + + GetTextFace(ctxcanvas->hDC, 50, type_face); + GetTextMetrics(ctxcanvas->hDC, &tm); /* get the current selected nativefont */ + + size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, ctxcanvas->canvas->font_size); + + strcpy(lf.lfFaceName, type_face); + lf.lfWeight = tm.tmWeight; + lf.lfHeight = -size_pixel; + lf.lfItalic = tm.tmItalic; + lf.lfUnderline = tm.tmUnderlined; + lf.lfStrikeOut = tm.tmStruckOut; + lf.lfCharSet = tm.tmCharSet; + lf.lfEscapement = ctxcanvas->font_angle; + lf.lfOrientation = ctxcanvas->font_angle; + lf.lfWidth = 0; + lf.lfOutPrecision = OUT_TT_PRECIS; + lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + lf.lfQuality = DEFAULT_QUALITY; + lf.lfPitchAndFamily = FF_DONTCARE|DEFAULT_PITCH; + + if (ChooseFont(&cf)) + { + if (rgbColors != cf.rgbColors) + cdCanvasSetForeground(ctxcanvas->canvas, sColorFromWindows(cf.rgbColors)); + + hFont = CreateFontIndirect(&lf); + } + else + return 0; + + bold = lf.lfWeight; + italic = lf.lfItalic; + size = lf.lfHeight; + strcpy(type_face, lf.lfFaceName); + underline = lf.lfUnderline; + strikeout = lf.lfStrikeOut; + + if (bold!=FW_NORMAL) style |= CD_BOLD; + if (italic) style |= CD_ITALIC; + if (underline) style |= CD_UNDERLINE; + if (strikeout) style |= CD_STRIKEOUT; + } + else + { + if (!cdParseIupWinFont(nativefont, type_face, &style, &size)) + { + if (!cdParsePangoFont(nativefont, type_face, &style, &size)) + return 0; + } + + if (style&CD_BOLD) + bold = FW_BOLD; + if (style&CD_ITALIC) + italic = 1; + if (style&CD_UNDERLINE) + underline = 1; + if (style&CD_STRIKEOUT) + strikeout = 1; + + size_pixel = cdGetFontSizePixels(ctxcanvas->canvas, size); + + hFont = CreateFont(-size_pixel, 0, ctxcanvas->font_angle, ctxcanvas->font_angle, + bold, italic, underline, strikeout, + DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_DONTCARE|DEFAULT_PITCH, type_face); + if (!hFont) return 0; + } + + if (ctxcanvas->hOldFont) SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont); + DeleteObject(ctxcanvas->hFont); + ctxcanvas->hFont = hFont; + ctxcanvas->hOldFont = SelectObject(ctxcanvas->hDC, ctxcanvas->hFont); + + GetTextMetrics(ctxcanvas->hDC, &tm); + ctxcanvas->font.max_width = tm.tmMaxCharWidth; + ctxcanvas->font.height = tm.tmHeight + tm.tmExternalLeading; + ctxcanvas->font.ascent = tm.tmAscent; + ctxcanvas->font.descent = tm.tmDescent; + + /* update cdfont parameters */ + ctxcanvas->canvas->font_style = style; + ctxcanvas->canvas->font_size = size; + strcpy(ctxcanvas->canvas->font_type_face, type_face); + + return 1; +} + +static double cdtextorientation(cdCtxCanvas* ctxcanvas, double angle) +{ + if (ctxcanvas->font_angle == angle) /* first time angle=0, do not create font twice */ + return angle; + + ctxcanvas->font_angle = (int)(angle * 10); + + cdfont(ctxcanvas, ctxcanvas->canvas->font_type_face, ctxcanvas->canvas->font_style, ctxcanvas->canvas->font_size); + + return angle; +} + +static void cdgetfontdim (cdCtxCanvas* ctxcanvas, int *max_width, int *line_height, int *ascent, int *descent) +{ + if (max_width) + *max_width = ctxcanvas->font.max_width; + + if (line_height) + *line_height = ctxcanvas->font.height; + + if (ascent) + *ascent = ctxcanvas->font.ascent; + + if (descent) + *descent = ctxcanvas->font.descent; + + return; +} + +/* +%F Desenha um retangulo no canvas todo com a cor do fundo. +*/ +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + RECT rect; + + if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF) + SelectClipRgn( ctxcanvas->hDC, NULL ); /* toda 'area do canvas */ + + SetRect(&rect, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + FillRect(ctxcanvas->hDC, &rect, ctxcanvas->hBkBrush); + + if (ctxcanvas->canvas->clip_mode != CD_CLIPOFF) + cdclip(ctxcanvas, ctxcanvas->canvas->clip_mode); +} + + +/******************************************************************/ +/* +%S Funcoes de imagens do cliente +*/ +/******************************************************************/ + +static void cdgetimagergb(cdCtxCanvas* ctxcanvas, unsigned char *red, unsigned char *green, unsigned char *blue, int x, int y, int w, int h) +{ + XFORM xForm; + cdwDIB dib; + HDC hDCMem; + HBITMAP hOldBitmap,hBitmap; + int yr; + + hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, w, h); + if (hBitmap == NULL) + return; + + hDCMem = CreateCompatibleDC(ctxcanvas->hDC); + + hOldBitmap = SelectObject(hDCMem, hBitmap); + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + { + GetWorldTransform(ctxcanvas->hDC, &xForm); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + } + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + y = _cdInvertYAxis(ctxcanvas->canvas, y); + + yr = y - (h - 1); /* y starts at the bottom of the image */ + BitBlt(hDCMem,0,0,w,h,ctxcanvas->hDC, x, yr, SRCCOPY); + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + dib.w = w; + dib.h = h; + dib.type = 0; + + if (!cdwCreateDIB(&dib)) + { + SelectObject(hDCMem, hOldBitmap); + DeleteObject(hBitmap); + DeleteDC(hDCMem); + return; + } + + GetDIBits(ctxcanvas->hDC, hBitmap, 0, h, dib.bits, dib.bmi, DIB_RGB_COLORS); + + SelectObject(hDCMem, hOldBitmap); + DeleteObject(hBitmap); + DeleteDC(hDCMem); + + cdwDIBDecodeRGB(&dib, red, green, blue); + + cdwKillDIB(&dib); +} + +static void sFixImageY(cdCanvas* canvas, int *y, int *h) +{ + /* Here, y is from top to bottom, + is at the bottom-left corner of the image if h>0 + is at the top-left corner of the image if h<0. (Undocumented feature) + cdCalcZoom expects Y at top-left if h>0 + and Y at bottom-left if h<0 + if h<0 then eh<0 to StretchDIBits mirror the image. + BUT!!!!!! AlphaBlend will NOT mirror the image. */ + + if (!canvas->invert_yaxis) + *h = -(*h); + + if (*h < 0) + *y -= ((*h) + 1); /* compensate for cdCalcZoom */ + else + *y -= ((*h) - 1); /* move Y to top-left corner, since it was at the bottom of the image */ +} + +static void cdputimagerectmap(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + cdwDIB dib; + int ew, eh, ex, ey; /* posicao da imagem com zoom no canvas e tamanho da imagem com zoom depois de otimizado */ + int bw, bh, bx, by; /* posicao dentro da imagem e tamanho dentro da imagem do pedaco que sera desenhado depois de otimizado */ + int rw, rh; /* tamanho dentro da imagem antes de otimizado */ + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + sFixImageY(ctxcanvas->canvas, &y, &h); + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + dib.w = bw; + dib.h = bh; + dib.type = 1; + + if (!cdwCreateDIBRefBuffer(&dib, &ctxcanvas->dib_bits, &ctxcanvas->bits_size)) + return; + + cdwDIBEncodeMapRect(&dib, index, colors, bx, by, width, height); + + StretchDIBits(ctxcanvas->hDC, + ex, ey, ew, eh, + 0, 0, bw, bh, + dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt); +} + +static void cdputimagerectrgb(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red, + const unsigned char *green, const unsigned char *blue, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + cdwDIB dib; + int ew, eh, ex, ey; + int bw, bh, bx, by; + int rw, rh; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + sFixImageY(ctxcanvas->canvas, &y, &h); + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + dib.w = bw; + dib.h = bh; + dib.type = 0; + + if (!cdwCreateDIBRefBuffer(&dib, &ctxcanvas->dib_bits, &ctxcanvas->bits_size)) + return; + + cdwDIBEncodeRGBRect(&dib, red, green, blue, bx, by, width, height); + + StretchDIBits(ctxcanvas->hDC, + ex, ey, ew, eh, + 0, 0, bw, bh, + dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt); +} + +static void cdputimagerectrgba(cdCtxCanvas* ctxcanvas, int width, int height, const unsigned char *red, + const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + cdwDIB dib; + HDC hDCMem; + HBITMAP hOldBitmap, hBitmap; + int ew, eh, ex, ey; + int bw, bh, bx, by; + int rw, rh; + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + + sFixImageY(ctxcanvas->canvas, &y, &h); + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + hDCMem = CreateCompatibleDC(ctxcanvas->hDC); + + if (cdwAlphaBlend) + { + BLENDFUNCTION blendfunc; + + dib.w = bw; + dib.h = bh; + dib.type = 2; /* RGBA */ + + hBitmap = cdwCreateDIBSection(&dib, hDCMem); + if (!hBitmap) + { + DeleteDC(hDCMem); + return; + } + + cdwDIBEncodeRGBARect(&dib, red, green, blue, alpha, bx, by, width, height); + + if (eh < 0) /* must mirror the image */ + { + XFORM xForm; + + eh = -eh; + + SetGraphicsMode(hDCMem, GM_ADVANCED); + ModifyWorldTransform(hDCMem, NULL, MWT_IDENTITY); + + /* configure a bottom-up coordinate system */ + xForm.eM11 = (FLOAT)1; + xForm.eM12 = (FLOAT)0; + xForm.eM21 = (FLOAT)0; + xForm.eM22 = (FLOAT)-1; + xForm.eDx = (FLOAT)0; + xForm.eDy = (FLOAT)(bh-1); + ModifyWorldTransform(hDCMem, &xForm, MWT_LEFTMULTIPLY); + } + + hOldBitmap = SelectObject(hDCMem, hBitmap); + + blendfunc.BlendOp = AC_SRC_OVER; + blendfunc.BlendFlags = 0; + blendfunc.SourceConstantAlpha = 0xFF; + blendfunc.AlphaFormat = AC_SRC_ALPHA; + + cdwAlphaBlend(ctxcanvas->hDC, + ex, ey, ew, eh, + hDCMem, + 0, 0, bw, bh, + blendfunc); + } + else + { + hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, ew, eh); /* captura do tamanho do destino */ + if (!hBitmap) + { + DeleteDC(hDCMem); + return; + } + + hOldBitmap = SelectObject(hDCMem, hBitmap); + + BitBlt(hDCMem, 0, 0, ew, eh, ctxcanvas->hDC, ex, ey, SRCCOPY); + + dib.w = ew; /* neste caso o tamanho usado e´ o de destino */ + dib.h = eh; + dib.type = 0; + + if (!cdwCreateDIB(&dib)) + { + SelectObject(hDCMem, hOldBitmap); + DeleteObject(hBitmap); + DeleteDC(hDCMem); + return; + } + + GetDIBits(hDCMem, hBitmap, 0, eh, dib.bits, dib.bmi, DIB_RGB_COLORS); + + cdwDIBEncodeRGBARectZoom(&dib, red, green, blue, alpha, width, height, bx, by, bw, bh); + + StretchDIBits(ctxcanvas->hDC, + ex, ey, ew, eh, + 0, 0, ew, eh, /* Nao tem zoom neste caso, pois e´ feito manualmente pela EncodeRGBA */ + dib.bits, dib.bmi, DIB_RGB_COLORS, ctxcanvas->RopBlt); + } + + SelectObject(hDCMem, hOldBitmap); + DeleteObject(hBitmap); + DeleteDC(hDCMem); + cdwKillDIB(&dib); +} + + +/********************************************************************/ +/* +%S Funcoes de imagens do servidor +*/ +/********************************************************************/ + +static void cdpixel(cdCtxCanvas* ctxcanvas, int x, int y, long int cd_color) +{ + SetPixelV(ctxcanvas->hDC, x, y, sColorToWindows(ctxcanvas, cd_color)); +} + +static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height) +{ + HDC hDCMem; + HBITMAP hOldBitmap,hBitmap; + cdCtxImage *ctximage; + void* rgba_dib = NULL; + unsigned char* alpha = NULL; + + if (ctxcanvas->img_format) + { + cdwDIB dib; + + dib.w = width; + dib.h = height; + if (ctxcanvas->img_format == 32) + dib.type = CDW_RGBA; + else + dib.type = CDW_RGB; + + hBitmap = cdwCreateDIBSection(&dib, ctxcanvas->hDC); + if (!hBitmap) + return NULL; + + rgba_dib = dib.bits; + alpha = ctxcanvas->img_alpha; + + cdwKillDIB(&dib); /* this will just remove the headers not the dib bits in this case */ + } + else + { + hBitmap = CreateCompatibleBitmap(ctxcanvas->hDC, width, height); + if (!hBitmap) + return NULL; + } + + hDCMem = CreateCompatibleDC(ctxcanvas->hDC); + hOldBitmap = SelectObject(hDCMem, hBitmap); + + PatBlt(hDCMem, 0, 0, width, height, WHITENESS); + + /* salva o contexto desta imagem */ + ctximage = (cdCtxImage*)malloc(sizeof(cdCtxImage)); + + ctximage->hDC = hDCMem; + ctximage->hBitmap = hBitmap; + ctximage->hOldBitmap = hOldBitmap; + ctximage->w = width; + ctximage->h = height; + ctximage->rgba_dib = rgba_dib; + ctximage->alpha = alpha; + + ctximage->bpp = ctxcanvas->canvas->bpp; + ctximage->xres = ctxcanvas->canvas->xres; + ctximage->yres = ctxcanvas->canvas->yres; + + ctximage->w_mm = ctximage->w / ctximage->xres; + ctximage->h_mm = ctximage->h / ctximage->yres; + + return ctximage; +} + +static void cdgetimage(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x, int y) +{ + int yr; + XFORM xForm; + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + { + GetWorldTransform(ctxcanvas->hDC, &xForm); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + } + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + y = _cdInvertYAxis(ctxcanvas->canvas, y); + + yr = y - (ctximage->h - 1); + BitBlt(ctximage->hDC, 0, 0, ctximage->w, ctximage->h, ctxcanvas->hDC, x, yr, SRCCOPY); + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); +} + +static void cdputimagerect(cdCtxCanvas* ctxcanvas, cdCtxImage *ctximage, int x0, int y0, int xmin, int xmax, int ymin, int ymax) +{ + int yr = y0 - (ymax-ymin+1)+1; /* y0 starts at the bottom of the image */ + + if (ctximage->alpha && ctximage->bpp == 32 && cdwAlphaBlend) + { + cdwDIB dib; + BLENDFUNCTION blendfunc; + blendfunc.BlendOp = AC_SRC_OVER; + blendfunc.BlendFlags = 0; + blendfunc.SourceConstantAlpha = 0xFF; + blendfunc.AlphaFormat = AC_SRC_ALPHA; + + dib.w = ctximage->w; + dib.h = ctximage->h; + dib.type = CDW_RGBA; + cdwCreateDIBRefBits(&dib, ctximage->rgba_dib); + + cdwDIBEncodeAlphaRect(&dib, ctximage->alpha, 0, 0, ctximage->w, ctximage->h); + + GdiFlush(); + cdwAlphaBlend(ctxcanvas->hDC, + x0, yr, xmax-xmin+1, ymax-ymin+1, + ctximage->hDC, + xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1, + blendfunc); + + cdwKillDIB(&dib); + } + else if(ctxcanvas->use_img_points) + { + POINT pts[3]; + pts[0] = ctxcanvas->img_points[0]; + pts[1] = ctxcanvas->img_points[1]; + pts[2] = ctxcanvas->img_points[2]; + if (ctxcanvas->canvas->invert_yaxis) + { + pts[0].y = _cdInvertYAxis(ctxcanvas->canvas, pts[0].y); + pts[1].y = _cdInvertYAxis(ctxcanvas->canvas, pts[1].y); + pts[2].y = _cdInvertYAxis(ctxcanvas->canvas, pts[2].y); + } + PlgBlt(ctxcanvas->hDC, pts, ctximage->hDC, xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1, ctxcanvas->img_mask, 0, 0); + } + else if (ctxcanvas->img_mask) + MaskBlt(ctxcanvas->hDC,x0,yr, xmax-xmin+1, ymax-ymin+1, ctximage->hDC, xmin, ctximage->h-ymax-1, ctxcanvas->img_mask, 0, 0, MAKEROP4(ctxcanvas->RopBlt, 0xAA0000)); + else + BitBlt(ctxcanvas->hDC,x0,yr, xmax-xmin+1, ymax-ymin+1, ctximage->hDC, xmin, ctximage->h-ymax-1, ctxcanvas->RopBlt); +} + +static void cdkillimage(cdCtxImage *ctximage) +{ + SelectObject(ctximage->hDC, ctximage->hOldBitmap); + DeleteObject(ctximage->hBitmap); + DeleteDC(ctximage->hDC); + free(ctximage); +} + +static void cdscrollarea(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + XFORM xForm; + RECT rect; + rect.left = xmin; + rect.right = xmax+1; + rect.top = ymin; + rect.bottom = ymax+1; + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + { + GetWorldTransform(ctxcanvas->hDC, &xForm); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + } + + if (ctxcanvas->canvas->invert_yaxis==0) // if 0, then the transform was reset + { + dy = -dy; + ymin = _cdInvertYAxis(ctxcanvas->canvas, ymin); + ymax = _cdInvertYAxis(ctxcanvas->canvas, ymax); + _cdSwapInt(ymin, ymax); + } + + ScrollDC(ctxcanvas->hDC, dx, dy, &rect, NULL, NULL, NULL); + + if (GetGraphicsMode(ctxcanvas->hDC) == GM_ADVANCED) + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); +} + +static void cdflush(cdCtxCanvas* ctxcanvas) +{ + (void)ctxcanvas; + GdiFlush(); +} + +/********************************************************************/ +/* +%S Atributos personalizados +*/ +/********************************************************************/ + +static void set_img_format_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + ctxcanvas->img_format = 0; + else + { + int bpp = 0; + sscanf(data, "%d", &bpp); + if (bpp == 0) + return; + + if (bpp == 32) + ctxcanvas->img_format = 32; + else + ctxcanvas->img_format = 24; + } +} + +static char* get_img_format_attrib(cdCtxCanvas* ctxcanvas) +{ + if (!ctxcanvas->img_format) + return NULL; + + if (ctxcanvas->img_format == 32) + return "32"; + else + return "24"; +} + +static cdAttribute img_format_attrib = +{ + "IMAGEFORMAT", + set_img_format_attrib, + get_img_format_attrib +}; + +static void set_img_alpha_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + ctxcanvas->img_alpha = NULL; + else + ctxcanvas->img_alpha = (unsigned char*)data; +} + +static char* get_img_alpha_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->img_alpha; +} + +static cdAttribute img_alpha_attrib = +{ + "IMAGEALPHA", + set_img_alpha_attrib, + get_img_alpha_attrib +}; + +static void set_img_mask_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data) + { + if (ctxcanvas->img_mask) DeleteObject(ctxcanvas->img_mask); + ctxcanvas->img_mask = NULL; + } + else + { + int w = 0, h = 0; + unsigned char *index = 0; + sscanf(data, "%d %d %p", &w, &h, &index); + if (w && h && index) + ctxcanvas->img_mask = Stipple2Bitmap(w, h, index, 1); + } +} + +static cdAttribute img_mask_attrib = +{ + "IMAGEMASK", + set_img_mask_attrib, + NULL +}; + +static void set_img_points_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + int p[6]; + + if (!data) + { + ctxcanvas->use_img_points = 0; + return; + } + + sscanf(data, "%d %d %d %d %d %d", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]); + + ctxcanvas->img_points[0].x = p[0]; + ctxcanvas->img_points[0].y = p[1]; + ctxcanvas->img_points[1].x = p[2]; + ctxcanvas->img_points[1].y = p[3]; + ctxcanvas->img_points[2].x = p[4]; + ctxcanvas->img_points[2].y = p[5]; + + ctxcanvas->use_img_points = 1; +} + +static char* get_img_points_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->use_img_points) + return NULL; + + sprintf(data, "%d %d %d %d %d %d", ctxcanvas->img_points[0].x, + ctxcanvas->img_points[0].y, + ctxcanvas->img_points[1].x, + ctxcanvas->img_points[1].y, + ctxcanvas->img_points[2].x, + ctxcanvas->img_points[2].y); + + return data; +} + +static cdAttribute img_points_attrib = +{ + "IMAGEPOINTS", + set_img_points_attrib, + get_img_points_attrib +}; + +static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + /* ignore ROTATE if transform is set */ + if (ctxcanvas->canvas->use_matrix) + return; + + if (data) + { + XFORM xForm; + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + + /* the rotation must be corrected because of the Y axis orientation */ + + SetGraphicsMode(ctxcanvas->hDC, GM_ADVANCED); + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + + xForm.eM11 = (FLOAT) cos(-CD_DEG2RAD*ctxcanvas->rotate_angle); + xForm.eM12 = (FLOAT) sin(-CD_DEG2RAD*ctxcanvas->rotate_angle); + xForm.eM21 = (FLOAT) -xForm.eM12; + xForm.eM22 = (FLOAT) xForm.eM11; + xForm.eDx = (FLOAT) ctxcanvas->rotate_center_x; + xForm.eDy = (FLOAT) _cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + + xForm.eM11 = (FLOAT) 1; + xForm.eM12 = (FLOAT) 0; + xForm.eM21 = (FLOAT) 0; + xForm.eM22 = (FLOAT) 1; + xForm.eDx = (FLOAT) -ctxcanvas->rotate_center_x; + xForm.eDy = (FLOAT) -_cdInvertYAxis(ctxcanvas->canvas, ctxcanvas->rotate_center_y); + ModifyWorldTransform(ctxcanvas->hDC, &xForm, MWT_LEFTMULTIPLY); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + + ModifyWorldTransform(ctxcanvas->hDC, NULL, MWT_IDENTITY); + SetGraphicsMode(ctxcanvas->hDC, GM_COMPATIBLE); + } +} + +static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static void set_fill_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + ctxcanvas->fill_attrib[0] = data[0]; +} + +static char* get_fill_attrib(cdCtxCanvas* ctxcanvas) +{ + return ctxcanvas->fill_attrib; +} + +static cdAttribute fill_attrib = +{ + "PENFILLPOLY", + set_fill_attrib, + get_fill_attrib +}; + +static void set_window_rgn(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + HRGN hrgn = CreateRectRgn(0,0,0,0); + CombineRgn(hrgn, ctxcanvas->new_rgn, NULL, RGN_COPY); + SetWindowRgn(ctxcanvas->hWnd, hrgn, TRUE); + } + else + SetWindowRgn(ctxcanvas->hWnd, NULL, TRUE); +} + +static cdAttribute window_rgn_attrib = +{ + "WINDOWRGN", + set_window_rgn, + NULL +}; + +static char* get_hdc_attrib(cdCtxCanvas* ctxcanvas) +{ + return (char*)ctxcanvas->hDC; +} + +static cdAttribute hdc_attrib = +{ + "HDC", + NULL, + get_hdc_attrib +}; + +/* +%F Cria o canvas para o driver Windows. +*/ +cdCtxCanvas *cdwCreateCanvas(cdCanvas* canvas, HWND hWnd, HDC hDC, int wtype) +{ + cdCtxCanvas* ctxcanvas; + LOGPEN logNullPen; + + ctxcanvas = (cdCtxCanvas*)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + /* store the base canvas */ + ctxcanvas->canvas = canvas; + + /* update canvas context */ + canvas->ctxcanvas = ctxcanvas; + + ctxcanvas->hWnd = hWnd; + ctxcanvas->hDC = hDC; + canvas->invert_yaxis = 1; + + /* linha nula para fill de interior apenas */ + logNullPen.lopnStyle = PS_NULL; + ctxcanvas->hNullPen = CreatePenIndirect(&logNullPen); + + ctxcanvas->logPen.lopnStyle = PS_SOLID; + ctxcanvas->logPen.lopnWidth.x = 1; /* 1 para que a linha possa ter estilo */ + ctxcanvas->logPen.lopnColor = 0; + ctxcanvas->rebuild_pen = 1; + + ctxcanvas->logBrush.lbStyle = BS_SOLID; + ctxcanvas->logBrush.lbColor = 0; + ctxcanvas->logBrush.lbHatch = HS_BDIAGONAL; + + ctxcanvas->clip_pnt = (POINT*)malloc(sizeof(POINT)*4); + memset(ctxcanvas->clip_pnt, 0, sizeof(POINT)*4); + ctxcanvas->clip_pnt_n = 4; + + ctxcanvas->wtype = wtype; + + SetStretchBltMode(ctxcanvas->hDC, COLORONCOLOR); + + ctxcanvas->fill_attrib[0] = '1'; + ctxcanvas->fill_attrib[1] = 0; + + cdRegisterAttribute(canvas, &hdc_attrib); + cdRegisterAttribute(canvas, &fill_attrib); + cdRegisterAttribute(canvas, &img_points_attrib); + cdRegisterAttribute(canvas, &img_mask_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + cdRegisterAttribute(canvas, &img_alpha_attrib); + cdRegisterAttribute(canvas, &img_format_attrib); + cdRegisterAttribute(canvas, &window_rgn_attrib); + + if (!cdwAlphaBlend) + { + HINSTANCE lib = LoadLibrary("Msimg32"); + if (lib) + cdwAlphaBlend = (AlphaBlendFunc)GetProcAddress(lib, "AlphaBlend"); + } + + return ctxcanvas; +} + +void cdwInitTable(cdCanvas* canvas) +{ + cdCtxCanvas* ctxcanvas = canvas->ctxcanvas; + + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdpoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + canvas->cxScrollArea = cdscrollarea; + canvas->cxNewRegion = cdnewregion; + canvas->cxIsPointInRegion = cdispointinregion; + canvas->cxOffsetRegion = cdoffsetregion; + canvas->cxGetRegionBox = cdgetregionbox; + + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxWriteMode = cdwritemode; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxTextOrientation = cdtextorientation; + canvas->cxTextAlignment = cdtextalignment; + canvas->cxPalette = cdpalette; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxTransform = cdtransform; + + canvas->cxKillCanvas = cdwKillCanvas; + canvas->cxFlush = cdflush; + + if (ctxcanvas->wtype == CDW_WIN || ctxcanvas->wtype == CDW_BMP) + { + canvas->cxClear = cdclear; + canvas->cxGetImageRGB = cdgetimagergb; + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + canvas->cxCreateImage = cdcreateimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxKillImage = cdkillimage; + } + + if (ctxcanvas->wtype == CDW_EMF) + canvas->cxPutImageRectRGBA = cdputimagerectrgba; +} diff --git a/cd/src/win32/cdwin.h b/cd/src/win32/cdwin.h new file mode 100755 index 0000000..a8230e7 --- /dev/null +++ b/cd/src/win32/cdwin.h @@ -0,0 +1,181 @@ +/** \file + * \brief Windows Base Driver + * + * See Copyright Notice in cd.h + */ + +#ifndef __CDWIN_H +#define __CDWIN_H + +#include +#include "cd.h" +#include "cd_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* Contexto de cada imagem no servidor */ +struct _cdCtxImage +{ + HDC hDC; /* handle para o contexto de imagem na memoria */ + HBITMAP hBitmap; /* handle para o bitmap associado */ + HBITMAP hOldBitmap; /* handle para o bitmap associado inicialmente */ + int w; /* largura da imagem */ + int h; /* altura da imagem */ + double w_mm, h_mm; /* size in mm */ + double xres, yres; /* resolution in pixels/mm */ + int bpp; + + void* rgba_dib; /* used by 32 bpp to set alpha before putimage */ + unsigned char* alpha; /* the alpha values must be stored here */ +}; + +/* Contexto de cada canvas (CanvasContext). */ +struct _cdCtxCanvas +{ + cdCanvas* canvas; + + HWND hWnd; /* handle para janela */ + HDC hDC; /* contexto gr'afico para janela */ + int release_dc; + + COLORREF fg, bg; /* foreground, backgound */ + + LOGPEN logPen; /* pena logica - struct com tipo, cor,... */ + HPEN hPen; /* handle para a pena corrente */ + HPEN hNullPen; /* handle da pena que nao desenha nada */ + HPEN hOldPen; /* pena anterior selecionado */ + int rebuild_pen; + + LOGBRUSH logBrush; /* pincel l'ogico - struct com tipo, cor,... */ + HBRUSH hBrush; /* handle para o pincel corrente */ + HBRUSH hOldBrush; /* brush anterior selecionado */ + HBRUSH hBkBrush; /* handle para o pincel com a cor de fundo */ + + HDC hDCMemPat; + HBITMAP hOldBitmapPat,hBitmapPat; + + HDC hDCMemStip; + HBITMAP hOldBitmapStip,hBitmapStip; + + HFONT hFont; /* handle para o fonte corrente */ + HFONT hOldFont; + + int font_angle; + + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + struct + { + int max_width; + int height; + int ascent; + int descent; + } font; + + POINT *clip_pnt; /* coordenadas do pixel no X,Y */ + int clip_pnt_n; /* numero de pontos correntes */ + HRGN clip_hrgn; + + HRGN new_rgn; + + HPALETTE hPal, hOldPal; /* handle para a paleta corrente */ + LOGPALETTE* pLogPal; /* paleta logica do canvas */ + + char *filename; /* Nome do arquivo para WMF */ + int wtype; /* Flag indicando qual o tipo de superficie */ + + HBITMAP hBitmapClip, hOldBitmapClip; /* Bitmap para copiar para clipboard */ + BITMAPINFO bmiClip; + BYTE* bitsClip; + DWORD RopBlt; /* Raster Operation for bitmaps */ + int isOwnedDC; /* usado pelo Native canvas */ + + BYTE* dib_bits; + int bits_size; + + cdImage* image_dbuffer; /* utilizado pelo driver de Double buffer */ + cdCanvas* canvas_dbuffer; + + HBITMAP img_mask; /* used by PutImage with mask and rotation and transparency */ + + POINT img_points[3]; + int use_img_points; + + char fill_attrib[2]; + + int img_format; + unsigned char* img_alpha; +}; + +enum{CDW_WIN, CDW_BMP, CDW_WMF, CDW_EMF}; + +/* Cria um canvas no driver Windows e inicializa valores default */ +cdCtxCanvas *cdwCreateCanvas(cdCanvas* canvas, HWND hWnd, HDC hDC, int wtype); +void cdwInitTable(cdCanvas* canvas); +void cdwRestoreDC(cdCtxCanvas *ctxcanvas); + +/* Remove valores comuns do driver Windows, deve ser chamado por todos os drivers */ +void cdwKillCanvas(cdCtxCanvas* canvas); + + +/* implemented in the wmfmeta.c module */ +void wmfMakePlaceableMetafile(HMETAFILE hmf, const char* filename, int w, int h); +void wmfWritePlacebleFile(HANDLE hFile, unsigned char* buffer, DWORD dwSize, LONG mm, LONG xExt, LONG yExt); + +/* implemented in the wmf_emf.c module */ +int cdplayWMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data); +int cdregistercallbackWMF(int cb, cdCallback func); +int cdplayEMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data); +int cdregistercallbackEMF(int cb, cdCallback func); + +/* Estrutura que descreve um DIB. The secondary members are pointers to the main dib pointer. */ +typedef struct _cdwDIB +{ + BYTE* dib; /* The DIB as it is defined */ + BITMAPINFO* bmi; /* Bitmap Info = Bitmap Info Header + Palette*/ + BITMAPINFOHEADER* bmih; /* Bitmap Info Header */ + RGBQUAD* bmic; /* Palette */ + BYTE* bits; /* Bitmap Bits */ + int w; + int h; + int type; /* RGB = 0 or MAP = 1 or RGBA = 2 (dib section only) */ +} cdwDIB; + +enum {CDW_RGB, CDW_MAP, CDW_RGBA}; + +int cdwCreateDIB(cdwDIB* dib); +void cdwKillDIB(cdwDIB* dib); + +HANDLE cdwCreateCopyHDIB(BITMAPINFO* bmi, BYTE* bits); +void cdwDIBReference(cdwDIB* dib, BYTE* bmi, BYTE* bits); +int cdwCreateDIBRefBuffer(cdwDIB* dib, unsigned char* *bits, int *size); +void cdwCreateDIBRefBits(cdwDIB* dib, unsigned char *bits); +HBITMAP cdwCreateDIBSection(cdwDIB* dib, HDC hDC); + +HPALETTE cdwDIBLogicalPalette(cdwDIB* dib); + +/* copy from DIB */ +void cdwDIBDecodeRGB(cdwDIB* dib, unsigned char *red, unsigned char *green, unsigned char *blue); +void cdwDIBDecodeMap(cdwDIB* dib, unsigned char *index, long *colors); + +/* copy to DIB */ +void cdwDIBEncodePattern(cdwDIB* dib, const long int *colors); +void cdwDIBEncodeMapRect(cdwDIB* dib, const unsigned char *index, const long int *colors, int xi, int yi, int wi, int hi); +void cdwDIBEncodeRGBRect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, int xi, int yi, int wi, int hi); +void cdwDIBEncodeRGBARect(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int xi, int yi, int wi, int hi); +void cdwDIBEncodeRGBARectZoom(cdwDIB* dib, const unsigned char *red, const unsigned char *green, const unsigned char *blue, const unsigned char *alpha, int w, int h, int xi, int yi, int wi, int hi); +void cdwDIBEncodeAlphaRect(cdwDIB* dib, const unsigned char *alpha, int xi, int yi, int wi, int hi); + + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef CDWIN_H */ + diff --git a/cd/src/win32/cdwnative.c b/cd/src/win32/cdwnative.c new file mode 100755 index 0000000..fdc223e --- /dev/null +++ b/cd/src/win32/cdwnative.c @@ -0,0 +1,209 @@ +/** \file + * \brief Windows Native Window Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cdwin.h" +#include "cdnative.h" + + +int cdGetScreenColorPlanes(void) +{ + int bpp; + HDC ScreenDC = GetDC(NULL); + bpp = GetDeviceCaps(ScreenDC, BITSPIXEL); + ReleaseDC(NULL, ScreenDC); + return bpp; +} + +void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm) +{ + HDC ScreenDC = GetDC(NULL); + if (width) *width = GetDeviceCaps(ScreenDC, HORZRES); + if (height) *height = GetDeviceCaps(ScreenDC, VERTRES); + if (width_mm) *width_mm = ((GetDeviceCaps(ScreenDC, HORZRES) * 25.4) / GetDeviceCaps(ScreenDC, LOGPIXELSX)); + if (height_mm) *height_mm = ((GetDeviceCaps(ScreenDC, VERTRES) * 25.4) / GetDeviceCaps(ScreenDC, LOGPIXELSY)); + ReleaseDC(NULL, ScreenDC); +} + +static void cdwReleaseDC(cdCtxCanvas *ctxcanvas) +{ + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldBrush); + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldPen); + SelectObject(ctxcanvas->hDC, ctxcanvas->hOldFont); + ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); + ctxcanvas->hDC = NULL; +} + +static int cdactivate(cdCtxCanvas *ctxcanvas) +{ + if (ctxcanvas->hWnd) + { + RECT rect; + HDC ScreenDC; + GetClientRect(ctxcanvas->hWnd, &rect); + ctxcanvas->canvas->w = rect.right - rect.left; + ctxcanvas->canvas->h = rect.bottom - rect.top; + + ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; + ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + + ScreenDC = GetDC(NULL); + ctxcanvas->canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL); + ReleaseDC(NULL, ScreenDC); + + if (ctxcanvas->canvas->use_matrix) + ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix); + } + + /* Se nao e' ownwer, tem que restaurar o contexto */ + if (!ctxcanvas->isOwnedDC) + { + if (ctxcanvas->hDC) /* deactivate not called */ + cdwReleaseDC(ctxcanvas); + + ctxcanvas->hDC = GetDC(ctxcanvas->hWnd); + cdwRestoreDC(ctxcanvas); + } + + return CD_OK; +} + +static void cddeactivate(cdCtxCanvas *ctxcanvas) +{ + /* Se nao e' ownwer, tem que liberar o contexto */ + if (!ctxcanvas->isOwnedDC && ctxcanvas->hDC) + cdwReleaseDC(ctxcanvas); +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + /* se nao e' owner e nao esta' ativo, simula ativacao */ + if (!ctxcanvas->isOwnedDC && !ctxcanvas->hDC) + { + ctxcanvas->hDC = GetDC(ctxcanvas->hWnd); + cdwRestoreDC(ctxcanvas); + } + + cdwKillCanvas(ctxcanvas); + + if (ctxcanvas->release_dc) + ReleaseDC(ctxcanvas->hWnd, ctxcanvas->hDC); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas* ctxcanvas; + HWND hWnd = NULL; + HDC hDC, ScreenDC; + int release_dc = 0; + + ScreenDC = GetDC(NULL); + canvas->bpp = GetDeviceCaps(ScreenDC, BITSPIXEL); + canvas->xres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSX)) / 25.4); + canvas->yres = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSY)) / 25.4); + ReleaseDC(NULL, ScreenDC); + + if (!data) + { + hDC = GetDC(NULL); + release_dc = 1; + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + } + else if (IsWindow((HWND)data)) + { + RECT rect; + hWnd = (HWND)data; + + hDC = GetDC(hWnd); + release_dc = 1; + + GetClientRect(hWnd, &rect); + canvas->w = rect.right - rect.left; + canvas->h = rect.bottom - rect.top; + } + else /* can be a HDC or a string */ + { + DWORD objtype = GetObjectType((HGDIOBJ)data); + if (objtype == OBJ_DC || objtype == OBJ_MEMDC || + objtype == OBJ_ENHMETADC || objtype == OBJ_METADC) + { + hDC = (HDC)data; + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + } + else + { + hDC = NULL; + canvas->w = 0; + canvas->h = 0; + sscanf((char*)data,"%p %dx%d", &hDC, &canvas->w, &canvas->h); + + if (!hDC || !canvas->w || !canvas->h) + return; + } + release_dc = 0; + } + + canvas->w_mm = ((double)canvas->w) / canvas->xres; + canvas->h_mm = ((double)canvas->h) / canvas->yres; + + /* Inicializa driver WIN32 */ + ctxcanvas = cdwCreateCanvas(canvas, hWnd, hDC, CDW_WIN); + + ctxcanvas->release_dc = release_dc; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; + + if (hWnd) + { + LONG style; + style = GetClassLong(hWnd, GCL_STYLE); + ctxcanvas->isOwnedDC = (int) ((style & CS_OWNDC) || (style & CS_CLASSDC)); + } + else + ctxcanvas->isOwnedDC = 1; + + /* Se nao e' ownwer, tem que liberar o contexto */ + if (!ctxcanvas->isOwnedDC) + cdwReleaseDC(ctxcanvas); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxActivate = cdactivate; + canvas->cxDeactivate = cddeactivate; +} + +static cdContext cdNativeContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextNativeWindow(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_NATIVEWINDOW); + if (ctx != NULL) + return ctx; + } + + return &cdNativeContext; +} diff --git a/cd/src/win32/cdwprn.c b/cd/src/win32/cdwprn.c new file mode 100755 index 0000000..95e4aca --- /dev/null +++ b/cd/src/win32/cdwprn.c @@ -0,0 +1,184 @@ +/** \file + * \brief Windows Printer Driver + * + * See Copyright Notice in cd.h + */ + + +#include +#include +#include + +#include "cdwin.h" +#include "cdprint.h" + +#ifndef DC_COLORDEVICE +#define DC_COLORDEVICE 32 /* declared only if WINVER 0x0500 */ +#endif + +/* +%F cdKillCanvas para Printer. +Termina a pagina e termina o documento, enviando-o para a impressora. +*/ +static void cdkillcanvas (cdCtxCanvas *ctxcanvas) +{ + EndPage(ctxcanvas->hDC); + EndDoc(ctxcanvas->hDC); + + cdwKillCanvas(ctxcanvas); + + DeleteDC(ctxcanvas->hDC); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +/* +%F cdFlush para Printer. +Termina uma pagina e inicia outra. +*/ +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + GdiFlush(); + EndPage(ctxcanvas->hDC); + + StartPage(ctxcanvas->hDC); + cdwRestoreDC(ctxcanvas); +} + +/* +%F cdCreateCanvas para Impresora. +Usa a impressora default. +*/ +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxCanvas* ctxcanvas; + char *data_str = (char*) data; + char docname[256] = "CD - Canvas Draw Document"; + DOCINFO di; + HDC hDC; + int dialog = 0, wtype; + PRINTDLG pd; + + /* Inicializa parametros */ + if (data_str == NULL) + return; + + if (data_str[0] != 0) + { + char *ptr = strstr(data_str, "-d"); + + if (ptr != NULL) + dialog = 1; + + if (data_str[0] != '-') + { + strcpy(docname, data_str); + + if (dialog) + docname[ptr - data_str - 1] = 0; + } + } + + ZeroMemory(&pd, sizeof(PRINTDLG)); + pd.lStructSize = sizeof(PRINTDLG); + pd.nCopies = 1; + + if (dialog) + { + pd.Flags = PD_RETURNDC | PD_USEDEVMODECOPIES | PD_COLLATE | PD_NOPAGENUMS | PD_NOSELECTION; + pd.hwndOwner = GetForegroundWindow(); + } + else + { + pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT; + } + + if (!PrintDlg(&pd)) + { + if(pd.hDevMode) + GlobalFree(pd.hDevMode); + if(pd.hDevNames) + GlobalFree(pd.hDevNames); + return; + } + + hDC = pd.hDC; + + /* Inicializa documento */ + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = docname; + di.lpszOutput = (LPTSTR) NULL; + di.lpszDatatype = (LPTSTR) NULL; + di.fwType = 0; + + StartDoc(hDC, &di); + + StartPage(hDC); + + wtype = CDW_EMF; + + /* Inicializa driver WIN32 */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, hDC, wtype); + + canvas->w = GetDeviceCaps(hDC, HORZRES); + canvas->h = GetDeviceCaps(hDC, VERTRES); + canvas->w_mm = (double) GetDeviceCaps(hDC, HORZSIZE); + canvas->h_mm = (double) GetDeviceCaps(hDC, VERTSIZE); + canvas->bpp = GetDeviceCaps(hDC, BITSPIXEL); + canvas->xres = canvas->w / canvas->w_mm; + canvas->yres = canvas->h / canvas->h_mm; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; + + /* PDF Writer returns bpp=1, so we check if color is supported and overwrite this value */ + if (canvas->bpp==1 && pd.hDevNames) + { + unsigned char* devnames = (unsigned char*)GlobalLock(pd.hDevNames); + DEVNAMES* dn = (DEVNAMES*)devnames; + char* name = (char*)(devnames + dn->wDeviceOffset); + char* port = (char*)(devnames + dn->wOutputOffset); + + if (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL)) + canvas->bpp = 24; + + GlobalUnlock(pd.hDevNames); + } + + if(pd.hDevMode) + GlobalFree(pd.hDevMode); + if(pd.hDevNames) + GlobalFree(pd.hDevNames); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxFlush = cdflush; +} + +static cdContext cdPrinterContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + +cdContext* cdContextPrinter(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_PRINTER); + if (ctx != NULL) + return ctx; + } + + return &cdPrinterContext; +} diff --git a/cd/src/win32/cdwwmf.c b/cd/src/win32/cdwwmf.c new file mode 100755 index 0000000..0571c9f --- /dev/null +++ b/cd/src/win32/cdwwmf.c @@ -0,0 +1,109 @@ +/** \file + * \brief Windows WMF Driver + * Aldus Placeable Metafile + * + * See Copyright Notice in cd.h + */ + + +#include +#include + +#include "cdwin.h" +#include "cdwmf.h" + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + HMETAFILE hmf; + + cdwKillCanvas(ctxcanvas); + + hmf = CloseMetaFile(ctxcanvas->hDC); + wmfMakePlaceableMetafile(hmf, ctxcanvas->filename, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + DeleteMetaFile(hmf); + + free(ctxcanvas->filename); + + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + free(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void* data) +{ + cdCtxCanvas* ctxcanvas; + char* strdata = (char*)data; + int w = 0, h = 0; + float res; + HDC ScreenDC; + FILE* fh; + char filename[10240] = ""; + + /* Inicializa parametros */ + if (strdata == NULL) + return; + + ScreenDC = GetDC(NULL); + res = (float)(((double)GetDeviceCaps(ScreenDC, LOGPIXELSX)) / 25.4); + ReleaseDC(NULL, ScreenDC); + + strdata += cdGetFileName(strdata, filename); + if (filename[0] == 0) + return; + + sscanf(strdata,"%dx%d %g", &w, &h, &res); + if (w == 0 || h == 0) + return; + + /* Verifica se o arquivo pode ser aberto para escrita */ + fh = fopen(filename, "w"); + if (fh == 0) + return; + + fclose(fh); + + /* Inicializa driver WIN32 */ + ctxcanvas = cdwCreateCanvas(canvas, NULL, CreateMetaFile(NULL), CDW_WMF); + + canvas->w = w; + canvas->h = h; + canvas->xres = res; + canvas->yres = res; + canvas->w_mm = ((double)w) / res; + canvas->h_mm = ((double)h) / res; + canvas->bpp = 24; + ctxcanvas->clip_pnt[2].x = ctxcanvas->clip_pnt[1].x = canvas->w - 1; + ctxcanvas->clip_pnt[3].y = ctxcanvas->clip_pnt[2].y = canvas->h - 1; + + /* Inicializacao de variaveis particulares para o WMF */ + ctxcanvas->filename = cdStrDup(filename); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdwInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + + /* overwrite the base Win32 driver functions */ + canvas->cxGetTextSize = cdgettextsizeEX; +} + +static cdContext cdWMFContext = +{ + CD_CAP_ALL & ~(CD_CAP_CLEAR | CD_CAP_YAXIS | CD_CAP_TEXTSIZE | + CD_CAP_CLIPAREA | CD_CAP_CLIPPOLY | CD_CAP_PATTERN | + CD_CAP_IMAGERGBA | CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | + CD_CAP_LINECAP | CD_CAP_LINEJOIN | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + cdplayWMF, + cdregistercallbackWMF +}; + +cdContext* cdContextWMF(void) +{ + return &cdWMFContext; +} diff --git a/cd/src/win32/wmf_emf.c b/cd/src/win32/wmf_emf.c new file mode 100755 index 0000000..d876874 --- /dev/null +++ b/cd/src/win32/wmf_emf.c @@ -0,0 +1,2121 @@ +/** \file + * \brief EMF and WMF Play + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cdwin.h" +#include "cdwmf.h" +#include "cdemf.h" + +/* placeable metafile data definitions */ +#define ALDUSKEY 0x9AC6CDD7 + +#ifndef PS_JOIN_MASK +#define PS_JOIN_MASK 0x0000F000 +#endif + +/* +%F Definicao do header do APM. Ver comentario no final deste arquivo. +*/ +typedef struct _APMFILEHEADER +{ + WORD key1, + key2, + hmf, + bleft, btop, bright, bbottom, + inch, + reserved1, + reserved2, + checksum; +} APMFILEHEADER; + + +/* coordinates convertion */ + +static double wmf_xfactor = 1; +static double wmf_yfactor = -1; /* negative because top-down orientation */ +static int wmf_xmin = 0; +static int wmf_ymin = 0; +static int wmf_left = 0; +static int wmf_bottom = 0; /* bottom and right are not included */ +static int wmf_top = 0; +static int wmf_right = 0; + +static int sScaleX(int x) +{ + return cdRound((x - wmf_left) * wmf_xfactor + wmf_xmin); +} + +static int sScaleY(int y) +{ + return cdRound((y - (wmf_bottom-1)) * wmf_yfactor + wmf_ymin); +} + +static int sScaleW(int w) +{ + int s = (int)(w * fabs(wmf_xfactor) + 0.5); + return s > 0? s: 1; +} + +static int sScaleH(int h) +{ + int s = (int)(h * fabs(wmf_yfactor) + 0.5); + return s > 0? s: 1; +} + +static void sCalcSizeX(int x) +{ + if (x < wmf_left) + { + wmf_left = x; + return; + } + + if (x+1 > wmf_right) + { + wmf_right = x+1; + return; + } +} + +static void sCalcSizeY(int y) +{ + if (y < wmf_top) + { + wmf_top = y; + return; + } + + if (y+1 > wmf_bottom) + { + wmf_bottom = y+1; + return; + } +} + +static int CALLBACK CalcSizeEMFEnumProc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData) +{ + switch (lpEMFR->iType) + { + case EMR_POLYGON: + { + EMRPOLYGON* data = (EMRPOLYGON*)lpEMFR; + int i; + for (i = 0; i < (int)data->cptl; i++) + { + sCalcSizeX(data->aptl[i].x); + sCalcSizeY(data->aptl[i].y); + } + + break; + } + case EMR_POLYLINE: + { + EMRPOLYLINE* data = (EMRPOLYLINE*)lpEMFR; + int i; + for (i = 0; i < (int)data->cptl; i++) + { + sCalcSizeX(data->aptl[i].x); + sCalcSizeY(data->aptl[i].y); + } + + break; + } + case EMR_POLYLINETO: + { + EMRPOLYLINETO* data = (EMRPOLYLINETO*)lpEMFR; + int i; + for (i = 0; i < (int)data->cptl; i++) + { + sCalcSizeX(data->aptl[i].x); + sCalcSizeY(data->aptl[i].y); + } + + break; + } + case EMR_POLYPOLYLINE: + { + EMRPOLYPOLYLINE* data = (EMRPOLYPOLYLINE*)lpEMFR; + POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->aptl can not be used if count greater than 1 */ + for (c = 0; c < (int)data->nPolys; c++) + { + for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++) + { + sCalcSizeX(aptl->x); + sCalcSizeY(aptl->y); + } + } + break; + } + case EMR_POLYPOLYGON: + { + EMRPOLYPOLYGON* data = (EMRPOLYPOLYGON*)lpEMFR; + POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->aptl can not be used if count greater than 1 */ + for (c = 0; c < (int)data->nPolys; c++) + { + for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++) + { + sCalcSizeX(aptl->x); + sCalcSizeY(aptl->y); + } + } + break; + } + case EMR_SETPIXELV: + { + EMRSETPIXELV* data = (EMRSETPIXELV*)lpEMFR; + sCalcSizeX(data->ptlPixel.x); + sCalcSizeY(data->ptlPixel.y); + break; + } + case EMR_MOVETOEX: + { + EMRMOVETOEX* data = (EMRMOVETOEX*)lpEMFR; + sCalcSizeX(data->ptl.x); + sCalcSizeY(data->ptl.y); + break; + } + case EMR_ANGLEARC: + { + EMRANGLEARC* data = (EMRANGLEARC*)lpEMFR; + int x, y; + + x = (int)(data->nRadius * cos(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle)); + y = (int)(data->nRadius * sin(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle)); + + sCalcSizeX(data->ptlCenter.x); + sCalcSizeY(data->ptlCenter.y); + sCalcSizeX(x); + sCalcSizeY(y); + break; + } + case EMR_ELLIPSE: + { + EMRELLIPSE* data = (EMRELLIPSE*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.top); + sCalcSizeY(data->rclBox.bottom); + break; + } + case EMR_RECTANGLE: + { + EMRRECTANGLE* data = (EMRRECTANGLE*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.bottom); + sCalcSizeY(data->rclBox.top); + break; + } + case EMR_ROUNDRECT: + { + EMRROUNDRECT* data = (EMRROUNDRECT*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.bottom); + sCalcSizeY(data->rclBox.top); + break; + } + case EMR_ARC: + { + EMRARC* data = (EMRARC*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.top); + sCalcSizeY(data->rclBox.bottom); + break; + } + case EMR_CHORD: + { + EMRCHORD* data = (EMRCHORD*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.top); + sCalcSizeY(data->rclBox.bottom); + break; + } + case EMR_PIE: + { + EMRPIE* data = (EMRPIE*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.top); + sCalcSizeY(data->rclBox.bottom); + break; + } + case EMR_LINETO: + { + EMRLINETO* data = (EMRLINETO*)lpEMFR; + sCalcSizeX(data->ptl.x); + sCalcSizeY(data->ptl.y); + break; + } + case EMR_ARCTO: + { + EMRARCTO* data = (EMRARCTO*)lpEMFR; + sCalcSizeX(data->rclBox.left); + sCalcSizeX(data->rclBox.right); + sCalcSizeY(data->rclBox.top); + sCalcSizeY(data->rclBox.bottom); + break; + } + case EMR_POLYDRAW: + { + int p; + EMRPOLYDRAW* data = (EMRPOLYDRAW*)lpEMFR; + + for(p = 0; p < (int)data->cptl; p++) + { + switch (data->abTypes[p]) + { + case PT_MOVETO: + { + sCalcSizeX(data->aptl[p].x); + sCalcSizeY(data->aptl[p].y); + break; + } + case PT_LINETO: + { + sCalcSizeX(data->aptl[p].x); + sCalcSizeY(data->aptl[p].y); + break; + } + } + } + break; + } + case EMR_BITBLT: + { + EMRBITBLT* data = (EMRBITBLT*)lpEMFR; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + sCalcSizeX(data->xDest); + sCalcSizeY(data->yDest); + sCalcSizeX(data->xDest + dib.w); + sCalcSizeY(data->yDest + abs(dib.h)); + break; + } + case EMR_STRETCHBLT: + { + EMRSTRETCHBLT* data = (EMRSTRETCHBLT*)lpEMFR; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + sCalcSizeX(data->xDest); + sCalcSizeY(data->yDest); + sCalcSizeX(data->xDest + data->cxDest); + sCalcSizeY(data->yDest + data->cyDest); + break; + } + case EMR_MASKBLT: + { + EMRMASKBLT* data = (EMRMASKBLT*)lpEMFR; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + sCalcSizeX(data->xDest); + sCalcSizeY(data->yDest); + sCalcSizeX(data->xDest + dib.w); + sCalcSizeY(data->yDest + abs(dib.h)); + break; + } + case EMR_SETDIBITSTODEVICE: + { + EMRSETDIBITSTODEVICE* data = (EMRSETDIBITSTODEVICE*)lpEMFR; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + sCalcSizeX(data->xDest); + sCalcSizeY(data->yDest); + sCalcSizeX(data->xDest + dib.w); + sCalcSizeY(data->yDest + abs(dib.h)); + break; + } + case EMR_STRETCHDIBITS: + { + EMRSTRETCHDIBITS* data = (EMRSTRETCHDIBITS*)lpEMFR; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + sCalcSizeX(data->xDest); + sCalcSizeY(data->yDest); + sCalcSizeX(data->xDest + data->cxDest); + sCalcSizeY(data->yDest + data->cyDest); + break; + } + case EMR_EXTTEXTOUTA: + { + EMREXTTEXTOUTA* data = (EMREXTTEXTOUTA*)lpEMFR; + sCalcSizeX(data->emrtext.ptlReference.x); + sCalcSizeY(data->emrtext.ptlReference.y); + break; + } + case EMR_EXTTEXTOUTW: + { + EMREXTTEXTOUTW* data = (EMREXTTEXTOUTW*)lpEMFR; + sCalcSizeX(data->emrtext.ptlReference.x); + sCalcSizeY(data->emrtext.ptlReference.y); + break; + } + case EMR_POLYGON16: + { + EMRPOLYGON16* data = (EMRPOLYGON16*)lpEMFR; + int i; + for (i = 0; i < (int)data->cpts; i++) + { + sCalcSizeX(data->apts[i].x); + sCalcSizeY(data->apts[i].y); + } + break; + } + case EMR_POLYLINE16: + { + EMRPOLYLINE16* data = (EMRPOLYLINE16*)lpEMFR; + int i; + for (i = 0; i < (int)data->cpts; i++) + { + sCalcSizeX(data->apts[i].x); + sCalcSizeY(data->apts[i].y); + } + break; + } + case EMR_POLYLINETO16: + { + EMRPOLYLINETO16* data = (EMRPOLYLINETO16*)lpEMFR; + int i; + for (i = 0; i < (int)data->cpts; i++) + { + sCalcSizeX(data->apts[i].x); + sCalcSizeY(data->apts[i].y); + } + break; + } + case EMR_POLYPOLYLINE16: + { + EMRPOLYPOLYLINE16* data = (EMRPOLYPOLYLINE16*)lpEMFR; + POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->apts can not be used if count greater than 1 */ + for (c = 0; c < (int)data->nPolys; c++) + { + for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++) + { + sCalcSizeX(apts->x); + sCalcSizeY(apts->y); + } + } + break; + } + case EMR_POLYPOLYGON16: + { + EMRPOLYPOLYGON16* data = (EMRPOLYPOLYGON16*)lpEMFR; + POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->apts can not be used if count greater than 1 */ + for (c = 0; c < (int)data->nPolys; c++) + { + for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++) + { + sCalcSizeX(apts->x); + sCalcSizeY(apts->y); + } + } + break; + } + case EMR_POLYDRAW16: + { + EMRPOLYDRAW16* data = (EMRPOLYDRAW16*)lpEMFR; + int p; + for(p = 0; p < (int)data->cpts; p++) + { + switch (data->abTypes[p]) + { + case PT_MOVETO: + { + sCalcSizeX(data->apts[p].x); + sCalcSizeY(data->apts[p].y); + break; + } + case PT_LINETO: + { + sCalcSizeX(data->apts[p].x); + sCalcSizeY(data->apts[p].y); + break; + } + } + } + break; + } + case EMR_POLYTEXTOUTA: + { + EMRPOLYTEXTOUTA* data = (EMRPOLYTEXTOUTA*)lpEMFR; + int t; + for (t = 0; t < data->cStrings; t++) + { + sCalcSizeX(data->aemrtext[t].ptlReference.x); + sCalcSizeY(data->aemrtext[t].ptlReference.y); + } + break; + } + case EMR_POLYTEXTOUTW: + { + EMRPOLYTEXTOUTW* data = (EMRPOLYTEXTOUTW*)lpEMFR; + int t; + for (t = 0; t < data->cStrings; t++) + { + sCalcSizeX(data->aemrtext[t].ptlReference.x); + sCalcSizeY(data->aemrtext[t].ptlReference.y); + } + break; + } + } + + return 1; +} + +static int CALLBACK EMFEnumProc(HDC hDC, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, int nObj, LPARAM lpData) +{ + static int curx = 0, cury = 0; + static int upd_xy = 0; + cdCanvas* canvas = (cdCanvas*)lpData; + + switch (lpEMFR->iType) + { + case EMR_SETWORLDTRANSFORM: + { + double matrix[6]; + EMRSETWORLDTRANSFORM* data = (EMRSETWORLDTRANSFORM*)lpEMFR; + matrix[0] = data->xform.eM11; + matrix[1] = data->xform.eM12; + matrix[2] = data->xform.eM21; + matrix[3] = data->xform.eM22; + matrix[4] = data->xform.eDx; + matrix[5] = data->xform.eDy; + cdCanvasTransform(canvas, matrix); + break; + } + case EMR_MODIFYWORLDTRANSFORM: + { + EMRMODIFYWORLDTRANSFORM* data = (EMRMODIFYWORLDTRANSFORM*)lpEMFR; + if (data->iMode == MWT_IDENTITY) + cdCanvasTransform(canvas, NULL); + else if (data->iMode == MWT_LEFTMULTIPLY) + { + double matrix[6]; + matrix[0] = data->xform.eM11; + matrix[1] = data->xform.eM12; + matrix[2] = data->xform.eM21; + matrix[3] = data->xform.eM22; + matrix[4] = data->xform.eDx; + matrix[5] = data->xform.eDy; + cdCanvasTransformMultiply(canvas, matrix); + } + break; + } + case EMR_POLYGON: + { + EMRPOLYGON* data = (EMRPOLYGON*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_FILL); + + for (i = 0; i < (int)data->cptl; i++) + cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYLINE: + { + EMRPOLYLINE* data = (EMRPOLYLINE*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->cptl; i++) + cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYBEZIER: + { + EMRPOLYBEZIER* data = (EMRPOLYBEZIER*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_BEZIER); + + for (i = 0; i < (int)data->cptl; i++) + cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYLINETO: + { + EMRPOLYLINETO* data = (EMRPOLYLINETO*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->cptl; i++) + cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y)); + + curx = data->aptl[data->cptl - 1].x; + cury = data->aptl[data->cptl - 1].y; + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYBEZIERTO: + { + EMRPOLYBEZIERTO* data = (EMRPOLYBEZIERTO*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_BEZIER); + + for (i = 0; i < (int)data->cptl; i++) + cdCanvasVertex(canvas, sScaleX(data->aptl[i].x), sScaleY(data->aptl[i].y)); + + curx = data->aptl[data->cptl - 1].x; + cury = data->aptl[data->cptl - 1].y; + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYPOLYLINE: + { + EMRPOLYPOLYLINE* data = (EMRPOLYPOLYLINE*)lpEMFR; + POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->aptl can not be used if count greater than 1 */ + + for (c = 0; c < (int)data->nPolys; c++) + { + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++) + cdCanvasVertex(canvas, sScaleX(aptl->x), sScaleY(aptl->y)); + + cdCanvasEnd(canvas); + } + break; + } + case EMR_POLYPOLYGON: + { + EMRPOLYPOLYGON* data = (EMRPOLYPOLYGON*)lpEMFR; + POINTL* aptl = (POINTL*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->aptl can not be used if count greater than 1 */ + + for (c = 0; c < (int)data->nPolys; c++) + { + cdCanvasBegin(canvas, CD_FILL); + + for (i = 0; i < (int)data->aPolyCounts[c]; i++, aptl++) + cdCanvasVertex(canvas, sScaleX(aptl->x), sScaleY(aptl->y)); + + cdCanvasEnd(canvas); + } + break; + } + case EMR_SETPIXELV: + { + EMRSETPIXELV* data = (EMRSETPIXELV*)lpEMFR; + cdCanvasPixel(canvas, sScaleX(data->ptlPixel.x), sScaleY(data->ptlPixel.y), cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor))); + break; + } + case EMR_SETBKMODE: + { + EMRSETBKMODE* data = (EMRSETBKMODE*)lpEMFR; + cdCanvasBackOpacity(canvas, data->iMode == TRANSPARENT? CD_TRANSPARENT: CD_OPAQUE); + break; + } + case EMR_SETROP2: + { + EMRSETROP2* data = (EMRSETROP2*)lpEMFR; + cdCanvasWriteMode(canvas, data->iMode == R2_NOTXORPEN? CD_NOT_XOR: (data->iMode == R2_XORPEN? CD_XOR: CD_REPLACE)); + break; + } + case EMR_SETTEXTALIGN: + { + EMRSETTEXTALIGN* data = (EMRSETTEXTALIGN*)lpEMFR; + upd_xy = 0; + + if (data->iMode & TA_UPDATECP) + { + upd_xy = 1; + data->iMode &= ~TA_UPDATECP; + } + + switch (data->iMode) + { + case 0: /* top-left */ + cdCanvasTextAlignment(canvas, CD_NORTH_WEST); + break; + case 2: /* top-right */ + cdCanvasTextAlignment(canvas, CD_NORTH_EAST); + break; + case 6: /* top-center */ + cdCanvasTextAlignment(canvas, CD_NORTH); + break; + case 8: /* bottom-left */ + cdCanvasTextAlignment(canvas, CD_SOUTH_WEST); + break; + case 10: /* bottom-right */ + cdCanvasTextAlignment(canvas, CD_SOUTH_EAST); + break; + case 14: /* bottom-center */ + cdCanvasTextAlignment(canvas, CD_SOUTH); + break; + case 24: /* baseline-left */ + cdCanvasTextAlignment(canvas, CD_BASE_LEFT); + break; + case 26: /* baseline-right */ + cdCanvasTextAlignment(canvas, CD_BASE_RIGHT); + break; + case 30: /* baseline-center */ + cdCanvasTextAlignment(canvas, CD_BASE_CENTER); + break; + } + + break; + } + case EMR_SETTEXTCOLOR: + { + EMRSETTEXTCOLOR* data = (EMRSETTEXTCOLOR*)lpEMFR; + cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor))); + break; + } + case EMR_SETBKCOLOR: + { + EMRSETBKCOLOR* data = (EMRSETBKCOLOR*)lpEMFR; + cdCanvasSetBackground(canvas, cdEncodeColor(GetRValue(data->crColor),GetGValue(data->crColor),GetBValue(data->crColor))); + break; + } + case EMR_MOVETOEX: + { + EMRMOVETOEX* data = (EMRMOVETOEX*)lpEMFR; + curx = data->ptl.x; + cury = data->ptl.y; + break; + } + case EMR_CREATEPEN: + { + EMRCREATEPEN* data = (EMRCREATEPEN*)lpEMFR; + int style; + + switch (data->lopn.lopnStyle) + { + case PS_SOLID: + style = CD_CONTINUOUS; + break; + case PS_DASH: + style = CD_DASHED; + break; + case PS_DOT: + style = CD_DOTTED; + break; + case PS_DASHDOT: + style = CD_DASH_DOT; + break; + case PS_DASHDOTDOT: + style = CD_DASH_DOT_DOT; + break; + case PS_NULL: + style = -1; + break; + default: + style = CD_CONTINUOUS; + break; + } + + if (style != -1) + { + cdCanvasLineStyle(canvas, style); + cdCanvasLineWidth(canvas, sScaleW(data->lopn.lopnWidth.x == 0? 1: data->lopn.lopnWidth.x)); + cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->lopn.lopnColor),GetGValue(data->lopn.lopnColor),GetBValue(data->lopn.lopnColor))); + } + break; + } + case EMR_EXTCREATEPEN: + { + EMREXTCREATEPEN* data = (EMREXTCREATEPEN*)lpEMFR; + int style; + + switch (data->elp.elpPenStyle & PS_STYLE_MASK) + { + case PS_SOLID: + style = CD_CONTINUOUS; + break; + case PS_DASH: + style = CD_DASHED; + break; + case PS_DOT: + style = CD_DOTTED; + break; + case PS_DASHDOT: + style = CD_DASH_DOT; + break; + case PS_DASHDOTDOT: + style = CD_DASH_DOT_DOT; + break; + case PS_NULL: + style = -1; + break; + case PS_USERSTYLE: + style = CD_CUSTOM; + cdCanvasLineStyleDashes(canvas, (int*)data->elp.elpStyleEntry, data->elp.elpNumEntries); + break; + default: + style = CD_CONTINUOUS; + break; + } + + if (style != -1) + { + switch (data->elp.elpPenStyle & PS_ENDCAP_MASK) + { + case PS_ENDCAP_FLAT: + cdCanvasLineCap(canvas, CD_CAPFLAT); + break; + case PS_ENDCAP_ROUND: + cdCanvasLineCap(canvas, CD_CAPROUND); + break; + case PS_ENDCAP_SQUARE: + cdCanvasLineCap(canvas, CD_CAPSQUARE); + break; + } + + switch (data->elp.elpPenStyle & PS_JOIN_MASK) + { + case PS_JOIN_MITER: + cdCanvasLineJoin(canvas, CD_MITER); + break; + case PS_JOIN_BEVEL: + cdCanvasLineJoin(canvas, CD_BEVEL); + break; + case PS_JOIN_ROUND: + cdCanvasLineJoin(canvas, CD_ROUND); + break; + } + + cdCanvasLineStyle(canvas, style); + cdCanvasLineWidth(canvas, sScaleW(data->elp.elpWidth == 0? 1: data->elp.elpWidth)); + cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->elp.elpColor),GetGValue(data->elp.elpColor),GetBValue(data->elp.elpColor))); + } + break; + } + case EMR_CREATEBRUSHINDIRECT: + { + EMRCREATEBRUSHINDIRECT* data = (EMRCREATEBRUSHINDIRECT*)lpEMFR; + cdCanvasSetForeground(canvas, cdEncodeColor(GetRValue(data->lb.lbColor),GetGValue(data->lb.lbColor),GetBValue(data->lb.lbColor))); + + switch (data->lb.lbStyle) + { + case BS_HATCHED: + { + int hatch = 0; + + switch (data->lb.lbHatch) + { + case HS_BDIAGONAL: + hatch = CD_BDIAGONAL; + break; + case HS_CROSS: + hatch = CD_CROSS; + break; + case HS_DIAGCROSS: + hatch = CD_DIAGCROSS; + break; + case HS_FDIAGONAL: + hatch = CD_FDIAGONAL; + break; + case HS_HORIZONTAL: + hatch = CD_HORIZONTAL; + break; + case HS_VERTICAL: + hatch = CD_VERTICAL; + break; + } + + cdCanvasHatch(canvas, hatch); + cdCanvasInteriorStyle(canvas, CD_HATCH); + break; + } + case BS_SOLID: + cdCanvasInteriorStyle(canvas, CD_SOLID); + break; + case BS_NULL: + cdCanvasInteriorStyle(canvas, CD_HOLLOW); + break; + default: + break; + } + break; + } + case EMR_ANGLEARC: + { + EMRANGLEARC* data = (EMRANGLEARC*)lpEMFR; + int x, y; + + x = (int)(data->nRadius * cos(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle)); + y = (int)(data->nRadius * sin(CD_DEG2RAD * data->eStartAngle + data->eSweepAngle)); + + cdCanvasLine(canvas, sScaleX(data->ptlCenter.x), sScaleY(data->ptlCenter.y), sScaleX(x), sScaleY(y)); + cdCanvasArc(canvas, data->ptlCenter.x, data->ptlCenter.y, 2 * data->nRadius, 2 * data->nRadius, data->eStartAngle, data->eStartAngle + data->eSweepAngle); + break; + } + case EMR_ELLIPSE: + { + EMRELLIPSE* data = (EMRELLIPSE*)lpEMFR; + int xc, yc, w, h; + + xc = sScaleX((data->rclBox.left + data->rclBox.right - 1) / 2); + w = sScaleW(data->rclBox.right - data->rclBox.left - 1); + yc = sScaleY((data->rclBox.top + data->rclBox.bottom - 1) / 2); + h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1); + + cdCanvasSector(canvas, xc, yc, w, h, 0, 360); + break; + } + case EMR_RECTANGLE: + { + EMRRECTANGLE* data = (EMRRECTANGLE*)lpEMFR; + cdCanvasBox (canvas, sScaleX(data->rclBox.left), sScaleX(data->rclBox.right-2), sScaleY(data->rclBox.bottom-2), sScaleY(data->rclBox.top)); + break; + } + case EMR_ROUNDRECT: + { + EMRROUNDRECT* data = (EMRROUNDRECT*)lpEMFR; + cdCanvasBox (canvas, sScaleX(data->rclBox.left), sScaleX(data->rclBox.right-2), sScaleY(data->rclBox.bottom-2), sScaleY(data->rclBox.top)); + break; + } + case EMR_ARC: + { + EMRARC* data = (EMRARC*)lpEMFR; + int xc, yc, w, h; + double angle1, angle2; + + xc = (data->rclBox.left + data->rclBox.right - 1) / 2; + yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2; + + w = sScaleW(data->rclBox.right - data->rclBox.left - 1); + h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1); + + angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + + if (angle1 == angle2) + angle2+=360; + + xc = sScaleX(xc); + yc = sScaleY(yc); + + cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + break; + } + case EMR_CHORD: + { + EMRCHORD* data = (EMRCHORD*)lpEMFR; + int xc, yc, w, h; + double angle1, angle2; + + xc = (data->rclBox.left + data->rclBox.right - 1) / 2; + yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2; + + w = sScaleW(data->rclBox.right - data->rclBox.left - 1); + h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1); + + angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + + if (angle1 == angle2) + angle2+=360; + + xc = sScaleX(xc); + yc = sScaleY(yc); + + cdCanvasChord(canvas, xc, yc, w, h, angle1, angle2); + break; + } + case EMR_PIE: + { + EMRPIE* data = (EMRPIE*)lpEMFR; + int xc, yc, w, h; + double angle1, angle2; + + xc = (data->rclBox.left + data->rclBox.right - 1) / 2; + yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2; + + w = sScaleW(data->rclBox.right - data->rclBox.left - 1); + h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1); + + angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + + if (angle1 == angle2) + angle2+=360; + + xc = sScaleX(xc); + yc = sScaleY(yc); + + cdCanvasSector(canvas, xc, yc, w, h, angle1, angle2); + break; + } + case EMR_CREATEPALETTE: + { + int k; + EMRCREATEPALETTE* data = (EMRCREATEPALETTE*)lpEMFR; + long palette[256]; + + for (k=0; k < data->lgpl.palNumEntries; k++) + palette[k] = cdEncodeColor(data->lgpl.palPalEntry[k].peRed, data->lgpl.palPalEntry[k].peGreen, data->lgpl.palPalEntry[k].peBlue); + + cdCanvasPalette(canvas, data->lgpl.palNumEntries, palette, CD_POLITE); + break; + } + case EMR_LINETO: + { + EMRLINETO* data = (EMRLINETO*)lpEMFR; + cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->ptl.x), sScaleY(data->ptl.y)); + curx = data->ptl.x; + cury = data->ptl.y; + break; + } + case EMR_ARCTO: + { + EMRARCTO* data = (EMRARCTO*)lpEMFR; + int xc, yc, w, h; + double angle1, angle2; + + xc = (data->rclBox.left + data->rclBox.right - 1) / 2; + yc = (data->rclBox.top + data->rclBox.bottom - 1) / 2; + + w = sScaleW(data->rclBox.right - data->rclBox.left - 1); + h = sScaleH(data->rclBox.bottom - data->rclBox.top - 1); + + angle1 = atan2((yc - data->ptlStart.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlStart.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + angle2 = atan2((yc - data->ptlEnd.y)*(data->rclBox.right - data->rclBox.left - 1), (data->ptlEnd.x - xc)*(data->rclBox.bottom - data->rclBox.top - 1)) / CD_DEG2RAD; + + if (angle1 == angle2) + angle2+=360; + + xc = sScaleX(xc); + yc = sScaleY(yc); + + cdCanvasArc(canvas, xc, yc, w, h, angle1, angle2); + + curx = data->ptlEnd.x; /* isto nao esta' certo mas e' a minha melhor aproximacao */ + cury = data->ptlEnd.y; + break; + } + case EMR_POLYDRAW: + { + int p; + EMRPOLYDRAW* data = (EMRPOLYDRAW*)lpEMFR; + + for(p = 0; p < (int)data->cptl; p++) + { + switch (data->abTypes[p]) + { + case PT_MOVETO: + { + curx = data->aptl[p].x; + cury = data->aptl[p].y; + break; + } + case PT_LINETO: + { + cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->aptl[p].x), sScaleY(data->aptl[p].y)); + curx = data->aptl[p].x; + cury = data->aptl[p].y; + break; + } + } + } + break; + } + case EMR_BITBLT: + { + EMRBITBLT* data = (EMRBITBLT*)lpEMFR; + int size; + cdwDIB dib; + int old_write_mode; + + if (data->dwRop == SRCINVERT) + old_write_mode = cdCanvasWriteMode(canvas, CD_XOR); + else + old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE); + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(index); + free(colors); + } + + cdCanvasWriteMode(canvas, old_write_mode); + break; + } + case EMR_STRETCHBLT: + { + EMRSTRETCHBLT* data = (EMRSTRETCHBLT*)lpEMFR; + int size; + cdwDIB dib; + int old_write_mode; + + if (data->dwRop == SRCINVERT) + old_write_mode = cdCanvasWriteMode(canvas, CD_XOR); + else + old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE); + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0); + + free(index); + free(colors); + } + + cdCanvasWriteMode(canvas, old_write_mode); + break; + } + case EMR_MASKBLT: + { + EMRMASKBLT* data = (EMRMASKBLT*)lpEMFR; + int size; + cdwDIB dib; + int old_write_mode; + + if (data->dwRop == SRCINVERT) + old_write_mode = cdCanvasWriteMode(canvas, CD_XOR); + else + old_write_mode = cdCanvasWriteMode(canvas, CD_REPLACE); + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(index); + free(colors); + } + + cdCanvasWriteMode(canvas, old_write_mode); + break; + } + case EMR_SETDIBITSTODEVICE: + { + EMRSETDIBITSTODEVICE* data = (EMRSETDIBITSTODEVICE*)lpEMFR; + int size; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), dib.w, dib.h, 0, 0, 0, 0); + + free(index); + free(colors); + } + break; + } + case EMR_STRETCHDIBITS: + { + EMRSTRETCHDIBITS* data = (EMRSTRETCHDIBITS*)lpEMFR; + int size; + cdwDIB dib; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmiSrc, ((BYTE*)data) + data->offBitsSrc); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + cdCanvasPutImageRectRGB(canvas, dib.w, abs(dib.h), r, g, b, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + cdCanvasPutImageRectMap(canvas, dib.w, abs(dib.h), index, colors, sScaleX(data->xDest), sScaleY(data->yDest + abs(dib.h)), sScaleW(data->cxDest), sScaleH(data->cyDest), 0, 0, 0, 0); + + free(index); + free(colors); + } + break; + } + case EMR_EXTCREATEFONTINDIRECTW: + { + EMREXTCREATEFONTINDIRECTW* data = (EMREXTCREATEFONTINDIRECTW*)lpEMFR; + int style, size; + char type_face[256]; + + style = CD_PLAIN; + + if (data->elfw.elfLogFont.lfWeight >= FW_BOLD) + style = CD_BOLD; + + if (data->elfw.elfLogFont.lfItalic == 1) + style = CD_ITALIC; + + if (data->elfw.elfLogFont.lfWeight >= FW_BOLD && data->elfw.elfLogFont.lfItalic == 1) + style = CD_BOLD_ITALIC; + + if (data->elfw.elfLogFont.lfUnderline) + style |= CD_UNDERLINE; + + if (data->elfw.elfLogFont.lfStrikeOut) + style |= CD_STRIKEOUT; + + WideCharToMultiByte(CP_ACP, 0, data->elfw.elfLogFont.lfFaceName, LF_FACESIZE, type_face, 256, NULL, NULL); + + size = sScaleH(abs(data->elfw.elfLogFont.lfHeight)); + if (size < 5) size = 5; + + if (data->elfw.elfLogFont.lfOrientation) + cdCanvasTextOrientation(canvas, data->elfw.elfLogFont.lfOrientation/10); + + cdCanvasFont(canvas, type_face, style, -size); + break; + } + case EMR_EXTTEXTOUTA: + { + EMREXTTEXTOUTA* data = (EMREXTTEXTOUTA*)lpEMFR; + + char* str = malloc(data->emrtext.nChars + 1); + memcpy(str, ((unsigned char*)data) + data->emrtext.offString, data->emrtext.nChars + 1); + str[data->emrtext.nChars] = 0; + + cdCanvasText(canvas, sScaleX(data->emrtext.ptlReference.x), sScaleY(data->emrtext.ptlReference.y), str); + + if (upd_xy == 1) + { + curx = data->emrtext.ptlReference.x; + cury = data->emrtext.ptlReference.y; + } + + free(str); + break; + } + case EMR_EXTTEXTOUTW: + { + EMREXTTEXTOUTW* data = (EMREXTTEXTOUTW*)lpEMFR; + char str[256]; + + WideCharToMultiByte(CP_ACP, 0, (unsigned short*)(((unsigned char*)data) + data->emrtext.offString), data->emrtext.nChars, str, 256, NULL, NULL); + + str[data->emrtext.nChars] = 0; + + cdCanvasText(canvas, sScaleX(data->emrtext.ptlReference.x), sScaleY(data->emrtext.ptlReference.y), str); + + if (upd_xy == 1) + { + curx = data->emrtext.ptlReference.x; + cury = data->emrtext.ptlReference.y; + } + break; + } + case EMR_SETPOLYFILLMODE: + { + EMRSETPOLYFILLMODE* data = (EMRSETPOLYFILLMODE*)lpEMFR; + if (data->iMode == ALTERNATE) + cdCanvasFillMode(canvas, CD_EVENODD); + else + cdCanvasFillMode(canvas, CD_WINDING); + break; + } + case EMR_POLYGON16: + { + EMRPOLYGON16* data = (EMRPOLYGON16*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_FILL); + + for (i = 0; i < (int)data->cpts; i++) + cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYLINE16: + { + EMRPOLYLINE16* data = (EMRPOLYLINE16*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->cpts; i++) + cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYLINETO16: + { + EMRPOLYLINETO16* data = (EMRPOLYLINETO16*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->cpts; i++) + cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y)); + + curx = data->apts[data->cpts - 1].x; + cury = data->apts[data->cpts - 1].y; + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYBEZIER16: + { + EMRPOLYBEZIER16* data = (EMRPOLYBEZIER16*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_BEZIER); + + for (i = 0; i < (int)data->cpts; i++) + cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y)); + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYBEZIERTO16: + { + EMRPOLYBEZIERTO16* data = (EMRPOLYBEZIERTO16*)lpEMFR; + int i; + + cdCanvasBegin(canvas, CD_BEZIER); + + for (i = 0; i < (int)data->cpts; i++) + cdCanvasVertex(canvas, sScaleX(data->apts[i].x), sScaleY(data->apts[i].y)); + + curx = data->apts[data->cpts - 1].x; + cury = data->apts[data->cpts - 1].y; + + cdCanvasEnd(canvas); + break; + } + case EMR_POLYPOLYLINE16: + { + EMRPOLYPOLYLINE16* data = (EMRPOLYPOLYLINE16*)lpEMFR; + POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->apts can not be used if count greater than 1 */ + + for (c = 0; c < (int)data->nPolys; c++) + { + cdCanvasBegin(canvas, CD_OPEN_LINES); + + for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++) + cdCanvasVertex(canvas, sScaleX(apts->x), sScaleY(apts->y)); + + cdCanvasEnd(canvas); + } + break; + } + case EMR_POLYPOLYGON16: + { + EMRPOLYPOLYGON16* data = (EMRPOLYPOLYGON16*)lpEMFR; + POINTS* apts = (POINTS*)(data->aPolyCounts + data->nPolys); /* skip the array of counts */ + int c, i; /* data->apts can not be used if count greater than 1 */ + + for (c = 0; c < (int)data->nPolys; c++) + { + cdCanvasBegin(canvas, CD_FILL); + + for (i = 0; i < (int)data->aPolyCounts[c]; i++, apts++) + cdCanvasVertex(canvas, sScaleX(apts->x), sScaleY(apts->y)); + + cdCanvasEnd(canvas); + } + break; + } + case EMR_POLYDRAW16: + { + int p; + EMRPOLYDRAW16* data = (EMRPOLYDRAW16*)lpEMFR; + + for(p = 0; p < (int)data->cpts; p++) + { + switch (data->abTypes[p]) + { + case PT_MOVETO: + { + curx = data->apts[p].x; + cury = data->apts[p].y; + break; + } + case PT_LINETO: + { + cdCanvasLine(canvas, sScaleX(curx), sScaleY(cury), sScaleX(data->apts[p].x), sScaleY(data->apts[p].y)); + curx = data->apts[p].x; + cury = data->apts[p].y; + break; + } + } + } + break; + } + case EMR_CREATEMONOBRUSH: + { + EMRCREATEMONOBRUSH* data = (EMRCREATEMONOBRUSH*)lpEMFR; + int size, i; + cdwDIB dib; + long *pattern; + unsigned char *stipple; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmi, ((BYTE*)data) + data->offBits); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.bmih->biBitCount == 1) + stipple = malloc(size); + else + pattern = (long*)malloc(size*sizeof(long)); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + for (i = 0; i < size; i++) + pattern[i] = cdEncodeColor(r[i], g[i], b[i]); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + if (dib.bmih->biBitCount == 1) + { + for (i = 0; i < size; i++) + stipple[i] = index[i]? 0: 1; + } + else + { + for (i = 0; i < size; i++) + pattern[i] = colors[index[i]]; + } + + free(index); + free(colors); + } + + if (dib.bmih->biBitCount == 1) + { + cdCanvasStipple(canvas, dib.w, abs(dib.h), stipple); + free(stipple); + } + else + { + cdCanvasPattern(canvas, dib.w, abs(dib.h), pattern); + free(pattern); + } + break; + } + case EMR_CREATEDIBPATTERNBRUSHPT: + { + EMRCREATEDIBPATTERNBRUSHPT* data = (EMRCREATEDIBPATTERNBRUSHPT*)lpEMFR; + int size, i; + cdwDIB dib; + long *pattern; + unsigned char *stipple; + + cdwDIBReference(&dib, ((BYTE*)data) + data->offBmi, ((BYTE*)data) + data->offBits); + + if (dib.type == -1) + break; + + size = dib.w*abs(dib.h); + + if (dib.bmih->biBitCount == 1) + stipple = malloc(size); + else + pattern = malloc(size*sizeof(long)); + + if (dib.type == 0) + { + unsigned char *r, *g, *b; + + r = (unsigned char*)malloc(size); + g = (unsigned char*)malloc(size); + b = (unsigned char*)malloc(size); + + cdwDIBDecodeRGB(&dib, r, g, b); + + for (i = 0; i < size; i++) + pattern[i] = cdEncodeColor(r[i], g[i], b[i]); + + free(r); + free(g); + free(b); + } + else + { + unsigned char *index; + long *colors; + + index = (unsigned char*)malloc(size); + colors = (long*)malloc(256*sizeof(long)); + + cdwDIBDecodeMap(&dib, index, colors); + + if (dib.bmih->biBitCount == 1) + { + for (i = 0; i < size; i++) + stipple[i] = index[i]? 0: 1; + } + else + { + for (i = 0; i < size; i++) + pattern[i] = colors[index[i]]; + } + + free(index); + free(colors); + } + + if (dib.bmih->biBitCount == 1) + { + cdCanvasStipple(canvas, dib.w, abs(dib.h), stipple); + free(stipple); + } + else + { + cdCanvasPattern(canvas, dib.w, abs(dib.h), pattern); + free(pattern); + } + break; + } + case EMR_POLYTEXTOUTA: + { + int t; + EMRPOLYTEXTOUTA* data = (EMRPOLYTEXTOUTA*)lpEMFR; + + for (t = 0; t < data->cStrings; t++) + { + char* str = malloc(data->aemrtext[t].nChars + 1); + memcpy(str, ((unsigned char*)data) + data->aemrtext[t].offString, data->aemrtext[t].nChars + 1); + str[data->aemrtext[t].nChars] = 0; + + cdCanvasText(canvas, sScaleX(data->aemrtext[t].ptlReference.x), sScaleY(data->aemrtext[t].ptlReference.y), str); + + free(str); + } + break; + } + case EMR_POLYTEXTOUTW: + { + int t; + EMRPOLYTEXTOUTW* data = (EMRPOLYTEXTOUTW*)lpEMFR; + char str[256]; + + for (t = 0; t < data->cStrings; t++) + { + WideCharToMultiByte(CP_ACP, 0, (unsigned short*)(((unsigned char*)data) + data->aemrtext[t].offString), data->aemrtext[t].nChars, str, 256, NULL, NULL); + str[data->aemrtext[t].nChars] = 0; + cdCanvasText(canvas, sScaleX(data->aemrtext[t].ptlReference.x), sScaleY(data->aemrtext[t].ptlReference.y), str); + } + break; + } + } + + return 1; +} + + +static cdSizeCB cdsizecbWMF = NULL; + +int cdregistercallbackWMF(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdsizecbWMF = (cdSizeCB)func; + return CD_OK; + } + + return CD_ERROR; +} + + +/*********************************************************************** +Read the metafile bits, metafile header and placeable +metafile header of a placeable metafile. +************************************************************************/ + +static HANDLE GetPlaceableMetaFile(int fh) +{ + HANDLE hMF; + HANDLE hMem; + LPSTR lpMem; + int wBytesRead; + APMFILEHEADER aldusMFHeader; + METAHEADER mfHeader; + + /* seek to beginning of file and read aldus header */ + lseek(fh, 0, 0); + + /* read the placeable header */ + wBytesRead = read(fh, (LPSTR)&aldusMFHeader, sizeof(APMFILEHEADER)); + + /* if there is an error, return */ + if(wBytesRead == -1 || wBytesRead < sizeof(APMFILEHEADER)) + return NULL; + + /* read the metafile header */ + wBytesRead = read(fh, (LPSTR)&mfHeader, sizeof(METAHEADER)); + + /* if there is an error return */ + if( wBytesRead == -1 || wBytesRead < sizeof(METAHEADER) ) + return NULL; + + /* allocate memory for the metafile bits */ + if (!(hMem = GlobalAlloc(GHND, mfHeader.mtSize * 2L))) + return NULL; + + /* lock the memory */ + if (!(lpMem = GlobalLock(hMem))) + { + GlobalFree(hMem); + return NULL; + } + + /* seek to the metafile bits */ + lseek(fh, sizeof(APMFILEHEADER), 0); + + /* read metafile bits */ + wBytesRead = read(fh, lpMem, (WORD)(mfHeader.mtSize * 2L)); + + /* if there was an error */ + if( wBytesRead == -1 ) + { + GlobalUnlock(hMem); + GlobalFree(hMem); + return NULL; + } + + if (!(hMF = SetMetaFileBitsEx(mfHeader.mtSize * 2L, lpMem))) + return NULL; + + GlobalUnlock(hMem); + GlobalFree(hMem); + + return hMF; +} + + +/* +%F cdPlay para WMF. +Interpreta os dados do WMF. +*/ +int cdplayWMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + char* filename = (char*)data; + int fh; + int wBytesRead; + DWORD dwIsAldus; + HANDLE hMF; + HENHMETAFILE hEMF; + ENHMETAHEADER emh; + BYTE* buffer; + int size; + + /* try to open the file. */ + fh = open(filename, O_BINARY | O_RDONLY); + + /* if opened failed */ + if (fh == -1) + return CD_ERROR; + + /* read the first dword of the file to see if it is a placeable wmf */ + wBytesRead = read(fh,(LPSTR)&dwIsAldus, sizeof(dwIsAldus)); + if (wBytesRead == -1 || wBytesRead < sizeof(dwIsAldus)) + { + close(fh); + return CD_ERROR; + } + + /* if this is windows metafile, not a placeable wmf */ + if (dwIsAldus != ALDUSKEY) + { + METAHEADER mfHeader; + + /* seek to the beginning of the file */ + lseek(fh, 0, 0); + + /* read the wmf header */ + wBytesRead = read(fh, (LPSTR)&mfHeader, sizeof(METAHEADER)); + + /* done with file so close it */ + close(fh); + + /* if read failed */ + if (wBytesRead == -1 || wBytesRead < sizeof(METAHEADER)) + return CD_ERROR; + + hMF = GetMetaFile(filename); + } + else /* this is a placeable metafile */ + { + /* convert the placeable format into something that can + be used with GDI metafile functions */ + hMF = GetPlaceableMetaFile(fh); + + /* close the file */ + close(fh); + } + + if (!hMF) + return CD_ERROR; + + size = GetMetaFileBitsEx(hMF, 0, NULL); + + buffer = malloc(size); + + GetMetaFileBitsEx(hMF, size, buffer); + + hEMF = SetWinMetaFileBits(size, buffer, NULL, NULL); + + GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh); + + /* when converted from WMF, only rclBounds is available */ + wmf_bottom = emh.rclBounds.bottom; + wmf_left = emh.rclBounds.left; + wmf_top = emh.rclBounds.top; + wmf_right = emh.rclBounds.right; + + if ((xmax-xmin+1)>1 && (ymax-ymin+1)>1) /* always update wmf_rect when scaling */ + EnumEnhMetaFile(NULL, hEMF, CalcSizeEMFEnumProc, NULL, NULL); + + if ((wmf_bottom-wmf_top)>1 && + (wmf_right-wmf_left)>1 && + (xmax-xmin+1)>1 && + (ymax-ymin+1)>1) + { + wmf_yfactor = ((double)(ymax-ymin+1)) / (double)(wmf_top-wmf_bottom); /* negative because top-down orientation */ + wmf_xfactor = ((double)(xmax-xmin+1)) / (double)(wmf_right-wmf_left); + wmf_xmin = xmin; + wmf_ymin = ymin; + } + else + { + wmf_yfactor = -1; /* negative because top-down orientation */ + wmf_xfactor = 1; + wmf_xmin = 0; + wmf_ymin = 0; + } + + free(buffer); + + if (cdsizecbWMF && dwIsAldus == ALDUSKEY) + { + int err; + err = cdsizecbWMF(canvas, wmf_right-wmf_left, wmf_bottom-wmf_top, 0, 0); + if (err) + { + DeleteEnhMetaFile (hEMF); + return CD_ERROR; + } + } + + EnumEnhMetaFile(NULL, hEMF, EMFEnumProc, canvas, NULL); + + DeleteEnhMetaFile (hEMF); + + DeleteMetaFile (hMF); + + return CD_OK; +} + + +static cdSizeCB cdsizecbEMF = NULL; + +int cdregistercallbackEMF(int cb, cdCallback func) +{ + switch (cb) + { + case CD_SIZECB: + cdsizecbEMF = (cdSizeCB)func; + return CD_OK; + } + + return CD_ERROR; +} + + +int cdplayEMF(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + char* filename = (char*)data; + HENHMETAFILE hEMF; + ENHMETAHEADER emh; + double xres, yres; + + hEMF = GetEnhMetaFile(filename); + + GetEnhMetaFileHeader(hEMF, sizeof(ENHMETAHEADER), &emh); + + /* this is obtained from the hdcRef of CreateEnhMetaFile */ + xres = ((double)emh.szlDevice.cx) / emh.szlMillimeters.cx; + yres = ((double)emh.szlDevice.cy) / emh.szlMillimeters.cy; + + /* this is the same as used in RECT of CreateEnhMetaFile */ + wmf_bottom = (int)((emh.rclFrame.bottom * yres) / 100); + wmf_left = (int)((emh.rclFrame.left * xres) / 100); + wmf_top = (int)((emh.rclFrame.top * yres) / 100); + wmf_right = (int)((emh.rclFrame.right * xres) / 100); + + if ((xmax-xmin+1)>1 && (ymax-ymin+1)>1) /* always update wmf_rect when scaling */ + EnumEnhMetaFile(NULL, hEMF, CalcSizeEMFEnumProc, NULL, NULL); + + if ((wmf_bottom-wmf_top)>1 && + (wmf_right-wmf_left)>1 && + (xmax-xmin+1)>1 && + (ymax-ymin+1)>1) + { + wmf_yfactor = ((double)(ymax-ymin+1)) / (double)(wmf_top-wmf_bottom); /* negative because top-down orientation */ + wmf_xfactor = ((double)(xmax-xmin+1)) / (double)(wmf_right-wmf_left); + wmf_xmin = xmin; + wmf_ymin = ymin; + } + else + { + wmf_yfactor = -1; /* negative because top-down orientation */ + wmf_xfactor = 1; + wmf_xmin = 0; + wmf_ymin = 0; + } + + if (cdsizecbEMF) + { + int err; + err = cdsizecbEMF(canvas, wmf_right-wmf_left, wmf_bottom-wmf_top, 0, 0); + if (err) + { + DeleteEnhMetaFile (hEMF); + return CD_ERROR; + } + } + + EnumEnhMetaFile(NULL, hEMF, EMFEnumProc, canvas, NULL); + + DeleteEnhMetaFile (hEMF); + + return CD_OK; +} + +/* +%F Calculo do CheckSum. +*/ +static WORD sAPMChecksum(APMFILEHEADER* papm) +{ + WORD* pw = (WORD*)papm; + WORD wSum = 0; + int i; + + /* The checksum in a Placeable Metafile header is calculated */ + /* by XOR-ing the first 10 words of the header. */ + + for (i = 0; i < 10; i++) + wSum ^= *pw++; + + return wSum; +} + + + +/* +Aldus placeable metafile format + + DWORD key; + HANDLE hmf; + RECT bbox; + WORD inch; + DWORD reserved; + WORD checksum; + char metafileData[]; + + These fields have the following meanings: + + Field Definition + + key Binary key that uniquely identifies this + file type. This must be 0x9AC6CDD7L. + + hmf Unused; must be zero. + + bbox The coordinates of a rectangle that tightly + bounds the picture. These coordinates are in + metafile units as defined below. + + inch The number of metafile units to the inch. To + avoid numeric overflow in PageMaker, this value + should be less than 1440. + + reserved A reserved double word. Must be zero. + + checksum A checksum of the 10 words that precede it, + calculated by XORing zero with these 10 words + and putting the result in the checksum field. + + metafileData The actual content of the Windows metafile + retrieved by copying the data returned by + GetMetafileBits to the file. The number of + bytes should be equal to the MS-DOS file length + minus 22. The content of a PageMaker placeable + metafile cannot currently exceed 64K (this may + have changed in 4.0). +*/ + +/* +%F Cria um APM em arquivo a partir de um WMF em memoria. +*/ +void wmfMakePlaceableMetafile(HMETAFILE hmf, const char* filename, int w, int h) +{ + int fh, nSize; + LPSTR lpData; + APMFILEHEADER APMHeader; + + fh = open(filename, O_CREAT | O_BINARY | O_WRONLY); + + APMHeader.key1 = 0xCDD7; + APMHeader.key2 = 0x9AC6; + APMHeader.hmf = 0; + APMHeader.bleft = 0; + APMHeader.btop = 0; + APMHeader.bright = (short)w; + APMHeader.bbottom = (short)h; + APMHeader.inch = 100; /* this number works fine in Word, etc.. */ + APMHeader.reserved1 = 0; + APMHeader.reserved2 = 0; + APMHeader.checksum = sAPMChecksum(&APMHeader); + + write(fh, (LPSTR)&APMHeader, sizeof(APMFILEHEADER)); + + nSize = GetMetaFileBitsEx(hmf, 0, NULL); + lpData = malloc(nSize); + GetMetaFileBitsEx(hmf, nSize, lpData); + + write(fh, lpData, nSize); + free(lpData); + + close(fh); +} + +void wmfWritePlacebleFile(HANDLE hFile, unsigned char* buffer, DWORD dwSize, LONG mm, LONG xExt, LONG yExt) +{ + DWORD nBytesWrite; + APMFILEHEADER APMHeader; + int w = xExt, h = yExt; + + if (mm == MM_ANISOTROPIC || mm == MM_ISOTROPIC) + { + int res = 30; + w = xExt / res; + h = yExt / res; + } + + APMHeader.key1 = 0xCDD7; + APMHeader.key2 = 0x9AC6; + APMHeader.hmf = 0; + APMHeader.bleft = 0; + APMHeader.btop = 0; + APMHeader.bright = (short)w; + APMHeader.bbottom = (short)h; + APMHeader.inch = 100; /* this number works fine in Word, etc.. */ + APMHeader.reserved1 = 0; + APMHeader.reserved2 = 0; + APMHeader.checksum = sAPMChecksum(&APMHeader); + + WriteFile(hFile, (LPSTR)&APMHeader, sizeof(APMFILEHEADER), &nBytesWrite, NULL); + WriteFile(hFile, buffer, dwSize, &nBytesWrite, NULL); +} + diff --git a/cd/src/x11/cdx11.c b/cd/src/x11/cdx11.c new file mode 100755 index 0000000..4f427e3 --- /dev/null +++ b/cd/src/x11/cdx11.c @@ -0,0 +1,2446 @@ +/** \file + * \brief X-Windows Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include "cdx11.h" +#include "xvertex.h" + +#include + +unsigned long (*cdxGetPixel)(cdCtxCanvas *ctxcanvas, unsigned long rgb); /* acesso a tabela de cores */ +void (*cdxGetRGB)(cdCtxCanvas *ctxcanvas, unsigned long pixel, + unsigned char* red, + unsigned char* green, + unsigned char* blue); /* acesso a tabela de cores */ +static XGCValues gcval; + +static int cdxDirectColorTable[256]; /* used with directColor visuals */ + +#define NUM_HATCHES 6 +#define HATCH_WIDTH 8 +#define HATCH_HEIGHT 8 +/* +** 6 padroes pre-definidos a serem acessados atraves de cdHatch( + CD_HORIZONTAL | CD_VERTICAL | CD_FDIAGONAL | CD_BDIAGONAL | + CD_CROSS | CD_DIAGCROSS) + +*/ +static char hatches[NUM_HATCHES][8] = { + {0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00}, /* HORIZONTAL */ + {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22}, /* VERTICAL */ + {0x08,0x10,0x20,0x40,0x80,0x01,0x02,0x04}, /* FDIAGONAL */ + {0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20}, /* BDIAGONAL */ + {0x22,0x22,0xFF,0x22,0x22,0x22,0xFF,0x22}, /* CROSS */ + {0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24} /* DIAGCROSS */ +}; + +/******************************************************/ + +static int cdxErrorHandler(Display* dpy, XErrorEvent *err) +{ + char msg[80]; + + /* Se for erro de BadMatch em XGetImage, tudo bem */ + if (err->request_code==X_GetImage && err->error_code==BadMatch) + return 0; + + /* Se for erro de BadAcess em XFreeColors, tudo bem */ + if (err->request_code==X_FreeColors && err->error_code==BadAccess) + return 0; + + XGetErrorText(dpy, err->error_code, msg, 80 ); + fprintf(stderr,"CanvasDraw: Xlib request %d: %s\n", err->request_code, msg); + + return 0; +} + +static void update_colors(cdCtxCanvas *ctxcanvas) +{ + XQueryColors(ctxcanvas->dpy, ctxcanvas->colormap, ctxcanvas->color_table, ctxcanvas->num_colors); +} + +static int find_color(cdCtxCanvas *ctxcanvas, XColor* xc1) +{ + int pos = 0, i; + unsigned long min_dist = ULONG_MAX, this_dist; + int dr, dg, db; + XColor* xc2; + + for (i=0; inum_colors; i++) + { + xc2 = &(ctxcanvas->color_table[i]); + + dr = (xc1->red - xc2->red) / 850; /* 0.30 / 255 */ + dg = (xc1->green - xc2->green) / 432; /* 0.59 / 255 */ + db = (xc1->blue - xc2->blue) / 2318; /* 0.11 / 255 */ + + this_dist = dr*dr + dg*dg + db*db; + + if (this_dist < min_dist) + { + min_dist = this_dist; + pos = i; + } + } + + return pos; +} + +/* Busca o RGB mais proximo na tabela de cores */ +static unsigned long nearest_rgb(cdCtxCanvas *ctxcanvas, XColor* xc) +{ + static int nearest_try = 0; + + int pos = find_color(ctxcanvas, xc); + + /* verifico se a cor ainda esta alocada */ + /* Try to allocate the closest match color. + This should fail only if the cell is read/write. + Otherwise, we're incrementing the cell's reference count. + (comentario extraido da biblioteca Mesa) */ + if (!XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &(ctxcanvas->color_table[pos]))) + { + /* nao esta, preciso atualizar a tabela e procurar novamente */ + /* isto acontece porque a cor encontrada pode ter sido de uma aplicacao que nao existe mais */ + /* uma vez atualizada, o problema nao ocorrera' na nova procura */ + /* ou a celula e' read write */ + + if (nearest_try == 1) + { + nearest_try = 0; + return ctxcanvas->color_table[pos].pixel; + } + + /* o que e' mais lento? + Dar um query colors em todo o nearest, --> Isso deve ser mais lento + ou fazer a busca acima antes e arriscar uma repeticao? */ + + update_colors(ctxcanvas); + + nearest_try = 1; /* garante que so' vai tentar isso uma vez */ + return nearest_rgb(ctxcanvas, xc); + } + + return ctxcanvas->color_table[pos].pixel; +} + +/* Funcao get_pixel usando tabela de conversao. \ + Usada quando nao estamos em TrueColor. */ +static unsigned long not_truecolor_get_pixel(cdCtxCanvas *ctxcanvas, unsigned long rgb) +{ + unsigned long pixel; + XColor xc; + xc.red = cdCOLOR8TO16(cdRed(rgb)); + xc.green = cdCOLOR8TO16(cdGreen(rgb)); + xc.blue = cdCOLOR8TO16(cdBlue(rgb)); + xc.flags = DoRed | DoGreen | DoBlue; + + /* verificamos se a nova cor ja' esta' disponivel */ + if (!XAllocColor(ctxcanvas->dpy, ctxcanvas->colormap, &xc)) + { + /* nao estava disponivel, procuro pela mais proxima na tabela de cores */ + pixel = nearest_rgb(ctxcanvas, &xc); + } + else + { + /* ja' estava disponivel */ + /* atualizo a tabela de cores */ + ctxcanvas->color_table[xc.pixel] = xc; + pixel = xc.pixel; + } + + return pixel; +} + +/* +%F Funcao usando tabela de conversao. \ + Usada quando nao estamos em TrueColor. +*/ +static void not_truecolor_get_rgb(cdCtxCanvas *ctxcanvas, unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue) +{ + XColor xc; + xc.pixel = pixel; + XQueryColor(ctxcanvas->dpy, ctxcanvas->colormap, &xc); + *red = cdCOLOR16TO8(xc.red); + *green = cdCOLOR16TO8(xc.green); + *blue = cdCOLOR16TO8(xc.blue); +} + +/* +%F Funcao get_rgb usada quando estamos em TrueColor. +*/ +static void truecolor_get_rgb(cdCtxCanvas *ctxcanvas, unsigned long pixel, unsigned char* red, unsigned char* green, unsigned char* blue) +{ + unsigned long r = pixel & ctxcanvas->vis->red_mask; + unsigned long g = pixel & ctxcanvas->vis->green_mask; + unsigned long b = pixel & ctxcanvas->vis->blue_mask; + if (ctxcanvas->rshift<0) r = r >> (-ctxcanvas->rshift); + else r = r << ctxcanvas->rshift; + if (ctxcanvas->gshift<0) g = g >> (-ctxcanvas->gshift); + else g = g << ctxcanvas->gshift; + if (ctxcanvas->bshift<0) b = b >> (-ctxcanvas->bshift); + else b = b << ctxcanvas->bshift; + *red = cdCOLOR16TO8(r); + *green = cdCOLOR16TO8(g); + *blue = cdCOLOR16TO8(b); +} + +/* +%F Funcao get_pixel usada quando estamos em TrueColor. +*/ +static unsigned long truecolor_get_pixel(cdCtxCanvas *ctxcanvas, unsigned long rgb) +{ + unsigned long r = cdCOLOR8TO16(cdRed(rgb)); + unsigned long g = cdCOLOR8TO16(cdGreen(rgb)); + unsigned long b = cdCOLOR8TO16(cdBlue(rgb)); + + if (ctxcanvas->rshift<0) + r = r << (-ctxcanvas->rshift); + else + r = r >> ctxcanvas->rshift; + + if (ctxcanvas->gshift<0) + g = g << (-ctxcanvas->gshift); + else + g = g >> ctxcanvas->gshift; + + if (ctxcanvas->bshift<0) + b = b << (-ctxcanvas->bshift); + else + b = b >> ctxcanvas->bshift; + + r = r & ctxcanvas->vis->red_mask; + g = g & ctxcanvas->vis->green_mask; + b = b & ctxcanvas->vis->blue_mask; + + return r | g | b; +} + +static int highbit(unsigned long ul) +{ +/* returns position of highest set bit in 'ul' as an integer (0-31), + or -1 if none */ + int i; unsigned long hb; + + hb = 0x80; hb = hb << 24; /* hb = 0x80000000UL */ + for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1); + return i; +} + +static void makeDirectCmap(cdCtxCanvas *ctxcanvas, Colormap cmap) +{ + int i, cmaplen, numgot; + unsigned char origgot[256]; + XColor c; + unsigned long rmask, gmask, bmask; + int rshift, gshift, bshift; + + rmask = ctxcanvas->vis->red_mask; + gmask = ctxcanvas->vis->green_mask; + bmask = ctxcanvas->vis->blue_mask; + + rshift = highbit(rmask) - 15; + gshift = highbit(gmask) - 15; + bshift = highbit(bmask) - 15; + + if (rshift<0) rmask = rmask << (-rshift); + else rmask = rmask >> rshift; + + if (gshift<0) gmask = gmask << (-gshift); + else gmask = gmask >> gshift; + + if (bshift<0) bmask = bmask << (-bshift); + else bmask = bmask >> bshift; + + cmaplen = ctxcanvas->vis->map_entries; + if (cmaplen>256) cmaplen=256; + + /* try to alloc a 'cmaplen' long grayscale colormap. May not get all + entries for whatever reason. Build table 'cdxDirectColorTable[]' that + maps range [0..(cmaplen-1)] into set of colors we did get */ + + for (i=0; i<256; i++) { origgot[i] = 0; cdxDirectColorTable[i] = i; } + + for (i=numgot=0; idpy, cmap, &c)) + { + origgot[i] = 1; + numgot++; + } + } + + if (numgot == 0) + return; + + /* cdxDirectColorTable may or may not have holes in it. */ + for (i=0; i= 0 && !origgot[i-numbak]) numbak++; + while ((i + numfwd) < cmaplen && !origgot[i+numfwd]) numfwd++; + + if (i-numbak<0 || !origgot[i-numbak]) numbak = 999; + if (i+numfwd>=cmaplen || !origgot[i+numfwd]) numfwd = 999; + + if (numbakcanvas->bpp <= 8) + { + unsigned long pixels[256]; + int i; + + /* libera todas as cores usadas na palette */ + for(i = 0; i < ctxcanvas->num_colors; i++) + pixels[i] = ctxcanvas->color_table[i].pixel; + + if (ctxcanvas->colormap != DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr)) + XFreeColormap(ctxcanvas->dpy, ctxcanvas->colormap); + } + + if (ctxcanvas->xidata) free(ctxcanvas->xidata); + if (ctxcanvas->font) XFreeFont(ctxcanvas->dpy, ctxcanvas->font); + if (ctxcanvas->last_hatch) XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_hatch); + if (ctxcanvas->clip_polygon) XFreePixmap(ctxcanvas->dpy, ctxcanvas->clip_polygon); + + if (ctxcanvas->new_region) + { + XFreeGC(ctxcanvas->dpy, ctxcanvas->region_aux_gc); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->region_aux); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->new_region); + } + + if (ctxcanvas->last_pattern) + { + XFreeGC(ctxcanvas->dpy, ctxcanvas->last_pattern_gc); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_pattern); + } + + if (ctxcanvas->last_stipple) + { + XFreeGC(ctxcanvas->dpy, ctxcanvas->last_stipple_gc); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_stipple); + } + + XFreeGC(ctxcanvas->dpy, ctxcanvas->gc); + + free(ctxcanvas); +} + +/******************************************************/ + +static void cdflush(cdCtxCanvas *ctxcanvas) +{ + XFlush(ctxcanvas->dpy); +} + +/******************************************************/ + +static Pixmap build_clip_polygon(cdCtxCanvas *ctxcanvas, XPoint* pnt, int n) +{ + Pixmap pix = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1); + GC gc = XCreateGC(ctxcanvas->dpy, pix, 0, NULL); + + XSetForeground(ctxcanvas->dpy, gc, 0); + XFillRectangle(ctxcanvas->dpy, pix, gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + + XSetForeground(ctxcanvas->dpy, gc, 1); + XSetFillRule(ctxcanvas->dpy, gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule); + XFillPolygon(ctxcanvas->dpy, pix, gc, pnt, n, Complex, CoordModeOrigin); + + XFreeGC(ctxcanvas->dpy, gc); + return pix; +} + +static void xsetclip_area(cdCtxCanvas *ctxcanvas) +{ + cdRect* clip_rect = &ctxcanvas->canvas->clip_rect; + if (ctxcanvas->canvas->use_matrix) + { + cdPoint poly[4]; + poly[0].x = clip_rect->xmin; poly[0].y = clip_rect->ymin; + poly[1].x = clip_rect->xmin; poly[1].y = clip_rect->ymax; + poly[2].x = clip_rect->xmax; poly[2].y = clip_rect->ymax; + poly[3].x = clip_rect->xmax; poly[3].y = clip_rect->ymin; + ctxcanvas->canvas->cxPoly(ctxcanvas, CD_CLIP, poly, 4); + } + else + { + XRectangle rect; + rect.x = (short)clip_rect->xmin; + rect.y = (short)clip_rect->ymin; + rect.width = (unsigned short)(clip_rect->xmax - clip_rect->xmin + 1); + rect.height = (unsigned short)(clip_rect->ymax - clip_rect->ymin + 1); + XSetClipRectangles(ctxcanvas->dpy, ctxcanvas->gc, 0, 0, &rect, 1, Unsorted); + } +} + +int cdxClip(cdCtxCanvas *ctxcanvas, int clip_mode) +{ + switch (clip_mode) + { + case CD_CLIPOFF: + XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, None); + break; + case CD_CLIPAREA: + xsetclip_area(ctxcanvas); + break; + case CD_CLIPPOLYGON: + if (ctxcanvas->clip_polygon) + XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->clip_polygon); + break; + case CD_CLIPREGION: + if (ctxcanvas->new_region) + XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->new_region); + break; + } + return clip_mode; +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_rect.xmin = xmin; + ctxcanvas->canvas->clip_rect.ymin = ymin; + ctxcanvas->canvas->clip_rect.xmax = xmax; + ctxcanvas->canvas->clip_rect.ymax = ymax; + cdxClip(ctxcanvas, CD_CLIPAREA); + } +} + +static void cdnewregion(cdCtxCanvas *ctxcanvas) +{ + if (ctxcanvas->new_region) + { + XFreeGC(ctxcanvas->dpy, ctxcanvas->region_aux_gc); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->region_aux); + XFreePixmap(ctxcanvas->dpy, ctxcanvas->new_region); + } + + ctxcanvas->new_region = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1); + + { + GC gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->new_region, 0, NULL); + XSetForeground(ctxcanvas->dpy, gc, 0); + XFillRectangle(ctxcanvas->dpy, ctxcanvas->new_region, gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + XFreeGC(ctxcanvas->dpy, gc); + } + + ctxcanvas->region_aux = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1); + ctxcanvas->region_aux_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->region_aux, 0, NULL); + XSetBackground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 0); +} + +static int cdispointinregion(cdCtxCanvas *ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_region) + return 0; + + if (x >= 0 && y >= 0 && x < ctxcanvas->canvas->w && y < ctxcanvas->canvas->h) + { + long p; + XImage* img = XGetImage(ctxcanvas->dpy, ctxcanvas->new_region, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1, XYPixmap); + p = XGetPixel(img, x, y); + XDestroyImage(img); + + if (p) return 1; + } + + return 0; +} + +static void cdgetregionbox(cdCtxCanvas *ctxcanvas, int *xmin, int *xmax, int *ymin, int *ymax) +{ + if (!ctxcanvas->new_region) + return; + + *xmin = ctxcanvas->canvas->w-1; + *xmax = 0; + *ymin = ctxcanvas->canvas->h-1; + *ymax = 0; + + { + int x, y; + long p; + XImage* img = XGetImage(ctxcanvas->dpy, ctxcanvas->new_region, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 1, XYPixmap); + + for (y = 0; y < ctxcanvas->canvas->h; y++) + { + for (x = 0; x < ctxcanvas->canvas->w; x++) + { + p = XGetPixel(img, x, y); + + if (p) + { + if (x < *xmin) *xmin = x; + if (x > *xmax) *xmax = x; + if (y < *ymin) *ymin = y; + if (y > *ymax) *ymax = y; + break; + } + } + + if (x != ctxcanvas->canvas->w-1) + { + for (x = ctxcanvas->canvas->w-1; x >= 0; x--) + { + p = XGetPixel(img, x, y); + + if (p) + { + if (x < *xmin) *xmin = x; + if (x > *xmax) *xmax = x; + if (y < *ymin) *ymin = y; + if (y > *ymax) *ymax = y; + break; + } + } + } + } + + XDestroyImage(img); + } +} + +static void sPrepareRegion(cdCtxCanvas *ctxcanvas) +{ + if (!ctxcanvas->new_region) + return; + + XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXcopy); + XSetForeground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 0); + XFillRectangle(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + XSetForeground(ctxcanvas->dpy, ctxcanvas->region_aux_gc, 1); +} + +static void sCombineRegion(cdCtxCanvas *ctxcanvas) +{ + switch(ctxcanvas->canvas->combine_mode) + { + case CD_UNION: + XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXor); + break; + case CD_INTERSECT: + XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXand); + break; + case CD_DIFFERENCE: + XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXandInverted); + break; + case CD_NOTINTERSECT: + XSetFunction(ctxcanvas->dpy, ctxcanvas->region_aux_gc, GXxor); + break; + } + + XCopyArea(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->new_region, ctxcanvas->region_aux_gc, + 0, 0, + ctxcanvas->canvas->w, ctxcanvas->canvas->h, + 0, 0); +} + +static void cdoffsetregion(cdCtxCanvas *ctxcanvas, int x, int y) +{ + if (!ctxcanvas->new_region) + return; + + sPrepareRegion(ctxcanvas); + + XCopyArea(ctxcanvas->dpy, ctxcanvas->new_region, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, + 0, 0, + ctxcanvas->canvas->w-x, ctxcanvas->canvas->h-y, + x, y); + + XCopyArea(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->new_region, ctxcanvas->region_aux_gc, + 0, 0, + ctxcanvas->canvas->w, ctxcanvas->canvas->h, + 0, 0); +} + +/******************************************************/ + +static int cdwritemode(cdCtxCanvas *ctxcanvas, int write_mode) +{ + switch (write_mode) + { + case CD_REPLACE: + XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXcopy); + break; + case CD_XOR: + XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXxor); + break; + case CD_NOT_XOR: + XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXequiv); + break; + } + + return write_mode; +} + +static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style) +{ + int sty = FillSolid; + + switch (style) + { + case CD_SOLID: + sty = FillSolid; + break; + case CD_HATCH : + if (!ctxcanvas->last_hatch) + return ctxcanvas->canvas->interior_style; + + XSetStipple(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_hatch); + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + sty = FillOpaqueStippled; + else + sty = FillStippled; + break; + case CD_STIPPLE: + XSetStipple(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_stipple); + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + sty = FillOpaqueStippled; + else + sty = FillStippled; + break; + case CD_PATTERN: + XSetTile(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->last_pattern); + sty = FillTiled; + break; + } + + XSetFillStyle(ctxcanvas->dpy, ctxcanvas->gc, sty); + + return style; +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int hatch_style) +{ + if (ctxcanvas->last_hatch) + XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_hatch); + + ctxcanvas->last_hatch = XCreatePixmapFromBitmapData(ctxcanvas->dpy, + ctxcanvas->wnd, hatches[hatch_style], + HATCH_WIDTH, HATCH_HEIGHT, 1, 0, 1); + + cdinteriorstyle(ctxcanvas, CD_HATCH); + + return hatch_style; +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *data) +{ + int x, y; + + if (ctxcanvas->last_stipple == 0 || (ctxcanvas->last_stipple_w != w || ctxcanvas->last_stipple_h != h)) + { + if (ctxcanvas->last_stipple != 0) + { + XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_stipple); + XFreeGC(ctxcanvas->dpy, ctxcanvas->last_stipple_gc); + } + + ctxcanvas->last_stipple = XCreatePixmap(ctxcanvas->dpy,ctxcanvas->wnd,w,h,1); + if (!ctxcanvas->last_stipple) return; + ctxcanvas->last_stipple_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->last_stipple, 0, 0); + ctxcanvas->last_stipple_w = w; + ctxcanvas->last_stipple_h = h; + } + + for (y=0; ydpy, ctxcanvas->last_stipple_gc, data[y*w+x]? 1: 0); + XDrawPoint(ctxcanvas->dpy, ctxcanvas->last_stipple, ctxcanvas->last_stipple_gc, x, h-y-1); + } + } + + cdinteriorstyle(ctxcanvas, CD_STIPPLE); +} + +static int find_match(unsigned long* palette, int pal_size, unsigned long color, unsigned char *match) +{ + int i; + + for (i=0;ilast_pattern == 0 || (ctxcanvas->last_pattern_w != w || ctxcanvas->last_pattern_h != h)) + { + if (ctxcanvas->last_pattern != 0) + { + XFreePixmap(ctxcanvas->dpy, ctxcanvas->last_pattern); + XFreeGC(ctxcanvas->dpy, ctxcanvas->last_pattern_gc); + } + + ctxcanvas->last_pattern = XCreatePixmap(ctxcanvas->dpy,ctxcanvas->wnd,w,h,ctxcanvas->depth); + if (!ctxcanvas->last_pattern) return; + ctxcanvas->last_pattern_gc = XCreateGC(ctxcanvas->dpy, ctxcanvas->last_pattern, 0, 0); + ctxcanvas->last_pattern_w = w; + ctxcanvas->last_pattern_h = h; + } + + pixels = (unsigned long*)malloc(w*h*sizeof(long)); + + if (ctxcanvas->canvas->bpp <= 8) + { + long int match_table[256]; /* X colors */ + unsigned long palette[256]; /* CD colors */ + unsigned char *index = (unsigned char*)malloc(size), match; + int pal_size = 1; + palette[0] = colors[0]; + + /* encontra as n primeiras cores diferentes da imagem (ate 256) */ + for(i=0;idpy, ctxcanvas->last_pattern_gc, pixels[y*w+x]); + XDrawPoint(ctxcanvas->dpy, ctxcanvas->last_pattern, ctxcanvas->last_pattern_gc, x, h-y-1); + } + } + + cdinteriorstyle(ctxcanvas, CD_PATTERN); + + free(pixels); +} + +static int cdlinestyle(cdCtxCanvas *ctxcanvas, int style) +{ + switch (style) + { + case CD_CONTINUOUS: + gcval.line_style = LineSolid; + break; + case CD_DASHED: + case CD_DOTTED: + case CD_DASH_DOT: + case CD_DASH_DOT_DOT: + { + static struct { + int size; + char list[6]; + } dashes[4] = { + { 2, { 6, 2 } }, + { 2, { 2, 2 } }, + { 4, { 6, 2, 2, 2 } }, + { 6, { 6, 2, 2, 2, 2, 2 } } + }; + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + gcval.line_style = LineDoubleDash; + else + gcval.line_style = LineOnOffDash; + + XSetDashes(ctxcanvas->dpy, ctxcanvas->gc, 0, dashes[style-CD_DASHED].list, + dashes[style-CD_DASHED].size); + break; + } + case CD_CUSTOM: + { + int i; + char* dash_style = (char*)malloc(ctxcanvas->canvas->line_dashes_count); + for (i = 0; i < ctxcanvas->canvas->line_dashes_count; i++) + dash_style[i] = (char)ctxcanvas->canvas->line_dashes[i]; + + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + gcval.line_style = LineDoubleDash; + else + gcval.line_style = LineOnOffDash; + + XSetDashes(ctxcanvas->dpy, ctxcanvas->gc, 0, dash_style, + ctxcanvas->canvas->line_dashes_count); + free(dash_style); + break; + } + } + XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCLineStyle, &gcval); + return style; +} + +static int cdlinewidth(cdCtxCanvas *ctxcanvas, int width) +{ + if (width == 1) + gcval.line_width = 0; + else + gcval.line_width = width; + + XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCLineWidth, &gcval); + + return width; +} + +static int cdlinecap(cdCtxCanvas *ctxcanvas, int cap) +{ + int cd2x_cap[] = {CapButt, CapProjecting, CapRound}; + + gcval.cap_style = cd2x_cap[cap]; + XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCCapStyle, &gcval); + + return cap; +} + +static int cdlinejoin(cdCtxCanvas *ctxcanvas, int join) +{ + int cd2x_join[] = {JoinMiter, JoinBevel, JoinRound}; + + gcval.join_style = cd2x_join[join]; + XChangeGC(ctxcanvas->dpy, ctxcanvas->gc, GCJoinStyle, &gcval); + + return join; +} + +static int cdbackopacity(cdCtxCanvas *ctxcanvas, int opaque) +{ + ctxcanvas->canvas->back_opacity = opaque; + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); + cdlinestyle(ctxcanvas, ctxcanvas->canvas->line_style); + return opaque; +} + +static int cdxGetFontSize(char* font_name) +{ + int i = 0; + while (i < 8) + { + font_name = strchr(font_name, '-')+1; + i++; + } + + *(strchr(font_name, '-')) = 0; + return atoi(font_name); +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + XFontStruct *font; + char **font_names_list; + char font_name[1024]; + char* foundry = "*"; + int i, num_fonts, font_size, near_size, change_italic = 0; + + /* no underline or strikeout support */ + + static char * type[] = + { + "medium-r", /* CD_PLAIN */ + "bold-r", /* CD_BOLD */ + "medium-i", /* CD_ITALIC */ + "bold-i" /* CD_BOLD_ITALIC */ + }; + + if (cdStrEqualNoCase(type_face, "System")) + type_face = "fixed"; + else if (cdStrEqualNoCase(type_face, "Monospace") || cdStrEqualNoCase(type_face, "Courier New")) + type_face = "courier"; + else if (cdStrEqualNoCase(type_face, "Serif") || cdStrEqualNoCase(type_face, "Times New Roman")) + type_face = "times"; + else if (cdStrEqualNoCase(type_face, "Sans") || cdStrEqualNoCase(type_face, "Arial")) + type_face = "helvetica"; + + if (cdStrEqualNoCase(type_face, "Fixed")) + foundry = "misc"; + + sprintf(font_name,"-%s-%s-%s-*-*-*-*-*-*-*-*-*-*", foundry, type_face, type[style&3]); + + font_names_list = XListFonts(ctxcanvas->dpy, font_name, 32767, &num_fonts); + if (!num_fonts) + { + /* try changing 'i' to 'o', for italic */ + if (style&CD_ITALIC) + { + change_italic = 1; + strstr(font_name, "-i-")[1] = 'o'; + font_names_list = XListFonts(ctxcanvas->dpy, font_name, 32767, &num_fonts); + } + + if (!num_fonts) + return 0; + } + + size = cdGetFontSizePoints(ctxcanvas->canvas, size); + + size *= 10; /* convert to deci-points */ + + near_size = -1000; + for (i=0; idpy, font_name); + if (!font) + return 0; + + if (ctxcanvas->font) + XFreeFont(ctxcanvas->dpy, ctxcanvas->font); + + ctxcanvas->font = font; + XSetFont(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->font->fid); + return 1; +} + +static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* nativefont) +{ + int size = 12, style = CD_PLAIN; + char type_face[1024]; + + if (nativefont[0] == '-') + { + XFontStruct *font = XLoadQueryFont(ctxcanvas->dpy, nativefont); + if (!font) + return 0; + + if (!cdParseXWinFont(nativefont, type_face, &style, &size)) + { + XFreeFont(ctxcanvas->dpy, font); + return 0; + } + + if (ctxcanvas->font) XFreeFont(ctxcanvas->dpy, ctxcanvas->font); + ctxcanvas->font = font; + XSetFont(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->font->fid); + } + else + { + if (!cdParsePangoFont(nativefont, type_face, &style, &size)) + return 0; + + if (!cdfont(ctxcanvas, type_face, style, size)) + return 0; + } + + /* update cdfont parameters */ + ctxcanvas->canvas->font_style = style; + ctxcanvas->canvas->font_size = size; + strcpy(ctxcanvas->canvas->font_type_face, type_face); + + return 1; +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + if (!ctxcanvas->font) return; + if (max_width) *max_width = ctxcanvas->font->max_bounds.width; + if (height) *height = ctxcanvas->font->ascent + ctxcanvas->font->descent; + if (ascent) *ascent = ctxcanvas->font->ascent; + if (descent) *descent = ctxcanvas->font->descent; +} + +static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color) +{ + XSetBackground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, color)); + return color; +} + +static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + ctxcanvas->fg = cdxGetPixel(ctxcanvas, color); + XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->fg); + return color; +} + +static void cdpalette(cdCtxCanvas *ctxcanvas, int n, const long int *palette, int mode) +{ + unsigned long pixels[256]; + int i; + + for(i = 0; i < ctxcanvas->num_colors; i++) + pixels[i] = ctxcanvas->color_table[i].pixel; + + XFreeColors(ctxcanvas->dpy, ctxcanvas->colormap, pixels, ctxcanvas->num_colors, 0); + + if (mode == CD_FORCE) + { + XColor xc; + int tokeep; + + /* se antes era POLITE aloca palette propria */ + if (ctxcanvas->colormap == DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr)) + ctxcanvas->colormap = XCreateColormap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->vis, AllocNone); + + /* se for FORCE ira' alocar todas as cores, + mas se o numero de cores desejado e' menor que o maximo + entao uso a diferenca para preservar as primeiras cores alocadas no colormap default. */ + tokeep = ctxcanvas->num_colors - n; + if (tokeep) + { + for (i=0; icolor_table[i].pixel=i; + + XQueryColors(ctxcanvas->dpy, DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr), ctxcanvas->color_table, tokeep); + + /* reservo estas cores para o CD tambem */ + for (i=0; idpy, ctxcanvas->colormap, &(ctxcanvas->color_table[i])); + } + + /*aloco todas as cores da palette para o CD */ + for (i=0; idpy, ctxcanvas->colormap, &xc); + } + + /* atualizo toda a tabela de cores */ + XSetWindowColormap(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->colormap); + update_colors(ctxcanvas); + } + else + { + /* se antes era FORCE, remove palette propria */ + if (ctxcanvas->colormap != DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr)) + { + XFreeColormap(ctxcanvas->dpy, ctxcanvas->colormap); + ctxcanvas->colormap = DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr); + } + + /* atualizo a tabela antes de acrescentar novas cores afinal liberamos todas as que podiamos antes disso */ + update_colors(ctxcanvas); + + /* se for POLITE apenas tento alocar todas as cores da palette */ + for (i=0; icanvas->interior_style == CD_SOLID) + return; + + if (set) + XSetFillStyle(ctxcanvas->dpy, ctxcanvas->gc, FillSolid); + else + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); +} + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + cdxCheckSolidStyle(ctxcanvas, 1); + XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, ctxcanvas->canvas->background)); + XFillRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); + XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, ctxcanvas->canvas->foreground)); + cdxCheckSolidStyle(ctxcanvas, 0); +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdMatrixTransformPoint(ctxcanvas->xmatrix, x1, y1, &x1, &y1); + cdMatrixTransformPoint(ctxcanvas->xmatrix, x2, y2, &x2, &y2); + } + + cdxCheckSolidStyle(ctxcanvas, 1); + XDrawLine(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x1, y1, x2, y2); + cdxCheckSolidStyle(ctxcanvas, 0); +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdarcSIM(ctxcanvas, xc, yc, w, h, a1, a2); + return; + } + + cdxCheckSolidStyle(ctxcanvas, 1); + XDrawArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); + cdxCheckSolidStyle(ctxcanvas, 0); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdsectorSIM(ctxcanvas, xc, yc, w, h, a1, a2); + return; + } + + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XSetArcMode(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ArcPieSlice); + XFillArc(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); + sCombineRegion(ctxcanvas); + } + else + { + XSetArcMode(ctxcanvas->dpy, ctxcanvas->gc, ArcPieSlice); + XFillArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); + } +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdchordSIM(ctxcanvas, xc, yc, w, h, a1, a2); + return; + } + + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XSetArcMode(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ArcChord); + XFillArc(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); + sCombineRegion(ctxcanvas); + } + else + { + XSetArcMode(ctxcanvas->dpy, ctxcanvas->gc, ArcChord); + XFillArc(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xc-w/2, yc-h/2, w, h, cdRound(a1*64), cdRound((a2 - a1)*64)); + } +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdrectSIM(ctxcanvas, xmin, xmax, ymin, ymax); + return; + } + + cdxCheckSolidStyle(ctxcanvas, 1); + XDrawRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xmin, ymin, xmax-xmin, ymax-ymin); + cdxCheckSolidStyle(ctxcanvas, 0); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->use_matrix) + { + cdboxSIM(ctxcanvas, xmin, xmax, ymin, ymax); + return; + } + + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XFillRectangle(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, xmin, ymin, xmax-xmin+1, ymax-ymin+1); + sCombineRegion(ctxcanvas); + } + else + XFillRectangle(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xmin, ymin, xmax-xmin+1, ymax-ymin+1); +} + +static int cd2xvertex [12] = {XR_TCENTRE, XR_BCENTRE, + XR_MRIGHT, XR_MLEFT, + XR_TRIGHT, XR_TLEFT, + XR_BRIGHT, XR_BLEFT, + XR_MCENTRE, XR_LEFT, + XR_CENTRE, XR_RIGHT}; + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *s, int len) +{ + int w, h, dir = -1; + + if (ctxcanvas->canvas->text_orientation != 0) + { + cdxCheckSolidStyle(ctxcanvas, 1); + + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); + + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XRotDrawString(ctxcanvas->dpy, ctxcanvas->font, ctxcanvas->canvas->text_orientation, + ctxcanvas->region_aux, ctxcanvas->region_aux_gc, x, y, s, len, + cd2xvertex[ctxcanvas->canvas->text_alignment], 0); + sCombineRegion(ctxcanvas); + } + else + XRotDrawString(ctxcanvas->dpy, ctxcanvas->font, ctxcanvas->canvas->text_orientation, + ctxcanvas->wnd, ctxcanvas->gc, x, y, s, len, + cd2xvertex[ctxcanvas->canvas->text_alignment], 0); + + cdxCheckSolidStyle(ctxcanvas, 0); + + return; + } + + w = XTextWidth(ctxcanvas->font, s, len); + h = ctxcanvas->font->ascent + ctxcanvas->font->descent; + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + x = x - w; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + x = x - w/2; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + x = x; + break; + } + + if (ctxcanvas->canvas->invert_yaxis) + dir = 1; + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + y = y; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + y = y - dir*ctxcanvas->font->descent; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + y = y + dir*(h - ctxcanvas->font->descent); + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + y = y + dir*(h/2 - ctxcanvas->font->descent); + break; + } + + cdxCheckSolidStyle(ctxcanvas, 1); + + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); + + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XSetFont(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ctxcanvas->font->fid); + XDrawString(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, x, y+1, s, len); + sCombineRegion(ctxcanvas); + } + else + XDrawString(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x, y+1, s, len); + + cdxCheckSolidStyle(ctxcanvas, 0); +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *s, int len, int *width, int *height) +{ + if (!ctxcanvas->font) return; + if (width) *width = XTextWidth(ctxcanvas->font, s, len); + if (height) *height = ctxcanvas->font->ascent + ctxcanvas->font->descent; +} + +void cdxPoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + XPoint* pnt = NULL; + + if (mode != CD_BEZIER) + { + pnt = (XPoint*)malloc((n+1) * sizeof(XPoint)); /* XPoint uses short for coordinates */ + + for (i = 0; i < n; i++) + { + int x = poly[i].x, + y = poly[i].y; + + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); + + pnt[i].x = (short)x; + pnt[i].y = (short)y; + } + } + + switch( mode ) + { + case CD_FILL: + if (ctxcanvas->canvas->new_region) + { + sPrepareRegion(ctxcanvas); + XSetFillRule(ctxcanvas->dpy, ctxcanvas->region_aux_gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule); + XFillPolygon(ctxcanvas->dpy, ctxcanvas->region_aux, ctxcanvas->region_aux_gc, + pnt, n, Complex, CoordModeOrigin); + sCombineRegion(ctxcanvas); + } + else + { + XSetFillRule(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule); + XFillPolygon(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, + pnt, n, Complex, CoordModeOrigin); + } + break; + case CD_CLOSED_LINES: + pnt[n].x = pnt[0].x; + pnt[n].y = pnt[0].y; + n++; + /* continua */ + case CD_OPEN_LINES: + { + cdxCheckSolidStyle(ctxcanvas, 1); + XDrawLines(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, pnt, n, CoordModeOrigin); + cdxCheckSolidStyle(ctxcanvas, 0); + break; + } + case CD_CLIP: + if (ctxcanvas->clip_polygon) XFreePixmap(ctxcanvas->dpy, ctxcanvas->clip_polygon); + ctxcanvas->clip_polygon = build_clip_polygon(ctxcanvas, pnt, n); + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdxClip(ctxcanvas, CD_CLIPPOLYGON); + break; + case CD_BEZIER: + cdSimPolyBezier(ctxcanvas->canvas, poly, n); + break; + } + + if (pnt) free(pnt); +} + +/******************************************************/ + +static int byte_order(void) +{ + unsigned short us = 0xFF00; + unsigned char *uc = (unsigned char *)&us; + return (uc[0]==0xFF) ? MSBFirst : LSBFirst; +} + +static void cdgetimagergb(cdCtxCanvas *ctxcanvas, unsigned char *r, unsigned char *g, unsigned char *b, int x, int y, int w, int h) +{ + int col, lin, pos; + XImage *xi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, x, y-h+1, w, h, ULONG_MAX, ZPixmap); + if (!xi) + { + fprintf(stderr, "CanvasDraw: error getting image\n"); + return; + } + + for (lin=0; linxidata) + { + ctxcanvas->xisize = size; + ctxcanvas->xidata = (long int *)malloc(ctxcanvas->xisize); + } + else if (ctxcanvas->xisize < size) + { + ctxcanvas->xisize = size; + ctxcanvas->xidata = (long int *)realloc(ctxcanvas->xidata, ctxcanvas->xisize); + } + + if (!ctxcanvas->xidata) + ctxcanvas->xisize = 0; + + return ctxcanvas->xidata; +} + +static XImage *map2ximage(cdCtxCanvas *ctxcanvas, int ew, int eh, const unsigned char *index, const long int * colors, int by, int bx, int bw, int bh, int iw) +{ + long int match_table[256]; + int i, j, pal_size; + unsigned long xcol; + XImage *xim; + int *fx, *fy, src, dst; + unsigned char idx; + + xim = (XImage *) NULL; + + /* Como nao sabemos o tamanho da palette a priori, + teremos que ver qual o maior indice usado na imagem. */ + pal_size = 0; + + for (i=0; i pal_size) + pal_size = idx; + } + } + + pal_size++; + + for (i = 0; i < pal_size; i++) + match_table[i] = cdxGetPixel(ctxcanvas, colors[i]); + + fx = cdGetZoomTable(ew, bw, bx); + fy = cdGetZoomTable(eh, bh, by); + + switch (ctxcanvas->depth) + { + case 8: + { + unsigned char *imagedata, *ip; + int imew, nullCount; + + nullCount = (4 - (ew % 4)) & 0x03; /* # of padding bytes per line */ + imew = ew + nullCount; + + /* Now get the image data - pad each scanline as necessary */ + imagedata = (unsigned char*)get_data_buffer(ctxcanvas, eh * imew); + if (!imagedata) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + for (i=0; idpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, imew); + if (!xim) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + } + break; + + case 12: + case 15: + case 16: + { + unsigned char *imagedata; + unsigned short *ip, *tip; + + /* Now get the image data - pad each scanline as necessary */ + imagedata = (unsigned char*)get_data_buffer(ctxcanvas, 2*ew*eh); + if (!imagedata) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 16, 0); + if (!xim) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + if (ctxcanvas->depth == 12 && xim->bits_per_pixel != 16) + { + xim->data = NULL; + XDestroyImage(xim); + fprintf(stderr,"No code for this type of display (depth=%d, bperpix=%d)", ctxcanvas->depth, xim->bits_per_pixel); + return NULL; + } + + ip = (unsigned short*)(imagedata + (eh-1)*xim->bytes_per_line); + + for (i=0; ibyte_order == MSBFirst) + { + *tip++ = (unsigned short)(xcol & 0xffff); + } + else + { + /* WAS *tip++ = ((xcol>>8) & 0xff) | ((xcol&0xff) << 8); */ + *tip++ = (unsigned short)(xcol); + } + } + + ip -= ew; + } + } + break; + + case 24: + case 32: + { + unsigned char *imagedata, *ip, *tip; + int do32; + + /* Now get the image data - pad each scanline as necessary */ + imagedata = (unsigned char*)get_data_buffer(ctxcanvas, 4*ew*eh); + if (!imagedata) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, 0); + if (!xim) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + do32 = (xim->bits_per_pixel == 32? 1: 0); + + ip = imagedata + (eh-1)*xim->bytes_per_line; + + for (i=0; ibyte_order == MSBFirst) + { + if (do32) *tip++ = 0; + *tip++ = (unsigned char)((xcol>>16) & 0xff); + *tip++ = (unsigned char)((xcol>>8) & 0xff); + *tip++ = (unsigned char)( xcol & 0xff); + } + else + { /* LSBFirst */ + *tip++ = (unsigned char)( xcol & 0xff); + *tip++ = (unsigned char)((xcol>>8) & 0xff); + *tip++ = (unsigned char)((xcol>>16) & 0xff); + if (do32) *tip++ = 0; + } + } + + ip -= xim->bytes_per_line; + } + } + break; + default: + { + /* Now get the image data - pad each scanline as necessary */ + unsigned long* imagedata = (unsigned long*)get_data_buffer(ctxcanvas, 4*ew*eh); + if (!imagedata) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + xim = XCreateImage(ctxcanvas->dpy,ctxcanvas->vis,ctxcanvas->depth,ZPixmap,0, (char *) imagedata, ew, eh, 32, ew*4); + if (!xim) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + xim->bits_per_pixel = 32; + xim->bytes_per_line = 4 * iw; + xim->byte_order = byte_order(); + xim->bitmap_bit_order = MSBFirst; + + for (i=0; ivis->red_mask; + gmask = ctxcanvas->vis->green_mask; + bmask = ctxcanvas->vis->blue_mask; + rshift = 7 - highbit(rmask); + gshift = 7 - highbit(gmask); + bshift = 7 - highbit(bmask); + + maplen = ctxcanvas->vis->map_entries; + if (maplen>256) maplen=256; + cshift = 7 - highbit((unsigned long) (maplen-1)); + + xim = XCreateImage(ctxcanvas->dpy, ctxcanvas->vis, ctxcanvas->depth, ZPixmap, 0, NULL, ew, eh, 32, 0); + if (!xim) + { + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + bperline = xim->bytes_per_line; + bperpix = xim->bits_per_pixel; + byte_order = xim->byte_order; + + if (bperpix != 8 && bperpix != 16 && bperpix != 24 && bperpix != 32) + { + XDestroyImage(xim); + fprintf(stderr, "CanvasDraw: bpp=%d not supported!\n", bperpix); + return NULL; + } + + imagedata = (unsigned char*)get_data_buffer(ctxcanvas, eh * bperline); + if (!imagedata) + { + XDestroyImage(xim); + fprintf(stderr, "CanvasDraw: not enough memory putting image\n"); + return NULL; + } + + fx = cdGetZoomTable(ew, bw, bx); + fy = cdGetZoomTable(eh, bh, by); + + xim->data = (char *) imagedata; + + lip = imagedata + (eh-1)*bperline; + + for (i=0; ivis->c_class == DirectColor) +#else + if (ctxcanvas->vis->class == DirectColor) +#endif + { + r = (unsigned long) cdxDirectColorTable[(r>>cshift) & 0xff] << cshift; + g = (unsigned long) cdxDirectColorTable[(g>>cshift) & 0xff] << cshift; + b = (unsigned long) cdxDirectColorTable[(b>>cshift) & 0xff] << cshift; + } + + /* shift the bits around */ + if (rshift<0) r = r << (-rshift); + else r = r >> rshift; + + if (gshift<0) g = g << (-gshift); + else g = g >> gshift; + + if (bshift<0) b = b << (-bshift); + else b = b >> bshift; + + r = r & rmask; + g = g & gmask; + b = b & bmask; + + xcol = r | g | b; + + if (bperpix == 32) + { + if (byte_order == MSBFirst) { + *ip++ = (unsigned char)((xcol>>24) & 0xff); + *ip++ = (unsigned char)((xcol>>16) & 0xff); + *ip++ = (unsigned char)((xcol>>8) & 0xff); + *ip++ = (unsigned char)( xcol & 0xff); + } + else + { /* LSBFirst */ + *ip++ = (unsigned char)( xcol & 0xff); + *ip++ = (unsigned char)((xcol>>8) & 0xff); + *ip++ = (unsigned char)((xcol>>16) & 0xff); + *ip++ = (unsigned char)((xcol>>24) & 0xff); + } + } + else if (bperpix == 24) + { + if (byte_order == MSBFirst) + { + *ip++ = (unsigned char)((xcol>>16) & 0xff); + *ip++ = (unsigned char)((xcol>>8) & 0xff); + *ip++ = (unsigned char)( xcol & 0xff); + } + else + { /* LSBFirst */ + *ip++ = (unsigned char)( xcol & 0xff); + *ip++ = (unsigned char)((xcol>>8) & 0xff); + *ip++ = (unsigned char)((xcol>>16) & 0xff); + } + } + else if (bperpix == 16) + { + if (byte_order == MSBFirst) + { + *ip++ = (unsigned char)((xcol>>8) & 0xff); + *ip++ = (unsigned char)( xcol & 0xff); + } + else { /* LSBFirst */ + *ip++ = (unsigned char)( xcol & 0xff); + *ip++ = (unsigned char)((xcol>>8) & 0xff); + } + } + else if (bperpix == 8) + { + *ip++ = (unsigned char)(xcol & 0xff); + } + } + } + + free(fx); + free(fy); + + return xim; +} + +static void cdputimagerectrgba_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int t_xmin, t_xmax, t_ymin, t_ymax, ew, eh, + t_x, t_y, dst_offset, size, nc, doff, rect[8]; + float i_x, i_y, xfactor, yfactor; + unsigned char *dst_r, *dst_g, *dst_b, *dst_a = NULL; + double inv_matrix[6]; + + /* calculate the destination limits */ + cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, rect); + + /* Setup inverse transform (use the original transform here, NOT ctxcanvas->xmatrix) */ + cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix); + + /* create an image for the destination area */ + ew = (t_xmax-t_xmin+1); + eh = (t_ymax-t_ymin+1); + size = ew*eh; + nc = 3; + if (a) nc = 4; + dst_r = malloc(nc*size); + if (!dst_r) + { + fprintf(stderr, "CanvasDraw: no enough memory\n"); + return; + } + dst_g = dst_r + size; + dst_b = dst_g + size; + if (a) dst_a = dst_b + size; + memset(dst_r, 0, nc*size); + + /* for all pixels in the destiny area */ + for(t_y = t_ymin; t_y <= t_ymax; t_y++) + { + dst_offset = (t_y-t_ymin) * ew; + + for(t_x = t_xmin; t_x <= t_xmax; t_x++) + { + cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix); + + if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) + { + doff = (t_x-t_xmin) + dst_offset; + *(dst_r+doff) = cdBilinearInterpolation(iw, ih, r, i_x, i_y); + *(dst_g+doff) = cdBilinearInterpolation(iw, ih, g, i_x, i_y); + *(dst_b+doff) = cdBilinearInterpolation(iw, ih, b, i_x, i_y); + if (a) *(dst_a+doff) = cdBilinearInterpolation(iw, ih, a, i_x, i_y); + } + } + } + + { + int ex = t_xmin, + ey = t_ymin + eh-1; /* XImage origin is at top-left */ + XImage *xi, *oxi = NULL; + Pixmap clip_polygon, clip_mask = 0; + XPoint pnt[4]; + + /* Since the transformation used was the original transformation, */ + /* must invert the Y axis here. */ + ey = _cdInvertYAxis(ctxcanvas->canvas, ey); + + /* use clipping to select only the transformed rectangle */ + pnt[0].x = (short)rect[0]; pnt[0].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[1]); + pnt[1].x = (short)rect[2]; pnt[1].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[3]); + pnt[2].x = (short)rect[4]; pnt[2].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[5]); + pnt[3].x = (short)rect[6]; pnt[3].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[7]); + clip_polygon = build_clip_polygon(ctxcanvas, pnt, 4); + + /* combine with the existing clipping */ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA || ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + clip_mask = ctxcanvas->clip_polygon; + else if (ctxcanvas->canvas->clip_mode == CD_CLIPREGION) + clip_mask = ctxcanvas->new_region; + XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXand); + XCopyArea(ctxcanvas->dpy, clip_mask, clip_polygon, ctxcanvas->gc, + 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0); + XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, clip_polygon); + cdwritemode(ctxcanvas, ctxcanvas->canvas->write_mode); /* reset XSetFunction */ + + if (a) + { + oxi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, ex, ey, ew, eh, ULONG_MAX, ZPixmap); + if (!oxi) + { + fprintf(stderr, "CanvasDraw: error getting image\n"); + free(dst_r); + return; + } + } + + xi = rgb2ximage(ctxcanvas, ew, eh, dst_r, dst_g, dst_b, dst_a, oxi, 0, 0, ew, eh, ew); + if (!xi) + return; + + XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh); + + /* reset cliping */ + XFreePixmap(ctxcanvas->dpy, clip_polygon); + cdxClip(ctxcanvas, ctxcanvas->canvas->clip_mode); + + xi->data = NULL; + XDestroyImage(xi); + if (oxi) XDestroyImage(oxi); + } + + free(dst_r); +} + +static void cdputimagerectmap_matrix(cdCtxCanvas* ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int t_xmin, t_xmax, t_ymin, t_ymax, ew, eh, + t_x, t_y, dst_offset, size, doff, rect[8]; + float i_x, i_y, xfactor, yfactor; + unsigned char *dst_index; + double inv_matrix[6]; + + /* calculate the destination limits */ + cdImageRGBCalcDstLimits(ctxcanvas->canvas, x, y, w, h, &t_xmin, &t_xmax, &t_ymin, &t_ymax, rect); + + /* Setup inverse transform (use the original transform here, NOT ctxcanvas->xmatrix) */ + cdImageRGBInitInverseTransform(w, h, xmin, xmax, ymin, ymax, &xfactor, &yfactor, ctxcanvas->canvas->matrix, inv_matrix); + + /* create an image for the destination area */ + ew = (t_xmax-t_xmin+1); + eh = (t_ymax-t_ymin+1); + size = ew*eh; + dst_index = malloc(size); + if (!dst_index) + { + fprintf(stderr, "CanvasDraw: no enough memory\n"); + return; + } + memset(dst_index, 0, size); + + /* for all pixels in the destiny area */ + for(t_y = t_ymin; t_y <= t_ymax; t_y++) + { + dst_offset = (t_y-t_ymin) * ew; + + for(t_x = t_xmin; t_x <= t_xmax; t_x++) + { + cdImageRGBInverseTransform(t_x, t_y, &i_x, &i_y, xfactor, yfactor, xmin, ymin, x, y, inv_matrix); + + if (i_x > xmin && i_y > ymin && i_x < xmax+1 && i_y < ymax+1) + { + doff = (t_x-t_xmin) + dst_offset; + *(dst_index+doff) = cdZeroOrderInterpolation(iw, ih, index, i_x, i_y); + } + } + } + + { + int ex = t_xmin, + ey = t_ymin + eh-1; /* XImage origin is at top-left */ + XImage *xi; + Pixmap clip_polygon, clip_mask = 0; + XPoint pnt[4]; + + /* Since the transformation used was the original transformation, */ + /* must invert the Y axis here. */ + ey = _cdInvertYAxis(ctxcanvas->canvas, ey); + + /* use clipping to select only the transformed rectangle */ + pnt[0].x = (short)rect[0]; pnt[0].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[1]); + pnt[1].x = (short)rect[2]; pnt[1].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[3]); + pnt[2].x = (short)rect[4]; pnt[2].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[5]); + pnt[3].x = (short)rect[6]; pnt[3].y = (short)_cdInvertYAxis(ctxcanvas->canvas, rect[7]); + clip_polygon = build_clip_polygon(ctxcanvas, pnt, 4); + + /* combine with the existing clipping */ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA || ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) + clip_mask = ctxcanvas->clip_polygon; + else if (ctxcanvas->canvas->clip_mode == CD_CLIPREGION) + clip_mask = ctxcanvas->new_region; + XSetFunction(ctxcanvas->dpy, ctxcanvas->gc, GXand); + XCopyArea(ctxcanvas->dpy, clip_mask, clip_polygon, ctxcanvas->gc, + 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h, 0, 0); + XSetClipMask(ctxcanvas->dpy, ctxcanvas->gc, clip_polygon); + cdwritemode(ctxcanvas, ctxcanvas->canvas->write_mode); /* reset XSetFunction */ + + xi = map2ximage(ctxcanvas, ew, eh, dst_index, colors, 0, 0, ew, eh, ew); + if (!xi) + return; + + XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh); + + /* reset cliping */ + XFreePixmap(ctxcanvas->dpy, clip_polygon); + cdxClip(ctxcanvas, ctxcanvas->canvas->clip_mode); + + xi->data = NULL; + XDestroyImage(xi); + } + + free(dst_index); +} + +static void cdputimagerectrgb(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int ew = w, eh = h, ex = x, ey = y; + int bw = iw, bh = ih, bx = 0, by = 0; + int rw, rh; + XImage *xi; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, NULL, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + y -= (h - 1); /* XImage origin is at top-left */ + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + xi = rgb2ximage(ctxcanvas, ew, eh, r, g, b, NULL, NULL, by, bx, bw, bh, iw); + if (!xi) + return; + + XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh); + + xi->data = NULL; + XDestroyImage(xi); +} + +static void cdputimagerectrgba(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + XImage *xi, *oxi; + int ew = w, eh = h, ex = x, ey = y; + int bw = iw, bh = ih, bx = 0, by = 0; + int rw, rh; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectrgba_matrix(ctxcanvas, iw, ih, r, g, b, a, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + y -= (h - 1); /* XImage origin is at top-left */ + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + oxi = XGetImage(ctxcanvas->dpy, ctxcanvas->wnd, ex, ey, ew, eh, ULONG_MAX, ZPixmap); + if (!oxi) + { + fprintf(stderr, "CanvasDraw: error getting image\n"); + return; + } + + xi = rgb2ximage(ctxcanvas, ew, eh, r, g, b, a, oxi, by, bx, bw, bh, iw); + if (!xi) + return; + + XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh); + + xi->data = NULL; + XDestroyImage(xi); + XDestroyImage(oxi); +} + +static void cdputimagerectmap(cdCtxCanvas *ctxcanvas, int iw, int ih, const unsigned char *index, const long int *colors, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax) +{ + int ew = w, eh = h, ex = x, ey = y; + int bw = iw, bh = ih, bx = 0, by = 0; + int rw, rh; + XImage *xi; + + if (ctxcanvas->canvas->use_matrix) + { + cdputimagerectmap_matrix(ctxcanvas, iw, ih, index, colors, x, y, w, h, xmin, xmax, ymin, ymax); + return; + } + + rw = xmax-xmin+1; + rh = ymax-ymin+1; + y -= (h - 1); /* XImage origin is at top-left */ + + if (!cdCalcZoom(ctxcanvas->canvas->w, x, w, &ex, &ew, xmin, rw, &bx, &bw, 1)) + return; + + if (!cdCalcZoom(ctxcanvas->canvas->h, y, h, &ey, &eh, ymin, rh, &by, &bh, 0)) + return; + + xi = map2ximage(ctxcanvas, ew, eh, index, colors, by, bx, bw, bh, iw); + if (!xi) + return; + + XPutImage(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, xi, 0, 0, ex, ey, ew, eh); + + xi->data = NULL; + XDestroyImage(xi); +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + if (ctxcanvas->canvas->foreground != color) + XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, cdxGetPixel(ctxcanvas, color)); + + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); + + XDrawPoint(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->gc, x, y); + + if (ctxcanvas->canvas->foreground != color) + XSetForeground(ctxcanvas->dpy, ctxcanvas->gc, ctxcanvas->fg); +} + +static cdCtxImage *cdcreateimage (cdCtxCanvas *ctxcanvas, int w, int h) +{ + GC gc; + cdCtxImage *ctximage = (cdCtxImage *)malloc(sizeof(cdCtxImage)); + + ctximage->w = w; + ctximage->h = h; + ctximage->depth = ctxcanvas->depth; + ctximage->dpy = ctxcanvas->dpy; + ctximage->scr = ctxcanvas->scr; + ctximage->vis = ctxcanvas->vis; + + ctximage->img = XCreatePixmap(ctxcanvas->dpy, ctxcanvas->wnd, w, h, ctxcanvas->depth); + if (!ctximage->img) + { + free(ctximage); + return (void *)0; + } + + gc = XCreateGC(ctximage->dpy, ctximage->img, 0, NULL); + XSetForeground(ctximage->dpy, gc, cdxGetPixel(ctxcanvas, CD_WHITE)); + XFillRectangle(ctximage->dpy, ctximage->img, gc, 0, 0, ctximage->w, ctxcanvas->canvas->h); + XFreeGC(ctximage->dpy, gc); + + return (void *)ctximage; +} + +static void cdgetimage (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y) +{ + XCopyArea(ctxcanvas->dpy, ctxcanvas->wnd, ctximage->img, ctxcanvas->gc, + x, y - ctximage->h+1, ctximage->w, ctximage->h, 0, 0); +} + +static void cdputimagerect (cdCtxCanvas *ctxcanvas, cdCtxImage *ctximage, int x, int y, int xmin, int xmax, int ymin, int ymax) +{ + XCopyArea(ctxcanvas->dpy, ctximage->img, ctxcanvas->wnd, ctxcanvas->gc, + xmin, ctximage->h-ymax-1, xmax-xmin+1, ymax-ymin+1, x, y-(ymax-ymin+1)+1); +} + +static void cdkillimage (cdCtxImage *ctximage) +{ + XFreePixmap(ctximage->dpy, ctximage->img); + free(ctximage); +} + +static void cdscrollarea (cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax, int dx, int dy) +{ + XCopyArea(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->wnd, ctxcanvas->gc, + xmin, ymin, + xmax-xmin+1, ymax-ymin+1, + xmin+dx, ymin+dy); +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ + if (matrix) + { + /* configure a bottom-up coordinate system */ + ctxcanvas->xmatrix[0] = 1; + ctxcanvas->xmatrix[1] = 0; + ctxcanvas->xmatrix[2] = 0; + ctxcanvas->xmatrix[3] = -1; + ctxcanvas->xmatrix[4] = 0; + ctxcanvas->xmatrix[5] = (ctxcanvas->canvas->h-1); + cdMatrixMultiply(matrix, ctxcanvas->xmatrix); + + ctxcanvas->canvas->invert_yaxis = 0; + } + else + { + ctxcanvas->canvas->invert_yaxis = 1; + } +} + +/******************************************************************/ + +static void set_rotate_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (data) + { + sscanf(data, "%g %d %d", &ctxcanvas->rotate_angle, + &ctxcanvas->rotate_center_x, + &ctxcanvas->rotate_center_y); + + cdCanvasTransformTranslate(ctxcanvas->canvas, ctxcanvas->rotate_center_x, ctxcanvas->rotate_center_y); + cdCanvasTransformRotate(ctxcanvas->canvas, ctxcanvas->rotate_angle); + cdCanvasTransformTranslate(ctxcanvas->canvas, -ctxcanvas->rotate_center_x, -ctxcanvas->rotate_center_y); + } + else + { + ctxcanvas->rotate_angle = 0; + ctxcanvas->rotate_center_x = 0; + ctxcanvas->rotate_center_y = 0; + + cdCanvasTransform(ctxcanvas->canvas, NULL); + } +} + +static char* get_rotate_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + if (!ctxcanvas->rotate_angle) + return NULL; + + sprintf(data, "%g %d %d", (double)ctxcanvas->rotate_angle, + ctxcanvas->rotate_center_x, + ctxcanvas->rotate_center_y); + + return data; +} + +static cdAttribute rotate_attrib = +{ + "ROTATE", + set_rotate_attrib, + get_rotate_attrib +}; + +static char* get_gc_attrib(cdCtxCanvas *ctxcanvas) +{ + return (char*)ctxcanvas->gc; +} + +static cdAttribute gc_attrib = +{ + "GC", + NULL, + get_gc_attrib +}; + +static void get_geometry(Display *dpy, Drawable wnd, cdCtxCanvas *ctxcanvas) +{ + Window root; + int x, y; + unsigned int w, h, b, d; + XGetGeometry(dpy, wnd, &root, &x, &y, &w, &h, &b, &d); + ctxcanvas->canvas->w = w; + ctxcanvas->canvas->h = h; + ctxcanvas->depth = d; +} + +cdCtxCanvas *cdxCreateCanvas(cdCanvas* canvas, Display *dpy, int scr, Drawable wnd, Visual *vis) +{ + static int first = 1; + cdCtxCanvas *ctxcanvas = (cdCtxCanvas *)malloc(sizeof(cdCtxCanvas)); + memset(ctxcanvas, 0, sizeof(cdCtxCanvas)); + + ctxcanvas->dpy = dpy; + ctxcanvas->scr = scr; + ctxcanvas->wnd = wnd; + ctxcanvas->vis = vis; + ctxcanvas->gc = XCreateGC(dpy, wnd, 0, NULL); + if (ctxcanvas->gc == 0) + { + free(canvas); + return NULL; + } + + ctxcanvas->canvas = canvas; + canvas->ctxcanvas = ctxcanvas; + + get_geometry(dpy, wnd, ctxcanvas); + + canvas->bpp = ctxcanvas->depth; + canvas->xres = ((double)DisplayWidth(dpy, scr) / (double)DisplayWidthMM(dpy, scr)); + canvas->yres = ((double)DisplayHeight(dpy, scr) / (double)DisplayHeightMM(dpy, scr)); + canvas->w_mm = ((double)canvas->w) / canvas->xres; + canvas->h_mm = ((double)canvas->h) / canvas->yres; + canvas->invert_yaxis = 1; + + if (first) + { + if (canvas->bpp > 8) + { + cdxGetRGB = truecolor_get_rgb; + cdxGetPixel = truecolor_get_pixel; + + /* make linear colormap for DirectColor visual */ +#ifdef __cplusplus + if (ctxcanvas->vis->c_class == DirectColor) +#else + if (ctxcanvas->vis->class == DirectColor) +#endif + makeDirectCmap(ctxcanvas, DefaultColormap(ctxcanvas->dpy, ctxcanvas->scr)); + } + else + { + cdxGetRGB = not_truecolor_get_rgb; + cdxGetPixel = not_truecolor_get_pixel; + } + } + + if (canvas->bpp > 8) + { + ctxcanvas->rshift = 15 - highbit(ctxcanvas->vis->red_mask); + ctxcanvas->gshift = 15 - highbit(ctxcanvas->vis->green_mask); + ctxcanvas->bshift = 15 - highbit(ctxcanvas->vis->blue_mask); + + ctxcanvas->num_colors = 0; + ctxcanvas->colormap = (Colormap)0; + + /* para canvas bpp <= 8 RGBA e' simulado com cdGetImageRGB */ + canvas->cxPutImageRectRGBA = cdputimagerectrgba; + } + else + { + int i; + + ctxcanvas->colormap = DefaultColormap(dpy, scr); + ctxcanvas->num_colors = 1L << canvas->bpp; + + for (i=0; inum_colors; i++) + ctxcanvas->color_table[i].pixel = i; + + update_colors(ctxcanvas); + } + + if (first) + { + if(!getenv("CD_XERROR")) + XSetErrorHandler(cdxErrorHandler); + } + + cdRegisterAttribute(canvas, &gc_attrib); + cdRegisterAttribute(canvas, &rotate_attrib); + + first = 0; + + return ctxcanvas; +} + +void cdxInitTable(cdCanvas* canvas) +{ + canvas->cxFlush = cdflush; + canvas->cxClear = cdclear; + canvas->cxPixel = cdpixel; + canvas->cxLine = cdline; + canvas->cxPoly = cdxPoly; + canvas->cxRect = cdrect; + canvas->cxBox = cdbox; + canvas->cxArc = cdarc; + canvas->cxSector = cdsector; + canvas->cxChord = cdchord; + canvas->cxText = cdtext; + + canvas->cxNewRegion = cdnewregion; + canvas->cxIsPointInRegion = cdispointinregion; + canvas->cxOffsetRegion = cdoffsetregion; + canvas->cxGetRegionBox = cdgetregionbox; + canvas->cxClip = cdxClip; + canvas->cxClipArea = cdcliparea; + canvas->cxWriteMode = cdwritemode; + canvas->cxLineStyle = cdlinestyle; + canvas->cxLineWidth = cdlinewidth; + canvas->cxLineCap = cdlinecap; + canvas->cxLineJoin = cdlinejoin; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxGetFontDim = cdgetfontdim; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxPalette = cdpalette; + canvas->cxBackground = cdbackground; + canvas->cxForeground = cdforeground; + canvas->cxTransform = cdtransform; + + canvas->cxGetImageRGB = cdgetimagergb; + canvas->cxScrollArea = cdscrollarea; + + canvas->cxCreateImage = cdcreateimage; + canvas->cxGetImage = cdgetimage; + canvas->cxPutImageRect = cdputimagerect; + canvas->cxKillImage = cdkillimage; + + canvas->cxPutImageRectRGB = cdputimagerectrgb; + canvas->cxPutImageRectMap = cdputimagerectmap; + + if (canvas->bpp > 8) + canvas->cxPutImageRectRGBA = cdputimagerectrgba; +} diff --git a/cd/src/x11/cdx11.h b/cd/src/x11/cdx11.h new file mode 100755 index 0000000..a68fdf9 --- /dev/null +++ b/cd/src/x11/cdx11.h @@ -0,0 +1,85 @@ +/** \file + * \brief X-Windows Base Driver + * + * See Copyright Notice in cd.h + */ + +#ifndef __CDX11_H +#define __CDX11_H + +#include +#include + +#include "cd.h" +#include "cd_private.h" + + +/* Hidden declaration for the Context Plus driver */ +typedef struct _cdxContextPlus cdxContextPlus; + +struct _cdCtxImage { + unsigned int w, h, depth; + Pixmap img; + Display *dpy; + int scr; + Visual *vis; +}; + +struct _cdCtxCanvas { + cdCanvas* canvas; + Display* dpy; /* display da aplicacao no X */ + Visual* vis; /* visual usado pela aplicacao */ + int scr; /* screen da aplicacao */ + GC gc; /* contexto grafico */ + Drawable wnd; /* drawable */ + long int fg; + Pixmap last_hatch; /* ultimo hatch setado pelo usuario */ + Pixmap last_stipple; /* ultimo stipple setado pelo usuario */ + Pixmap last_pattern; /* ultimo pattern setado pelo usuario */ + GC last_stipple_gc; + int last_stipple_w; + int last_stipple_h; + GC last_pattern_gc; + int last_pattern_w; + int last_pattern_h; + XFontStruct *font; /* fonte de caracteres no X */ + unsigned int depth; /* depth do canvas */ + Pixmap clip_polygon; /* poligono de clipping */ + Pixmap new_region, region_aux; + GC region_aux_gc; + void *data; /* informacoes especificas do driver */ + long int *xidata; /* ximage cache */ + int xisize; + Colormap colormap; /* colormap para todos os canvas */ + XColor color_table[256]; /* tabela de cores do colormap */ + int num_colors; /* tamanho maximo da tabela de cores */ + int rshift; /* constante red para calculo truecolor */ + int gshift; /* constante green para calculo truecolor */ + int bshift; /* constante blue para calculo truecolor */ + double xmatrix[6]; /* transformation matrix that includes axis inversion */ + float rotate_angle; + int rotate_center_x, + rotate_center_y; + + cdImage* image_dbuffer; /* utilizado pelo driver de Double buffer */ + cdCanvas* canvas_dbuffer; + + cdxContextPlus* ctxplus; +}; + +#define cdCOLOR8TO16(_x) (_x*257) /* 65535/255 = 257 */ +#define cdCOLOR16TO8(_x) ((unsigned char)(_x/257)) + +extern unsigned long (*cdxGetPixel)(cdCtxCanvas *ctxcanvas, unsigned long rgb); +extern void (*cdxGetRGB)(cdCtxCanvas *ctxcanvas, unsigned long pixel, + unsigned char* red, + unsigned char* green, + unsigned char* blue); + +cdCtxCanvas *cdxCreateCanvas(cdCanvas* canvas, Display *dpy, int scr, Drawable wnd, Visual *vis); +void cdxInitTable(cdCanvas* canvas); +void cdxKillCanvas(cdCtxCanvas *ctxcanvas); +int cdxClip(cdCtxCanvas *ctxcanvas, int clip_mode); +void cdxPoly(cdCtxCanvas *ctxcanvas, int mode, cdPoint* poly, int n); + +#endif diff --git a/cd/src/x11/cdxclp.c b/cd/src/x11/cdxclp.c new file mode 100755 index 0000000..d775fde --- /dev/null +++ b/cd/src/x11/cdxclp.c @@ -0,0 +1,136 @@ +/** \file + * \brief X-Windows Clipboard Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include + +#include +#include + +#include "cd.h" +#include "cd_private.h" +#include "cdclipbd.h" +#include "cdmf.h" +#include "cdmf_private.h" + + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + char* buffer; + long dwSize; + FILE* file; + char filename[10240]; + cdCanvasMF* mfcanvas = (cdCanvasMF*)ctxcanvas; + Display* dpy = (Display*)mfcanvas->data; + + /* guardar antes de remover o canvas */ + strcpy(filename, mfcanvas->filename); + + cdkillcanvasMF(mfcanvas); + + file = fopen(filename, "r"); + fseek(file, 0, SEEK_END); + dwSize = ftell(file); + fseek(file, 0, SEEK_SET); + + buffer = (char*)malloc(dwSize); + fread(buffer, dwSize, 1, file); + + fclose(file); + + remove(filename); + + XStoreBytes(dpy, buffer, dwSize); +} + +static int cdplay(cdCanvas* canvas, int xmin, int xmax, int ymin, int ymax, void *data) +{ + char filename[1024]; + char* buffer; + int dwSize; + FILE* file; + + buffer = XFetchBytes((Display*)data, &dwSize); + if (!buffer) + return CD_ERROR; + + tmpnam(filename); + file = fopen(filename, "w"); + fwrite(buffer, dwSize, 1, file); + fclose(file); + + cdCanvasPlay(canvas, CD_METAFILE, xmin, xmax, ymin, ymax, filename); + + remove(filename); + + XFree(buffer); + + return CD_OK; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char tmpPath[512]; + char* str = (char*)data; + Display* dpy = NULL; + + /* Inicializa parametros */ + if (str == NULL) + return; + +#ifdef SunOS_OLD + sscanf(str, "%d", &dpy); +#else + sscanf(str, "%p", &dpy); +#endif + + if (!dpy) + return; + + str = strstr(str, " "); + if (!str) + return; + + str++; + tmpnam(tmpPath); + + strcat(tmpPath, " "); + strcat(tmpPath, str); + + cdcreatecanvasMF(canvas, str); + if (!canvas->ctxcanvas) + return; + + { + cdCanvasMF* mfcanvas = (cdCanvasMF*)canvas->ctxcanvas; + mfcanvas->data = dpy; + } +} + +static void cdinittable(cdCanvas* canvas) +{ + cdinittableMF(canvas); + canvas->cxKillCanvas = cdkillcanvas; +} + + +static cdContext cdClipboardContext = +{ + CD_CAP_ALL & ~(CD_CAP_GETIMAGERGB | CD_CAP_IMAGESRV | CD_CAP_FONTDIM | CD_CAP_TEXTSIZE), + 0, + cdcreatecanvas, + cdinittable, + cdplay, + NULL +}; + +cdContext* cdContextClipboard(void) +{ + return &cdClipboardContext; +} + + diff --git a/cd/src/x11/cdxdbuf.c b/cd/src/x11/cdxdbuf.c new file mode 100755 index 0000000..835687c --- /dev/null +++ b/cd/src/x11/cdxdbuf.c @@ -0,0 +1,168 @@ +/** \file + * \brief X-Windows Double Buffer Driver + * + * See Copyright Notice in cd.h + */ + +#include "cdx11.h" +#include "cddbuf.h" +#include +#include + + +static void cdkillcanvas (cdCtxCanvas* ctxcanvas) +{ + cdKillImage(ctxcanvas->image_dbuffer); + cdxKillCanvas(ctxcanvas); +} + +static void cddeactivate(cdCtxCanvas* ctxcanvas) +{ + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + /* this is done in the canvas_dbuffer context */ + cdCanvasDeactivate(canvas_dbuffer); +} + +static void cdflush(cdCtxCanvas* ctxcanvas) +{ + int old_writemode; + cdImage* image_dbuffer = ctxcanvas->image_dbuffer; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* flush the writing in the image */ + XFlush(ctxcanvas->dpy); + + /* this is done in the canvas_dbuffer context */ + /* Flush can be affected by Origin and Clipping, but not WriteMode */ + old_writemode = cdCanvasWriteMode(canvas_dbuffer, CD_REPLACE); + cdCanvasPutImageRect(canvas_dbuffer, image_dbuffer, 0, 0, 0, 0, 0, 0); + cdCanvasWriteMode(canvas_dbuffer, old_writemode); +} + +static void cdcreatecanvas(cdCanvas* canvas, cdCanvas* canvas_dbuffer) +{ + int w, h; + cdCtxCanvas* ctxcanvas; + cdImage* image_dbuffer; + cdCtxImage* ctximage; + + cdCanvasActivate(canvas_dbuffer); + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + /* this is done in the canvas_dbuffer context */ + image_dbuffer = cdCanvasCreateImage(canvas_dbuffer, w, h); + if (!image_dbuffer) + return; + + ctximage = image_dbuffer->ctximage; + + /* Inicializa driver DBuffer */ + ctxcanvas = cdxCreateCanvas(canvas, ctximage->dpy, ctximage->scr, ctximage->img, ctximage->vis); + if (!ctxcanvas) + return; + + ctxcanvas->image_dbuffer = image_dbuffer; + ctxcanvas->canvas_dbuffer = canvas_dbuffer; +} + +static int cdactivate(cdCtxCanvas* ctxcanvas) +{ + int w, h; + cdCanvas* canvas_dbuffer = ctxcanvas->canvas_dbuffer; + + /* this is done in the canvas_dbuffer context */ + /* this will update canvas size */ + cdCanvasActivate(canvas_dbuffer); + w = canvas_dbuffer->w; + h = canvas_dbuffer->h; + if (w==0) w=1; + if (h==0) h=1; + + /* check if the size changed */ + if (w != ctxcanvas->image_dbuffer->w || + h != ctxcanvas->image_dbuffer->h) + { + cdCanvas* canvas = ctxcanvas->canvas; + /* save the current, if the rebuild fail */ + cdImage* old_image_dbuffer = ctxcanvas->image_dbuffer; + cdCtxCanvas* old_ctxcanvas = ctxcanvas; + + /* if the image is rebuild, the canvas that uses the image must be also rebuild */ + + /* rebuild the image and the canvas */ + canvas->ctxcanvas = NULL; + canvas->context->cxCreateCanvas(canvas, canvas_dbuffer); + if (!canvas->ctxcanvas) + { + canvas->ctxcanvas = old_ctxcanvas; + return CD_ERROR; + } + + /* remove the old image and canvas */ + cdKillImage(old_image_dbuffer); + cdxKillCanvas(old_ctxcanvas); + + ctxcanvas = canvas->ctxcanvas; + + /* update canvas attributes */ + canvas->cxBackground(ctxcanvas, canvas->background); + canvas->cxForeground(ctxcanvas, canvas->foreground); + canvas->cxBackOpacity(ctxcanvas, canvas->back_opacity); + canvas->cxWriteMode(ctxcanvas, canvas->write_mode); + canvas->cxLineStyle(ctxcanvas, canvas->line_style); + canvas->cxLineWidth(ctxcanvas, canvas->line_width); + canvas->cxLineCap(ctxcanvas, canvas->line_cap); + canvas->cxLineJoin(ctxcanvas, canvas->line_join); + canvas->cxHatch(ctxcanvas, canvas->hatch_style); + if (canvas->stipple) canvas->cxStipple(ctxcanvas, canvas->stipple_w, canvas->stipple_h, canvas->stipple); + if (canvas->pattern) canvas->cxPattern(ctxcanvas, canvas->pattern_w, canvas->pattern_h, canvas->pattern); + canvas->cxInteriorStyle(ctxcanvas, canvas->interior_style); + if (canvas->native_font[0] == 0) canvas->cxFont(ctxcanvas, canvas->font_type_face, canvas->font_style, canvas->font_size); + else canvas->cxNativeFont(ctxcanvas, canvas->native_font); +/* canvas->cxTextAlignment(ctxcanvas, canvas->text_alignment); */ +/* canvas->cxTextOrientation(ctxcanvas, canvas->text_orientation); */ + if (canvas->clip_mode == CD_CLIPAREA && canvas->cxClipArea) canvas->cxClipArea(ctxcanvas, canvas->clip_rect.xmin, canvas->clip_rect.xmax, canvas->clip_rect.ymin, canvas->clip_rect.ymax); +/* if (canvas->clip_mode == CD_CLIPAREA && canvas->cxFClipArea) canvas->cxFClipArea(ctxcanvas, canvas->clip_frect.xmin, canvas->clip_frect.xmax, canvas->clip_frect.ymin, canvas->clip_frect.ymax); */ + if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_poly) canvas->cxPoly(ctxcanvas, CD_CLIP, canvas->clip_poly, canvas->clip_poly_n); +/* if (canvas->clip_mode == CD_CLIPPOLYGON && canvas->clip_fpoly) canvas->cxFPoly(ctxcanvas, CD_CLIP, canvas->clip_fpoly, canvas->clip_poly_n); */ + if (canvas->clip_mode != CD_CLIPOFF) canvas->cxClip(ctxcanvas, canvas->clip_mode); + } + + return CD_OK; +} + +static void cdinittable(cdCanvas* canvas) +{ + cdxInitTable(canvas); + + canvas->cxActivate = cdactivate; + canvas->cxDeactivate = cddeactivate; + canvas->cxFlush = cdflush; + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdDBufferContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | + CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + +cdContext* cdContextDBuffer(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_DBUFFER); + if (ctx != NULL) + return ctx; + } + + return &cdDBufferContext; +} diff --git a/cd/src/x11/cdximg.c b/cd/src/x11/cdximg.c new file mode 100755 index 0000000..8131f78 --- /dev/null +++ b/cd/src/x11/cdximg.c @@ -0,0 +1,52 @@ +/** \file + * \brief X-Windows Image Driver + * + * See Copyright Notice in cd.h + */ + +#include + +#include "cdx11.h" +#include "cdimage.h" + + +static void cdkillcanvas(cdCtxCanvas* ctxcanvas) +{ + cdxKillCanvas(ctxcanvas); +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + cdCtxImage *ctximage = ((cdImage*)data)->ctximage; + cdxCreateCanvas(canvas, ctximage->dpy, ctximage->scr, ctximage->img, ctximage->vis); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdxInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; +} + +static cdContext cdImageContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ), + 0, + cdcreatecanvas, + cdinittable, + NULL, + NULL +}; + + +cdContext* cdContextImage(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_IMAGE); + if (ctx != NULL) + return ctx; + } + + return &cdImageContext; +} diff --git a/cd/src/x11/cdxnative.c b/cd/src/x11/cdxnative.c new file mode 100755 index 0000000..c708d20 --- /dev/null +++ b/cd/src/x11/cdxnative.c @@ -0,0 +1,165 @@ +/** \file + * \brief X-Windows Native Window Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include + +#include "cdx11.h" +#include "cdnative.h" + + +int cdGetScreenColorPlanes(void) +{ + static int first = 1; + static int bpp; + + if (first) + { + int nitems; + XVisualInfo info; + Display* drv_display = XOpenDisplay(NULL); + + info.depth = 24; + if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL) + { + bpp = 24; + XCloseDisplay(drv_display); + return bpp; + } + + info.depth = 16; + if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL) + { + bpp = 16; + XCloseDisplay(drv_display); + return bpp; + } + + info.depth = 8; + if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL) + { + bpp = 8; + XCloseDisplay(drv_display); + return bpp; + } + + info.depth = 4; + if (XGetVisualInfo(drv_display, VisualDepthMask, &info, &nitems) != NULL) + { + bpp = 4; + XCloseDisplay(drv_display); + return bpp; + } + + bpp = 2; + XCloseDisplay(drv_display); + + first = 0; + } + + return bpp; +} + +void cdGetScreenSize(int *width, int *height, double *width_mm, double *height_mm) +{ + static int first = 1; + static int dpy_width, dpy_height, dpy_width_mm, dpy_height_mm; + + if (first) + { + Display* drv_display = XOpenDisplay(NULL); + int drv_screen = DefaultScreen (drv_display); + + dpy_width = DisplayWidth(drv_display,drv_screen); + dpy_height = DisplayHeight(drv_display,drv_screen); + dpy_width_mm = DisplayWidthMM(drv_display,drv_screen); + dpy_height_mm = DisplayHeightMM(drv_display,drv_screen); + + XCloseDisplay(drv_display); + + first = 0; + } + + if (width) *width = dpy_width; + if (height) *height = dpy_height; + if (width_mm) *width_mm = dpy_width_mm; + if (height_mm) *height_mm = dpy_height_mm; +} + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + cdxKillCanvas(ctxcanvas); +} + +static int cdactivate(cdCtxCanvas *ctxcanvas) +{ + Window root; + int x, y; + unsigned int bw, d; + XGetGeometry(ctxcanvas->dpy, ctxcanvas->wnd, &root, &x, &y, + (unsigned int*)&ctxcanvas->canvas->w, (unsigned int*)&ctxcanvas->canvas->h, &bw, &d); + + ctxcanvas->canvas->w_mm = ((double)ctxcanvas->canvas->w) / ctxcanvas->canvas->xres; + ctxcanvas->canvas->h_mm = ((double)ctxcanvas->canvas->h) / ctxcanvas->canvas->yres; + + if (ctxcanvas->canvas->use_matrix) + ctxcanvas->canvas->cxTransform(ctxcanvas, ctxcanvas->canvas->matrix); + + return CD_OK; +} + +static void cdcreatecanvas(cdCanvas* canvas, void *data) +{ + char* data_str = (char*)data; + Window wnd; + Display *dpy; + XWindowAttributes wa; + +#ifdef SunOS_OLD + sscanf(data_str, "%d %lu", &dpy, &wnd); +#else + sscanf(data_str, "%p %lu", &dpy, &wnd); +#endif + + if (!dpy || !wnd) + return; + + XGetWindowAttributes(dpy, wnd, &wa); + cdxCreateCanvas(canvas, dpy, XScreenNumberOfScreen(wa.screen), wnd, wa.visual); +} + +static void cdinittable(cdCanvas* canvas) +{ + cdxInitTable(canvas); + + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxActivate = cdactivate; +} + +/******************************************************/ + +static cdContext cdNativeWindowContext = +{ + CD_CAP_ALL & ~(CD_CAP_PLAY | CD_CAP_YAXIS | CD_CAP_FPRIMTIVES ), + 1, + cdcreatecanvas, + cdinittable, + NULL, + NULL, +}; + + +cdContext* cdContextNativeWindow(void) +{ + if (cdUseContextPlus(CD_QUERY)) + { + cdContext* ctx = cdGetContextPlus(CD_CTX_NATIVEWINDOW); + if (ctx != NULL) + return ctx; + } + + return &cdNativeWindowContext; +} diff --git a/cd/src/x11/xvertex.c b/cd/src/x11/xvertex.c new file mode 100755 index 0000000..e1ca7ee --- /dev/null +++ b/cd/src/x11/xvertex.c @@ -0,0 +1,1431 @@ +/* ********************************************************************** */ + +/* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) +* +* Permission to use, copy, modify, and distribute this software and its +* documentation for any purpose and without fee is hereby granted, provided +* that the above copyright notice appear in all copies and that both the +* copyright notice and this permission notice appear in supporting +* documentation. All work developed as a consequence of the use of +* this program should duly acknowledge such use. No representations are +* made about the suitability of this software for any purpose. It is +* provided "as is" without express or implied warranty. +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "xvertex.h" + + +/* ---------------------------------------------------------------------- */ + + +/* Make sure cache size is set */ + +#ifndef CACHE_SIZE_LIMIT +#define CACHE_SIZE_LIMIT 300 +#endif /*CACHE_SIZE_LIMIT */ + +/* Make sure a cache method is specified */ + +#ifndef CACHE_XIMAGES +#ifndef CACHE_BITMAPS +#define CACHE_BITMAPS +#endif /*CACHE_BITMAPS*/ +#endif /*CACHE_XIMAGES*/ + + +/* ---------------------------------------------------------------------- */ + + +/* Debugging macros */ + +#ifdef DEBUG +#define DEBUG_PRINT1(a) printf (a) +#define DEBUG_PRINT2(a, b) printf (a, b) +#define DEBUG_PRINT3(a, b, c) printf (a, b, c) +#define DEBUG_PRINT4(a, b, c, d) printf (a, b, c, d) +#define DEBUG_PRINT5(a, b, c, d, e) printf (a, b, c, d, e) +#else +#define DEBUG_PRINT1(a) (a) +#define DEBUG_PRINT2(a, b) (a, b) +#define DEBUG_PRINT3(a, b, c) (a, b, c) +#define DEBUG_PRINT4(a, b, c, d) (a, b, c, d) +#define DEBUG_PRINT5(a, b, c, d, e) (a, b, c, d, e) +#endif /*DEBUG*/ + + + +/* ---------------------------------------------------------------------- */ + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + + +/* ---------------------------------------------------------------------- */ + + +/* A structure holding everything needed for a rotated string */ + +typedef struct rotated_text_item_template { + Pixmap bitmap; + XImage *ximage; + + char *text; + char *font_name; + Font fid; + double angle; + int align; + double magnify; + + int cols_in; + int rows_in; + int cols_out; + int rows_out; + + int nl; + int max_width; + double *corners_x; + double *corners_y; + + long int size; + int cached; + + struct rotated_text_item_template *next; +} RotatedTextItem; + +static RotatedTextItem *first_text_item=NULL; + + +/* ---------------------------------------------------------------------- */ + + +/* A structure holding current magnification and bounding box padding */ + +static struct style_template { + double magnify; + int bbx_pad; +} style={ + 1., + 0 +}; + + +/* ---------------------------------------------------------------------- */ + +static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, double angle, const char *text, int len, int align); +static void XRotAddToLinkedList(Display *dpy, RotatedTextItem *item); +static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage); +static void XRotFreeTextItem(Display *dpy, RotatedTextItem *item); + +/* ---------------------------------------------------------------------- */ + +/**************************************************************************/ +/* Routine to mimic `my_strdup()' (some machines don't have it) */ +/**************************************************************************/ + +static char *my_strdup(const char *str, int len) +{ + char *s; + + if(str==NULL) + return NULL; + + s=(char *)malloc((unsigned)(len+1)); + if(s!=NULL) + { + memcpy(s, str, len); + s[len]=0; + } + + return s; +} + +/**************************************************************************/ +/* Routine to replace `strtok' : this one returns a zero length string if */ +/* it encounters two consecutive delimiters */ +/**************************************************************************/ + +static char *my_strtok(char *str1, const char *str2) +{ + char *ret; + int i, j, stop, len2; + static int start, len; + static char *stext; + + if(str2==NULL) + return NULL; + + /* initialise if str1 not NULL */ + if(str1!=NULL) + { + start=0; + stext=str1; + len=strlen(str1); + } + + /* run out of tokens ? */ + if(start>=len) + return NULL; + + len2 = strlen(str2); + + /* loop through characters */ + for(i=start; ibyte_order=I->bitmap_bit_order=MSBFirst; + return I; +} + +/* ---------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Draw a horizontal string in a quick fashion */ +/**************************************************************************/ + +static int XRotDrawHorizontalString(Display *dpy, XFontStruct *font, Drawable drawable, GC gc, int x, int y, const char *text, int len, int align, int bg) +{ + GC my_gc; + int nl=1, i; + int height; + int xp, yp; + char *str1, *str2, *str3; + char *str2_a="\0", *str2_b="\n\0"; + int dir, asc, desc; + XCharStruct overall; + + DEBUG_PRINT1("**\nHorizontal text.\n"); + + /* this gc has similar properties to the user's gc (including stipple) */ + my_gc=XCreateGC(dpy, drawable, 0, 0); + XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle| GCTileStipXOrigin|GCTileStipYOrigin|GCPlaneMask, my_gc); + XSetFont(dpy, my_gc, font->fid); + + /* count number of sections in string */ + if(align!=XR_LEFT) + for(i=0; iascent+font->descent; + + /* y position */ + if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT) + yp=y+font->ascent; + else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT) + yp=y-nl*height/2+font->ascent; + else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT) + yp=y-nl*height+font->ascent; + else + yp=y; + + str1=my_strdup(text, len); + if(str1==NULL) + return 1; + + /* loop through each section in the string */ + str3=my_strtok(str1, str2); + do + { + int len3 = strlen(str3); + XTextExtents(font, str3, len3, &dir, &asc, &desc, &overall); + + /* where to draw section in x ? */ + if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT) + xp=x; + else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE) + xp=x-overall.rbearing/2; + else + xp=x-overall.rbearing; + + /* draw string onto bitmap */ + if(!bg) + XDrawString(dpy, drawable, my_gc, xp, yp, str3, len3); + else + XDrawImageString(dpy, drawable, my_gc, xp, yp, str3, len3); + + /* move to next line */ + yp+=height; + + str3=my_strtok((char *)NULL, str2); + } while(str3!=NULL); + + free(str1); + XFreeGC(dpy, my_gc); + + return 0; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Query cache for a match with this font/text/angle/alignment */ +/* request, otherwise arrange for its creation */ +/**************************************************************************/ + +static RotatedTextItem *XRotRetrieveFromCache(Display *dpy, XFontStruct *font, double angle, const char *text, int len, int align) +{ + Font fid; + char *font_name=NULL; + unsigned long name_value; + RotatedTextItem *item=NULL; + RotatedTextItem *i1=first_text_item; + + /* get font name, if it exists */ + if(XGetFontProperty(font, XA_FONT, &name_value)) { + DEBUG_PRINT1("got font name OK\n"); + font_name=XGetAtomName(dpy, name_value); + fid=0; + } +#ifdef CACHE_FID + /* otherwise rely (unreliably?) on font ID */ + else { + DEBUG_PRINT1("can't get fontname, caching FID\n"); + font_name=NULL; + fid=font->fid; + } +#else + /* not allowed to cache font ID's */ + else { + DEBUG_PRINT1("can't get fontname, can't cache\n"); + font_name=NULL; + fid=0; + } +#endif /*CACHE_FID*/ + + /* look for a match in cache */ + + /* matching formula: + identical text; + identical fontname (if defined, font ID's if not); + angles close enough (<0.00001 here, could be smaller); + HORIZONTAL alignment matches, OR it's a one line string; + magnifications the same */ + + while(i1 && !item) + { + /* match everything EXCEPT fontname/ID */ + if(strcmp(text, i1->text)==0 && + fabs(angle-i1->angle)<0.00001 && + style.magnify==i1->magnify && + (i1->nl==1 || + ((align==0)?9:(align-1))%3== + ((i1->align==0)?9:(i1->align-1))%3)) + { + + /* now match fontname/ID */ + if(font_name!=NULL && i1->font_name!=NULL) + { + if(strcmp(font_name, i1->font_name)==0) + { + item=i1; + DEBUG_PRINT1("Matched against font names\n"); + } + else + i1=i1->next; + } +#ifdef CACHE_FID + else if(font_name==NULL && i1->font_name==NULL) + { + if(fid==i1->fid) + { + item=i1; + DEBUG_PRINT1("Matched against FID's\n"); + } + else + i1=i1->next; + } +#endif /*CACHE_FID*/ + else + i1=i1->next; + } + else + i1=i1->next; + } + + if(item) + DEBUG_PRINT1("**\nFound target in cache.\n"); + if(!item) + DEBUG_PRINT1("**\nNo match in cache.\n"); + + /* no match */ + if(!item) + { + /* create new item */ + item=XRotCreateTextItem(dpy, font, angle, text, len, align); + if(!item) + return NULL; + + /* record what it shows */ + item->text=my_strdup(text, len); + + /* fontname or ID */ + if(font_name!=NULL) + { + item->font_name=my_strdup(font_name, strlen(font_name)); + item->fid=0; + } + else + { + item->font_name=NULL; + item->fid=fid; + } + + item->angle=angle; + item->align=align; + item->magnify=style.magnify; + + /* cache it */ + XRotAddToLinkedList(dpy, item); + } + + if(font_name) + XFree(font_name); + + /* if XImage is cached, need to recreate the bitmap */ + +#ifdef CACHE_XIMAGES + { + GC depth_one_gc; + + /* create bitmap to hold rotated text */ + item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy), + item->cols_out, item->rows_out, 1); + + /* depth one gc */ + depth_one_gc=XCreateGC(dpy, item->bitmap, 0, 0); + XSetBackground(dpy, depth_one_gc, 0); + XSetForeground(dpy, depth_one_gc, 1); + + /* make the text bitmap from XImage */ + XPutImage(dpy, item->bitmap, depth_one_gc, item->ximage, 0, 0, 0, 0, + item->cols_out, item->rows_out); + + XFreeGC(dpy, depth_one_gc); + } +#endif /*CACHE_XIMAGES*/ + + return item; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Create a rotated text item */ +/**************************************************************************/ + +static RotatedTextItem *XRotCreateTextItem(Display *dpy, XFontStruct *font, double angle, const char *text, int len, int align) +{ + RotatedTextItem *item=NULL; + Pixmap canvas; + GC font_gc; + XImage *I_in; + register int i, j; + char *str1, *str2, *str3; + char *str2_a="\0", *str2_b="\n\0"; + int height; + int byte_w_in, byte_w_out; + int xp, yp; + double sin_angle, cos_angle; + int it, jt; + double di, dj; + int ic=0; + double xl, xr, xinc; + int byte_out; + int dir, asc, desc; + XCharStruct overall; + int old_cols_in=0, old_rows_in=0; + + /* allocate memory */ + item=(RotatedTextItem *)malloc((unsigned)sizeof(RotatedTextItem)); + if(!item) + return NULL; + + /* count number of sections in string */ + item->nl=1; + if(align!=XR_LEFT) + for(i=0; inl++; + + /* ignore newline characters if not doing alignment */ + if(align==XR_LEFT) + str2=str2_a; + else + str2=str2_b; + + /* find width of longest section */ + str1=my_strdup(text, len); + if(str1==NULL) + return NULL; + + str3=my_strtok(str1, str2); + + XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall); + + item->max_width=overall.rbearing; + + /* loop through each section */ + do + { + str3=my_strtok((char *)NULL, str2); + + if(str3!=NULL) + { + XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall); + + if(overall.rbearing>item->max_width) + item->max_width=overall.rbearing; + } + } while(str3!=NULL); + + free(str1); + + /* overall font height */ + height=font->ascent+font->descent; + + /* dimensions horizontal text will have */ + item->cols_in=item->max_width; + item->rows_in=item->nl*height; + + /* bitmap for drawing on */ + canvas=XCreatePixmap(dpy, DefaultRootWindow(dpy), + item->cols_in, item->rows_in, 1); + + /* create a GC for the bitmap */ + font_gc=XCreateGC(dpy, canvas, 0, 0); + XSetBackground(dpy, font_gc, 0); + XSetFont(dpy, font_gc, font->fid); + + /* make sure the bitmap is blank */ + XSetForeground(dpy, font_gc, 0); + XFillRectangle(dpy, canvas, font_gc, 0, 0, + item->cols_in+1, item->rows_in+1); + XSetForeground(dpy, font_gc, 1); + + /* pre-calculate sin and cos */ + sin_angle=sin(angle); + cos_angle=cos(angle); + + if (fabs(sin_angle)==1.0) cos_angle=0; + if (fabs(cos_angle)==1.0) sin_angle=0; + + /* text background will be drawn using XFillPolygon */ + item->corners_x= + (double *)malloc((unsigned)(4*item->nl*sizeof(double))); + if(!item->corners_x) + return NULL; + + item->corners_y= + (double *)malloc((unsigned)(4*item->nl*sizeof(double))); + if(!item->corners_y) + return NULL; + + /* draw text horizontally */ + + /* start at top of bitmap */ + yp=font->ascent; + + str1=my_strdup(text, len); + if(str1==NULL) + return NULL; + + str3=my_strtok(str1, str2); + + /* loop through each section in the string */ + do + { + XTextExtents(font, str3, strlen(str3), &dir, &asc, &desc, &overall); + + /* where to draw section in x ? */ + if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT) + xp=0; + else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE) + xp=(item->max_width-overall.rbearing)/2; + else + xp=item->max_width-overall.rbearing; + + /* draw string onto bitmap */ + XDrawString(dpy, canvas, font_gc, xp, yp, str3, strlen(str3)); + + /* keep a note of corner positions of this string */ + item->corners_x[ic]=((double)xp-(double)item->cols_in/2)*style.magnify; + item->corners_y[ic]=((double)(yp-font->ascent)-(double)item->rows_in/2) + *style.magnify; + item->corners_x[ic+1]=item->corners_x[ic]; + item->corners_y[ic+1]=item->corners_y[ic]+(double)height*style.magnify; + item->corners_x[item->nl*4-1-ic]=item->corners_x[ic]+ + (double)overall.rbearing*style.magnify; + item->corners_y[item->nl*4-1-ic]=item->corners_y[ic]; + item->corners_x[item->nl*4-2-ic]= + item->corners_x[item->nl*4-1-ic]; + item->corners_y[item->nl*4-2-ic]=item->corners_y[ic+1]; + + ic+=2; + + /* move to next line */ + yp+=height; + + str3=my_strtok((char *)NULL, str2); + } while(str3!=NULL); + + free(str1); + + /* create image to hold horizontal text */ + I_in=MakeXImage(dpy, item->cols_in, item->rows_in); + if(I_in==NULL) + return NULL; + + /* extract horizontal text */ + XGetSubImage(dpy, canvas, 0, 0, item->cols_in, item->rows_in, 1, XYPixmap, I_in, 0, 0); + I_in->format=XYBitmap; + + /* magnify horizontal text */ + if(style.magnify!=1.) + { + I_in=XRotMagnifyImage(dpy, I_in); + + old_cols_in=item->cols_in; + old_rows_in=item->rows_in; + item->cols_in=(double)item->cols_in*style.magnify; + item->rows_in=(double)item->rows_in*style.magnify; + } + + /* how big will rotated text be ? */ + item->cols_out=fabs((double)item->rows_in*sin_angle) + + fabs((double)item->cols_in*cos_angle) +0.99999 +2; + + item->rows_out=fabs((double)item->rows_in*cos_angle) + + fabs((double)item->cols_in*sin_angle) +0.99999 +2; + + if(item->cols_out%2==0) + item->cols_out++; + + if(item->rows_out%2==0) + item->rows_out++; + + /* create image to hold rotated text */ + item->ximage=MakeXImage(dpy, item->cols_out, item->rows_out); + if(item->ximage==NULL) + return NULL; + + byte_w_in=(item->cols_in-1)/8+1; + byte_w_out=(item->cols_out-1)/8+1; + + /* we try to make this bit as fast as possible - which is why it looks + a bit over-the-top */ + + /* vertical distance from centre */ + dj=0.5-(double)item->rows_out/2; + + /* where abouts does text actually lie in rotated image? */ + if(angle==0 || angle==M_PI/2 || angle==M_PI || angle==3*M_PI/2) + { + xl=0; + xr=(double)item->cols_out; + xinc=0; + } + else if(anglecols_out/2+ + (dj-(double)item->rows_in/(2*cos_angle))/ + tan(angle)-2; + + xr=(double)item->cols_out/2+ + (dj+(double)item->rows_in/(2*cos_angle))/ + tan(angle)+2; + + xinc=1./tan(angle); + } + else + { + xl=(double)item->cols_out/2+ + (dj+(double)item->rows_in/(2*cos_angle))/ + tan(angle)-2; + + xr=(double)item->cols_out/2+ + (dj-(double)item->rows_in/(2*cos_angle))/ + tan(angle)+2; + + xinc=1./tan(angle); + } + + /* loop through all relevent bits in rotated image */ + for(j=0; jrows_out; j++) + { + /* no point re-calculating these every pass */ + di=(double)((xl<0)?0:(int)xl)+0.5-(double)item->cols_out/2; + byte_out=(item->rows_out-j-1)*byte_w_out; + + /* loop through meaningful columns */ + for(i=((xl<0)?0:(int)xl);i<((xr>=item->cols_out)?item->cols_out:(int)xr); i++) + { + /* rotate coordinates */ + it=(double)item->cols_in/2 + ( di*cos_angle + dj*sin_angle); + jt=(double)item->rows_in/2 - (-di*sin_angle + dj*cos_angle); + + /* set pixel if required */ + if(it>=0 && itcols_in && jt>=0 && jtrows_in) + if((I_in->data[jt*byte_w_in+it/8] & 128>>(it%8))>0) + item->ximage->data[byte_out+i/8]|=128>>i%8; + + di+=1; + } + + dj+=1; + xl+=xinc; + xr+=xinc; + } + + XDestroyImage(I_in); + + if(style.magnify!=1.) + { + item->cols_in=old_cols_in; + item->rows_in=old_rows_in; + } + + +#ifdef CACHE_BITMAPS + + /* create a bitmap to hold rotated text */ + item->bitmap=XCreatePixmap(dpy, DefaultRootWindow(dpy), + item->cols_out, item->rows_out, 1); + + /* make the text bitmap from XImage */ + XPutImage(dpy, item->bitmap, font_gc, item->ximage, 0, 0, 0, 0, + item->cols_out, item->rows_out); + + XDestroyImage(item->ximage); + +#endif /*CACHE_BITMAPS*/ + + XFreeGC(dpy, font_gc); + XFreePixmap(dpy, canvas); + + return item; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Adds a text item to the end of the cache, removing as many items */ +/* from the front as required to keep cache size below limit */ +/**************************************************************************/ + +static void XRotAddToLinkedList(Display *dpy, RotatedTextItem *item) +{ + + static long int current_size=0; + static RotatedTextItem *last=NULL; + RotatedTextItem *i1=first_text_item, *i2=NULL; + +#ifdef CACHE_BITMAPS + + /* I don't know how much memory a pixmap takes in the server - + probably this + a bit more we can't account for */ + + item->size=((item->cols_out-1)/8+1)*item->rows_out; + +#else + + /* this is pretty much the size of a RotatedTextItem */ + + item->size=((item->cols_out-1)/8+1)*item->rows_out + + sizeof(XImage) + strlen(item->text) + + item->nl*8*sizeof(double) + sizeof(RotatedTextItem); + + if(item->font_name!=NULL) + item->size+=strlen(item->font_name); + else + item->size+=sizeof(Font); + +#endif /*CACHE_BITMAPS */ + +#ifdef DEBUG + /* count number of items in cache, for debugging */ + { + int i=0; + + while(i1) { + i++; + i1=i1->next; + } + DEBUG_PRINT2("Cache has %d items.\n", i); + i1=first_text_item; + } +#endif + + DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%d\n", + current_size, item->size, CACHE_SIZE_LIMIT*1024); + + /* if this item is bigger than whole cache, forget it */ + if(item->size>CACHE_SIZE_LIMIT*1024) { + DEBUG_PRINT1("Too big to cache\n\n"); + item->cached=0; + return; + } + + /* remove elements from cache as needed */ + while(i1 && current_size+item->size>CACHE_SIZE_LIMIT*1024) { + + DEBUG_PRINT2("Removed %ld bytes\n", i1->size); + + if(i1->font_name!=NULL) + DEBUG_PRINT5(" (`%s'\n %s\n angle=%f align=%d)\n", + i1->text, i1->font_name, i1->angle, i1->align); + +#ifdef CACHE_FID + if(i1->font_name==NULL) + DEBUG_PRINT5(" (`%s'\n FID=%ld\n angle=%f align=%d)\n", + i1->text, i1->fid, i1->angle, i1->align); +#endif /*CACHE_FID*/ + + current_size-=i1->size; + + i2=i1->next; + + /* free resources used by the unlucky item */ + XRotFreeTextItem(dpy, i1); + + /* remove it from linked list */ + first_text_item=i2; + i1=i2; + } + + /* add new item to end of linked list */ + if(first_text_item==NULL) { + item->next=NULL; + first_text_item=item; + last=item; + } + else { + item->next=NULL; + last->next=item; + last=item; + } + + /* new cache size */ + current_size+=item->size; + + item->cached=1; + + DEBUG_PRINT1("Added item to cache.\n"); +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Free the resources used by a text item */ +/**************************************************************************/ + +static void XRotFreeTextItem(Display *dpy, RotatedTextItem *item) +{ + free(item->text); + + if(item->font_name!=NULL) + free(item->font_name); + + free((char *)item->corners_x); + free((char *)item->corners_y); + +#ifdef CACHE_BITMAPS + XFreePixmap(dpy, item->bitmap); +#else + XDestroyImage(item->ximage); +#endif /* CACHE_BITMAPS */ + + free((char *)item); +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Magnify an XImage using bilinear interpolation */ +/**************************************************************************/ + +static XImage *XRotMagnifyImage(Display *dpy, XImage *ximage) +{ + int i, j; + double x, y; + double u,t; + XImage *I_out; + int cols_in, rows_in; + int cols_out, rows_out; + register int i2, j2; + double z1, z2, z3, z4; + int byte_width_in, byte_width_out; + double mag_inv; + + /* size of input image */ + cols_in=ximage->width; + rows_in=ximage->height; + + /* size of final image */ + cols_out=(double)cols_in*style.magnify; + rows_out=(double)rows_in*style.magnify; + + /* this will hold final image */ + I_out=MakeXImage(dpy, cols_out, rows_out); + if(I_out==NULL) + return NULL; + + /* width in bytes of input, output images */ + byte_width_in=(cols_in-1)/8+1; + byte_width_out=(cols_out-1)/8+1; + + /* for speed */ + mag_inv=1./style.magnify; + + y=0.; + + /* loop over magnified image */ + for(j2=0; j2data[j*byte_width_in+i/8] & 128>>(i%8))>0; + z2=z1; + z3=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0; + z4=z3; + } + /* top edge */ + else if(i!=cols_in-1 && j==rows_in-1) + { + t=x-(double)i; + u=0; + + z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; + z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0; + z3=z2; + z4=z1; + } + /* top right corner */ + else if(i==cols_in-1 && j==rows_in-1) + { + u=0; + t=0; + + z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; + z2=z1; + z3=z1; + z4=z1; + } + /* somewhere `safe' */ + else + { + t=x-(double)i; + u=y-(double)j; + + z1=(ximage->data[j*byte_width_in+i/8] & 128>>(i%8))>0; + z2=(ximage->data[j*byte_width_in+(i+1)/8] & 128>>((i+1)%8))>0; + z3=(ximage->data[(j+1)*byte_width_in+(i+1)/8] & + 128>>((i+1)%8))>0; + z4=(ximage->data[(j+1)*byte_width_in+i/8] & 128>>(i%8))>0; + } + + /* if interpolated value is greater than 0.5, set bit */ + if(((1-t)*(1-u)*z1 + t*(1-u)*z2 + t*u*z3 + (1-t)*u*z4)>0.5) + I_out->data[j2*byte_width_out+i2/8]|=128>>i2%8; + + x+=mag_inv; + } + y+=mag_inv; + } + + /* destroy original */ + XDestroyImage(ximage); + + /* return big image */ + return I_out; +} + + + + +/**************************************************************************/ +/* Return version/copyright information */ +/**************************************************************************/ + +double XRotVersion(char* str, int n) +{ + if(str!=NULL) + strncpy(str, XV_COPYRIGHT, n); + return XV_VERSION; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Set the font magnification factor for all subsequent operations */ +/**************************************************************************/ + +void XRotSetMagnification(double m) +{ + if(m>0.) + style.magnify=m; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Set the padding used when calculating bounding boxes */ +/**************************************************************************/ + +void XRotSetBoundingBoxPad(int p) +{ + if(p>=0) + style.bbx_pad=p; +} + + +/* ---------------------------------------------------------------------- */ + + +/**************************************************************************/ +/* Calculate the bounding box some text will have when painted */ +/**************************************************************************/ + +XPoint *XRotTextExtents(Display* dpy, XFontStruct* font, double angle, int x, int y, const char* text, int len, int align) +{ + register int i; + char *str1, *str2, *str3; + char *str2_a="\0", *str2_b="\n\0"; + int height; + double sin_angle, cos_angle; + int nl, max_width; + int cols_in, rows_in; + double hot_x, hot_y; + XPoint *xp_in, *xp_out; + int dir, asc, desc; + XCharStruct overall; + + /* manipulate angle to 0<=angle<360 degrees */ + while(angle<0) + angle+=360; + + while(angle>360) + angle-=360; + + angle*=M_PI/180; + + /* count number of sections in string */ + nl=1; + if(align!=XR_LEFT) + for(i=0; imax_width) + max_width=overall.rbearing; + } + } while(str3!=NULL); + + free(str1); + + /* overall font height */ + height=font->ascent+font->descent; + + /* dimensions horizontal text will have */ + cols_in=max_width; + rows_in=nl*height; + + /* pre-calculate sin and cos */ + sin_angle=sin(angle); + cos_angle=cos(angle); + + /* y position */ + if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT) + hot_y=(double)rows_in/2*style.magnify; + else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT) + hot_y=0; + else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT) + hot_y=-(double)rows_in/2*style.magnify; + else + hot_y=-((double)rows_in/2-(double)font->descent)*style.magnify; + + /* x position */ + if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT) + hot_x=-(double)max_width/2*style.magnify; + else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE) + hot_x=0; + else + hot_x=(double)max_width/2*style.magnify; + + /* reserve space for XPoints */ + xp_in=(XPoint *)malloc((unsigned)(5*sizeof(XPoint))); + if(!xp_in) + return NULL; + + xp_out=(XPoint *)malloc((unsigned)(5*sizeof(XPoint))); + if(!xp_out) + return NULL; + + /* bounding box when horizontal, relative to bitmap centre */ + xp_in[0].x=-(double)cols_in*style.magnify/2-style.bbx_pad; + xp_in[0].y= (double)rows_in*style.magnify/2+style.bbx_pad; + xp_in[1].x= (double)cols_in*style.magnify/2+style.bbx_pad; + xp_in[1].y= (double)rows_in*style.magnify/2+style.bbx_pad; + xp_in[2].x= (double)cols_in*style.magnify/2+style.bbx_pad; + xp_in[2].y=-(double)rows_in*style.magnify/2-style.bbx_pad; + xp_in[3].x=-(double)cols_in*style.magnify/2-style.bbx_pad; + xp_in[3].y=-(double)rows_in*style.magnify/2-style.bbx_pad; + xp_in[4].x=xp_in[0].x; + xp_in[4].y=xp_in[0].y; + + /* rotate and translate bounding box */ + for(i=0; i<5; i++) + { + xp_out[i].x=(double)x + ( ((double)xp_in[i].x-hot_x)*cos_angle + + ((double)xp_in[i].y+hot_y)*sin_angle); + + xp_out[i].y=(double)y + (-((double)xp_in[i].x-hot_x)*sin_angle + + ((double)xp_in[i].y+hot_y)*cos_angle); + } + + free((char *)xp_in); + + return xp_out; +} + +/* ---------------------------------------------------------------------- */ + +/**************************************************************************/ +/* Aligns and paints a rotated string */ +/**************************************************************************/ + +int XRotDrawString(Display* dpy, XFontStruct* font, double angle, Drawable drawable, GC gc, int x, int y, const char* text, int len, int align, int bg) +{ + int i; + GC my_gc; + int xp, yp; + double hot_x, hot_y; + double hot_xp, hot_yp; + double sin_angle, cos_angle; + RotatedTextItem *item; + Pixmap bitmap_to_paint; + + /* manipulate angle to 0<=angle<360 degrees */ + while(angle<0) + angle+=360; + + while(angle>=360) + angle-=360; + + angle*=M_PI/180; + + /* horizontal text made easy */ + if(angle==0. && style.magnify==1.) + return(XRotDrawHorizontalString(dpy, font, drawable, gc, x, y, text, len, align, bg)); + + /* get a rotated bitmap */ + item=XRotRetrieveFromCache(dpy, font, angle, text, len, align); + if(item==NULL) + return 0; + + /* this gc has similar properties to the user's gc */ + my_gc=XCreateGC(dpy, drawable, 0, 0); + XCopyGC(dpy, gc, GCForeground|GCBackground|GCFunction|GCPlaneMask, my_gc); + + /* alignment : which point (hot_x, hot_y) relative to bitmap centre + coincides with user's specified point? */ + + /* y position */ + if(align==XR_TLEFT || align==XR_TCENTRE || align==XR_TRIGHT) + hot_y=(double)item->rows_in/2*style.magnify; + else if(align==XR_MLEFT || align==XR_MCENTRE || align==XR_MRIGHT) + hot_y=0; + else if(align==XR_BLEFT || align==XR_BCENTRE || align==XR_BRIGHT) + hot_y=-(double)item->rows_in/2*style.magnify; + else + hot_y=-((double)item->rows_in/2-(double)font->descent)*style.magnify; + + /* x position */ + if(align==XR_TLEFT || align==XR_MLEFT || align==XR_BLEFT || align==XR_LEFT) + hot_x=-(double)item->max_width/2*style.magnify; + else if(align==XR_TCENTRE || align==XR_MCENTRE || align==XR_BCENTRE || align==XR_CENTRE) + hot_x=0; + else + hot_x=(double)item->max_width/2*style.magnify; + + /* pre-calculate sin and cos */ + sin_angle=sin(angle); + cos_angle=cos(angle); + + /* rotate hot_x and hot_y around bitmap centre */ + hot_xp= hot_x*cos_angle - hot_y*sin_angle; + hot_yp= hot_x*sin_angle + hot_y*cos_angle; + + /* text background will be drawn using XFillPolygon */ + if(bg) + { + GC depth_one_gc; + XPoint *xpoints; + Pixmap empty_stipple; + + /* reserve space for XPoints */ + xpoints=(XPoint *)malloc((unsigned)(4*item->nl*sizeof(XPoint))); + if(!xpoints) + return 1; + + /* rotate corner positions */ + for(i=0; i<4*item->nl; i++) + { + xpoints[i].x=(double)x + ( (item->corners_x[i]-hot_x)*cos_angle + + (item->corners_y[i]+hot_y)*sin_angle); + + xpoints[i].y=(double)y + (-(item->corners_x[i]-hot_x)*sin_angle + + (item->corners_y[i]+hot_y)*cos_angle); + } + + /* we want to swap foreground and background colors here; + XGetGCValues() is only available in R4+ */ + + empty_stipple=XCreatePixmap(dpy, drawable, 1, 1, 1); + + depth_one_gc=XCreateGC(dpy, empty_stipple, 0, 0); + XSetForeground(dpy, depth_one_gc, 0); + XFillRectangle(dpy, empty_stipple, depth_one_gc, 0, 0, 2, 2); + + XSetStipple(dpy, my_gc, empty_stipple); + XSetFillStyle(dpy, my_gc, FillOpaqueStippled); + + XFillPolygon(dpy, drawable, my_gc, xpoints, 4*item->nl, Nonconvex, + CoordModeOrigin); + + /* free our resources */ + free((char *)xpoints); + XFreeGC(dpy, depth_one_gc); + XFreePixmap(dpy, empty_stipple); + } + + /* where should top left corner of bitmap go ? */ + xp=(double)x-((double)item->cols_out/2 +hot_xp); + yp=(double)y-((double)item->rows_out/2 -hot_yp); + + /* by default we draw the rotated bitmap, solid */ + bitmap_to_paint=item->bitmap; + + /* handle user stippling */ +#ifndef X11R3 + { + GC depth_one_gc; + XGCValues values; + Pixmap new_bitmap, inverse; + + /* try and get some GC properties */ + if(XGetGCValues(dpy, gc, + GCStipple|GCFillStyle|GCForeground|GCBackground| + GCTileStipXOrigin|GCTileStipYOrigin, + &values)) + { + /* only do this if stippling requested */ + if((values.fill_style==FillStippled || + values.fill_style==FillOpaqueStippled) && !bg) + { + /* opaque stipple: draw rotated text in background colour */ + if(values.fill_style==FillOpaqueStippled) + { + XSetForeground(dpy, my_gc, values.background); + XSetFillStyle(dpy, my_gc, FillStippled); + XSetStipple(dpy, my_gc, item->bitmap); + XSetTSOrigin(dpy, my_gc, xp, yp); + XFillRectangle(dpy, drawable, my_gc, xp, yp, + item->cols_out, item->rows_out); + XSetForeground(dpy, my_gc, values.foreground); + } + + /* this will merge the rotated text and the user's stipple */ + new_bitmap=XCreatePixmap(dpy, drawable, + item->cols_out, item->rows_out, 1); + + /* create a GC */ + depth_one_gc=XCreateGC(dpy, new_bitmap, 0, 0); + XSetForeground(dpy, depth_one_gc, 1); + XSetBackground(dpy, depth_one_gc, 0); + + /* set the relative stipple origin */ + XSetTSOrigin(dpy, depth_one_gc, + values.ts_x_origin-xp, values.ts_y_origin-yp); + + /* fill the whole bitmap with the user's stipple */ + XSetStipple(dpy, depth_one_gc, values.stipple); + XSetFillStyle(dpy, depth_one_gc, FillOpaqueStippled); + XFillRectangle(dpy, new_bitmap, depth_one_gc, + 0, 0, item->cols_out, item->rows_out); + + /* set stipple origin back to normal */ + XSetTSOrigin(dpy, depth_one_gc, 0, 0); + + /* this will contain an inverse copy of the rotated text */ + inverse=XCreatePixmap(dpy, drawable, + item->cols_out, item->rows_out, 1); + + /* invert text */ + XSetFillStyle(dpy, depth_one_gc, FillSolid); + XSetFunction(dpy, depth_one_gc, GXcopyInverted); + XCopyArea(dpy, item->bitmap, inverse, depth_one_gc, + 0, 0, item->cols_out, item->rows_out, 0, 0); + + /* now delete user's stipple everywhere EXCEPT on text */ + XSetForeground(dpy, depth_one_gc, 0); + XSetBackground(dpy, depth_one_gc, 1); + XSetStipple(dpy, depth_one_gc, inverse); + XSetFillStyle(dpy, depth_one_gc, FillStippled); + XSetFunction(dpy, depth_one_gc, GXcopy); + XFillRectangle(dpy, new_bitmap, depth_one_gc, + 0, 0, item->cols_out, item->rows_out); + + /* free resources */ + XFreePixmap(dpy, inverse); + XFreeGC(dpy, depth_one_gc); + + /* this is the new bitmap */ + bitmap_to_paint=new_bitmap; + } + } + } +#endif /*X11R3*/ + + /* paint text using stipple technique */ + XSetFillStyle(dpy, my_gc, FillStippled); + XSetStipple(dpy, my_gc, bitmap_to_paint); + XSetTSOrigin(dpy, my_gc, xp, yp); + XFillRectangle(dpy, drawable, my_gc, xp, yp, + item->cols_out, item->rows_out); + + /* free our resources */ + XFreeGC(dpy, my_gc); + + /* stippled bitmap no longer needed */ + if(bitmap_to_paint!=item->bitmap) + XFreePixmap(dpy, bitmap_to_paint); + +#ifdef CACHE_XIMAGES + XFreePixmap(dpy, item->bitmap); +#endif /*CACHE_XIMAGES*/ + + /* if item isn't cached, destroy it completely */ + if(!item->cached) + XRotFreeTextItem(dpy,item); + + /* we got to the end OK! */ + return 0; +} + + diff --git a/cd/src/x11/xvertex.h b/cd/src/x11/xvertex.h new file mode 100755 index 0000000..8bb247d --- /dev/null +++ b/cd/src/x11/xvertex.h @@ -0,0 +1,31 @@ +/* ************************************************************************ */ +/* Header file for the `xvertext 5.0' routines. + + Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) */ +/* ************************************************************************ */ + +#ifndef __XVERTEXT_H +#define __XVERTEXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define XV_VERSION 5.0 +#define XV_COPYRIGHT \ + "xvertext routines Copyright (c) 1993 Alan Richardson" + +/* text alignment */ +enum {XR_LEFT, XR_CENTRE, XR_RIGHT, XR_TLEFT, XR_TCENTRE, XR_TRIGHT, XR_MLEFT, XR_MCENTRE, XR_MRIGHT, XR_BLEFT, XR_BCENTRE, XR_BRIGHT}; + +double XRotVersion(char* str, int n); +void XRotSetMagnification(double m); +void XRotSetBoundingBoxPad(int p); +XPoint *XRotTextExtents(Display* dpy, XFontStruct* font, double angle, int x, int y, const char* text, int len, int align); +int XRotDrawString(Display* dpy, XFontStruct* font, double angle, Drawable drawable, GC gc, int x, int y, const char* text, int len, int align, int bg); + +#ifdef __cplusplus +} +#endif + +#endif /* _XVERTEXT_INCLUDED_ */ diff --git a/cd/src/xrender/cdxrender.c b/cd/src/xrender/cdxrender.c new file mode 100755 index 0000000..4dc69e2 --- /dev/null +++ b/cd/src/xrender/cdxrender.c @@ -0,0 +1,1137 @@ +/** file + * brief XRender Base Driver + * + * See Copyright Notice in cd.h + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "cdx11.h" +#include "cddbuf.h" +#include "cdimage.h" +#include "cdnative.h" +#include "truetype.h" +#include "sim.h" + +#include + +#define NUM_HATCHES 6 +static unsigned char hatches[NUM_HATCHES][8] = { + {0x00,0x00,0xFF,0x00,0x00,0x00,0xFF,0x00}, /* HORIZONTAL */ + {0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22}, /* VERTICAL */ + {0x08,0x10,0x20,0x40,0x80,0x01,0x02,0x04}, /* FDIAGONAL */ + {0x10,0x08,0x04,0x02,0x01,0x80,0x40,0x20}, /* BDIAGONAL */ + {0x22,0x22,0xFF,0x22,0x22,0x22,0xFF,0x22}, /* CROSS */ + {0x18,0x18,0x24,0x42,0x81,0x81,0x42,0x24} /* DIAGCROSS */ +}; + +struct _cdxContextPlus +{ + XftDraw* draw; + Picture solid_pic, pattern_pic, fill_picture, dst_picture; + XftFont *font, + *flat_font; /* used only for text size when orientation!=0 */ + XRenderPictFormat* maskFormat; + + int antialias; + +#if (RENDER_MAJOR>0 || RENDER_MINOR>=10) + XLinearGradient linegradient; + Picture linegradient_pic; +#endif + + void (*cxKillCanvas)(cdCtxCanvas* ctxcanvas); +}; + + +static void xrInitColor(XRenderColor *rendercolor, long color) +{ + rendercolor->red = cdCOLOR8TO16(cdRed(color)); + rendercolor->green = cdCOLOR8TO16(cdGreen(color)); + rendercolor->blue = cdCOLOR8TO16(cdBlue(color)); + rendercolor->alpha = cdCOLOR8TO16(cdAlpha(color)); +} + +static void xrPolyFill(cdCtxCanvas* ctxcanvas, XPointDouble* fpoly, int n) +{ + XRenderCompositeDoublePoly(ctxcanvas->dpy, PictOpOver, ctxcanvas->ctxplus->fill_picture, + ctxcanvas->ctxplus->dst_picture, ctxcanvas->ctxplus->maskFormat, 0, 0, 0, 0, + fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?EvenOddRule:WindingRule); +} + +static void xrLine(cdCtxCanvas *ctxcanvas, XPointDouble* fpoly) +{ + XRenderCompositeDoublePoly(ctxcanvas->dpy, PictOpOver, ctxcanvas->ctxplus->solid_pic, + ctxcanvas->ctxplus->dst_picture, ctxcanvas->ctxplus->maskFormat, 0, 0, 0, 0, + fpoly, 4, 0); +} + +static void xrSetClipMask(cdCtxCanvas* ctxcanvas, Pixmap clip_mask) +{ + XRenderPictureAttributes pa; + pa.clip_mask = clip_mask; + XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, CPClipMask, &pa); +} + +static void xrSetClipArea(cdCtxCanvas* ctxcanvas) +{ + cdRect* clip_rect = &ctxcanvas->canvas->clip_rect; + XRectangle rect; + rect.x = (short)clip_rect->xmin; + rect.y = (short)clip_rect->ymin; + rect.width = (unsigned short)(clip_rect->xmax - clip_rect->xmin + 1); + rect.height = (unsigned short)(clip_rect->ymax - clip_rect->ymin + 1); + XRenderSetPictureClipRectangles(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, 0, 0, &rect, 1); +} + +static int cdclip(cdCtxCanvas *ctxcanvas, int clip_mode) +{ + switch (clip_mode) + { + case CD_CLIPOFF: + xrSetClipMask(ctxcanvas, None); + break; + case CD_CLIPAREA: + xrSetClipArea(ctxcanvas); + break; + case CD_CLIPPOLYGON: + if (ctxcanvas->clip_polygon) + xrSetClipMask(ctxcanvas, ctxcanvas->clip_polygon); + break; + case CD_CLIPREGION: + if (ctxcanvas->new_region) + xrSetClipMask(ctxcanvas, ctxcanvas->new_region); + break; + } + + /* call original method, to set the clipping for the PutImage* methods */ + cdxClip(ctxcanvas, clip_mode); + + return clip_mode; +} + +static void cdcliparea(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + if (ctxcanvas->canvas->clip_mode == CD_CLIPAREA) + { + ctxcanvas->canvas->clip_rect.xmin = xmin; + ctxcanvas->canvas->clip_rect.ymin = ymin; + ctxcanvas->canvas->clip_rect.xmax = xmax; + ctxcanvas->canvas->clip_rect.ymax = ymax; + cdclip(ctxcanvas, CD_CLIPAREA); + } +} + +static void cdfline(cdCtxCanvas *ctxcanvas, double x1, double y1, double x2, double y2) +{ + int ix1, ix2, iy1, iy2; + +#ifndef CD_XRENDER_MATRIX + if (ctxcanvas->canvas->use_matrix) + { + cdfMatrixTransformPoint(ctxcanvas->xmatrix, x1, y1, &x1, &y1); + cdfMatrixTransformPoint(ctxcanvas->xmatrix, x2, y2, &x2, &y2); + } +#endif + + ix1 = _cdRound(x1); + ix2 = _cdRound(x2); + iy1 = _cdRound(y1); + iy2 = _cdRound(y2); + if ((ctxcanvas->canvas->line_width == 1) && + ((ix1 == ix2 && ix1==x1) || (iy1 == iy2 && iy1==y1))) + { + XRenderColor rendercolor; + xrInitColor(&rendercolor, ctxcanvas->canvas->foreground); + if (ix2 < ix1) _cdSwapInt(ix2, ix1); + if (iy2 < iy1) _cdSwapInt(iy2, iy1); + XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, ix1, iy1, ix2-ix1+1, iy2-iy1+1); + } + else + { + double half_width = ctxcanvas->canvas->line_width/2.0; + XPointDouble fpoly[4]; + + /* XRender does not have a function to draw lines. + So we have to draw a poligon that covers the line area. */ + + double dx = x2-x1; + double dy = y2-y1; + double d = half_width/hypot(dx, dy); + double dnx = d*dx; + double dny = d*dy; + + fpoly[0].x = x1 + dny; + fpoly[0].y = y1 - dnx; + fpoly[1].x = x1 - dny; + fpoly[1].y = y1 + dnx; + fpoly[2].x = fpoly[1].x + dx; + fpoly[2].y = fpoly[1].y + dy; + fpoly[3].x = fpoly[0].x + dx; + fpoly[3].y = fpoly[0].y + dy; + + xrLine(ctxcanvas, fpoly); + } +} + +static void cdline(cdCtxCanvas *ctxcanvas, int x1, int y1, int x2, int y2) +{ + cdfline(ctxcanvas, (double)x1, (double)y1, (double)x2, (double)y2); +} + +static void cdrect(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfSimRect(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void cdbox(cdCtxCanvas *ctxcanvas, int xmin, int xmax, int ymin, int ymax) +{ + cdfSimBox(ctxcanvas, (double)xmin, (double)xmax, (double)ymin, (double)ymax); +} + +static void xrFixAngles(cdCtxCanvas *ctxcanvas, double *angle1, double *angle2) +{ + if (ctxcanvas->canvas->invert_yaxis) + { + double temp = 360 - *angle1; + *angle1 = 360 - *angle2; + *angle2 = temp; + } +} + +static void cdarc(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimArc(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2); +} + +static void cdfarc(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimArc(ctxcanvas, xc, yc, w, h, a1, a2); +} + +static void cdfsector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1); +} + +static void cdsector(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimElipse(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, 1); +} + +static void cdfchord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0); +} + +static void cdchord(cdCtxCanvas *ctxcanvas, int xc, int yc, int w, int h, double a1, double a2) +{ + xrFixAngles(ctxcanvas, &a1, &a2); + cdfSimElipse(ctxcanvas, (double)xc, (double)yc, (double)w, (double)h, a1, a2, 0); +} + +static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n) +{ + int i; + + switch(mode) + { + case CD_CLOSED_LINES: + fpoly[n] = fpoly[0]; + n++; + /* continue */ + case CD_OPEN_LINES: + for (i = 0; i< n - 1; i++) + cdfline(ctxcanvas, fpoly[i].x, fpoly[i].y, fpoly[i+1].x, fpoly[i+1].y); + break; + case CD_BEZIER: + cdfSimPolyBezier(ctxcanvas->canvas, fpoly, n); + break; + case CD_FILL: + { + if (ctxcanvas->canvas->new_region) + { + cdPoint* poly = malloc(sizeof(cdPoint)*n); + + for (i = 0; icanvas->use_matrix) + cdfMatrixTransformPoint(ctxcanvas->xmatrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y); +#endif + } + + xrPolyFill(ctxcanvas, poly, n); + + free(poly); + } + } + break; + case CD_CLIP: + { + cdPoint* poly = malloc(sizeof(cdPoint)*n); + + for (i = 0; icanvas->clip_mode == CD_CLIPPOLYGON) cdclip(ctxcanvas, CD_CLIPPOLYGON); + } + break; + } +} + +static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n) +{ + int i; + + switch(mode) + { + case CD_CLOSED_LINES: + poly[n] = poly[0]; + n++; + /* continue */ + case CD_OPEN_LINES: + for (i = 0; icanvas, fpoly, n); + + free(fpoly); + } + break; + case CD_FILL: + { + if (ctxcanvas->canvas->new_region) + { + cdxPoly(ctxcanvas, CD_FILL, poly, n); + } + else + { + XPointDouble* fpoly = malloc(sizeof(XPointDouble)*n); + + for (i = 0; icanvas->use_matrix) + cdfMatrixTransformPoint(ctxcanvas->xmatrix, fpoly[i].x, fpoly[i].y, &fpoly[i].x, &fpoly[i].y); +#endif + } + + xrPolyFill(ctxcanvas, fpoly, n); + + free(fpoly); + } + } + break; + case CD_CLIP: + cdxPoly(ctxcanvas, CD_CLIP, poly, n); + if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON) cdclip(ctxcanvas, CD_CLIPPOLYGON); + break; + } +} + +static void cdtransform(cdCtxCanvas *ctxcanvas, const double* matrix) +{ +#ifndef CD_XRENDER_MATRIX + if (matrix) + { + /* configure a bottom-up coordinate system */ + ctxcanvas->xmatrix[0] = 1; + ctxcanvas->xmatrix[1] = 0; + ctxcanvas->xmatrix[2] = 0; + ctxcanvas->xmatrix[3] = -1; + ctxcanvas->xmatrix[4] = 0; + ctxcanvas->xmatrix[5] = (ctxcanvas->canvas->h-1); + cdMatrixMultiply(matrix, ctxcanvas->xmatrix); + + ctxcanvas->canvas->invert_yaxis = 0; + } + else + { + ctxcanvas->canvas->invert_yaxis = 1; + } +#else + XTransform transform; + double identity[6] = {1, 0, 0, 1, 0, 0}; + + if (!matrix) + matrix = &identity[0]; + + transform.matrix[0][0] = XDoubleToFixed(matrix[0]); /* |m0 m2 m4| |00 01 02| */ + transform.matrix[0][1] = XDoubleToFixed(matrix[2]); /* |m1 m3 m5| = |10 11 12| */ + transform.matrix[0][2] = XDoubleToFixed(matrix[4]); /* |0 0 1| |20 21 22| */ + transform.matrix[1][0] = XDoubleToFixed(matrix[1]); + transform.matrix[1][1] = XDoubleToFixed(matrix[3]); + transform.matrix[1][2] = XDoubleToFixed(matrix[5]); + transform.matrix[2][0] = XDoubleToFixed(0); + transform.matrix[2][1] = XDoubleToFixed(0); + transform.matrix[2][2] = XDoubleToFixed(1); + + /* TODO: This is not working. It gives a BadPicture error */ + XRenderSetPictureTransform(ctxcanvas->dpy, ctxcanvas->ctxplus->dst_picture, &transform); +#endif +} + +static int cdinteriorstyle(cdCtxCanvas *ctxcanvas, int style) +{ + switch (style) + { + case CD_SOLID: + if (!ctxcanvas->ctxplus->solid_pic) + return ctxcanvas->canvas->interior_style; + ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->solid_pic; + break; + case CD_HATCH: + case CD_STIPPLE: + case CD_PATTERN: + if (!ctxcanvas->ctxplus->pattern_pic) + return ctxcanvas->canvas->interior_style; + ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->pattern_pic; + break; + } + return style; +} + +static void cdpattern(cdCtxCanvas *ctxcanvas, int w, int h, const long int *colors) +{ + int x, y; + Pixmap pixmap; + XRenderPictureAttributes pa; + XRenderPictFormat* format; + + if (ctxcanvas->ctxplus->pattern_pic) + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->pattern_pic); + + format = XRenderFindStandardFormat(ctxcanvas->dpy, PictStandardARGB32); + pixmap = XCreatePixmap(ctxcanvas->dpy, DefaultRootWindow(ctxcanvas->dpy), w, h, format->depth); + pa.repeat = 1; + ctxcanvas->ctxplus->pattern_pic = XRenderCreatePicture(ctxcanvas->dpy, pixmap, format, CPRepeat, &pa); + + for (y=0; ydpy, PictOpSrc, ctxcanvas->ctxplus->pattern_pic, &rendercolor, x, h-y-1, 1, 1); + } + } + + cdinteriorstyle(ctxcanvas, CD_PATTERN); +} + +static void cdstipple(cdCtxCanvas *ctxcanvas, int w, int h, const unsigned char *data) +{ + int x, y, i; + long transparent = cdEncodeAlpha(0, 0); + long int *colors = malloc(sizeof(long)*w*h); + + for (y=0; ycanvas->back_opacity == CD_OPAQUE) + { + if (data[i]) + colors[i] = ctxcanvas->canvas->foreground; + else + colors[i] = ctxcanvas->canvas->background; + } + else + { + if (data[i]) + colors[i] = ctxcanvas->canvas->foreground; + else + colors[i] = transparent; + } + } + } + + cdpattern(ctxcanvas, w, h, colors); + free(colors); +} + +static int cdhatch(cdCtxCanvas *ctxcanvas, int hatch_style) +{ + int y; + unsigned char data[8*8]; + unsigned char *hatch = hatches[hatch_style]; + + for (y=0; y<8; y++) + { + int i = y*8; + unsigned char c = hatch[y]; + data[i+7] = (c&0x01)>>0; + data[i+6] = (c&0x02)>>1; + data[i+5] = (c&0x04)>>2; + data[i+4] = (c&0x08)>>3; + data[i+3] = (c&0x10)>>4; + data[i+2] = (c&0x20)>>5; + data[i+1] = (c&0x40)>>6; + data[i+0] = (c&0x80)>>7; + } + + cdstipple(ctxcanvas, 8, 8, data); + return hatch_style; +} + +static int cdbackopacity(cdCtxCanvas *ctxcanvas, int back_opacity) +{ + ctxcanvas->canvas->back_opacity = back_opacity; + if (ctxcanvas->canvas->interior_style == CD_STIPPLE) + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + else if (ctxcanvas->canvas->interior_style == CD_HATCH) + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + return back_opacity; +} + +static void cdclear(cdCtxCanvas* ctxcanvas) +{ + XRenderColor rendercolor; + xrInitColor(&rendercolor, ctxcanvas->canvas->background); + XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, 0, 0, ctxcanvas->canvas->w, ctxcanvas->canvas->h); +} + +static void cdpixel(cdCtxCanvas *ctxcanvas, int x, int y, long int color) +{ + XRenderColor rendercolor; + xrInitColor(&rendercolor, color); + XRenderFillRectangle(ctxcanvas->dpy, PictOpSrc, ctxcanvas->ctxplus->dst_picture, &rendercolor, x, y, 1, 1); +} + +#if (RENDER_MAJOR==0 && RENDER_MINOR<10) +static Picture XRenderCreateSolidFill(Display *dpy, const XRenderColor *color) +{ + Picture pict; + XRenderPictureAttributes pa; + XRenderPictFormat* format = XRenderFindStandardFormat(dpy, PictStandardARGB32); + Pixmap pix = XCreatePixmap(dpy, DefaultRootWindow(dpy), 1, 1, format->depth); + pa.repeat = True; + pict = XRenderCreatePicture(dpy, pix, format, CPRepeat, &pa); + XFreePixmap(dpy, pix); + + XRenderFillRectangle(dpy, PictOpSrc, pict, color, 0, 0, 1, 1); + return pict; +} +#endif + +static long int cdforeground(cdCtxCanvas *ctxcanvas, long int color) +{ + XRenderPictureAttributes pa; + XRenderColor rendercolor; + xrInitColor(&rendercolor, color); + if (ctxcanvas->ctxplus->solid_pic) + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic); + ctxcanvas->ctxplus->solid_pic = XRenderCreateSolidFill(ctxcanvas->dpy, &rendercolor); + pa.repeat = 1; + XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic, CPRepeat, &pa); + if (ctxcanvas->canvas->interior_style == CD_STIPPLE) + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + else if (ctxcanvas->canvas->interior_style == CD_HATCH) + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + else if (ctxcanvas->canvas->interior_style == CD_SOLID) + cdinteriorstyle(ctxcanvas, CD_SOLID); + return color; +} + +static long int cdbackground(cdCtxCanvas *ctxcanvas, long int color) +{ + if (ctxcanvas->canvas->back_opacity == CD_OPAQUE) + { + if (ctxcanvas->canvas->interior_style == CD_STIPPLE) + cdstipple(ctxcanvas, ctxcanvas->canvas->stipple_w, ctxcanvas->canvas->stipple_h, ctxcanvas->canvas->stipple); + else if (ctxcanvas->canvas->interior_style == CD_HATCH) + cdhatch(ctxcanvas, ctxcanvas->canvas->hatch_style); + } + return color; +} + +static int cdfont(cdCtxCanvas *ctxcanvas, const char *type_face, int style, int size) +{ + char font_name[1024]; + XftFont *font; + char matrix[200] = ""; + + /* no underline or strikeout support */ + + static char* type_style[] = + { + "", /* CD_PLAIN */ + ":bold", /* CD_BOLD */ + ":slant=italic,oblique", /* CD_ITALIC */ + ":bold:slant=italic,oblique" /* CD_BOLD_ITALIC */ + }; + + if (cdStrEqualNoCase(type_face, "Fixed") || cdStrEqualNoCase(type_face, "System")) + type_face = "monospace"; + else if (cdStrEqualNoCase(type_face, "Courier") || cdStrEqualNoCase(type_face, "Courier New")) + type_face = "monospace"; + else if (cdStrEqualNoCase(type_face, "Times") || cdStrEqualNoCase(type_face, "Times New Roman")) + type_face = "serif"; + else if (cdStrEqualNoCase(type_face, "Helvetica") || cdStrEqualNoCase(type_face, "Arial")) + type_face = "sans"; + + if (ctxcanvas->canvas->text_orientation) + { + double angle = CD_DEG2RAD*ctxcanvas->canvas->text_orientation; + double cos_angle = cos(angle); + double sin_angle = sin(angle); + + sprintf(matrix,":matrix=%f %f %f %f", cos_angle, -sin_angle, sin_angle, cos_angle); + } + + size = cdGetFontSizePoints(ctxcanvas->canvas, size); + + sprintf(font_name,"%s-%d%s%s", type_face, size, type_style[style&3], matrix); + font = XftFontOpenName(ctxcanvas->dpy, ctxcanvas->scr, font_name); + if (!font) + return 0; + + if (ctxcanvas->ctxplus->font) + XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font); + + if (ctxcanvas->canvas->text_orientation) + { + /* XftTextExtents8 will return the size of the rotated text, but we want the size without orientation. + So create a font without orientation just to return the correct text size. */ + + if (ctxcanvas->ctxplus->flat_font) + XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font); + + sprintf(font_name,"%s-%d%s", type_face, size, type_style[style&3]); + ctxcanvas->ctxplus->flat_font = XftFontOpenName(ctxcanvas->dpy, ctxcanvas->scr, font_name); + } + + ctxcanvas->ctxplus->font = font; + + return 1; +} + +static int cdnativefont(cdCtxCanvas *ctxcanvas, const char* nativefont) +{ + int size = 12, style = CD_PLAIN; + char type_face[1024]; + + if (nativefont[0] == '-') + { + XftFont *font = XftFontOpenXlfd(ctxcanvas->dpy, ctxcanvas->scr, nativefont); + if (!font) + return 0; + + if (!cdParseXWinFont(nativefont, type_face, &style, &size)) + { + XftFontClose(ctxcanvas->dpy, font); + return 0; + } + + if (ctxcanvas->ctxplus->font) + XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font); + + ctxcanvas->canvas->text_orientation = 0; /* orientation not supported when using XLFD */ + + ctxcanvas->ctxplus->font = font; + } + else + { + if (!cdParsePangoFont(nativefont, type_face, &style, &size)) + return 0; + + if (!cdfont(ctxcanvas, type_face, style, size)) + return 0; + } + + /* update cdfont parameters */ + ctxcanvas->canvas->font_style = style; + ctxcanvas->canvas->font_size = size; + strcpy(ctxcanvas->canvas->font_type_face, type_face); + + return 1; +} + +static double cdtextorientation(cdCtxCanvas *ctxcanvas, double angle) +{ + /* must recriate the font if orientation changes */ + ctxcanvas->canvas->text_orientation = angle; + cdfont(ctxcanvas, ctxcanvas->canvas->font_type_face, ctxcanvas->canvas->font_style, ctxcanvas->canvas->font_size); + return angle; +} + +static void cdgetfontdim(cdCtxCanvas *ctxcanvas, int *max_width, int *height, int *ascent, int *descent) +{ + if (!ctxcanvas->ctxplus->font) + return; + + if (max_width) *max_width = ctxcanvas->ctxplus->font->max_advance_width; + if (height) *height = ctxcanvas->ctxplus->font->ascent + ctxcanvas->ctxplus->font->descent; + if (ascent) *ascent = ctxcanvas->ctxplus->font->ascent; + if (descent) *descent = ctxcanvas->ctxplus->font->descent; +} + +static void cdgettextsize(cdCtxCanvas *ctxcanvas, const char *text, int len, int *width, int *height) +{ + XGlyphInfo extents; + if (!ctxcanvas->ctxplus->font) + return; + + if (ctxcanvas->canvas->text_orientation) + XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font, (XftChar8*)text, len, &extents); + else + XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->font, (XftChar8*)text, len, &extents); + + if (width) *width = extents.width+extents.x; + if (height) *height = extents.height+extents.y; +} + +static void cdtext(cdCtxCanvas *ctxcanvas, int x, int y, const char *text, int len) +{ + XGlyphInfo extents; + int ox, oy, w, h, descent, dir = -1; + + if (!ctxcanvas->ctxplus->font) + return; + + if (ctxcanvas->canvas->text_orientation) + XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font, (XftChar8*)text, len, &extents); + else + XftTextExtents8(ctxcanvas->dpy, ctxcanvas->ctxplus->font, (XftChar8*)text, len, &extents); + w = extents.width+extents.x; + h = extents.height+extents.y; + + descent = ctxcanvas->ctxplus->font->descent; + + ox = x; + oy = y; + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_RIGHT: + case CD_NORTH_EAST: + case CD_EAST: + case CD_SOUTH_EAST: + x = x - w; + break; + case CD_BASE_CENTER: + case CD_CENTER: + case CD_NORTH: + case CD_SOUTH: + x = x - w/2; + break; + case CD_BASE_LEFT: + case CD_NORTH_WEST: + case CD_WEST: + case CD_SOUTH_WEST: + x = x; + break; + } + + if (ctxcanvas->canvas->invert_yaxis) + dir = 1; + + switch (ctxcanvas->canvas->text_alignment) + { + case CD_BASE_LEFT: + case CD_BASE_CENTER: + case CD_BASE_RIGHT: + y = y; + break; + case CD_SOUTH_EAST: + case CD_SOUTH_WEST: + case CD_SOUTH: + y = y - dir*descent; + break; + case CD_NORTH_EAST: + case CD_NORTH: + case CD_NORTH_WEST: + y = y + dir*(h - descent); + break; + case CD_CENTER: + case CD_EAST: + case CD_WEST: + y = y + dir*(h/2 - descent); + break; + } + + if (ctxcanvas->canvas->text_orientation) + { + double angle = CD_DEG2RAD*ctxcanvas->canvas->text_orientation; + double cos_angle = cos(angle); + double sin_angle = sin(angle); + + /* manually rotate the initial point */ + cdRotatePoint(ctxcanvas->canvas, x, y, ox, oy, &x, &y, sin_angle, cos_angle); + } + +#ifndef CD_XRENDER_MATRIX + if (ctxcanvas->canvas->use_matrix) + cdMatrixTransformPoint(ctxcanvas->xmatrix, x, y, &x, &y); +#endif + + if (!ctxcanvas->canvas->new_region) + { + XftColor xftcolor; + XRenderColor rendercolor; + xrInitColor(&rendercolor, ctxcanvas->canvas->foreground); + XftColorAllocValue(ctxcanvas->dpy, ctxcanvas->vis, ctxcanvas->colormap, &rendercolor, &xftcolor); + XftDrawString8(ctxcanvas->ctxplus->draw, &xftcolor, ctxcanvas->ctxplus->font, x, y, (XftChar8*)text, len); + } +} + +/******************************************************************/ + +#if (RENDER_MAJOR>0 || RENDER_MINOR>=10) +static void set_linegradient_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (ctxcanvas->ctxplus->linegradient_pic) + { + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic); + ctxcanvas->ctxplus->linegradient_pic = 0; + } + + if (data) + { + XRenderPictureAttributes pa; + XFixed stops[2]; + XRenderColor colors[2]; + int x1, y1, x2, y2; + sscanf(data, "%d %d %d %d", &x1, &y1, &x2, &y2); + + if (ctxcanvas->canvas->invert_yaxis) + { + y1 = _cdInvertYAxis(ctxcanvas->canvas, y1); + y2 = _cdInvertYAxis(ctxcanvas->canvas, y2); + } + + stops[0] = XDoubleToFixed(0.0); + stops[1] = XDoubleToFixed(1.0); + + xrInitColor(&colors[0], ctxcanvas->canvas->foreground); + xrInitColor(&colors[1], ctxcanvas->canvas->background); + + ctxcanvas->ctxplus->linegradient.p1.x = XDoubleToFixed((double)x1); + ctxcanvas->ctxplus->linegradient.p1.y = XDoubleToFixed((double)y1); + ctxcanvas->ctxplus->linegradient.p2.x = XDoubleToFixed((double)x2); + ctxcanvas->ctxplus->linegradient.p2.y = XDoubleToFixed((double)y2); + + ctxcanvas->ctxplus->linegradient_pic = XRenderCreateLinearGradient(ctxcanvas->dpy, &ctxcanvas->ctxplus->linegradient, stops, colors, 2); + pa.repeat = 1; + XRenderChangePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic, CPRepeat, &pa); + + ctxcanvas->ctxplus->fill_picture = ctxcanvas->ctxplus->linegradient_pic; + } + else + cdinteriorstyle(ctxcanvas, ctxcanvas->canvas->interior_style); +} + +static char* get_linegradient_attrib(cdCtxCanvas* ctxcanvas) +{ + static char data[100]; + + sprintf(data, "%d %d %d %d", (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p1.x), + (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p1.y), + (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p2.x), + (int)XFixedToDouble(ctxcanvas->ctxplus->linegradient.p2.y)); + + return data; +} + +static cdAttribute linegradient_attrib = +{ + "LINEGRADIENT", + set_linegradient_attrib, + get_linegradient_attrib +}; +#endif + +static void set_aa_attrib(cdCtxCanvas* ctxcanvas, char* data) +{ + if (!data || data[0] == '0') + ctxcanvas->ctxplus->antialias = 0; + else + ctxcanvas->ctxplus->antialias = 1; + + ctxcanvas->ctxplus->maskFormat = XRenderFindStandardFormat(ctxcanvas->dpy, ctxcanvas->ctxplus->antialias? PictStandardA8: PictStandardA1); +} + +static char* get_aa_attrib(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->ctxplus->antialias) + return "1"; + else + return "0"; +} + +static cdAttribute aa_attrib = +{ + "ANTIALIAS", + set_aa_attrib, + get_aa_attrib +}; + +static char cdxXRenderVersion[50] = ""; + +static char* get_version_attrib(cdCtxCanvas* ctxcanvas) +{ + if (ctxcanvas->ctxplus) + return cdxXRenderVersion; + else + return "0"; +} + +static cdAttribute version_attrib = +{ + "XRENDERVERSION", + NULL, + get_version_attrib +}; + +static void cdkillcanvas(cdCtxCanvas *ctxcanvas) +{ + /* fill_picture is NOT released, since it is a pointer to one of the other pictures */ + if (ctxcanvas->ctxplus->solid_pic) + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->solid_pic); + + if (ctxcanvas->ctxplus->pattern_pic) + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->pattern_pic); + +#if (RENDER_MAJOR>0 || RENDER_MINOR>=10) + if (ctxcanvas->ctxplus->linegradient_pic) + XRenderFreePicture(ctxcanvas->dpy, ctxcanvas->ctxplus->linegradient_pic); +#endif + + if (ctxcanvas->ctxplus->flat_font) + XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->flat_font); + + if (ctxcanvas->ctxplus->font) + XftFontClose(ctxcanvas->dpy, ctxcanvas->ctxplus->font); + + XftDrawDestroy(ctxcanvas->ctxplus->draw); + free(ctxcanvas->ctxplus); + + /* call original method */ + ctxcanvas->ctxplus->cxKillCanvas(ctxcanvas); +} + +static void xrInitTable(cdCanvas* canvas) +{ + /* set new methods */ + canvas->cxKillCanvas = cdkillcanvas; + canvas->cxClip = cdclip; + canvas->cxClipArea = cdcliparea; + canvas->cxTransform = cdtransform; + canvas->cxInteriorStyle = cdinteriorstyle; + canvas->cxBackOpacity = cdbackopacity; + canvas->cxForeground = cdforeground; + canvas->cxBackground = cdbackground; + canvas->cxHatch = cdhatch; + canvas->cxStipple = cdstipple; + canvas->cxPattern = cdpattern; + canvas->cxTextOrientation = cdtextorientation; + + canvas->cxPixel = cdpixel; + canvas->cxClear = cdclear; + canvas->cxLine = cdline; + canvas->cxFLine = cdfline; + canvas->cxRect = cdrect; + canvas->cxFRect = cdfSimRect; + canvas->cxBox = cdbox; + canvas->cxFBox = cdfSimBox; + canvas->cxArc = cdarc; + canvas->cxFArc = cdfarc; + canvas->cxSector = cdsector; + canvas->cxFSector = cdfsector; + canvas->cxChord = cdchord; + canvas->cxFChord = cdfchord; + canvas->cxPoly = cdpoly; + canvas->cxFPoly = cdfpoly; + + /* TODO: canvas->cxPutImageRectRGBA = cdputimagerectrgba; */ + + canvas->cxFont = cdfont; + canvas->cxNativeFont = cdnativefont; + canvas->cxGetTextSize = cdgettextsize; + canvas->cxText = cdtext; + canvas->cxGetFontDim = cdgetfontdim; +} + +static void xrCreateContextPlus(cdCtxCanvas *ctxcanvas) +{ + ctxcanvas->ctxplus = (cdxContextPlus *)malloc(sizeof(cdxContextPlus)); + memset(ctxcanvas->ctxplus, 0, sizeof(cdxContextPlus)); + + if (cdxXRenderVersion[0] == 0 && XftDefaultHasRender(ctxcanvas->dpy)) + sprintf(cdxXRenderVersion,"%d.%d", RENDER_MAJOR, RENDER_MINOR); + + cdRegisterAttribute(ctxcanvas->canvas, &aa_attrib); + cdRegisterAttribute(ctxcanvas->canvas, &version_attrib); +#if (RENDER_MAJOR>0 || RENDER_MINOR>=10) + cdRegisterAttribute(ctxcanvas->canvas, &linegradient_attrib); +#endif + + ctxcanvas->ctxplus->draw = XftDrawCreate(ctxcanvas->dpy, ctxcanvas->wnd, ctxcanvas->vis, ctxcanvas->colormap); + ctxcanvas->ctxplus->dst_picture = XftDrawPicture(ctxcanvas->ctxplus->draw); + ctxcanvas->ctxplus->maskFormat = XRenderFindStandardFormat(ctxcanvas->dpy, PictStandardA8); + + ctxcanvas->ctxplus->antialias = 1; +} + +/*******************************************************************************************************/ + +static cdContext cdDBufferContext = {0,0,NULL,NULL,NULL,NULL}; +static cdContext cdNativeWindowContext = {0,0,NULL,NULL,NULL,NULL}; +static cdContext cdImageContext = {0,0,NULL,NULL,NULL,NULL}; + +static void (*cdcreatecanvasDBUFFER)(cdCanvas* canvas, void* data) = NULL; +static void (*cdcreatecanvasNATIVE)(cdCanvas* canvas, void* data) = NULL; +static void (*cdcreatecanvasIMAGE)(cdCanvas* canvas, void* data) = NULL; + +static void (*cdinittableDBUFFER)(cdCanvas* canvas) = NULL; +static void (*cdinittableNATIVE)(cdCanvas* canvas) = NULL; +static void (*cdinittableIMAGE)(cdCanvas* canvas) = NULL; + +static void (*cdkillcanvasDBUFFER)(cdCtxCanvas* ctxcanvas) = NULL; +static void (*cdkillcanvasNATIVE)(cdCtxCanvas* ctxcanvas) = NULL; +static void (*cdkillcanvasIMAGE)(cdCtxCanvas* ctxcanvas) = NULL; + +static void xrCreateCanvasDBUFFER(cdCanvas* canvas, void *data) +{ + cdcreatecanvasDBUFFER(canvas, data); /* call original first */ + xrCreateContextPlus(canvas->ctxcanvas); + canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasDBUFFER; /* must set it here since CreateContext clears the structure */ +} + +static void xrInitTableDBUFFER(cdCanvas* canvas) +{ + if (!cdkillcanvasDBUFFER) cdkillcanvasDBUFFER = canvas->cxKillCanvas; /* save original method */ + cdinittableDBUFFER(canvas); + xrInitTable(canvas); +} + +cdContext* cdContextDBufferPlus(void) +{ + if (!cdDBufferContext.plus) + { + int old_plus = cdUseContextPlus(0); /* disable context plus */ + cdDBufferContext = *cdContextDBuffer(); /* copy original context */ + cdDBufferContext.plus = 1; /* mark as plus */ + + /* save original methods */ + cdcreatecanvasDBUFFER = cdDBufferContext.cxCreateCanvas; + cdinittableDBUFFER = cdDBufferContext.cxInitTable; + + /* replace by new methods */ + cdDBufferContext.cxCreateCanvas = xrCreateCanvasDBUFFER; + cdDBufferContext.cxInitTable = xrInitTableDBUFFER; + + cdUseContextPlus(old_plus); /* enable context plus */ + } + return &cdDBufferContext; +} + +static void xrCreateCanvasNATIVE(cdCanvas* canvas, void *data) +{ + cdcreatecanvasNATIVE(canvas, data); + xrCreateContextPlus(canvas->ctxcanvas); + canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasNATIVE; +} + +static void xrInitTableNATIVE(cdCanvas* canvas) +{ + if (!cdkillcanvasNATIVE) cdkillcanvasNATIVE = canvas->cxKillCanvas; + cdinittableNATIVE(canvas); + xrInitTable(canvas); +} + +cdContext* cdContextNativeWindowPlus(void) +{ + if (!cdNativeWindowContext.plus) + { + int old_plus = cdUseContextPlus(0); + cdNativeWindowContext = *cdContextNativeWindow(); + cdcreatecanvasNATIVE = cdNativeWindowContext.cxCreateCanvas; + cdinittableNATIVE = cdNativeWindowContext.cxInitTable; + cdNativeWindowContext.cxCreateCanvas = xrCreateCanvasNATIVE; + cdNativeWindowContext.cxInitTable = xrInitTableNATIVE; + cdNativeWindowContext.plus = 1; + cdUseContextPlus(old_plus); + } + return &cdNativeWindowContext; +} + +static void xrCreateCanvasIMAGE(cdCanvas* canvas, void *data) +{ + cdcreatecanvasIMAGE(canvas, data); + xrCreateContextPlus(canvas->ctxcanvas); + canvas->ctxcanvas->ctxplus->cxKillCanvas = cdkillcanvasIMAGE; +} + +static void xrInitTableIMAGE(cdCanvas* canvas) +{ + if (!cdkillcanvasIMAGE) cdkillcanvasIMAGE = canvas->cxKillCanvas; + cdinittableIMAGE(canvas); + xrInitTable(canvas); +} + +cdContext* cdContextImagePlus(void) +{ + if (!cdImageContext.plus) + { + int old_plus = cdUseContextPlus(0); + cdImageContext = *cdContextImage(); + cdcreatecanvasIMAGE = cdImageContext.cxCreateCanvas; + cdinittableIMAGE = cdImageContext.cxInitTable; + cdImageContext.cxCreateCanvas = xrCreateCanvasIMAGE; + cdImageContext.cxInitTable = xrInitTableIMAGE; + cdImageContext.plus = 1; + cdUseContextPlus(old_plus); + } + return &cdImageContext; +} diff --git a/cd/src/xrender/cdxrplus.c b/cd/src/xrender/cdxrplus.c new file mode 100755 index 0000000..f938a6f --- /dev/null +++ b/cd/src/xrender/cdxrplus.c @@ -0,0 +1,26 @@ +/** \file + * \brief X-Render Control + * + * See Copyright Notice in cd.h + */ + +#include "cd.h" +#include "cd_private.h" +#include +#include + +cdContext* cdContextNativeWindowPlus(void); +cdContext* cdContextImagePlus(void); +cdContext* cdContextDBufferPlus(void); + +void cdInitContextPlus(void) +{ + cdContext* ctx_list[NUM_CONTEXTPLUS]; + memset(ctx_list, 0, sizeof(ctx_list)); + + ctx_list[CD_CTX_NATIVEWINDOW] = cdContextNativeWindowPlus(); + ctx_list[CD_CTX_IMAGE] = cdContextImagePlus(); + ctx_list[CD_CTX_DBUFFER] = cdContextDBufferPlus(); + + cdInitContextPlusList(ctx_list); +} -- cgit v1.2.3