diff options
Diffstat (limited to 'cd/src/sim')
| -rwxr-xr-x | cd/src/sim/cd_truetype.c | 177 | ||||
| -rwxr-xr-x | cd/src/sim/cd_truetype.h | 46 | ||||
| -rwxr-xr-x | cd/src/sim/cdfontex.c | 646 | ||||
| -rwxr-xr-x | cd/src/sim/sim.c | 326 | ||||
| -rwxr-xr-x | cd/src/sim/sim.h | 55 | ||||
| -rwxr-xr-x | cd/src/sim/sim_linepolyfill.c | 1000 | ||||
| -rwxr-xr-x | cd/src/sim/sim_other.c | 411 | ||||
| -rwxr-xr-x | cd/src/sim/sim_primitives.c | 524 | ||||
| -rwxr-xr-x | cd/src/sim/truetype.h | 46 | 
9 files changed, 3231 insertions, 0 deletions
| 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 <string.h> +#include <stdlib.h> +#include <memory.h> +#include <stdio.h> + +#include "cd_truetype.h" + +/******************************************* +        Inicializa o Rasterizador +********************************************/ + +#ifdef WIN32 +#include <windows.h> +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 <stdlib.h> +#include <string.h> + +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 <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <memory.h> + +#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 <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <memory.h> +#include <assert.h> + +#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 <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <memory.h> + +#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 <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <memory.h> + +#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_ */ + | 
