diff --git a/README.md b/README.md deleted file mode 100644 index 3f39cc0..0000000 --- a/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# cavepedia - -## Requirements - -- go 1.16+ -- konvajs 7.2.5 -- survex img.{c,h} 1.2.45 diff --git a/Skydusky.3d b/Skydusky.3d deleted file mode 100644 index 8617464..0000000 Binary files a/Skydusky.3d and /dev/null differ diff --git a/launch.sh b/launch.sh index a32bcc9..3deec96 100755 --- a/launch.sh +++ b/launch.sh @@ -5,23 +5,15 @@ set -e build () { pushd ./src &>/dev/null -# go get honnef.co/go/tools/cmd/staticcheck - go mod tidy + go get honnef.co/go/tools/cmd/staticcheck + go get github.com/zserge/lorca gofmt -w . -# staticcheck . - CGO_ENABLED=1 go build -o ./kavea -v . + staticcheck . + CGO_ENABLED=1 GOARCH=amd64 go build -o ./cavepedia_linux_amd64 -v . popd &>/dev/null } -run () { - ./src/kavea -} - -release () { - build -} - $@ diff --git a/src/common.go b/src/common.go deleted file mode 100644 index 4a0128c..0000000 --- a/src/common.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "log" - "net/http" -) - -func checkError(err error) bool { - if err != nil { - log.Print("ERROR! " + err.Error()) - return false - } - return true -} - -/* HTTP */ -func checkWebError(w http.ResponseWriter, err error) bool { - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return false - } - return true -} - -//func getURLParam(r *http.Request, param string) string { -// paramList, exists := r.URL.Query()[param] -// if !exists { -// return "" -// } -// return paramList[0] -//} diff --git a/src/go.mod b/src/go.mod index f10f0c6..f6df017 100644 --- a/src/go.mod +++ b/src/go.mod @@ -2,7 +2,4 @@ module git.seaturtle.pw/pew/kavea go 1.16 -require ( - github.com/zserge/lorca v0.1.10 - golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect -) +require github.com/zserge/lorca v0.1.10 diff --git a/src/go.sum b/src/go.sum deleted file mode 100644 index 50f399c..0000000 --- a/src/go.sum +++ /dev/null @@ -1,14 +0,0 @@ -github.com/zserge/lorca v0.1.10 h1:f/xBJ3D3ipcVRCcvN8XqZnpoKcOXV8I4vwqlFyw7ruc= -github.com/zserge/lorca v0.1.10/go.mod h1:bVmnIbIRlOcoV285KIRSe4bUABKi7R7384Ycuum6e4A= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/src/img.c b/src/img.c deleted file mode 100644 index 93e5ac3..0000000 --- a/src/img.c +++ /dev/null @@ -1,2778 +0,0 @@ -/* img.c - * Routines for reading and writing Survex ".3d" image files - * Copyright (C) 1993-2021 Olly Betts - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "img.h" - -#define TIMENA "?" -#ifdef IMG_HOSTED -# define INT32_T int32_t -# define UINT32_T uint32_t -# include "debug.h" -# include "filelist.h" -# include "filename.h" -# include "message.h" -# include "useful.h" -# define TIMEFMT msg(/*%a,%Y.%m.%d %H:%M:%S %Z*/107) -#else -# ifdef HAVE_STDINT_H -# include -# define INT32_T int32_t -# define UINT32_T uint32_t -# else -# include -# if INT_MAX >= 2147483647 -# define INT32_T int -# define UINT32_T unsigned -# else -# define INT32_T long -# define UINT32_T unsigned long -# endif -# endif -# define TIMEFMT "%a,%Y.%m.%d %H:%M:%S %Z" -# define EXT_SVX_3D "3d" -# define EXT_SVX_POS "pos" -# define FNM_SEP_EXT '.' -# define METRES_PER_FOOT 0.3048 /* exact value */ -# define xosmalloc(L) malloc((L)) -# define xosrealloc(L,S) realloc((L),(S)) -# define osfree(P) free((P)) -# define osnew(T) (T*)malloc(sizeof(T)) - -/* in IMG_HOSTED mode, this tests if a filename refers to a directory */ -# define fDirectory(X) 0 -/* open file FNM with mode MODE, maybe using path PTH and/or extension EXT */ -/* path isn't used in img.c, but EXT is */ -# define fopenWithPthAndExt(PTH,FNM,EXT,MODE,X) \ - ((*(X) = NULL), fopen(FNM,MODE)) -# ifndef PUTC -# define PUTC(C, FH) putc(C, FH) -# endif -# ifndef GETC -# define GETC(FH) getc(FH) -# endif -# define fputsnl(S, FH) (fputs((S), (FH)) == EOF ? EOF : putc('\n', (FH))) -# define SVX_ASSERT(X) - -#ifdef __cplusplus -# include -using std::max; -using std::min; -#else -/* Return max/min of two numbers. */ -/* May be defined already (e.g. by Borland C in stdlib.h) */ -/* NB Bad news if X or Y has side-effects... */ -# ifndef max -# define max(X, Y) ((X) > (Y) ? (X) : (Y)) -# endif -# ifndef min -# define min(X, Y) ((X) < (Y) ? (X) : (Y)) -# endif -#endif - -static INT32_T -get32(FILE *fh) -{ - UINT32_T w = GETC(fh); - w |= (UINT32_T)GETC(fh) << 8l; - w |= (UINT32_T)GETC(fh) << 16l; - w |= (UINT32_T)GETC(fh) << 24l; - return (INT32_T)w; -} - -static void -put32(UINT32_T w, FILE *fh) -{ - PUTC((char)(w), fh); - PUTC((char)(w >> 8l), fh); - PUTC((char)(w >> 16l), fh); - PUTC((char)(w >> 24l), fh); -} - -static short -get16(FILE *fh) -{ - UINT32_T w = GETC(fh); - w |= (UINT32_T)GETC(fh) << 8l; - return (short)w; -} - -static void -put16(short word, FILE *fh) -{ - unsigned short w = (unsigned short)word; - PUTC((char)(w), fh); - PUTC((char)(w >> 8l), fh); -} - -static char * -baseleaf_from_fnm(const char *fnm) -{ - const char *p; - const char *q; - char * res; - size_t len; - - p = fnm; - q = strrchr(p, '/'); - if (q) p = q + 1; - q = strrchr(p, '\\'); - if (q) p = q + 1; - - q = strrchr(p, FNM_SEP_EXT); - if (q) len = (const char *)q - p; else len = strlen(p); - - res = (char *)xosmalloc(len + 1); - if (!res) return NULL; - memcpy(res, p, len); - res[len] = '\0'; - return res; -} -#endif - -static char * my_strdup(const char *str); - -static time_t -mktime_with_tz(struct tm * tm, const char * tz) -{ - time_t r; - char * old_tz = getenv("TZ"); -#ifdef _MSC_VER - if (old_tz) { - old_tz = my_strdup(old_tz); - if (!old_tz) - return (time_t)-1; - } - if (_putenv_s("TZ", tz) != 0) { - osfree(old_tz); - return (time_t)-1; - } -#elif defined HAVE_SETENV - if (old_tz) { - old_tz = my_strdup(old_tz); - if (!old_tz) - return (time_t)-1; - } - if (setenv("TZ", tz, 1) < 0) { - osfree(old_tz); - return (time_t)-1; - } -#else - char * p; - if (old_tz) { - size_t len = strlen(old_tz) + 1; - p = (char *)xosmalloc(len + 3); - if (!p) - return (time_t)-1; - memcpy(p, "TZ=", 3); - memcpy(p + 3, tz, len); - old_tz = p; - } - p = (char *)xosmalloc(strlen(tz) + 4); - if (!p) { - osfree(old_tz); - return (time_t)-1; - } - memcpy(p, "TZ=", 3); - strcpy(p + 3, tz); - if (putenv(p) != 0) { - osfree(p); - osfree(old_tz); - return (time_t)-1; - } -#define CLEANUP() osfree(p) -#endif - tzset(); - r = mktime(tm); - if (old_tz) { -#ifdef _MSC_VER - _putenv_s("TZ", old_tz); -#elif !defined HAVE_SETENV - putenv(old_tz); -#else - setenv("TZ", old_tz, 1); -#endif - osfree(old_tz); - } else { -#ifdef _MSC_VER - _putenv_s("TZ", ""); -#elif !defined HAVE_UNSETENV - putenv((char*)"TZ"); -#else - unsetenv("TZ"); -#endif - } -#ifdef CLEANUP - CLEANUP(); -#undef CLEANUP -#endif - return r; -} - -static unsigned short -getu16(FILE *fh) -{ - return (unsigned short)get16(fh); -} - -#include - -#if !defined HAVE_LROUND && !defined HAVE_DECL_LROUND -/* The autoconf tests are not in use, but C99 and C++11 both added lround(), - * so set HAVE_LROUND and HAVE_DECL_LROUND conservatively based on the language - * standard version the compiler claims to support. */ -# if (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) || \ - (defined __cplusplus && __cplusplus >= 201103L) -# define HAVE_LROUND 1 -# define HAVE_DECL_LROUND 1 -# endif -#endif - -#ifdef HAVE_LROUND -# if defined HAVE_DECL_LROUND && !HAVE_DECL_LROUND -/* On older systems, the prototype may be missing. */ -extern long lround(double); -# endif -# define my_lround lround -#else -static long -my_lround(double x) { - return (x >= 0.0) ? (long)(x + 0.5) : -(long)(0.5 - x); -} -#endif - -/* portable case insensitive string compare */ -#if defined(strcasecmp) || defined(HAVE_STRCASECMP) -# define my_strcasecmp strcasecmp -#else -static int my_strcasecmp(const char *s1, const char *s2) { - unsigned char c1, c2; - do { - c1 = *s1++; - c2 = *s2++; - } while (c1 && toupper(c1) == toupper(c2)); - /* now calculate real difference */ - return c1 - c2; -} -#endif - -unsigned int img_output_version = IMG_VERSION_MAX; - -static img_errcode img_errno = IMG_NONE; - -#define FILEID "Survex 3D Image File" - -#define EXT_PLT "plt" -#define EXT_PLF "plf" - -/* Attempt to string paste to ensure we are passed a literal string */ -#define LITLEN(S) (sizeof(S"") - 1) - -/* Fake "version numbers" for non-3d formats we can read. */ -#define VERSION_CMAP_SHOT -4 -#define VERSION_CMAP_STATION -3 -#define VERSION_COMPASS_PLT -2 -#define VERSION_SURVEX_POS -1 - -static char * -my_strdup(const char *str) -{ - char *p; - size_t len = strlen(str) + 1; - p = (char *)xosmalloc(len); - if (p) memcpy(p, str, len); - return p; -} - -#define getline_alloc(FH) getline_alloc_len(FH, NULL) - -static char * -getline_alloc_len(FILE *fh, size_t * p_len) -{ - int ch; - size_t i = 0; - size_t len = 16; - char *buf = (char *)xosmalloc(len); - if (!buf) return NULL; - - ch = GETC(fh); - while (ch != '\n' && ch != '\r' && ch != EOF) { - buf[i++] = ch; - if (i == len - 1) { - char *p; - len += len; - p = (char *)xosrealloc(buf, len); - if (!p) { - osfree(buf); - return NULL; - } - buf = p; - } - ch = GETC(fh); - } - if (ch == '\n' || ch == '\r') { - int otherone = ch ^ ('\n' ^ '\r'); - ch = GETC(fh); - /* if it's not the other eol character, put it back */ - if (ch != otherone) ungetc(ch, fh); - } - buf[i] = '\0'; - if (p_len) *p_len = i; - return buf; -} - -img_errcode -img_error(void) -{ - return img_errno; -} - -static int -check_label_space(img *pimg, size_t len) -{ - if (len > pimg->buf_len) { - char *b = (char *)xosrealloc(pimg->label_buf, len); - if (!b) return 0; - pimg->label = (pimg->label - pimg->label_buf) + b; - pimg->label_buf = b; - pimg->buf_len = len; - } - return 1; -} - -/* Check if a station name should be included. */ -static int -stn_included(img *pimg) -{ - if (!pimg->survey_len) return 1; - size_t l = pimg->survey_len; - const char *s = pimg->label_buf; - if (strncmp(pimg->survey, s, l + 1) != 0) { - return 0; - } - pimg->label += l + 1; - return 1; -} - -/* Check if a survey name should be included. */ -static int -survey_included(img *pimg) -{ - if (!pimg->survey_len) return 1; - size_t l = pimg->survey_len; - const char *s = pimg->label_buf; - if (strncmp(pimg->survey, s, l) != 0 || - !(s[l] == '.' || s[l] == '\0')) { - return 0; - } - pimg->label += l; - /* skip the dot if there */ - if (*pimg->label) pimg->label++; - return 1; -} - -/* Check if a survey name in a buffer should be included. - * - * For "foreign" formats which just have one level of surveys. - */ -static int -buf_included(img *pimg, const char *buf, size_t len) -{ - return pimg->survey_len == len && strncmp(buf, pimg->survey, len) == 0; -} - -#define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\ - (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\ - my_strcasecmp((F) + (L) - LITLEN(E), E) == 0) - -img * -img_open_survey(const char *fnm, const char *survey) -{ - img *pimg; - FILE *fh; - char* filename_opened = NULL; - - if (fDirectory(fnm)) { - img_errno = IMG_DIRECTORY; - return NULL; - } - - fh = fopenWithPthAndExt("", fnm, EXT_SVX_3D, "rb", &filename_opened); - pimg = img_read_stream_survey(fh, fclose, - filename_opened ? filename_opened : fnm, - survey); - if (pimg) { - pimg->filename_opened = filename_opened; - } else { - osfree(filename_opened); - } - return pimg; -} - -img * -img_read_stream_survey(FILE *stream, int (*close_func)(FILE*), - const char *fnm, - const char *survey) -{ - img *pimg; - size_t len; - char buf[LITLEN(FILEID) + 9]; - int ch; - - if (stream == NULL) { - img_errno = IMG_FILENOTFOUND; - return NULL; - } - - pimg = osnew(img); - if (pimg == NULL) { - img_errno = IMG_OUTOFMEMORY; - if (close_func) close_func(stream); - return NULL; - } - - pimg->fh = stream; - pimg->close_func = close_func; - - pimg->buf_len = 257; - pimg->label_buf = (char *)xosmalloc(pimg->buf_len); - if (!pimg->label_buf) { - if (pimg->close_func) pimg->close_func(pimg->fh); - osfree(pimg); - img_errno = IMG_OUTOFMEMORY; - return NULL; - } - - pimg->fRead = 1; /* reading from this file */ - img_errno = IMG_NONE; - - pimg->flags = 0; - pimg->filename_opened = NULL; - - /* for version >= 3 we use label_buf to store the prefix for reuse */ - /* for VERSION_COMPASS_PLT, 0 value indicates we haven't - * entered a survey yet */ - /* for VERSION_CMAP_SHOT, we store the last station here - * to detect whether we MOVE or LINE */ - pimg->label_len = 0; - pimg->label_buf[0] = '\0'; - - pimg->survey = NULL; - pimg->survey_len = 0; - pimg->separator = '.'; -#if IMG_API_VERSION == 0 - pimg->date1 = pimg->date2 = 0; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = pimg->days2 = -1; -#endif - pimg->is_extended_elevation = 0; - - pimg->style = pimg->oldstyle = img_STYLE_UNKNOWN; - - pimg->l = pimg->r = pimg->u = pimg->d = -1.0; - - pimg->title = pimg->datestamp = pimg->cs = NULL; - pimg->datestamp_numeric = (time_t)-1; - - if (survey) { - len = strlen(survey); - if (len) { - if (survey[len - 1] == '.') len--; - if (len) { - char *p; - pimg->survey = (char *)xosmalloc(len + 2); - if (!pimg->survey) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - memcpy(pimg->survey, survey, len); - /* Set title to leaf survey name */ - pimg->survey[len] = '\0'; - p = strrchr(pimg->survey, '.'); - if (p) p++; else p = pimg->survey; - pimg->title = my_strdup(p); - if (!pimg->title) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - pimg->survey[len] = '.'; - pimg->survey[len + 1] = '\0'; - } - } - pimg->survey_len = len; - } - - /* [VERSION_COMPASS_PLT, VERSION_CMAP_STATION, VERSION_CMAP_SHOT] pending - * IMG_LINE or IMG_MOVE - both have 4 added. - * [VERSION_SURVEX_POS] already skipped heading line, or there wasn't one - * [version 0] not in the middle of a 'LINE' command - * [version >= 3] not in the middle of turning a LINE into a MOVE - */ - pimg->pending = 0; - - len = strlen(fnm); - if (has_ext(fnm, len, EXT_SVX_POS)) { -pos_file: - pimg->version = VERSION_SURVEX_POS; - if (!pimg->survey) pimg->title = baseleaf_from_fnm(fnm); - pimg->datestamp = my_strdup(TIMENA); - if (!pimg->datestamp) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - pimg->start = 0; - return pimg; - } - - if (has_ext(fnm, len, EXT_PLT) || has_ext(fnm, len, EXT_PLF)) { - long fpos; -plt_file: - pimg->version = VERSION_COMPASS_PLT; - /* Spaces aren't legal in Compass station names, but dots are, so - * use space as the level separator */ - pimg->separator = ' '; - pimg->start = 0; - if (!pimg->survey) pimg->title = baseleaf_from_fnm(fnm); - pimg->datestamp = my_strdup(TIMENA); - if (!pimg->datestamp) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - while (1) { - ch = GETC(pimg->fh); - switch (ch) { - case '\x1a': - fseek(pimg->fh, -1, SEEK_CUR); - /* FALL THRU */ - case EOF: - pimg->start = ftell(pimg->fh); - return pimg; - case 'N': { - char *line, *q; - fpos = ftell(pimg->fh) - 1; - if (!pimg->survey) { - /* FIXME : if there's only one survey in the file, it'd be nice - * to use its description as the title here... - */ - ungetc('N', pimg->fh); - pimg->start = fpos; - return pimg; - } - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - len = 0; - while (line[len] > 32) ++len; - if (!buf_included(pimg, line, len)) { - osfree(line); - continue; - } - q = strchr(line + len, 'C'); - if (q && q[1]) { - osfree(pimg->title); - pimg->title = my_strdup(q + 1); - } else if (!pimg->title) { - pimg->title = my_strdup(pimg->label); - } - osfree(line); - if (!pimg->title) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - if (!pimg->start) pimg->start = fpos; - fseek(pimg->fh, pimg->start, SEEK_SET); - return pimg; - } - case 'M': case 'D': - pimg->start = ftell(pimg->fh) - 1; - break; - } - while (ch != '\n' && ch != '\r') { - ch = GETC(pimg->fh); - } - } - } - - /* Although these are often referred to as "CMAP .XYZ files", it seems - * that actually, the extension .XYZ isn't used, rather .SHT (shot - * variant, produced by CMAP v16 and later), .UNA (unadjusted) and - * .ADJ (adjusted) extensions are. Since img has long checked for - * .XYZ, we continue to do so in case anyone is relying on it. - */ - if (has_ext(fnm, len, "sht") || - has_ext(fnm, len, "adj") || - has_ext(fnm, len, "una") || - has_ext(fnm, len, "xyz")) { - char *line; -xyz_file: - /* Spaces aren't legal in CMAP station names, but dots are, so - * use space as the level separator. */ - pimg->separator = ' '; - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - /* There doesn't seem to be a spec for what happens after 1999 with cmap - * files, so this code allows for: - * * 21xx -> xx (up to 2150) - * * 21xx -> 1xx (up to 2199) - * * full year being specified instead of 2 digits - */ - len = strlen(line); - if (len > 59) { - /* Don't just truncate at column 59, allow for a > 2 digit year. */ - char * p = strstr(line + len, "Page"); - if (p) { - while (p > line && p[-1] == ' ') - --p; - *p = '\0'; - len = p - line; - } else { - line[59] = '\0'; - } - } - if (len > 45) { - /* YY/MM/DD HH:MM */ - struct tm tm; - unsigned long v; - char * p; - pimg->datestamp = my_strdup(line + 45); - p = pimg->datestamp; - v = strtoul(p, &p, 10); - if (v <= 50) { - /* In the absence of a spec for cmap files, assume <= 50 means 21st - * century. */ - v += 2000; - } else if (v < 200) { - /* Map 100-199 to 21st century. */ - v += 1900; - } - if (v == ULONG_MAX || *p++ != '/') - goto bad_cmap_date; - tm.tm_year = v - 1900; - v = strtoul(p, &p, 10); - if (v < 1 || v > 12 || *p++ != '/') - goto bad_cmap_date; - tm.tm_mon = v - 1; - v = strtoul(p, &p, 10); - if (v < 1 || v > 31 || *p++ != ' ') - goto bad_cmap_date; - tm.tm_mday = v; - v = strtoul(p, &p, 10); - if (v >= 24 || *p++ != ':') - goto bad_cmap_date; - tm.tm_hour = v; - v = strtoul(p, &p, 10); - if (v >= 60) - goto bad_cmap_date; - tm.tm_min = v; - if (*p == ':') { - v = strtoul(p + 1, &p, 10); - if (v > 60) - goto bad_cmap_date; - tm.tm_sec = v; - } else { - tm.tm_sec = 0; - } - tm.tm_isdst = 0; - /* We have no indication of what timezone this timestamp is in. It's - * probably local time for whoever processed the data, so just assume - * UTC, which is at least fairly central in the possibilities. - */ - pimg->datestamp_numeric = mktime_with_tz(&tm, ""); - } else { - pimg->datestamp = my_strdup(TIMENA); - } -bad_cmap_date: - if (strncmp(line, " Cave Survey Data Processed by CMAP ", - LITLEN(" Cave Survey Data Processed by CMAP ")) == 0) { - len = 0; - } else { - if (len > 45) { - line[45] = '\0'; - len = 45; - } - while (len > 2 && line[len - 1] == ' ') --len; - if (len > 2) { - line[len] = '\0'; - pimg->title = my_strdup(line + 2); - } - } - if (len <= 2) pimg->title = baseleaf_from_fnm(fnm); - osfree(line); - if (!pimg->datestamp || !pimg->title) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - if (line[0] != ' ' || (line[1] != 'S' && line[1] != 'O')) { - img_errno = IMG_BADFORMAT; - goto error; - } - if (line[1] == 'S') { - pimg->version = VERSION_CMAP_STATION; - } else { - pimg->version = VERSION_CMAP_SHOT; - } - osfree(line); - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - goto error; - } - if (line[0] != ' ' || line[1] != '-') { - img_errno = IMG_BADFORMAT; - goto error; - } - osfree(line); - pimg->start = ftell(pimg->fh); - return pimg; - } - - if (fread(buf, LITLEN(FILEID) + 1, 1, pimg->fh) != 1 || - memcmp(buf, FILEID"\n", LITLEN(FILEID) + 1) != 0) { - if (fread(buf + LITLEN(FILEID) + 1, 8, 1, pimg->fh) == 1 && - memcmp(buf, FILEID"\r\nv0.01\r\n", LITLEN(FILEID) + 9) == 0) { - /* v0 3d file with DOS EOLs */ - pimg->version = 0; - goto v03d; - } - rewind(pimg->fh); - if (buf[1] == ' ') { - if (buf[0] == ' ') { - /* Looks like a CMAP .xyz file ... */ - goto xyz_file; - } else if (strchr("ZSNF", buf[0])) { - /* Looks like a Compass .plt file ... */ - /* Almost certainly it'll start "Z " */ - goto plt_file; - } - } - if (buf[0] == '(') { - /* Looks like a Survex .pos file ... */ - goto pos_file; - } - img_errno = IMG_BADFORMAT; - goto error; - } - - /* check file format version */ - ch = GETC(pimg->fh); - pimg->version = 0; - if (tolower(ch) == 'b') { - /* binary file iff B/b prefix */ - pimg->version = 1; - ch = GETC(pimg->fh); - } - if (ch != 'v') { - img_errno = IMG_BADFORMAT; - goto error; - } - ch = GETC(pimg->fh); - if (ch == '0') { - if (fread(buf, 4, 1, pimg->fh) != 1 || memcmp(buf, ".01\n", 4) != 0) { - img_errno = IMG_BADFORMAT; - goto error; - } - /* nothing special to do */ - } else if (pimg->version == 0) { - if (ch < '2' || ch > '0' + IMG_VERSION_MAX || GETC(pimg->fh) != '\n') { - img_errno = IMG_TOONEW; - goto error; - } - pimg->version = ch - '0'; - } else { - img_errno = IMG_BADFORMAT; - goto error; - } - -v03d: - { - size_t title_len; - char * title = getline_alloc_len(pimg->fh, &title_len); - if (pimg->version == 8 && title) { - /* We sneak in an extra field after a zero byte here, containing the - * specified coordinate system (if any). Older readers will just - * not see it (which is fine), and this trick avoids us having to - * bump the 3d format version. - */ - size_t real_len = strlen(title); - if (real_len != title_len) { - pimg->cs = my_strdup(title + real_len + 1); - } - } - if (!pimg->title) { - pimg->title = title; - } else { - osfree(title); - } - } - pimg->datestamp = getline_alloc(pimg->fh); - if (!pimg->title || !pimg->datestamp) { - img_errno = IMG_OUTOFMEMORY; - error: - osfree(pimg->title); - osfree(pimg->cs); - osfree(pimg->datestamp); - osfree(pimg->filename_opened); - if (pimg->close_func) pimg->close_func(pimg->fh); - osfree(pimg); - return NULL; - } - - if (pimg->version >= 8) { - int flags = GETC(pimg->fh); - if (flags & img_FFLAG_EXTENDED) pimg->is_extended_elevation = 1; - } else { - len = strlen(pimg->title); - if (len > 11 && strcmp(pimg->title + len - 11, " (extended)") == 0) { - pimg->title[len - 11] = '\0'; - pimg->is_extended_elevation = 1; - } - } - - if (pimg->datestamp[0] == '@') { - unsigned long v; - char * p; - errno = 0; - v = strtoul(pimg->datestamp + 1, &p, 10); - if (errno == 0 && *p == '\0') - pimg->datestamp_numeric = v; - /* FIXME: We're assuming here that the C time_t epoch is 1970, which is - * true for Unix-like systems, macOS and Windows, but isn't guaranteed - * by ISO C. - */ - } else { - /* %a,%Y.%m.%d %H:%M:%S %Z */ - struct tm tm; - unsigned long v; - char * p = pimg->datestamp; - while (isalpha((unsigned char)*p)) ++p; - if (*p == ',') ++p; - while (isspace((unsigned char)*p)) ++p; - v = strtoul(p, &p, 10); - if (v == ULONG_MAX || *p++ != '.') - goto bad_3d_date; - tm.tm_year = v - 1900; - v = strtoul(p, &p, 10); - if (v < 1 || v > 12 || *p++ != '.') - goto bad_3d_date; - tm.tm_mon = v - 1; - v = strtoul(p, &p, 10); - if (v < 1 || v > 31 || *p++ != ' ') - goto bad_3d_date; - tm.tm_mday = v; - v = strtoul(p, &p, 10); - if (v >= 24 || *p++ != ':') - goto bad_3d_date; - tm.tm_hour = v; - v = strtoul(p, &p, 10); - if (v >= 60 || *p++ != ':') - goto bad_3d_date; - tm.tm_min = v; - v = strtoul(p, &p, 10); - if (v > 60) - goto bad_3d_date; - tm.tm_sec = v; - tm.tm_isdst = 0; - while (isspace((unsigned char)*p)) ++p; - /* p now points to the timezone string. - * - * However, it's likely to be a string like "BST", and such strings can - * be ambiguous (BST could be UTC+1 or UTC+6), so it is impossible to - * reliably convert in all cases. Just pass what we have to tzset() - if - * it doesn't handle it, UTC will be used. - */ - pimg->datestamp_numeric = mktime_with_tz(&tm, p); - } -bad_3d_date: - - pimg->start = ftell(pimg->fh); - - return pimg; -} - -int -img_rewind(img *pimg) -{ - if (!pimg->fRead) { - img_errno = IMG_WRITEERROR; - return 0; - } - if (fseek(pimg->fh, pimg->start, SEEK_SET) != 0) { - img_errno = IMG_READERROR; - return 0; - } - clearerr(pimg->fh); - /* [VERSION_SURVEX_POS] already skipped heading line, or there wasn't one - * [version 0] not in the middle of a 'LINE' command - * [version >= 3] not in the middle of turning a LINE into a MOVE */ - pimg->pending = 0; - - img_errno = IMG_NONE; - - /* for version >= 3 we use label_buf to store the prefix for reuse */ - /* for VERSION_COMPASS_PLT, 0 value indicates we haven't entered a survey - * yet */ - /* for VERSION_CMAP_SHOT, we store the last station here to detect whether - * we MOVE or LINE */ - pimg->label_len = 0; - pimg->style = img_STYLE_UNKNOWN; - return 1; -} - -img * -img_open_write_cs(const char *fnm, const char *title, const char *cs, int flags) -{ - if (fDirectory(fnm)) { - img_errno = IMG_DIRECTORY; - return NULL; - } - - return img_write_stream(fopen(fnm, "wb"), fclose, title, cs, flags); -} - -img * -img_write_stream(FILE *stream, int (*close_func)(FILE*), - const char *title, const char *cs, int flags) -{ - time_t tm; - img *pimg; - - if (stream == NULL) { - img_errno = IMG_FILENOTFOUND; - return NULL; - } - - pimg = osnew(img); - if (pimg == NULL) { - img_errno = IMG_OUTOFMEMORY; - if (close_func) close_func(stream); - return NULL; - } - - pimg->fh = stream; - pimg->close_func = close_func; - pimg->buf_len = 257; - pimg->label_buf = (char *)xosmalloc(pimg->buf_len); - if (!pimg->label_buf) { - if (pimg->close_func) pimg->close_func(pimg->fh); - osfree(pimg); - img_errno = IMG_OUTOFMEMORY; - return NULL; - } - - pimg->filename_opened = NULL; - - /* Output image file header */ - fputs("Survex 3D Image File\n", pimg->fh); /* file identifier string */ - if (img_output_version < 2) { - pimg->version = 1; - fputs("Bv0.01\n", pimg->fh); /* binary file format version number */ - } else { - pimg->version = (img_output_version > IMG_VERSION_MAX) ? IMG_VERSION_MAX : img_output_version; - fprintf(pimg->fh, "v%d\n", pimg->version); /* file format version no. */ - } - - fputs(title, pimg->fh); - if (pimg->version < 8 && (flags & img_FFLAG_EXTENDED)) { - /* Older format versions append " (extended)" to the title to mark - * extended elevations. */ - size_t len = strlen(title); - if (len < 11 || strcmp(title + len - 11, " (extended)") != 0) - fputs(" (extended)", pimg->fh); - } - if (pimg->version == 8 && cs && *cs) { - /* We sneak in an extra field after a zero byte here, containing the - * specified coordinate system (if any). Older readers will just not - * see it (which is fine), and this trick avoids us having to bump the - * 3d format version. - */ - PUTC('\0', pimg->fh); - fputs(cs, pimg->fh); - } - PUTC('\n', pimg->fh); - - tm = time(NULL); - if (tm == (time_t)-1) { - fputsnl(TIMENA, pimg->fh); - } else if (pimg->version <= 7) { - char date[256]; - /* output current date and time in format specified */ - strftime(date, 256, TIMEFMT, localtime(&tm)); - fputsnl(date, pimg->fh); - } else { - fprintf(pimg->fh, "@%ld\n", (long)tm); - } - - if (pimg->version >= 8) { - /* Clear bit one in case anyone has been passing true for fBinary. */ - flags &=~ 1; - PUTC(flags, pimg->fh); - } - -#if 0 - if (img_output_version >= 5) { - static const unsigned char codelengths[32] = { - 4, 8, 8, 16, 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 - }; - fwrite(codelengths, 32, 1, pimg->fh); - } -#endif - pimg->fRead = 0; /* writing to this file */ - img_errno = IMG_NONE; - - /* for version >= 3 we use label_buf to store the prefix for reuse */ - pimg->label_buf[0] = '\0'; - pimg->label_len = 0; - -#if IMG_API_VERSION == 0 - pimg->date1 = pimg->date2 = 0; - pimg->olddate1 = pimg->olddate2 = 0; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = pimg->days2 = -1; - pimg->olddays1 = pimg->olddays2 = -1; -#endif - pimg->style = pimg->oldstyle = img_STYLE_UNKNOWN; - - pimg->l = pimg->r = pimg->u = pimg->d = -1.0; - - pimg->n_legs = 0; - pimg->length = 0.0; - pimg->E = pimg->H = pimg->V = 0.0; - - /* Don't check for write errors now - let img_close() report them... */ - return pimg; -} - -static void -read_xyz_station_coords(img_point *pt, const char *line) -{ - char num[12]; - memcpy(num, line + 6, 9); - num[9] = '\0'; - pt->x = atof(num) / METRES_PER_FOOT; - memcpy(num, line + 15, 9); - pt->y = atof(num) / METRES_PER_FOOT; - memcpy(num, line + 24, 8); - num[8] = '\0'; - pt->z = atof(num) / METRES_PER_FOOT; -} - -static void -read_xyz_shot_coords(img_point *pt, const char *line) -{ - char num[12]; - memcpy(num, line + 40, 10); - num[10] = '\0'; - pt->x = atof(num) / METRES_PER_FOOT; - memcpy(num, line + 50, 10); - pt->y = atof(num) / METRES_PER_FOOT; - memcpy(num, line + 60, 9); - num[9] = '\0'; - pt->z = atof(num) / METRES_PER_FOOT; -} - -static void -subtract_xyz_shot_deltas(img_point *pt, const char *line) -{ - char num[12]; - memcpy(num, line + 15, 9); - num[9] = '\0'; - pt->x -= atof(num) / METRES_PER_FOOT; - memcpy(num, line + 24, 8); - num[8] = '\0'; - pt->y -= atof(num) / METRES_PER_FOOT; - memcpy(num, line + 32, 8); - pt->z -= atof(num) / METRES_PER_FOOT; -} - -static int -read_coord(FILE *fh, img_point *pt) -{ - SVX_ASSERT(fh); - SVX_ASSERT(pt); - pt->x = get32(fh) / 100.0; - pt->y = get32(fh) / 100.0; - pt->z = get32(fh) / 100.0; - if (ferror(fh) || feof(fh)) { - img_errno = feof(fh) ? IMG_BADFORMAT : IMG_READERROR; - return 0; - } - return 1; -} - -static int -skip_coord(FILE *fh) -{ - return (fseek(fh, 12, SEEK_CUR) == 0); -} - -static int -read_v3label(img *pimg) -{ - char *q; - long len = GETC(pimg->fh); - if (len == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (len == 0xfe) { - len += get16(pimg->fh); - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - } else if (len == 0xff) { - len = get32(pimg->fh); - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - if (feof(pimg->fh) || len < 0xfe + 0xffff) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - } - - if (!check_label_space(pimg, pimg->label_len + len + 1)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - q = pimg->label_buf + pimg->label_len; - pimg->label_len += len; - if (len && fread(q, len, 1, pimg->fh) != 1) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - q[len] = '\0'; - return 0; -} - -static int -read_v8label(img *pimg, int common_flag, size_t common_val) -{ - char *q; - size_t del, add; - if (common_flag) { - if (common_val == 0) return 0; - add = del = common_val; - } else { - int ch = GETC(pimg->fh); - if (ch == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (ch != 0x00) { - del = ch >> 4; - add = ch & 0x0f; - } else { - ch = GETC(pimg->fh); - if (ch == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (ch != 0xff) { - del = ch; - } else { - del = get32(pimg->fh); - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - } - ch = GETC(pimg->fh); - if (ch == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (ch != 0xff) { - add = ch; - } else { - add = get32(pimg->fh); - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - } - } - - if (add > del && !check_label_space(pimg, pimg->label_len + add - del + 1)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - } - if (del > pimg->label_len) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - pimg->label_len -= del; - q = pimg->label_buf + pimg->label_len; - pimg->label_len += add; - if (add && fread(q, add, 1, pimg->fh) != 1) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - q[add] = '\0'; - return 0; -} - -static int img_read_item_new(img *pimg, img_point *p); -static int img_read_item_v3to7(img *pimg, img_point *p); -static int img_read_item_ancient(img *pimg, img_point *p); -static int img_read_item_ascii_wrapper(img *pimg, img_point *p); -static int img_read_item_ascii(img *pimg, img_point *p); - -int -img_read_item(img *pimg, img_point *p) -{ - pimg->flags = 0; - - if (pimg->version >= 8) { - return img_read_item_new(pimg, p); - } else if (pimg->version >= 3) { - return img_read_item_v3to7(pimg, p); - } else if (pimg->version >= 1) { - return img_read_item_ancient(pimg, p); - } else { - return img_read_item_ascii_wrapper(pimg, p); - } -} - -static int -img_read_item_new(img *pimg, img_point *p) -{ - int result; - int opt; - pimg->l = pimg->r = pimg->u = pimg->d = -1.0; - if (pimg->pending >= 0x40) { - if (pimg->pending == 256) { - pimg->pending = 0; - return img_XSECT_END; - } - *p = pimg->mv; - pimg->flags = (int)(pimg->pending) & 0x3f; - pimg->pending = 0; - return img_LINE; - } - again3: /* label to goto if we get a prefix, date, or lrud */ - pimg->label = pimg->label_buf; - opt = GETC(pimg->fh); - if (opt == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (opt >> 6 == 0) { - if (opt <= 4) { - if (opt == 0 && pimg->style == 0) - return img_STOP; /* end of data marker */ - /* STYLE */ - pimg->style = opt; - goto again3; - } - if (opt >= 0x10) { - switch (opt) { - case 0x10: { /* No date info */ -#if IMG_API_VERSION == 0 - pimg->date1 = pimg->date2 = 0; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = pimg->days2 = -1; -#endif - break; - } - case 0x11: { /* Single date */ - int days1 = (int)getu16(pimg->fh); -#if IMG_API_VERSION == 0 - pimg->date2 = pimg->date1 = (days1 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days2 = pimg->days1 = days1; -#endif - break; - } - case 0x12: { /* Date range (short) */ - int days1 = (int)getu16(pimg->fh); - int days2 = days1 + GETC(pimg->fh) + 1; -#if IMG_API_VERSION == 0 - pimg->date1 = (days1 - 25567) * 86400; - pimg->date2 = (days2 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = days1; - pimg->days2 = days2; -#endif - break; - } - case 0x13: { /* Date range (long) */ - int days1 = (int)getu16(pimg->fh); - int days2 = (int)getu16(pimg->fh); -#if IMG_API_VERSION == 0 - pimg->date1 = (days1 - 25567) * 86400; - pimg->date2 = (days2 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = days1; - pimg->days2 = days2; -#endif - break; - } - case 0x1f: /* Error info */ - pimg->n_legs = get32(pimg->fh); - pimg->length = get32(pimg->fh) / 100.0; - pimg->E = get32(pimg->fh) / 100.0; - pimg->H = get32(pimg->fh) / 100.0; - pimg->V = get32(pimg->fh) / 100.0; - return img_ERROR_INFO; - case 0x30: case 0x31: /* LRUD */ - case 0x32: case 0x33: /* Big LRUD! */ - if (read_v8label(pimg, 0, 0) == img_BAD) return img_BAD; - pimg->flags = (int)opt & 0x01; - if (opt < 0x32) { - pimg->l = get16(pimg->fh) / 100.0; - pimg->r = get16(pimg->fh) / 100.0; - pimg->u = get16(pimg->fh) / 100.0; - pimg->d = get16(pimg->fh) / 100.0; - } else { - pimg->l = get32(pimg->fh) / 100.0; - pimg->r = get32(pimg->fh) / 100.0; - pimg->u = get32(pimg->fh) / 100.0; - pimg->d = get32(pimg->fh) / 100.0; - } - if (!stn_included(pimg)) { - return img_XSECT_END; - } - /* If this is the last cross-section in this passage, set - * pending so we return img_XSECT_END next time. */ - if (pimg->flags & 0x01) { - pimg->pending = 256; - pimg->flags &= ~0x01; - } - return img_XSECT; - default: /* 0x25 - 0x2f and 0x34 - 0x3f are currently unallocated. */ - img_errno = IMG_BADFORMAT; - return img_BAD; - } - goto again3; - } - if (opt != 15) { - /* 1-14 and 16-31 reserved */ - img_errno = IMG_BADFORMAT; - return img_BAD; - } - result = img_MOVE; - } else if (opt >= 0x80) { - if (read_v8label(pimg, 0, 0) == img_BAD) return img_BAD; - - result = img_LABEL; - - if (!stn_included(pimg)) { - if (!skip_coord(pimg->fh)) return img_BAD; - pimg->pending = 0; - goto again3; - } - - pimg->flags = (int)opt & 0x7f; - } else if ((opt >> 6) == 1) { - if (read_v8label(pimg, opt & 0x20, 0) == img_BAD) return img_BAD; - - result = img_LINE; - - if (!survey_included(pimg)) { - if (!read_coord(pimg->fh, &(pimg->mv))) return img_BAD; - pimg->pending = 15; - goto again3; - } - - if (pimg->pending) { - *p = pimg->mv; - if (!read_coord(pimg->fh, &(pimg->mv))) return img_BAD; - pimg->pending = opt; - return img_MOVE; - } - pimg->flags = (int)opt & 0x1f; - } else { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (!read_coord(pimg->fh, p)) return img_BAD; - pimg->pending = 0; - return result; -} - -static int -img_read_item_v3to7(img *pimg, img_point *p) -{ - int result; - int opt; - pimg->l = pimg->r = pimg->u = pimg->d = -1.0; - if (pimg->pending == 256) { - pimg->pending = 0; - return img_XSECT_END; - } - if (pimg->pending >= 0x80) { - *p = pimg->mv; - pimg->flags = (int)(pimg->pending) & 0x3f; - pimg->pending = 0; - return img_LINE; - } - again3: /* label to goto if we get a prefix, date, or lrud */ - pimg->label = pimg->label_buf; - opt = GETC(pimg->fh); - if (opt == EOF) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - switch (opt >> 6) { - case 0: - if (opt == 0) { - if (!pimg->label_len) return img_STOP; /* end of data marker */ - pimg->label_len = 0; - goto again3; - } - if (opt < 15) { - /* 1-14 mean trim that many levels from current prefix */ - int c; - if (pimg->label_len <= 17) { - /* zero prefix using "0" */ - img_errno = IMG_BADFORMAT; - return img_BAD; - } - /* extra - 1 because label_len points to one past the end */ - c = pimg->label_len - 17 - 1; - while (pimg->label_buf[c] != '.' || --opt > 0) { - if (--c < 0) { - /* zero prefix using "0" */ - img_errno = IMG_BADFORMAT; - return img_BAD; - } - } - c++; - pimg->label_len = c; - goto again3; - } - if (opt == 15) { - result = img_MOVE; - break; - } - if (opt >= 0x20) { - switch (opt) { - case 0x20: /* Single date */ - if (pimg->version < 7) { - int date1 = get32(pimg->fh); -#if IMG_API_VERSION == 0 - pimg->date2 = pimg->date1 = date1; -#else /* IMG_API_VERSION == 1 */ - if (date1 != 0) { - pimg->days2 = pimg->days1 = (date1 / 86400) + 25567; - } else { - pimg->days2 = pimg->days1 = -1; - } -#endif - } else { - int days1 = (int)getu16(pimg->fh); -#if IMG_API_VERSION == 0 - pimg->date2 = pimg->date1 = (days1 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days2 = pimg->days1 = days1; -#endif - } - break; - case 0x21: /* Date range (short for v7+) */ - if (pimg->version < 7) { - INT32_T date1 = get32(pimg->fh); - INT32_T date2 = get32(pimg->fh); -#if IMG_API_VERSION == 0 - pimg->date1 = date1; - pimg->date2 = date2; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = (date1 / 86400) + 25567; - pimg->days2 = (date2 / 86400) + 25567; -#endif - } else { - int days1 = (int)getu16(pimg->fh); - int days2 = days1 + GETC(pimg->fh) + 1; -#if IMG_API_VERSION == 0 - pimg->date1 = (days1 - 25567) * 86400; - pimg->date2 = (days2 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = days1; - pimg->days2 = days2; -#endif - } - break; - case 0x22: /* Error info */ - pimg->n_legs = get32(pimg->fh); - pimg->length = get32(pimg->fh) / 100.0; - pimg->E = get32(pimg->fh) / 100.0; - pimg->H = get32(pimg->fh) / 100.0; - pimg->V = get32(pimg->fh) / 100.0; - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - return img_ERROR_INFO; - case 0x23: { /* v7+: Date range (long) */ - if (pimg->version < 7) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - int days1 = (int)getu16(pimg->fh); - int days2 = (int)getu16(pimg->fh); - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } -#if IMG_API_VERSION == 0 - pimg->date1 = (days1 - 25567) * 86400; - pimg->date2 = (days2 - 25567) * 86400; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = days1; - pimg->days2 = days2; -#endif - break; - } - case 0x24: { /* v7+: No date info */ -#if IMG_API_VERSION == 0 - pimg->date1 = pimg->date2 = 0; -#else /* IMG_API_VERSION == 1 */ - pimg->days1 = pimg->days2 = -1; -#endif - break; - } - case 0x30: case 0x31: /* LRUD */ - case 0x32: case 0x33: /* Big LRUD! */ - if (read_v3label(pimg) == img_BAD) return img_BAD; - pimg->flags = (int)opt & 0x01; - if (opt < 0x32) { - pimg->l = get16(pimg->fh) / 100.0; - pimg->r = get16(pimg->fh) / 100.0; - pimg->u = get16(pimg->fh) / 100.0; - pimg->d = get16(pimg->fh) / 100.0; - } else { - pimg->l = get32(pimg->fh) / 100.0; - pimg->r = get32(pimg->fh) / 100.0; - pimg->u = get32(pimg->fh) / 100.0; - pimg->d = get32(pimg->fh) / 100.0; - } - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - if (!stn_included(pimg)) { - return img_XSECT_END; - } - /* If this is the last cross-section in this passage, set - * pending so we return img_XSECT_END next time. */ - if (pimg->flags & 0x01) { - pimg->pending = 256; - pimg->flags &= ~0x01; - } - return img_XSECT; - default: /* 0x25 - 0x2f and 0x34 - 0x3f are currently unallocated. */ - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - goto again3; - } - /* 16-31 mean remove (n - 15) characters from the prefix */ - /* zero prefix using 0 */ - if (pimg->label_len <= (size_t)(opt - 15)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - pimg->label_len -= (opt - 15); - goto again3; - case 1: - if (read_v3label(pimg) == img_BAD) return img_BAD; - - result = img_LABEL; - - if (!stn_included(pimg)) { - if (!skip_coord(pimg->fh)) return img_BAD; - pimg->pending = 0; - goto again3; - } - - pimg->flags = (int)opt & 0x3f; - break; - case 2: - if (read_v3label(pimg) == img_BAD) return img_BAD; - - result = img_LINE; - - if (!survey_included(pimg)) { - if (!read_coord(pimg->fh, &(pimg->mv))) return img_BAD; - pimg->pending = 15; - goto again3; - } - - if (pimg->pending) { - *p = pimg->mv; - if (!read_coord(pimg->fh, &(pimg->mv))) return img_BAD; - pimg->pending = opt; - return img_MOVE; - } - pimg->flags = (int)opt & 0x3f; - break; - default: - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (!read_coord(pimg->fh, p)) return img_BAD; - pimg->pending = 0; - return result; -} - -static int -img_read_item_ancient(img *pimg, img_point *p) -{ - int result; - static long opt_lookahead = 0; - static img_point pt = { 0.0, 0.0, 0.0 }; - long opt; - - again: /* label to goto if we get a cross */ - pimg->label = pimg->label_buf; - pimg->label[0] = '\0'; - - if (pimg->version == 1) { - if (opt_lookahead) { - opt = opt_lookahead; - opt_lookahead = 0; - } else { - opt = get32(pimg->fh); - } - } else { - opt = GETC(pimg->fh); - } - - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - - switch (opt) { - case -1: case 0: - return img_STOP; /* end of data marker */ - case 1: - /* skip coordinates */ - if (!skip_coord(pimg->fh)) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - goto again; - case 2: case 3: { - size_t len; - result = img_LABEL; - if (!fgets(pimg->label_buf, pimg->buf_len, pimg->fh)) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - if (pimg->label[0] == '\\') pimg->label++; - len = strlen(pimg->label); - if (len == 0 || pimg->label[len - 1] != '\n') { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - /* Ignore empty labels in some .3d files (caused by a bug) */ - if (len == 1) goto again; - pimg->label[len - 1] = '\0'; - pimg->flags = img_SFLAG_UNDERGROUND; /* no flags given... */ - if (opt == 2) goto done; - break; - } - case 6: case 7: { - long len; - result = img_LABEL; - - if (opt == 7) - pimg->flags = GETC(pimg->fh); - else - pimg->flags = img_SFLAG_UNDERGROUND; /* no flags given... */ - - len = get32(pimg->fh); - - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - - /* Ignore empty labels in some .3d files (caused by a bug) */ - if (len == 0) goto again; - if (!check_label_space(pimg, len + 1)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - if (fread(pimg->label_buf, len, 1, pimg->fh) != 1) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - pimg->label_buf[len] = '\0'; - break; - } - case 4: - result = img_MOVE; - break; - case 5: - result = img_LINE; - break; - default: - switch ((int)opt & 0xc0) { - case 0x80: - pimg->flags = (int)opt & 0x3f; - result = img_LINE; - break; - case 0x40: { - char *q; - pimg->flags = (int)opt & 0x3f; - result = img_LABEL; - if (!fgets(pimg->label_buf, pimg->buf_len, pimg->fh)) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - q = pimg->label_buf + strlen(pimg->label_buf) - 1; - /* Ignore empty-labels in some .3d files (caused by a bug) */ - if (q == pimg->label_buf) goto again; - if (*q != '\n') { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - *q = '\0'; - break; - } - default: - img_errno = IMG_BADFORMAT; - return img_BAD; - } - break; - } - - if (!read_coord(pimg->fh, &pt)) return img_BAD; - - if (result == img_LABEL && !stn_included(pimg)) { - goto again; - } - - done: - *p = pt; - - if (result == img_MOVE && pimg->version == 1) { - /* peek at next code and see if it's an old-style label */ - opt_lookahead = get32(pimg->fh); - - if (feof(pimg->fh)) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - - if (opt_lookahead == 2) return img_read_item_ancient(pimg, p); - } - - return result; -} - -static int -img_read_item_ascii_wrapper(img *pimg, img_point *p) -{ - /* We need to set the default locale for fscanf() to work on - * numbers with "." as decimal point. */ - int result; - char * current_locale = my_strdup(setlocale(LC_NUMERIC, NULL)); - setlocale(LC_NUMERIC, "C"); - result = img_read_item_ascii(pimg, p); - setlocale(LC_NUMERIC, current_locale); - free(current_locale); - return result; -} - -/* Handle all ASCII formats. */ -static int -img_read_item_ascii(img *pimg, img_point *p) -{ - int result; - pimg->label = pimg->label_buf; - if (pimg->version == 0) { - ascii_again: - pimg->label[0] = '\0'; - if (feof(pimg->fh)) return img_STOP; - if (pimg->pending) { - pimg->pending = 0; - result = img_LINE; - } else { - char cmd[7]; - /* Stop if nothing found */ - if (fscanf(pimg->fh, "%6s", cmd) < 1) return img_STOP; - if (strcmp(cmd, "move") == 0) - result = img_MOVE; - else if (strcmp(cmd, "draw") == 0) - result = img_LINE; - else if (strcmp(cmd, "line") == 0) { - /* set flag to indicate to process second triplet as LINE */ - pimg->pending = 1; - result = img_MOVE; - } else if (strcmp(cmd, "cross") == 0) { - if (fscanf(pimg->fh, "%lf%lf%lf", &p->x, &p->y, &p->z) < 3) { - img_errno = feof(pimg->fh) ? IMG_BADFORMAT : IMG_READERROR; - return img_BAD; - } - goto ascii_again; - } else if (strcmp(cmd, "name") == 0) { - size_t off = 0; - int ch = GETC(pimg->fh); - if (ch == ' ') ch = GETC(pimg->fh); - while (ch != ' ') { - if (ch == '\n' || ch == EOF) { - img_errno = ferror(pimg->fh) ? IMG_READERROR : IMG_BADFORMAT; - return img_BAD; - } - if (off == pimg->buf_len) { - if (!check_label_space(pimg, pimg->buf_len * 2)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - } - pimg->label_buf[off++] = ch; - ch = GETC(pimg->fh); - } - pimg->label_buf[off] = '\0'; - - pimg->label = pimg->label_buf; - if (pimg->label[0] == '\\') pimg->label++; - - pimg->flags = img_SFLAG_UNDERGROUND; /* default flags */ - - result = img_LABEL; - } else { - img_errno = IMG_BADFORMAT; - return img_BAD; /* unknown keyword */ - } - } - - if (fscanf(pimg->fh, "%lf%lf%lf", &p->x, &p->y, &p->z) < 3) { - img_errno = ferror(pimg->fh) ? IMG_READERROR : IMG_BADFORMAT; - return img_BAD; - } - - if (result == img_LABEL && !stn_included(pimg)) { - goto ascii_again; - } - - return result; - } else if (pimg->version == VERSION_SURVEX_POS) { - /* Survex .pos file */ - int ch; - size_t off; - pimg->flags = img_SFLAG_UNDERGROUND; /* default flags */ - againpos: - while (fscanf(pimg->fh, "(%lf,%lf,%lf )", &p->x, &p->y, &p->z) != 3) { - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - if (feof(pimg->fh)) return img_STOP; - if (pimg->pending) { - img_errno = IMG_BADFORMAT; - return img_BAD; - } - pimg->pending = 1; - /* ignore rest of line */ - do { - ch = GETC(pimg->fh); - } while (ch != '\n' && ch != '\r' && ch != EOF); - } - - pimg->label_buf[0] = '\0'; - do { - ch = GETC(pimg->fh); - } while (ch == ' ' || ch == '\t'); - if (ch == '\n' || ch == EOF) { - /* If there's no label, set img_SFLAG_ANON. */ - pimg->flags |= img_SFLAG_ANON; - return img_LABEL; - } - pimg->label_buf[0] = ch; - off = 1; - while (!feof(pimg->fh)) { - if (!fgets(pimg->label_buf + off, pimg->buf_len - off, pimg->fh)) { - img_errno = IMG_READERROR; - return img_BAD; - } - - off += strlen(pimg->label_buf + off); - if (off && pimg->label_buf[off - 1] == '\n') { - pimg->label_buf[off - 1] = '\0'; - break; - } - if (!check_label_space(pimg, pimg->buf_len * 2)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - } - - pimg->label = pimg->label_buf; - - if (pimg->label[0] == '\\') pimg->label++; - - if (!stn_included(pimg)) goto againpos; - - return img_LABEL; - } else if (pimg->version == VERSION_COMPASS_PLT) { - /* Compass .plt file */ - if (pimg->pending > 0) { - /* -1 signals we've entered the first survey we want to - * read, and need to fudge lots if the first action is 'D'... - */ - /* pending MOVE or LINE */ - int r = pimg->pending - 4; - pimg->pending = 0; - pimg->flags = 0; - pimg->label[pimg->label_len] = '\0'; - return r; - } - - while (1) { - char *line; - char *q; - size_t len = 0; - int ch = GETC(pimg->fh); - - switch (ch) { - case '\x1a': case EOF: /* Don't insist on ^Z at end of file */ - return img_STOP; - case 'X': case 'F': case 'S': - /* bounding boX (marks end of survey), Feature survey, or - * new Section - skip to next survey */ - if (pimg->survey) return img_STOP; -skip_to_N: - while (1) { - do { - ch = GETC(pimg->fh); - } while (ch != '\n' && ch != '\r' && ch != EOF); - while (ch == '\n' || ch == '\r') ch = GETC(pimg->fh); - if (ch == 'N') break; - if (ch == '\x1a' || ch == EOF) return img_STOP; - } - /* FALLTHRU */ - case 'N': - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - while (line[len] > 32) ++len; - if (pimg->label_len == 0) pimg->pending = -1; - if (!check_label_space(pimg, len + 1)) { - osfree(line); - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - pimg->label_len = len; - pimg->label = pimg->label_buf; - memcpy(pimg->label, line, len); - pimg->label[len] = '\0'; - osfree(line); - break; - case 'M': case 'D': { - /* Move or Draw */ - long fpos = -1; - if (pimg->survey && pimg->label_len == 0) { - /* We're only holding onto this line in case the first line - * of the 'N' is a 'D', so skip it for now... - */ - goto skip_to_N; - } - if (ch == 'D' && pimg->pending == -1) { - if (pimg->survey) { - fpos = ftell(pimg->fh) - 1; - fseek(pimg->fh, pimg->start, SEEK_SET); - ch = GETC(pimg->fh); - pimg->pending = 0; - } else { - /* If a file actually has a 'D' before any 'M', then - * pretend the 'D' is an 'M' - one of the examples - * in the docs was like this! */ - ch = 'M'; - } - } - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - /* Compass stores coordinates as North, East, Up = (y,x,z)! */ - if (sscanf(line, "%lf%lf%lf", &p->y, &p->x, &p->z) != 3) { - osfree(line); - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - } else { - img_errno = IMG_BADFORMAT; - } - return img_BAD; - } - p->x *= METRES_PER_FOOT; - p->y *= METRES_PER_FOOT; - p->z *= METRES_PER_FOOT; - q = strchr(line, 'S'); - if (!q) { - osfree(line); - img_errno = IMG_BADFORMAT; - return img_BAD; - } - ++q; - len = 0; - while (q[len] > ' ') ++len; - q[len] = '\0'; - len += 2; /* ' ' and '\0' */ - if (!check_label_space(pimg, pimg->label_len + len)) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - pimg->label = pimg->label_buf; - if (pimg->label_len) { - pimg->label[pimg->label_len] = ' '; - memcpy(pimg->label + pimg->label_len + 1, q, len - 1); - } else { - memcpy(pimg->label, q, len - 1); - } - q += len - 1; - /* Now read LRUD. Technically, this is optional but virtually - * all PLT files have it (with dummy negative values if no LRUD - * was measured) and some versions of Compass can't read PLT - * files without it! - */ - while (*q && *q <= ' ') q++; - if (*q == 'P') { - if (sscanf(q + 1, "%lf%lf%lf%lf", - &pimg->l, &pimg->r, &pimg->u, &pimg->d) != 4) { - osfree(line); - if (ferror(pimg->fh)) { - img_errno = IMG_READERROR; - } else { - img_errno = IMG_BADFORMAT; - } - return img_BAD; - } - pimg->l *= METRES_PER_FOOT; - pimg->r *= METRES_PER_FOOT; - pimg->u *= METRES_PER_FOOT; - pimg->d *= METRES_PER_FOOT; - } else { - pimg->l = pimg->r = pimg->u = pimg->d = -1; - } - osfree(line); - pimg->flags = img_SFLAG_UNDERGROUND; /* default flags */ - if (fpos != -1) { - fseek(pimg->fh, fpos, SEEK_SET); - } else { - pimg->pending = (ch == 'M' ? img_MOVE : img_LINE) + 4; - } - return img_LABEL; - } - default: - img_errno = IMG_BADFORMAT; - return img_BAD; - } - } - } else { - /* CMAP .xyz file */ - char *line = NULL; - char *q; - size_t len; - - if (pimg->pending) { - /* pending MOVE or LINE or LABEL or STOP */ - int r = pimg->pending - 4; - /* Set label to empty - don't use "" as we adjust label relative - * to label_buf when label_buf is reallocated. */ - pimg->label = pimg->label_buf + strlen(pimg->label_buf); - pimg->flags = 0; - if (r == img_LABEL) { - /* nasty magic */ - read_xyz_shot_coords(p, pimg->label_buf + 16); - subtract_xyz_shot_deltas(p, pimg->label_buf + 16); - pimg->pending = img_STOP + 4; - return img_MOVE; - } - - pimg->pending = 0; - - if (r == img_STOP) { - /* nasty magic */ - read_xyz_shot_coords(p, pimg->label_buf + 16); - return img_LINE; - } - - return r; - } - - pimg->label = pimg->label_buf; - do { - osfree(line); - if (feof(pimg->fh)) return img_STOP; - line = getline_alloc(pimg->fh); - if (!line) { - img_errno = IMG_OUTOFMEMORY; - return img_BAD; - } - } while (line[0] == ' ' || line[0] == '\0'); - if (line[0] == '\x1a') return img_STOP; - - len = strlen(line); - if (pimg->version == VERSION_CMAP_STATION) { - /* station variant */ - if (len < 37) { - osfree(line); - img_errno = IMG_BADFORMAT; - return img_BAD; - } - memcpy(pimg->label, line, 6); - q = (char *)memchr(pimg->label, ' ', 6); - if (!q) q = pimg->label + 6; - *q = '\0'; - - read_xyz_station_coords(p, line); - - /* FIXME: look at prev for lines (line + 32, 5) */ - /* FIXME: duplicate stations... */ - return img_LABEL; - } else { - /* Shot variant (VERSION_CMAP_SHOT) */ - char old[8], new_[8]; - if (len < 61) { - osfree(line); - img_errno = IMG_BADFORMAT; - return img_BAD; - } - - memcpy(old, line, 7); - q = (char *)memchr(old, ' ', 7); - if (!q) q = old + 7; - *q = '\0'; - - memcpy(new_, line + 7, 7); - q = (char *)memchr(new_, ' ', 7); - if (!q) q = new_ + 7; - *q = '\0'; - - pimg->flags = img_SFLAG_UNDERGROUND; - - if (strcmp(old, new_) == 0) { - pimg->pending = img_MOVE + 4; - read_xyz_shot_coords(p, line); - strcpy(pimg->label, new_); - osfree(line); - return img_LABEL; - } - - if (strcmp(old, pimg->label) == 0) { - pimg->pending = img_LINE + 4; - read_xyz_shot_coords(p, line); - strcpy(pimg->label, new_); - osfree(line); - return img_LABEL; - } - - pimg->pending = img_LABEL + 4; - read_xyz_shot_coords(p, line); - strcpy(pimg->label, new_); - memcpy(pimg->label + 16, line, 70); - - osfree(line); - return img_LABEL; - } - } -} - -static void -write_coord(FILE *fh, double x, double y, double z) -{ - SVX_ASSERT(fh); - /* Output in cm */ - static INT32_T X_, Y_, Z_; - INT32_T X = my_lround(x * 100.0); - INT32_T Y = my_lround(y * 100.0); - INT32_T Z = my_lround(z * 100.0); - - X_ -= X; - Y_ -= Y; - Z_ -= Z; - put32(X, fh); - put32(Y, fh); - put32(Z, fh); - X_ = X; Y_ = Y; Z_ = Z; -} - -static int -write_v3label(img *pimg, int opt, const char *s) -{ - size_t len, n, dot; - - /* find length of common prefix */ - dot = 0; - for (len = 0; s[len] == pimg->label_buf[len] && s[len] != '\0'; len++) { - if (s[len] == '.') dot = len + 1; - } - - SVX_ASSERT(len <= pimg->label_len); - n = pimg->label_len - len; - if (len == 0) { - if (pimg->label_len) PUTC(0, pimg->fh); - } else if (n <= 16) { - if (n) PUTC(n + 15, pimg->fh); - } else if (dot == 0) { - if (pimg->label_len) PUTC(0, pimg->fh); - len = 0; - } else { - const char *p = pimg->label_buf + dot; - n = 1; - for (len = pimg->label_len - dot - 17; len; len--) { - if (*p++ == '.') n++; - } - if (n <= 14) { - PUTC(n, pimg->fh); - len = dot; - } else { - if (pimg->label_len) PUTC(0, pimg->fh); - len = 0; - } - } - - n = strlen(s + len); - PUTC(opt, pimg->fh); - if (n < 0xfe) { - PUTC(n, pimg->fh); - } else if (n < 0xffff + 0xfe) { - PUTC(0xfe, pimg->fh); - put16((short)(n - 0xfe), pimg->fh); - } else { - PUTC(0xff, pimg->fh); - put32(n, pimg->fh); - } - fwrite(s + len, n, 1, pimg->fh); - - n += len; - pimg->label_len = n; - if (!check_label_space(pimg, n + 1)) - return 0; /* FIXME: distinguish out of memory... */ - memcpy(pimg->label_buf + len, s + len, n - len + 1); - - return !ferror(pimg->fh); -} - -static int -write_v8label(img *pimg, int opt, int common_flag, size_t common_val, - const char *s) -{ - size_t len, del, add; - - /* find length of common prefix */ - for (len = 0; s[len] == pimg->label_buf[len] && s[len] != '\0'; len++) { - } - - SVX_ASSERT(len <= pimg->label_len); - del = pimg->label_len - len; - add = strlen(s + len); - - if (add == common_val && del == common_val) { - PUTC(opt | common_flag, pimg->fh); - } else { - PUTC(opt, pimg->fh); - if (del <= 15 && add <= 15 && (del || add)) { - PUTC((del << 4) | add, pimg->fh); - } else { - PUTC(0x00, pimg->fh); - if (del < 0xff) { - PUTC(del, pimg->fh); - } else { - PUTC(0xff, pimg->fh); - put32(del, pimg->fh); - } - if (add < 0xff) { - PUTC(add, pimg->fh); - } else { - PUTC(0xff, pimg->fh); - put32(add, pimg->fh); - } - } - } - - if (add) - fwrite(s + len, add, 1, pimg->fh); - - pimg->label_len = len + add; - if (add > del && !check_label_space(pimg, pimg->label_len + 1)) - return 0; /* FIXME: distinguish out of memory... */ - - memcpy(pimg->label_buf + len, s + len, add + 1); - - return !ferror(pimg->fh); -} - -static void -img_write_item_date_new(img *pimg) -{ - int same, unset; - /* Only write dates when they've changed. */ -#if IMG_API_VERSION == 0 - if (pimg->date1 == pimg->olddate1 && pimg->date2 == pimg->olddate2) - return; - - same = (pimg->date1 == pimg->date2); - unset = (pimg->date1 == 0); -#else /* IMG_API_VERSION == 1 */ - if (pimg->days1 == pimg->olddays1 && pimg->days2 == pimg->olddays2) - return; - - same = (pimg->days1 == pimg->days2); - unset = (pimg->days1 == -1); -#endif - - if (same) { - if (unset) { - PUTC(0x10, pimg->fh); - } else { - PUTC(0x11, pimg->fh); -#if IMG_API_VERSION == 0 - put16(pimg->date1 / 86400 + 25567, pimg->fh); -#else /* IMG_API_VERSION == 1 */ - put16(pimg->days1, pimg->fh); -#endif - } - } else { -#if IMG_API_VERSION == 0 - int diff = (pimg->date2 - pimg->date1) / 86400; - if (diff > 0 && diff <= 256) { - PUTC(0x12, pimg->fh); - put16(pimg->date1 / 86400 + 25567, pimg->fh); - PUTC(diff - 1, pimg->fh); - } else { - PUTC(0x13, pimg->fh); - put16(pimg->date1 / 86400 + 25567, pimg->fh); - put16(pimg->date2 / 86400 + 25567, pimg->fh); - } -#else /* IMG_API_VERSION == 1 */ - int diff = pimg->days2 - pimg->days1; - if (diff > 0 && diff <= 256) { - PUTC(0x12, pimg->fh); - put16(pimg->days1, pimg->fh); - PUTC(diff - 1, pimg->fh); - } else { - PUTC(0x13, pimg->fh); - put16(pimg->days1, pimg->fh); - put16(pimg->days2, pimg->fh); - } -#endif - } -#if IMG_API_VERSION == 0 - pimg->olddate1 = pimg->date1; - pimg->olddate2 = pimg->date2; -#else /* IMG_API_VERSION == 1 */ - pimg->olddays1 = pimg->days1; - pimg->olddays2 = pimg->days2; -#endif -} - -static void -img_write_item_date(img *pimg) -{ - int same, unset; - /* Only write dates when they've changed. */ -#if IMG_API_VERSION == 0 - if (pimg->date1 == pimg->olddate1 && pimg->date2 == pimg->olddate2) - return; - - same = (pimg->date1 == pimg->date2); - unset = (pimg->date1 == 0); -#else /* IMG_API_VERSION == 1 */ - if (pimg->days1 == pimg->olddays1 && pimg->days2 == pimg->olddays2) - return; - - same = (pimg->days1 == pimg->days2); - unset = (pimg->days1 == -1); -#endif - - if (same) { - if (img_output_version < 7) { - PUTC(0x20, pimg->fh); -#if IMG_API_VERSION == 0 - put32(pimg->date1, pimg->fh); -#else /* IMG_API_VERSION == 1 */ - put32((pimg->days1 - 25567) * 86400, pimg->fh); -#endif - } else { - if (unset) { - PUTC(0x24, pimg->fh); - } else { - PUTC(0x20, pimg->fh); -#if IMG_API_VERSION == 0 - put16(pimg->date1 / 86400 + 25567, pimg->fh); -#else /* IMG_API_VERSION == 1 */ - put16(pimg->days1, pimg->fh); -#endif - } - } - } else { - if (img_output_version < 7) { - PUTC(0x21, pimg->fh); -#if IMG_API_VERSION == 0 - put32(pimg->date1, pimg->fh); - put32(pimg->date2, pimg->fh); -#else /* IMG_API_VERSION == 1 */ - put32((pimg->days1 - 25567) * 86400, pimg->fh); - put32((pimg->days2 - 25567) * 86400, pimg->fh); -#endif - } else { -#if IMG_API_VERSION == 0 - int diff = (pimg->date2 - pimg->date1) / 86400; - if (diff > 0 && diff <= 256) { - PUTC(0x21, pimg->fh); - put16(pimg->date1 / 86400 + 25567, pimg->fh); - PUTC(diff - 1, pimg->fh); - } else { - PUTC(0x23, pimg->fh); - put16(pimg->date1 / 86400 + 25567, pimg->fh); - put16(pimg->date2 / 86400 + 25567, pimg->fh); - } -#else /* IMG_API_VERSION == 1 */ - int diff = pimg->days2 - pimg->days1; - if (diff > 0 && diff <= 256) { - PUTC(0x21, pimg->fh); - put16(pimg->days1, pimg->fh); - PUTC(diff - 1, pimg->fh); - } else { - PUTC(0x23, pimg->fh); - put16(pimg->days1, pimg->fh); - put16(pimg->days2, pimg->fh); - } -#endif - } - } -#if IMG_API_VERSION == 0 - pimg->olddate1 = pimg->date1; - pimg->olddate2 = pimg->date2; -#else /* IMG_API_VERSION == 1 */ - pimg->olddays1 = pimg->days1; - pimg->olddays2 = pimg->days2; -#endif -} - -static void -img_write_item_new(img *pimg, int code, int flags, const char *s, - double x, double y, double z); -static void -img_write_item_v3to7(img *pimg, int code, int flags, const char *s, - double x, double y, double z); -static void -img_write_item_ancient(img *pimg, int code, int flags, const char *s, - double x, double y, double z); - -void -img_write_item(img *pimg, int code, int flags, const char *s, - double x, double y, double z) -{ - if (!pimg) return; - if (pimg->version >= 8) { - img_write_item_new(pimg, code, flags, s, x, y, z); - } else if (pimg->version >= 3) { - img_write_item_v3to7(pimg, code, flags, s, x, y, z); - } else { - img_write_item_ancient(pimg, code, flags, s, x, y, z); - } -} - -static void -img_write_item_new(img *pimg, int code, int flags, const char *s, - double x, double y, double z) -{ - switch (code) { - case img_LABEL: - write_v8label(pimg, 0x80 | flags, 0, -1, s); - break; - case img_XSECT: { - INT32_T l, r, u, d, max_dim; - img_write_item_date_new(pimg); - l = (INT32_T)my_lround(pimg->l * 100.0); - r = (INT32_T)my_lround(pimg->r * 100.0); - u = (INT32_T)my_lround(pimg->u * 100.0); - d = (INT32_T)my_lround(pimg->d * 100.0); - if (l < 0) l = -1; - if (r < 0) r = -1; - if (u < 0) u = -1; - if (d < 0) d = -1; - max_dim = max(max(l, r), max(u, d)); - flags = (flags & img_XFLAG_END) ? 1 : 0; - if (max_dim >= 32768) flags |= 2; - write_v8label(pimg, 0x30 | flags, 0, -1, s); - if (flags & 2) { - /* Big passage! Need to use 4 bytes. */ - put32(l, pimg->fh); - put32(r, pimg->fh); - put32(u, pimg->fh); - put32(d, pimg->fh); - } else { - put16(l, pimg->fh); - put16(r, pimg->fh); - put16(u, pimg->fh); - put16(d, pimg->fh); - } - return; - } - case img_MOVE: - PUTC(15, pimg->fh); - break; - case img_LINE: - img_write_item_date_new(pimg); - if (pimg->style != pimg->oldstyle) { - switch (pimg->style) { - case img_STYLE_NORMAL: - case img_STYLE_DIVING: - case img_STYLE_CARTESIAN: - case img_STYLE_CYLPOLAR: - case img_STYLE_NOSURVEY: - PUTC(pimg->style, pimg->fh); - break; - } - pimg->oldstyle = pimg->style; - } - write_v8label(pimg, 0x40 | flags, 0x20, 0x00, s ? s : ""); - break; - default: /* ignore for now */ - return; - } - write_coord(pimg->fh, x, y, z); -} - -static void -img_write_item_v3to7(img *pimg, int code, int flags, const char *s, - double x, double y, double z) -{ - switch (code) { - case img_LABEL: - write_v3label(pimg, 0x40 | flags, s); - break; - case img_XSECT: { - INT32_T l, r, u, d, max_dim; - /* Need at least version 5 for img_XSECT. */ - if (pimg->version < 5) return; - img_write_item_date(pimg); - l = (INT32_T)my_lround(pimg->l * 100.0); - r = (INT32_T)my_lround(pimg->r * 100.0); - u = (INT32_T)my_lround(pimg->u * 100.0); - d = (INT32_T)my_lround(pimg->d * 100.0); - if (l < 0) l = -1; - if (r < 0) r = -1; - if (u < 0) u = -1; - if (d < 0) d = -1; - max_dim = max(max(l, r), max(u, d)); - flags = (flags & img_XFLAG_END) ? 1 : 0; - if (max_dim >= 32768) flags |= 2; - write_v3label(pimg, 0x30 | flags, s); - if (flags & 2) { - /* Big passage! Need to use 4 bytes. */ - put32(l, pimg->fh); - put32(r, pimg->fh); - put32(u, pimg->fh); - put32(d, pimg->fh); - } else { - put16(l, pimg->fh); - put16(r, pimg->fh); - put16(u, pimg->fh); - put16(d, pimg->fh); - } - return; - } - case img_MOVE: - PUTC(15, pimg->fh); - break; - case img_LINE: - if (pimg->version >= 4) { - img_write_item_date(pimg); - } - write_v3label(pimg, 0x80 | flags, s ? s : ""); - break; - default: /* ignore for now */ - return; - } - write_coord(pimg->fh, x, y, z); -} - -static void -img_write_item_ancient(img *pimg, int code, int flags, const char *s, - double x, double y, double z) -{ - size_t len; - INT32_T opt = 0; - SVX_ASSERT(pimg->version > 0); - switch (code) { - case img_LABEL: - if (pimg->version == 1) { - /* put a move before each label */ - img_write_item_ancient(pimg, img_MOVE, 0, NULL, x, y, z); - put32(2, pimg->fh); - fputsnl(s, pimg->fh); - return; - } - len = strlen(s); - if (len > 255 || strchr(s, '\n')) { - /* long label - not in early incarnations of v2 format, but few - * 3d files will need these, so better not to force incompatibility - * with a new version I think... */ - PUTC(7, pimg->fh); - PUTC(flags, pimg->fh); - put32(len, pimg->fh); - fputs(s, pimg->fh); - } else { - PUTC(0x40 | (flags & 0x3f), pimg->fh); - fputsnl(s, pimg->fh); - } - opt = 0; - break; - case img_MOVE: - opt = 4; - break; - case img_LINE: - if (pimg->version > 1) { - opt = 0x80 | (flags & 0x3f); - break; - } - opt = 5; - break; - default: /* ignore for now */ - return; - } - if (pimg->version == 1) { - put32(opt, pimg->fh); - } else { - if (opt) PUTC(opt, pimg->fh); - } - write_coord(pimg->fh, x, y, z); -} - -/* Write error information for the current traverse - * n_legs is the number of legs in the traverse - * length is the traverse length (in m) - * E is the ratio of the observed misclosure to the theoretical one - * H is the ratio of the observed horizontal misclosure to the theoretical one - * V is the ratio of the observed vertical misclosure to the theoretical one - */ -void -img_write_errors(img *pimg, int n_legs, double length, - double E, double H, double V) -{ - PUTC((pimg->version >= 8 ? 0x1f : 0x22), pimg->fh); - put32(n_legs, pimg->fh); - put32((INT32_T)my_lround(length * 100.0), pimg->fh); - put32((INT32_T)my_lround(E * 100.0), pimg->fh); - put32((INT32_T)my_lround(H * 100.0), pimg->fh); - put32((INT32_T)my_lround(V * 100.0), pimg->fh); -} - -int -img_close(img *pimg) -{ - int result = 1; - if (pimg) { - if (pimg->fh) { - if (pimg->fRead) { - osfree(pimg->survey); - osfree(pimg->title); - osfree(pimg->cs); - osfree(pimg->datestamp); - } else { - /* write end of data marker */ - switch (pimg->version) { - case 1: - put32((INT32_T)-1, pimg->fh); - break; - default: - if (pimg->version <= 7 ? - (pimg->label_len != 0) : - (pimg->style != img_STYLE_NORMAL)) { - PUTC(0, pimg->fh); - } - /* FALL THROUGH */ - case 2: - PUTC(0, pimg->fh); - break; - } - } - if (ferror(pimg->fh)) result = 0; - if (pimg->close_func && pimg->close_func(pimg->fh)) - result = 0; - if (!result) img_errno = pimg->fRead ? IMG_READERROR : IMG_WRITEERROR; - } - osfree(pimg->label_buf); - osfree(pimg->filename_opened); - osfree(pimg); - } - return result; -} diff --git a/src/img.h b/src/img.h deleted file mode 100644 index a616615..0000000 --- a/src/img.h +++ /dev/null @@ -1,413 +0,0 @@ -/* img.h - * Header file for routines to read and write processed survey data files - * - * These routines support reading processed survey data in a variety of formats - * - currently: - * - * - Survex ".3d" image files - * - Survex ".pos" files - * - Compass Plot files (".plt" and ".plf") - * - CMAP XYZ files (".sht", ".adj", ".una", ".xyz") - * - * Writing Survex ".3d" image files is supported. - * - * Copyright (C) Olly Betts 1993,1994,1997,2001,2002,2003,2004,2005,2006,2010,2011,2012,2013,2014,2016,2018 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef IMG_H -# define IMG_H - -/* Define IMG_API_VERSION if you want more recent versions of the img API. - * - * 0 (default) The old API. date1 and date2 give the survey date as time_t. - * Set to 0 for "unknown". - * 1 days1 and days2 give survey dates as days since 1st Jan 1900. - * Set to -1 for "unknown". - */ -#ifndef IMG_API_VERSION -# define IMG_API_VERSION 0 -#elif IMG_API_VERSION > 1 -# error IMG_API_VERSION > 1 too new -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include /* for time_t */ - -# define img_BAD -2 -# define img_STOP -1 -# define img_MOVE 0 -# define img_LINE 1 -/* NB: img_CROSS is never output and ignored on input. - * Put crosses where labels are. */ -/* # define img_CROSS 2 */ -# define img_LABEL 3 -# define img_XSECT 4 -# define img_XSECT_END 5 -/* Loop closure information for the *preceding* traverse (img_MOVE + one or - * more img_LINEs). */ -# define img_ERROR_INFO 6 - -/* Leg flags */ -# define img_FLAG_SURFACE 0x01 -# define img_FLAG_DUPLICATE 0x02 -# define img_FLAG_SPLAY 0x04 - -/* Station flags */ -# define img_SFLAG_SURFACE 0x01 -# define img_SFLAG_UNDERGROUND 0x02 -# define img_SFLAG_ENTRANCE 0x04 -# define img_SFLAG_EXPORTED 0x08 -# define img_SFLAG_FIXED 0x10 -# define img_SFLAG_ANON 0x20 -# define img_SFLAG_WALL 0x40 - -/* File-wide flags */ -# define img_FFLAG_EXTENDED 0x80 - -/* When writing img_XSECT, img_XFLAG_END in pimg->flags means this is the last - * img_XSECT in this tube: - */ -# define img_XFLAG_END 0x01 - -# define img_STYLE_UNKNOWN -1 -# define img_STYLE_NORMAL 0 -# define img_STYLE_DIVING 1 -# define img_STYLE_CARTESIAN 2 -# define img_STYLE_CYLPOLAR 3 -# define img_STYLE_NOSURVEY 4 - -/* 3D coordinates (in metres) */ -typedef struct { - double x, y, z; -} img_point; - -typedef struct { - /* Members you can access when reading (don't touch when writing): */ - char *label; - int flags; - char *title; - /* If the coordinate system was specified, this contains a PROJ4 string - * describing it. If not, this member will be NULL. - */ - char *cs; - /* Older .3d format versions stored a human readable datestamp string. - * Format versions >= 8 versions store a string consisting of "@" followed - * by the number of seconds since midnight UTC on 1/1/1970. Some foreign - * formats contain a human readable string, others no date information - * (which results in "?" being returned). - */ - char *datestamp; - /* The datestamp as a time_t (or (time_t)-1 if not available). - * - * For 3d format versions >= 8, this is a reliable value and in UTC. Older - * 3d format versions store a human readable time, which img will attempt - * to decode, but it may fail, particularly with handling timezones. Even - * if it does work, beware that times in local time where DST applies are - * inherently ambiguous around when the clocks go back. - * - * CMAP XYZ files contain a timestamp. It's probably in localtime (but - * without any timezone information) and the example files are all pre-2000 - * and have two digit years. We do our best to turn these into a useful - * time_t value. - */ - time_t datestamp_numeric; - char separator; /* character used to separate survey levels ('.' usually) */ - - /* Members that can be set when writing: */ -#if IMG_API_VERSION == 0 - time_t date1, date2; -#else /* IMG_API_VERSION == 1 */ - int days1, days2; -#endif - double l, r, u, d; - - /* Error information - valid when img_ERROR_INFO is returned: */ - int n_legs; - double length; - double E, H, V; - - /* The filename actually opened (e.g. may have ".3d" added). - * - * This is only set if img opened the filename - if an existing stream - * is used (via img_read_stream() or similar) then this member will be - * NULL. - */ - char * filename_opened; - - /* Non-zero if reading an extended elevation: */ - int is_extended_elevation; - - /* Members that can be set when writing: */ - /* The style of the data - one of the img_STYLE_* constants above */ - int style; - - /* All other members are for internal use only: */ - FILE *fh; /* file handle of image file */ - int (*close_func)(FILE*); - char *label_buf; - size_t buf_len; - size_t label_len; - int fRead; /* 1 for reading, 0 for writing */ - long start; - /* version of file format: - * -4 => CMAP .xyz file, shot format - * -3 => CMAP .xyz file, station format - * -2 => Compass .plt file - * -1 => .pos file - * 0 => 0.01 ascii - * 1 => 0.01 binary, - * 2 => byte actions and flags - * 3 => prefixes for legs; compressed prefixes - * 4 => survey date - * 5 => LRUD info - * 6 => error info - * 7 => more compact dates with wider range - * 8 => lots of changes - */ - int version; - char *survey; - size_t survey_len; - int pending; /* for old style text format files and survey filtering */ - img_point mv; -#if IMG_API_VERSION == 0 - time_t olddate1, olddate2; -#else /* IMG_API_VERSION == 1 */ - int olddays1, olddays2; -#endif - int oldstyle; -} img; - -/* Which version of the file format to output (defaults to newest) */ -extern unsigned int img_output_version; - -/* Minimum supported value for img_output_version: */ -#define IMG_VERSION_MIN 1 - -/* Maximum supported value for img_output_version: */ -#define IMG_VERSION_MAX 8 - -/* Open a processed survey data file for reading - * - * fnm is the filename - * - * Returns pointer to an img struct or NULL - */ -#define img_open(F) img_open_survey((F), NULL) - -/* Open a processed survey data file for reading - * - * fnm is the filename - * - * survey points to a survey name to restrict reading to (or NULL for all - * survey data in the file) - * - * Returns pointer to an img struct or NULL - */ -img *img_open_survey(const char *fnm, const char *survey); - -/* Read processed survey data from an existing stream. - * - * stream is a FILE* open on the stream (can be NULL which will give error - * IMG_FILENOTFOUND so you don't need to handle that case specially). The - * stream should be opened for reading in binary mode and positioned at the - * start of the survey data file. - * - * close_func is a function to call to close the stream (most commonly - * fclose, or pclose if the stream was opened using popen()) or NULL if - * the caller wants to take care of closing the stream. - * - * filename is used to determine the format based on the file extension, - * and also the leafname with the extension removed is used for the survey - * title for formats which don't support a title or when no title is - * specified. If you're not interested in default titles, you can just - * pass the extension including a leading "." - e.g. ".3d". May not be - * NULL. - * - * Returns pointer to an img struct or NULL on error. Any close function - * specified is called on error (unless stream is NULL). - */ -#define img_read_stream(S, C, F) img_read_stream_survey((S), (C), (F), NULL) - -/* Read processed survey data from an existing stream. - * - * stream is a FILE* open on the stream (can be NULL which will give error - * IMG_FILENOTFOUND so you don't need to handle that case specially). The - * stream should be opened for reading in binary mode and positioned at the - * start of the survey data file. - * - * close_func is a function to call to close the stream (most commonly - * fclose, or pclose if the stream was opened using popen()) or NULL if - * the caller wants to take care of closing the stream. - * - * filename is used to determine the format based on the file extension, - * and also the leafname with the extension removed is used for the survey - * title for formats which don't support a title or when no title is - * specified. If you're not interested in default titles, you can just - * pass the extension including a leading "." - e.g. ".3d". filename must - * not be NULL. - * - * survey points to a survey name to restrict reading to (or NULL for all - * survey data in the file) - * - * Returns pointer to an img struct or NULL on error. Any close function - * specified is called on error. - */ -img *img_read_stream_survey(FILE *stream, int (*close_func)(FILE*), - const char *filename, - const char *survey); - -/* Open a .3d file for output with no specified coordinate system - * - * This is a very thin wrapper around img_open_write_cs() which passes NULL for - * cs, provided for compatibility with the API provided before support for - * coordinate systems was added. - * - * See img_open_write_cs() for documentation. - */ -#define img_open_write(F, T, S) img_open_write_cs(F, T, NULL, S) - -/* Open a .3d file for output in a specified coordinate system - * - * fnm is the filename - * - * title is the title - * - * cs is a PROJ4 string describing the coordinate system (or NULL to not - * specify a coordinate system). - * - * flags contains a bitwise-or of any file-wide flags - currently only one - * is available: img_FFLAG_EXTENDED. - * - * Returns pointer to an img struct or NULL for error (check img_error() - * for details) - */ -img *img_open_write_cs(const char *fnm, const char *title, const char * cs, - int flags); - -/* Write a .3d file to a stream - * - * stream is a FILE* open on the stream (can be NULL which will give error - * IMG_FILENOTFOUND so you don't need to handle that case specially). The - * stream should be opened for writing in binary mode. - * - * close_func is a function to call to close the stream (most commonly - * fclose, or pclose if the stream was opened using popen()) or NULL if - * the caller wants to take care of closing the stream. - * - * title is the title - * - * cs is a PROJ4 string describing the coordinate system (or NULL to not - * specify a coordinate system). - * - * flags contains a bitwise-or of any file-wide flags - currently only one - * is available: img_FFLAG_EXTENDED. - * - * Returns pointer to an img struct or NULL for error (check img_error() - * for details). Any close function specified is called on error (unless - * stream is NULL). - */ -img *img_write_stream(FILE *stream, int (*close_func)(FILE*), - const char *title, const char * cs, int flags); - -/* Read an item from a processed survey data file - * - * pimg is a pointer to an img struct returned by img_open() - * - * coordinates are returned in p - * - * flags and label name are returned in fields in pimg - * - * Returns img_XXXX as #define-d above - */ -int img_read_item(img *pimg, img_point *p); - -/* Write a item to a .3d file - * - * pimg is a pointer to an img struct returned by img_open_write() - * - * code is one of the img_XXXX #define-d above - * - * flags is the leg, station, or xsect flags - * (meaningful for img_LINE, img_LABEL, and img_XSECT respectively) - * - * s is the label (only meaningful for img_LABEL) - * - * x, y, z are the coordinates - */ -void img_write_item(img *pimg, int code, int flags, const char *s, - double x, double y, double z); - -/* Write error information for the current traverse - * - * n_legs is the number of legs in the traverse - * - * length is the traverse length (in m) - * - * E is the ratio of the observed misclosure to the theoretical one - * - * H is the ratio of the observed horizontal misclosure to the theoretical one - * - * V is the ratio of the observed vertical misclosure to the theoretical one - */ -void img_write_errors(img *pimg, int n_legs, double length, - double E, double H, double V); - -/* rewind a processed survey data file opened for reading - * - * This is useful if you want to read the data in several passes. - * - * pimg is a pointer to an img struct returned by img_open() - * - * Returns: non-zero for success, zero for error (check img_error() for - * details) - */ -int img_rewind(img *pimg); - -/* Close a processed survey data file - * - * pimg is a pointer to an img struct returned by img_open() or - * img_open_write() - * - * Returns: non-zero for success, zero for error (check img_error() for - * details) - */ -int img_close(img *pimg); - -/* Codes returned by img_error */ -typedef enum { - IMG_NONE = 0, IMG_FILENOTFOUND, IMG_OUTOFMEMORY, - IMG_CANTOPENOUT, IMG_BADFORMAT, IMG_DIRECTORY, - IMG_READERROR, IMG_WRITEERROR, IMG_TOONEW -} img_errcode; - -/* Read the error code - * - * If img_open(), img_open_survey() or img_open_write() returns NULL, or - * img_rewind() or img_close() returns 0, or img_read_item() returns img_BAD - * then you can call this function to discover why. - */ -img_errcode img_error(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/kavea b/src/kavea deleted file mode 100755 index 7601720..0000000 Binary files a/src/kavea and /dev/null differ diff --git a/src/main.go b/src/main.go index e345bf5..ad18241 100644 --- a/src/main.go +++ b/src/main.go @@ -1,17 +1,14 @@ package main import ( - "embed" "log" "net/http" "runtime" + "github.com/blevesearch/bleve/v2" "github.com/zserge/lorca" ) -//go:embed templates -var templatesHTML embed.FS - //go:embed static var staticFiles embed.FS @@ -20,11 +17,11 @@ func main() { /* Web Server */ http.Handle("/static/", http.FileServer(http.FS(staticFiles))) - http.Handle("/favicon.ico", http.RedirectHandler("/static/favicon.ico", http.StatusMovedPermanently)) - http.HandleFunc("/", GetHome) + http.HandleFunc("/", GetHome) // Redirects to /search if auth'd - // Start in separate goroutine + /* Start Web Server */ go func() { + log.Println("Server is running!") log.Fatal(http.ListenAndServe(":3000", nil)) }() diff --git a/src/static/js/kavea.js b/src/static/js/kavea.js deleted file mode 100644 index c0927a3..0000000 --- a/src/static/js/kavea.js +++ /dev/null @@ -1,32 +0,0 @@ -var stage = new Konva.Stage({ - container: 'container', - width: window.innerWidth, - height: window.innerHeight, -}); - -// add canvas element -var layer = new Konva.Layer(); -stage.add(layer); - -// create shape -var box = new Konva.Rect({ - x: 50, - y: 50, - width: 100, - height: 50, - fill: '#00D2FF', - stroke: 'black', - strokeWidth: 4, - draggable: true, -}); -layer.add(box); - -layer.draw(); - -// add cursor styling -box.on('mouseover', function () { - document.body.style.cursor = 'pointer'; -}); -box.on('mouseout', function () { - document.body.style.cursor = 'default'; -}); diff --git a/src/static/js/konva.7.2.5.min.js b/src/static/js/konva.7.2.5.min.js deleted file mode 100644 index 96bbb89..0000000 --- a/src/static/js/konva.7.2.5.min.js +++ /dev/null @@ -1,12 +0,0 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Konva=e()}(this,(function(){"use strict"; -/* - * Konva JavaScript Framework v7.2.5 - * http://konvajs.org/ - * Licensed under the MIT - * Date: Wed Mar 03 2021 - * - * Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS) - * Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva) - * - * @license - */var t=Math.PI/180;var e=function(t){var e=t.indexOf("msie ");if(e>0)return parseInt(t.substring(e+5,t.indexOf(".",e)),10);if(t.indexOf("trident/")>0){var i=t.indexOf("rv:");return parseInt(t.substring(i+3,t.indexOf(".",i)),10)}var n=t.indexOf("edge/");return n>0&&parseInt(t.substring(n+5,t.indexOf(".",n)),10)},i=function(t){var i=t.toLowerCase(),n=/(chrome)[ /]([\w.]+)/.exec(i)||/(webkit)[ /]([\w.]+)/.exec(i)||/(opera)(?:.*version|)[ /]([\w.]+)/.exec(i)||/(msie) ([\w.]+)/.exec(i)||i.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(i)||[],r=!!t.match(/Android|BlackBerry|iPhone|iPad|iPod|Opera Mini|IEMobile/i),o=!!t.match(/IEMobile/i);return{browser:n[1]||"",version:n[2]||"0",isIE:e(i),mobile:r,ieMobile:o}},n="undefined"!=typeof global?global:"undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope?self:{},r={_global:n,version:"7.2.5",isBrowser:"undefined"!=typeof window&&("[object Window]"==={}.toString.call(window)||"[object global]"==={}.toString.call(window)),isUnminified:/param/.test(function(t){}.toString()),dblClickWindow:400,getAngle:function(e){return r.angleDeg?e*t:e},enableTrace:!1,_pointerEventsEnabled:!1,hitOnDragEnabled:!1,captureTouchEventsEnabled:!1,listenClickTap:!1,inDblClickWindow:!1,pixelRatio:void 0,dragDistance:3,angleDeg:!0,showWarnings:!0,dragButtons:[0,1],isDragging:function(){return r.DD.isDragging},isDragReady:function(){return!!r.DD.node},UA:i(n.navigator&&n.navigator.userAgent||""),document:n.document,_injectGlobal:function(t){n.Konva=t},_parseUA:i},o={},a=function(t){o[t.prototype.getClassName()]=t,r[t.prototype.getClassName()]=t},s=function(){function t(){}return t.toCollection=function(e){var i,n=new t,r=e.length;for(i=0;i0?Math.acos(t/a):-Math.acos(t/a),o.scaleX=a,o.scaleY=r/a,o.skewX=(t*i+e*n)/r,o.skewY=0}else if(0!=i||0!=n){var s=Math.sqrt(i*i+n*n);o.rotation=Math.PI/2-(n>0?Math.acos(-i/s):-Math.acos(i/s)),o.scaleX=r/s,o.scaleY=s,o.skewX=0,o.skewY=(t*i+e*n)/r}return o.rotation=f._getRotation(o.rotation),o},t}(),l=Math.PI/180,c=180/Math.PI,d={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,132,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,255,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,203],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[119,128,144],slategrey:[119,128,144],snow:[255,255,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],transparent:[255,255,255,0],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,5]},u=/rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/,p=[],f={_isElement:function(t){return!(!t||1!=t.nodeType)},_isFunction:function(t){return!!(t&&t.constructor&&t.call&&t.apply)},_isPlainObject:function(t){return!!t&&t.constructor===Object},_isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},_isNumber:function(t){return"[object Number]"===Object.prototype.toString.call(t)&&!isNaN(t)&&isFinite(t)},_isString:function(t){return"[object String]"===Object.prototype.toString.call(t)},_isBoolean:function(t){return"[object Boolean]"===Object.prototype.toString.call(t)},isObject:function(t){return t instanceof Object},isValidSelector:function(t){if("string"!=typeof t)return!1;var e=t[0];return"#"===e||"."===e||e===e.toUpperCase()},_sign:function(t){return 0===t||t>0?1:-1},requestAnimFrame:function(t){p.push(t),1===p.length&&requestAnimationFrame((function(){var t=p;p=[],t.forEach((function(t){t()}))}))},createCanvasElement:function(){var t=document.createElement("canvas");try{t.style=t.style||{}}catch(t){}return t},createImageElement:function(){return document.createElement("img")},_isInDocument:function(t){for(;t=t.parentNode;)if(t==document)return!0;return!1},_simplifyArray:function(t){var e,i,n=[],r=t.length,o=f;for(e=0;e>16&255,g:e>>8&255,b:255&e}},getRandomColor:function(){for(var t=(16777215*Math.random()<<0).toString(16);t.length<6;)t="0"+t;return"#"+t},get:function(t,e){return void 0===t?e:t},getRGB:function(t){var e;return t in d?{r:(e=d[t])[0],g:e[1],b:e[2]}:"#"===t[0]?this._hexToRgb(t.substring(1)):"rgb("===t.substr(0,4)?(e=u.exec(t.replace(/ /g,"")),{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10)}):{r:0,g:0,b:0}},colorToRGBA:function(t){return t=t||"black",f._namedColorToRBA(t)||f._hex3ColorToRGBA(t)||f._hex6ColorToRGBA(t)||f._rgbColorToRGBA(t)||f._rgbaColorToRGBA(t)||f._hslColorToRGBA(t)},_namedColorToRBA:function(t){var e=d[t.toLowerCase()];return e?{r:e[0],g:e[1],b:e[2],a:1}:null},_rgbColorToRGBA:function(t){if(0===t.indexOf("rgb(")){var e=(t=t.match(/rgb\(([^)]+)\)/)[1]).split(/ *, */).map(Number);return{r:e[0],g:e[1],b:e[2],a:1}}},_rgbaColorToRGBA:function(t){if(0===t.indexOf("rgba(")){var e=(t=t.match(/rgba\(([^)]+)\)/)[1]).split(/ *, */).map(Number);return{r:e[0],g:e[1],b:e[2],a:e[3]}}},_hex6ColorToRGBA:function(t){if("#"===t[0]&&7===t.length)return{r:parseInt(t.slice(1,3),16),g:parseInt(t.slice(3,5),16),b:parseInt(t.slice(5,7),16),a:1}},_hex3ColorToRGBA:function(t){if("#"===t[0]&&4===t.length)return{r:parseInt(t[1]+t[1],16),g:parseInt(t[2]+t[2],16),b:parseInt(t[3]+t[3],16),a:1}},_hslColorToRGBA:function(t){if(/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.test(t)){var e=/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(t);e[0];var i=e.slice(1),n=Number(i[0])/360,r=Number(i[1])/100,o=Number(i[2])/100,a=void 0,s=void 0,h=void 0;if(0===r)return h=255*o,{r:Math.round(h),g:Math.round(h),b:Math.round(h),a:1};for(var l=2*o-(a=o<.5?o*(1+r):o+r-o*r),c=[0,0,0],d=0;d<3;d++)(s=n+1/3*-(d-1))<0&&s++,s>1&&s--,h=6*s<1?l+6*(a-l)*s:2*s<1?a:3*s<2?l+(a-l)*(2/3-s)*6:l,c[d]=255*h;return{r:Math.round(c[0]),g:Math.round(c[1]),b:Math.round(c[2]),a:1}}},haveIntersection:function(t,e){return!(e.x>t.x+t.width||e.x+e.widtht.y+t.height||e.y+e.height1?(a=i,s=n,h=(i-r)*(i-r)+(n-o)*(n-o)):h=((a=t+c*(i-t))-r)*(a-r)+((s=e+c*(n-e))-o)*(s-o)}return[a,s,h]},_getProjectionToLine:function(t,e,i){var n=f.cloneObject(t),r=Number.MAX_VALUE;return e.forEach((function(o,a){if(i||a!==e.length-1){var s=e[(a+1)%e.length],h=f._getProjectionToSegment(o.x,o.y,s.x,s.y,t.x,t.y),l=h[0],c=h[1],d=h[2];de.length){var a=e;e=t,t=a}for(n=0;n255?255:t<0?0:Math.round(t)}function y(){if(r.isUnminified)return function(t,e){return f._isNumber(t)||f.warn(g(t)+' is a not valid value for "'+e+'" attribute. The value should be a number.'),t}}function m(t){if(r.isUnminified)return function(e,i){var n=f._isNumber(e),r=f._isArray(e)&&e.length==t;return n||r||f.warn(g(e)+' is a not valid value for "'+i+'" attribute. The value should be a number or Array('+t+")"),e}}function _(){if(r.isUnminified)return function(t,e){return f._isNumber(t)||"auto"===t||f.warn(g(t)+' is a not valid value for "'+e+'" attribute. The value should be a number or "auto".'),t}}function b(){if(r.isUnminified)return function(t,e){return f._isString(t)||f.warn(g(t)+' is a not valid value for "'+e+'" attribute. The value should be a string.'),t}}function x(){if(r.isUnminified)return function(t,e){var i=f._isString(t),n="[object CanvasGradient]"===Object.prototype.toString.call(t);return i||n||f.warn(g(t)+' is a not valid value for "'+e+'" attribute. The value should be a string or a native gradient.'),t}}function S(){if(r.isUnminified)return function(t,e){return!0===t||!1===t||f.warn(g(t)+' is a not valid value for "'+e+'" attribute. The value should be a boolean.'),t}}var w={addGetterSetter:function(t,e,i,n,r){w.addGetter(t,e,i),w.addSetter(t,e,n,r),w.addOverloadedGetterSetter(t,e)},addGetter:function(t,e,i){var n="get"+f._capitalize(e);t.prototype[n]=t.prototype[n]||function(){var t=this.attrs[e];return void 0===t?i:t}},addSetter:function(t,e,i,n){var r="set"+f._capitalize(e);t.prototype[r]||w.overWriteSetter(t,e,i,n)},overWriteSetter:function(t,e,i,n){var r="set"+f._capitalize(e);t.prototype[r]=function(t){return i&&null!=t&&(t=i.call(this,t,e)),this._setAttr(e,t),n&&n.call(this),this}},addComponentsGetterSetter:function(t,e,i,n,o){var a,s,h=i.length,l=f._capitalize,c="get"+l(e),d="set"+l(e);t.prototype[c]=function(){var t={};for(a=0;a=100&&e.shift()},t.prototype.reset=function(){var t=this.getCanvas().getPixelRatio();this.setTransform(1*t,0,0,1*t,0,0)},t.prototype.getCanvas=function(){return this.canvas},t.prototype.clear=function(t){var e=this.getCanvas();t?this.clearRect(t.x||0,t.y||0,t.width||0,t.height||0):this.clearRect(0,0,e.getWidth()/e.pixelRatio,e.getHeight()/e.pixelRatio)},t.prototype._applyLineCap=function(t){var e=t.getLineCap();e&&this.setAttr("lineCap",e)},t.prototype._applyOpacity=function(t){var e=t.getAbsoluteOpacity();1!==e&&this.setAttr("globalAlpha",e)},t.prototype._applyLineJoin=function(t){var e=t.attrs.lineJoin;e&&this.setAttr("lineJoin",e)},t.prototype.setAttr=function(t,e){this._context[t]=e},t.prototype.arc=function(t,e,i,n,r,o){this._context.arc(t,e,i,n,r,o)},t.prototype.arcTo=function(t,e,i,n,r){this._context.arcTo(t,e,i,n,r)},t.prototype.beginPath=function(){this._context.beginPath()},t.prototype.bezierCurveTo=function(t,e,i,n,r,o){this._context.bezierCurveTo(t,e,i,n,r,o)},t.prototype.clearRect=function(t,e,i,n){this._context.clearRect(t,e,i,n)},t.prototype.clip=function(){this._context.clip()},t.prototype.closePath=function(){this._context.closePath()},t.prototype.createImageData=function(t,e){var i=arguments;return 2===i.length?this._context.createImageData(t,e):1===i.length?this._context.createImageData(t):void 0},t.prototype.createLinearGradient=function(t,e,i,n){return this._context.createLinearGradient(t,e,i,n)},t.prototype.createPattern=function(t,e){return this._context.createPattern(t,e)},t.prototype.createRadialGradient=function(t,e,i,n,r,o){return this._context.createRadialGradient(t,e,i,n,r,o)},t.prototype.drawImage=function(t,e,i,n,r,o,a,s,h){var l=arguments,c=this._context;3===l.length?c.drawImage(t,e,i):5===l.length?c.drawImage(t,e,i,n,r):9===l.length&&c.drawImage(t,e,i,n,r,o,a,s,h)},t.prototype.ellipse=function(t,e,i,n,r,o,a,s){this._context.ellipse(t,e,i,n,r,o,a,s)},t.prototype.isPointInPath=function(t,e){return this._context.isPointInPath(t,e)},t.prototype.fill=function(){this._context.fill()},t.prototype.fillRect=function(t,e,i,n){this._context.fillRect(t,e,i,n)},t.prototype.strokeRect=function(t,e,i,n){this._context.strokeRect(t,e,i,n)},t.prototype.fillText=function(t,e,i){this._context.fillText(t,e,i)},t.prototype.measureText=function(t){return this._context.measureText(t)},t.prototype.getImageData=function(t,e,i,n){return this._context.getImageData(t,e,i,n)},t.prototype.lineTo=function(t,e){this._context.lineTo(t,e)},t.prototype.moveTo=function(t,e){this._context.moveTo(t,e)},t.prototype.rect=function(t,e,i,n){this._context.rect(t,e,i,n)},t.prototype.putImageData=function(t,e,i){this._context.putImageData(t,e,i)},t.prototype.quadraticCurveTo=function(t,e,i,n){this._context.quadraticCurveTo(t,e,i,n)},t.prototype.restore=function(){this._context.restore()},t.prototype.rotate=function(t){this._context.rotate(t)},t.prototype.save=function(){this._context.save()},t.prototype.scale=function(t,e){this._context.scale(t,e)},t.prototype.setLineDash=function(t){this._context.setLineDash?this._context.setLineDash(t):"mozDash"in this._context?this._context.mozDash=t:"webkitLineDash"in this._context&&(this._context.webkitLineDash=t)},t.prototype.getLineDash=function(){return this._context.getLineDash()},t.prototype.setTransform=function(t,e,i,n,r,o){this._context.setTransform(t,e,i,n,r,o)},t.prototype.stroke=function(){this._context.stroke()},t.prototype.strokeText=function(t,e,i,n){this._context.strokeText(t,e,i,n)},t.prototype.transform=function(t,e,i,n,r,o){this._context.transform(t,e,i,n,r,o)},t.prototype.translate=function(t,e){this._context.translate(t,e)},t.prototype._enableTrace=function(){var t,e,i=this,n=T.length,r=f._simplifyArray,o=this.setAttr,a=function(t){var n,o=i[t];i[t]=function(){return e=r(Array.prototype.slice.call(arguments,0)),n=o.apply(i,arguments),i._trace({method:t,args:e}),n}};for(t=0;t0&&t[0].getDepth()<=r&&s(t)}(o.getStage().getChildren()),a},t.prototype.getDepth=function(){for(var t=0,e=this.parent;e;)t++,e=e.parent;return t},t.prototype._batchTransformChanges=function(t){this._batchingTransformChange=!0,t(),this._batchingTransformChange=!1,this._needClearTransformCache&&(this._clearCache("transform"),this._clearSelfAndDescendantCache("absoluteTransform",!0)),this._needClearTransformCache=!1},t.prototype.setPosition=function(t){var e=this;return this._batchTransformChanges((function(){e.x(t.x),e.y(t.y)})),this},t.prototype.getPosition=function(){return{x:this.x(),y:this.y()}},t.prototype.getAbsolutePosition=function(t){for(var e=!1,i=this.parent;i;){if(i.isCached()){e=!0;break}i=i.parent}e&&!t&&(t=!0);var n=this.getAbsoluteTransform(t).getMatrix(),r=new h,o=this.offset();return r.m=n.slice(),r.translate(o.x,o.y),r.getTranslation()},t.prototype.setAbsolutePosition=function(t){var e=this._clearTransform();this.attrs.x=e.x,this.attrs.y=e.y,delete e.x,delete e.y,this._clearCache("transform");var i=this._getAbsoluteTransform().copy();return i.invert(),i.translate(t.x,t.y),t={x:this.attrs.x+i.getTranslation().x,y:this.attrs.y+i.getTranslation().y},this._setTransform(e),this.setPosition({x:t.x,y:t.y}),this._clearCache("transform"),this._clearSelfAndDescendantCache("absoluteTransform"),this},t.prototype._setTransform=function(t){var e;for(e in t)this.attrs[e]=t[e]},t.prototype._clearTransform=function(){var t={x:this.x(),y:this.y(),rotation:this.rotation(),scaleX:this.scaleX(),scaleY:this.scaleY(),offsetX:this.offsetX(),offsetY:this.offsetY(),skewX:this.skewX(),skewY:this.skewY()};return this.attrs.x=0,this.attrs.y=0,this.attrs.rotation=0,this.attrs.scaleX=1,this.attrs.scaleY=1,this.attrs.offsetX=0,this.attrs.offsetY=0,this.attrs.skewX=0,this.attrs.skewY=0,t},t.prototype.move=function(t){var e=t.x,i=t.y,n=this.x(),r=this.y();return void 0!==e&&(n+=e),void 0!==i&&(r+=i),this.setPosition({x:n,y:r}),this},t.prototype._eachAncestorReverse=function(t,e){var i,n,r=[],o=this.getParent();if(!e||e._id!==this._id){for(r.unshift(this);o&&(!e||o._id!==e._id);)r.unshift(o),o=o.parent;for(i=r.length,n=0;n0&&(this.parent.children.splice(t,1),this.parent.children.splice(t-1,0,this),this.parent._setChildrenIndices(),!0)},t.prototype.moveToBottom=function(){if(!this.parent)return f.warn("Node has no parent. moveToBottom function is ignored."),!1;var t=this.index;return t>0&&(this.parent.children.splice(t,1),this.parent.children.unshift(this),this.parent._setChildrenIndices(),!0)},t.prototype.setZIndex=function(t){if(!this.parent)return f.warn("Node has no parent. zIndex parameter is ignored."),this;(t<0||t>=this.parent.children.length)&&f.warn("Unexpected value "+t+" for zIndex property. zIndex is just index of a node in children of its parent. Expected value is from 0 to "+(this.parent.children.length-1)+".");var e=this.index;return this.parent.children.splice(e,1),this.parent.children.splice(t,0,this),this.parent._setChildrenIndices(),this},t.prototype.getAbsoluteOpacity=function(){return this._getCache("absoluteOpacity",this._getAbsoluteOpacity)},t.prototype._getAbsoluteOpacity=function(){var t=this.opacity(),e=this.getParent();return e&&!e._isUnderCache&&(t*=e.getAbsoluteOpacity()),t},t.prototype.moveTo=function(t){return this.getParent()!==t&&(this._remove(),t.add(this)),this},t.prototype.toObject=function(){var t,e,i,n,r={},o=this.getAttrs();for(t in r.attrs={},o)e=o[t],f.isObject(e)&&!f._isPlainObject(e)&&!f._isArray(e)||(i="function"==typeof this[t]&&this[t],delete o[t],n=i?i.call(this):null,o[t]=e,n!==e&&(r.attrs[t]=e));return r.className=this.getClassName(),f._prepareToStringify(r)},t.prototype.toJSON=function(){return JSON.stringify(this.toObject())},t.prototype.getParent=function(){return this.parent},t.prototype.findAncestors=function(t,e,i){var n=[];e&&this._isMatch(t)&&n.push(this);for(var r=this.parent;r;){if(r===i)return n;r._isMatch(t)&&n.push(r),r=r.parent}return n},t.prototype.isAncestorOf=function(t){return!1},t.prototype.findAncestor=function(t,e,i){return this.findAncestors(t,e,i)[0]},t.prototype._isMatch=function(t){if(!t)return!1;if("function"==typeof t)return t(this);var e,i,n=t.replace(/ /g,"").split(","),r=n.length;for(e=0;e=0)&&!this.isDragging()){var i=!1;D._dragElements.forEach((function(t){e.isAncestorOf(t.node)&&(i=!0)})),i||this._createDragElement(t)}}))},t.prototype._dragChange=function(){if(this.attrs.draggable)this._listenDrag();else{if(this._dragCleanup(),!this.getStage())return;var t=D._dragElements.get(this._id),e=t&&"dragging"===t.dragStatus,i=t&&"ready"===t.dragStatus;e?this.stopDrag():i&&D._dragElements.delete(this._id)}},t.prototype._dragCleanup=function(){this.off("mousedown.konva"),this.off("touchstart.konva")},t.create=function(t,e){return f._isString(t)&&(t=JSON.parse(t)),this._createNode(t,e)},t._createNode=function(e,i){var n,r,a,s=t.prototype.getClassName.call(e),h=e.children;if(i&&(e.attrs.container=i),o[s]||(f.warn('Can not find a node with class name "'+s+'". Fallback to "Shape".'),s="Shape"),n=new(0,o[s])(e.attrs),h)for(r=h.length,a=0;a0},e.prototype.removeChildren=function(){for(var t,e=0;e1){for(var i=0;i0?e[0]:void 0},e.prototype._generalFind=function(t,e){var i=[];return this._descendants((function(n){var r=n._isMatch(t);return r&&i.push(n),!(!r||!e)})),s.toCollection(i)},e.prototype._descendants=function(t){for(var e=0;e-1&&nt.splice(i,1),this},e.prototype.getPointerPosition=function(){var t=this._pointerPositions[0]||this._changedPointerPositions[0];return t?{x:t.x,y:t.y}:(f.warn("Pointer position is missing and not registered by the stage. Looks like it is outside of the stage container. You can set it manually from event: stage.setPointersPositions(event);"),null)},e.prototype._getPointerById=function(t){return this._pointerPositions.find((function(e){return e.id===t}))},e.prototype.getPointersPositions=function(){return this._pointerPositions},e.prototype.getStage=function(){return this},e.prototype.getContent=function(){return this.content},e.prototype._toKonvaCanvas=function(t){(t=t||{}).x=t.x||0,t.y=t.y||0,t.width=t.width||this.width(),t.height=t.height||this.height();var e=new E({width:t.width,height:t.height,pixelRatio:t.pixelRatio||1}),i=e.getContext()._context,n=this.children;return(t.x||t.y)&&i.translate(-1*t.x,-1*t.y),n.each((function(e){if(e.isVisible()){var n=e._toKonvaCanvas(t);i.drawImage(n._canvas,t.x,t.y,n.getWidth()/n.getPixelRatio(),n.getHeight()/n.getPixelRatio())}})),e},e.prototype.getIntersection=function(t,e){if(!t)return null;var i,n,r=this.children;for(i=r.length-1;i>=0;i--)if(n=r[i].getIntersection(t,e))return n;return null},e.prototype._resizeDOM=function(){var t=this.width(),e=this.height();this.content&&(this.content.style.width=t+"px",this.content.style.height=e+"px"),this.bufferCanvas.setSize(t,e),this.bufferHitCanvas.setSize(t,e),this.children.each((function(i){i.setSize({width:t,height:e}),i.draw()}))},e.prototype.add=function(e){if(arguments.length>1){for(var i=0;i5&&f.warn("The stage has "+n+" layers. Recommended maximum number of layers is 3-5. Adding more layers into the stage may drop the performance. Rethink your tree structure, you can use Konva.Group."),e.setSize({width:this.width(),height:this.height()}),e.draw(),r.isBrowser&&this.content.appendChild(e.canvas._canvas),this},e.prototype.getParent=function(){return null},e.prototype.getLayer=function(){return null},e.prototype.hasPointerCapture=function(t){return J(t,this)},e.prototype.setPointerCapture=function(t){Z(t,this)},e.prototype.releaseCapture=function(t){$(t)},e.prototype.getLayers=function(){return this.getChildren()},e.prototype._bindContentEvents=function(){if(r.isBrowser)for(var t=0;t0},e.prototype.destroy=function(){return X.prototype.destroy.call(this),delete ht[this.colorKey],delete this.colorKey,this},e.prototype._useBufferCanvas=function(t){var e;if(!this.getStage())return!1;if(!(null===(e=this.attrs.perfectDrawEnabled)||void 0===e||e))return!1;var i=t||this.hasFill(),n=this.hasStroke(),r=1!==this.getAbsoluteOpacity();if(i&&n&&r)return!0;var o=this.hasShadow(),a=this.shadowForStrokeEnabled();return!!(i&&n&&o&&a)},e.prototype.setStrokeHitEnabled=function(t){f.warn("strokeHitEnabled property is deprecated. Please use hitStrokeWidth instead."),t?this.hitStrokeWidth("auto"):this.hitStrokeWidth(0)},e.prototype.getStrokeHitEnabled=function(){return 0!==this.hitStrokeWidth()},e.prototype.getSelfRect=function(){var t=this.size();return{x:this._centroid?-t.width/2:0,y:this._centroid?-t.height/2:0,width:t.width,height:t.height}},e.prototype.getClientRect=function(t){void 0===t&&(t={});var e=t.skipTransform,i=t.relativeTo,n=this.getSelfRect(),r=!t.skipStroke&&this.hasStroke()&&this.strokeWidth()||0,o=n.width+r,a=n.height+r,s=!t.skipShadow&&this.hasShadow(),h=s?this.shadowOffsetX():0,l=s?this.shadowOffsetY():0,c=o+Math.abs(h),d=a+Math.abs(l),u=s&&this.shadowBlur()||0,p=c+2*u,f=d+2*u,g=0;Math.round(r/2)!==r/2&&(g=1);var v={width:p+g,height:f+g,x:-Math.round(r/2+u)+Math.min(h,0)+n.x,y:-Math.round(r/2+u)+Math.min(l,0)+n.y};return e?v:this._transformedRect(v,i)},e.prototype.drawScene=function(t,e){var i,n,r=this.getLayer(),o=t||r.getCanvas(),a=o.getContext(),s=this._getCanvasCache(),h=this.getSceneFunc(),l=this.hasShadow(),c=o.isCache,d=o.isCache,u=e===this;if(!this.isVisible()&&!c)return this;if(s){a.save();var p=this.getAbsoluteTransform(e).getMatrix();return a.transform(p[0],p[1],p[2],p[3],p[4],p[5]),this._drawCachedSceneCanvas(a),a.restore(),this}if(!h)return this;if(a.save(),this._useBufferCanvas()&&!d){(n=(i=this.getStage().bufferCanvas).getContext()).clear(),n.save(),n._applyLineJoin(this);var f=this.getAbsoluteTransform(e).getMatrix();n.transform(f[0],f[1],f[2],f[3],f[4],f[5]),h.call(this,n,this),n.restore();var g=i.pixelRatio;l&&a._applyShadow(this),a._applyOpacity(this),a._applyGlobalCompositeOperation(this),a.drawImage(i._canvas,0,0,i.width/g,i.height/g)}else{if(a._applyLineJoin(this),!u){f=this.getAbsoluteTransform(e).getMatrix();a.transform(f[0],f[1],f[2],f[3],f[4],f[5]),a._applyOpacity(this),a._applyGlobalCompositeOperation(this)}l&&a._applyShadow(this),h.call(this,a,this)}return a.restore(),this},e.prototype.drawHit=function(t,e,i){if(void 0===i&&(i=!1),!this.shouldDrawHit(e,i))return this;var n=this.getLayer(),r=t||n.hitCanvas,o=r&&r.getContext(),a=this.hitFunc()||this.sceneFunc(),s=this._getCanvasCache(),h=s&&s.hit;if(this.colorKey||(console.log(this),f.warn("Looks like your canvas has a destroyed shape in it. Do not reuse shape after you destroyed it. See the shape in logs above. If you want to reuse shape you should call remove() instead of destroy()")),h){o.save();var l=this.getAbsoluteTransform(e).getMatrix();return o.transform(l[0],l[1],l[2],l[3],l[4],l[5]),this._drawCachedHitCanvas(o),o.restore(),this}if(!a)return this;if(o.save(),o._applyLineJoin(this),!(this===e)){var c=this.getAbsoluteTransform(e).getMatrix();o.transform(c[0],c[1],c[2],c[3],c[4],c[5])}return a.call(this,o,this),o.restore(),this},e.prototype.drawHitFromCache=function(t){void 0===t&&(t=0);var e,i,n,r,o,a=this._getCanvasCache(),s=this._getCachedSceneCanvas(),h=a.hit,l=h.getContext(),c=h.getWidth(),d=h.getHeight();l.clear(),l.drawImage(s._canvas,0,0,c,d);try{for(n=(i=(e=l.getImageData(0,0,c,d)).data).length,r=f._hexToRgb(this.colorKey),o=0;ot?(i[o]=r.r,i[o+1]=r.g,i[o+2]=r.b,i[o+3]=255):i[o+3]=0;l.putImageData(e,0,0)}catch(t){f.error("Unable to draw hit graph from cached scene canvas. "+t.message)}return this},e.prototype.hasPointerCapture=function(t){return J(t,this)},e.prototype.setPointerCapture=function(t){Z(t,this)},e.prototype.releaseCapture=function(t){$(t)},e}(X);lt.prototype._fillFunc=function(t){t.fill()},lt.prototype._strokeFunc=function(t){t.stroke()},lt.prototype._fillFuncHit=function(t){t.fill()},lt.prototype._strokeFuncHit=function(t){t.stroke()},lt.prototype._centroid=!1,lt.prototype.nodeType="Shape",a(lt),lt.prototype.eventListeners={},lt.prototype.on.call(lt.prototype,"shadowColorChange.konva shadowBlurChange.konva shadowOffsetChange.konva shadowOpacityChange.konva shadowEnabledChange.konva",(function(){this._clearCache("hasShadow")})),lt.prototype.on.call(lt.prototype,"shadowColorChange.konva shadowOpacityChange.konva shadowEnabledChange.konva",(function(){this._clearCache("shadowRGBA")})),lt.prototype.on.call(lt.prototype,"fillPriorityChange.konva fillPatternImageChange.konva fillPatternRepeatChange.konva fillPatternScaleXChange.konva fillPatternScaleYChange.konva",(function(){this._clearCache("patternImage")})),lt.prototype.on.call(lt.prototype,"fillPriorityChange.konva fillLinearGradientColorStopsChange.konva fillLinearGradientStartPointXChange.konva fillLinearGradientStartPointYChange.konva fillLinearGradientEndPointXChange.konva fillLinearGradientEndPointYChange.konva",(function(){this._clearCache("linearGradient")})),lt.prototype.on.call(lt.prototype,"fillPriorityChange.konva fillRadialGradientColorStopsChange.konva fillRadialGradientStartPointXChange.konva fillRadialGradientStartPointYChange.konva fillRadialGradientEndPointXChange.konva fillRadialGradientEndPointYChange.konva fillRadialGradientStartRadiusChange.konva fillRadialGradientEndRadiusChange.konva",(function(){this._clearCache("radialGradient")})),w.addGetterSetter(lt,"stroke",void 0,x()),w.addGetterSetter(lt,"strokeWidth",2,y()),w.addGetterSetter(lt,"fillAfterStrokeEnabled",!1),w.addGetterSetter(lt,"hitStrokeWidth","auto",_()),w.addGetterSetter(lt,"strokeHitEnabled",!0,S()),w.addGetterSetter(lt,"perfectDrawEnabled",!0,S()),w.addGetterSetter(lt,"shadowForStrokeEnabled",!0,S()),w.addGetterSetter(lt,"lineJoin"),w.addGetterSetter(lt,"lineCap"),w.addGetterSetter(lt,"sceneFunc"),w.addGetterSetter(lt,"hitFunc"),w.addGetterSetter(lt,"dash"),w.addGetterSetter(lt,"dashOffset",0,y()),w.addGetterSetter(lt,"shadowColor",void 0,b()),w.addGetterSetter(lt,"shadowBlur",0,y()),w.addGetterSetter(lt,"shadowOpacity",1,y()),w.addComponentsGetterSetter(lt,"shadowOffset",["x","y"]),w.addGetterSetter(lt,"shadowOffsetX",0,y()),w.addGetterSetter(lt,"shadowOffsetY",0,y()),w.addGetterSetter(lt,"fillPatternImage"),w.addGetterSetter(lt,"fill",void 0,x()),w.addGetterSetter(lt,"fillPatternX",0,y()),w.addGetterSetter(lt,"fillPatternY",0,y()),w.addGetterSetter(lt,"fillLinearGradientColorStops"),w.addGetterSetter(lt,"strokeLinearGradientColorStops"),w.addGetterSetter(lt,"fillRadialGradientStartRadius",0),w.addGetterSetter(lt,"fillRadialGradientEndRadius",0),w.addGetterSetter(lt,"fillRadialGradientColorStops"),w.addGetterSetter(lt,"fillPatternRepeat","repeat"),w.addGetterSetter(lt,"fillEnabled",!0),w.addGetterSetter(lt,"strokeEnabled",!0),w.addGetterSetter(lt,"shadowEnabled",!0),w.addGetterSetter(lt,"dashEnabled",!0),w.addGetterSetter(lt,"strokeScaleEnabled",!0),w.addGetterSetter(lt,"fillPriority","color"),w.addComponentsGetterSetter(lt,"fillPatternOffset",["x","y"]),w.addGetterSetter(lt,"fillPatternOffsetX",0,y()),w.addGetterSetter(lt,"fillPatternOffsetY",0,y()),w.addComponentsGetterSetter(lt,"fillPatternScale",["x","y"]),w.addGetterSetter(lt,"fillPatternScaleX",1,y()),w.addGetterSetter(lt,"fillPatternScaleY",1,y()),w.addComponentsGetterSetter(lt,"fillLinearGradientStartPoint",["x","y"]),w.addComponentsGetterSetter(lt,"strokeLinearGradientStartPoint",["x","y"]),w.addGetterSetter(lt,"fillLinearGradientStartPointX",0),w.addGetterSetter(lt,"strokeLinearGradientStartPointX",0),w.addGetterSetter(lt,"fillLinearGradientStartPointY",0),w.addGetterSetter(lt,"strokeLinearGradientStartPointY",0),w.addComponentsGetterSetter(lt,"fillLinearGradientEndPoint",["x","y"]),w.addComponentsGetterSetter(lt,"strokeLinearGradientEndPoint",["x","y"]),w.addGetterSetter(lt,"fillLinearGradientEndPointX",0),w.addGetterSetter(lt,"strokeLinearGradientEndPointX",0),w.addGetterSetter(lt,"fillLinearGradientEndPointY",0),w.addGetterSetter(lt,"strokeLinearGradientEndPointY",0),w.addComponentsGetterSetter(lt,"fillRadialGradientStartPoint",["x","y"]),w.addGetterSetter(lt,"fillRadialGradientStartPointX",0),w.addGetterSetter(lt,"fillRadialGradientStartPointY",0),w.addComponentsGetterSetter(lt,"fillRadialGradientEndPoint",["x","y"]),w.addGetterSetter(lt,"fillRadialGradientEndPointX",0),w.addGetterSetter(lt,"fillRadialGradientEndPointY",0),w.addGetterSetter(lt,"fillPatternRotation",0),w.backCompat(lt,{dashArray:"dash",getDashArray:"getDash",setDashArray:"getDash",drawFunc:"sceneFunc",getDrawFunc:"getSceneFunc",setDrawFunc:"setSceneFunc",drawHitFunc:"hitFunc",getDrawHitFunc:"getHitFunc",setDrawHitFunc:"setHitFunc"}),s.mapMethods(lt);var ct=[{x:0,y:0},{x:-1,y:-1},{x:1,y:-1},{x:1,y:1},{x:-1,y:1}],dt=ct.length,ut=function(t){function e(e){var i=t.call(this,e)||this;return i.canvas=new E,i.hitCanvas=new O({pixelRatio:1}),i._waitingForDraw=!1,i.on("visibleChange.konva",i._checkVisibility),i._checkVisibility(),i.on("imageSmoothingEnabledChange.konva",i._setSmoothEnabled),i._setSmoothEnabled(),i}return P(e,t),e.prototype.createPNGStream=function(){return this.canvas._canvas.createPNGStream()},e.prototype.getCanvas=function(){return this.canvas},e.prototype.getHitCanvas=function(){return this.hitCanvas},e.prototype.getContext=function(){return this.getCanvas().getContext()},e.prototype.clear=function(t){return this.getContext().clear(t),this.getHitCanvas().getContext().clear(t),this},e.prototype.setZIndex=function(e){t.prototype.setZIndex.call(this,e);var i=this.getStage();return i&&(i.content.removeChild(this.getCanvas()._canvas),e0?{antialiased:!0}:{}},e.prototype.drawScene=function(t,e){var i=this.getLayer(),n=t||i&&i.getCanvas();return this._fire("beforeDraw",{node:this}),this.clearBeforeDraw()&&n.getContext().clear(),U.prototype.drawScene.call(this,n,e),this._fire("draw",{node:this}),this},e.prototype.drawHit=function(t,e){var i=this.getLayer(),n=t||i&&i.hitCanvas;return i&&i.clearBeforeDraw()&&i.getHitCanvas().getContext().clear(),U.prototype.drawHit.call(this,n,e),this},e.prototype.enableHitGraph=function(){return this.hitGraphEnabled(!0),this},e.prototype.disableHitGraph=function(){return this.hitGraphEnabled(!1),this},e.prototype.setHitGraphEnabled=function(t){f.warn("hitGraphEnabled method is deprecated. Please use layer.listening() instead."),this.listening(t)},e.prototype.getHitGraphEnabled=function(t){return f.warn("hitGraphEnabled method is deprecated. Please use layer.listening() instead."),this.listening()},e.prototype.toggleHitCanvas=function(){if(this.parent){var t=this.parent;!!this.hitCanvas._canvas.parentNode?t.content.removeChild(this.hitCanvas._canvas):t.content.appendChild(this.hitCanvas._canvas)}},e}(U);ut.prototype.nodeType="Layer",a(ut),w.addGetterSetter(ut,"imageSmoothingEnabled",!0),w.addGetterSetter(ut,"clearBeforeDraw",!0),w.addGetterSetter(ut,"hitGraphEnabled",!0,S()),s.mapMethods(ut);var pt=function(t){function e(e){var i=t.call(this,e)||this;return i.listening(!1),f.warn('Konva.Fast layer is deprecated. Please use "new Konva.Layer({ listening: false })" instead.'),i}return P(e,t),e}(ut);pt.prototype.nodeType="FastLayer",a(pt),s.mapMethods(pt);var ft=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._validateAdd=function(t){var e=t.getType();"Group"!==e&&"Shape"!==e&&f.throw("You may only add groups and shapes to groups.")},e}(U);ft.prototype.nodeType="Group",a(ft),s.mapMethods(ft);var gt=n.performance&&n.performance.now?function(){return n.performance.now()}:function(){return(new Date).getTime()},vt=function(){function t(e,i){this.id=t.animIdCounter++,this.frame={time:0,timeDiff:0,lastTime:gt(),frameRate:0},this.func=e,this.setLayers(i)}return t.prototype.setLayers=function(t){var e=[];return e=t?t.length>0?t:[t]:[],this.layers=e,this},t.prototype.getLayers=function(){return this.layers},t.prototype.addLayer=function(t){var e,i=this.layers,n=i.length;for(e=0;ethis.duration?this.yoyo?(this._time=this.duration,this.reverse()):this.finish():t<0?this.yoyo?(this._time=0,this.play()):this.reset():(this._time=t,this.update())},t.prototype.getTime=function(){return this._time},t.prototype.setPosition=function(t){this.prevPos=this._pos,this.propFunc(t),this._pos=t},t.prototype.getPosition=function(t){return void 0===t&&(t=this._time),this.func(t,this.begin,this._change,this.duration)},t.prototype.play=function(){this.state=2,this._startTime=this.getTimer()-this._time,this.onEnterFrame(),this.fire("onPlay")},t.prototype.reverse=function(){this.state=3,this._time=this.duration-this._time,this._startTime=this.getTimer()-this._time,this.onEnterFrame(),this.fire("onReverse")},t.prototype.seek=function(t){this.pause(),this._time=t,this.update(),this.fire("onSeek")},t.prototype.reset=function(){this.pause(),this._time=0,this.update(),this.fire("onReset")},t.prototype.finish=function(){this.pause(),this._time=this.duration,this.update(),this.fire("onFinish")},t.prototype.update=function(){this.setPosition(this.getPosition(this._time)),this.fire("onUpdate")},t.prototype.onEnterFrame=function(){var t=this.getTimer()-this._startTime;2===this.state?this.setTime(t):3===this.state&&this.setTime(this.duration-t)},t.prototype.pause=function(){this.state=1,this.fire("onPause")},t.prototype.getTimer=function(){return(new Date).getTime()},t}(),xt=function(){function t(e){var i,n,o=this,a=e.node,s=a._id,h=e.easing||St.Linear,l=!!e.yoyo;i=void 0===e.duration?.3:0===e.duration?.001:e.duration,this.node=a,this._id=mt++;var c=a.getLayer()||(a instanceof r.Stage?a.getLayers():null);for(n in c||f.error("Tween constructor have `node` that is not in a layer. Please add node into layer first."),this.anim=new vt((function(){o.tween.onEnterFrame()}),c),this.tween=new bt(n,(function(t){o._tweenFunc(t)}),h,0,1,1e3*i,l),this._addListeners(),t.attrs[s]||(t.attrs[s]={}),t.attrs[s][this._id]||(t.attrs[s][this._id]={}),t.tweens[s]||(t.tweens[s]={}),e)void 0===yt[n]&&this._addAttr(n,e[n]);this.reset(),this.onFinish=e.onFinish,this.onReset=e.onReset,this.onUpdate=e.onUpdate}return t.prototype._addAttr=function(e,i){var n,r,o,a,s,h,l,c,d=this.node,u=d._id;if((o=t.tweens[u][e])&&delete t.attrs[u][o][e],n=d.getAttr(e),f._isArray(i))if(r=[],s=Math.max(i.length,n.length),"points"===e&&i.length!==n.length&&(i.length>n.length?(l=n,n=f._prepareArrayForTween(n,i,d.closed())):(h=i,i=f._prepareArrayForTween(i,n,d.closed()))),0===e.indexOf("fill"))for(a=0;a4){for(i=(e=this.getTensionPoints()).length,n=s?0:4,s||t.quadraticCurveTo(e[0],e[1],e[2],e[3]);n4;o&&(r=this.getTensionPoints());var a,s,h=n.length;o?(a=n[h-2]-(r[r.length-2]+r[r.length-4])/2,s=n[h-1]-(r[r.length-1]+r[r.length-3])/2):(a=n[h-2]-n[h-4],s=n[h-1]-n[h-3]);var l=(Math.atan2(s,a)+i)%i,c=this.pointerLength(),d=this.pointerWidth();e.save(),e.beginPath(),e.translate(n[h-2],n[h-1]),e.rotate(l),e.moveTo(0,0),e.lineTo(-c,d/2),e.lineTo(-c,-d/2),e.closePath(),e.restore(),this.pointerAtBeginning()&&(e.save(),e.translate(n[0],n[1]),o?(a=(r[0]+r[2])/2-n[0],s=(r[1]+r[3])/2-n[1]):(a=n[2]-n[0],s=n[3]-n[1]),e.rotate((Math.atan2(-s,-a)+i)%i),e.moveTo(0,0),e.lineTo(-c,d/2),e.lineTo(-c,-d/2),e.closePath(),e.restore());var u=this.dashEnabled();u&&(this.attrs.dashEnabled=!1,e.setLineDash([])),e.fillStrokeShape(this),u&&(this.attrs.dashEnabled=!0)},e.prototype.getSelfRect=function(){var e=t.prototype.getSelfRect.call(this),i=this.pointerWidth()/2;return{x:e.x-i,y:e.y-i,width:e.width+2*i,height:e.height+2*i}},e}(Pt);kt.prototype.className="Arrow",a(kt),w.addGetterSetter(kt,"pointerLength",10,y()),w.addGetterSetter(kt,"pointerWidth",10,y()),w.addGetterSetter(kt,"pointerAtBeginning",!1),s.mapMethods(kt);var Tt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._sceneFunc=function(t){t.beginPath(),t.arc(0,0,this.attrs.radius||0,0,2*Math.PI,!1),t.closePath(),t.fillStrokeShape(this)},e.prototype.getWidth=function(){return 2*this.radius()},e.prototype.getHeight=function(){return 2*this.radius()},e.prototype.setWidth=function(t){this.radius()!==t/2&&this.radius(t/2)},e.prototype.setHeight=function(t){this.radius()!==t/2&&this.radius(t/2)},e}(lt);Tt.prototype._centroid=!0,Tt.prototype.className="Circle",Tt.prototype._attrsAffectingSize=["radius"],a(Tt),w.addGetterSetter(Tt,"radius",0,y()),s.mapMethods(Tt);var At=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._sceneFunc=function(t){var e=this.radiusX(),i=this.radiusY();t.beginPath(),t.save(),e!==i&&t.scale(1,i/e),t.arc(0,0,e,0,2*Math.PI,!1),t.restore(),t.closePath(),t.fillStrokeShape(this)},e.prototype.getWidth=function(){return 2*this.radiusX()},e.prototype.getHeight=function(){return 2*this.radiusY()},e.prototype.setWidth=function(t){this.radiusX(t/2)},e.prototype.setHeight=function(t){this.radiusY(t/2)},e}(lt);At.prototype.className="Ellipse",At.prototype._centroid=!0,At.prototype._attrsAffectingSize=["radiusX","radiusY"],a(At),w.addComponentsGetterSetter(At,"radius",["x","y"]),w.addGetterSetter(At,"radiusX",0,y()),w.addGetterSetter(At,"radiusY",0,y()),s.mapMethods(At);var Mt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._useBufferCanvas=function(){return t.prototype._useBufferCanvas.call(this,!0)},e.prototype._sceneFunc=function(t){var e,i=this.getWidth(),n=this.getHeight(),r=this.attrs.image;if(r){var o=this.attrs.cropWidth,a=this.attrs.cropHeight;e=o&&a?[r,this.cropX(),this.cropY(),o,a,0,0,i,n]:[r,0,0,i,n]}(this.hasFill()||this.hasStroke())&&(t.beginPath(),t.rect(0,0,i,n),t.closePath(),t.fillStrokeShape(this)),r&&t.drawImage.apply(t,e)},e.prototype._hitFunc=function(t){var e=this.width(),i=this.height();t.beginPath(),t.rect(0,0,e,i),t.closePath(),t.fillStrokeShape(this)},e.prototype.getWidth=function(){var t,e;return null!==(t=this.attrs.width)&&void 0!==t?t:(null===(e=this.image())||void 0===e?void 0:e.width)||0},e.prototype.getHeight=function(){var t,e;return null!==(t=this.attrs.height)&&void 0!==t?t:(null===(e=this.image())||void 0===e?void 0:e.height)||0},e.fromURL=function(t,i){var n=f.createImageElement();n.onload=function(){var t=new e({image:n});i(t)},n.crossOrigin="Anonymous",n.src=t},e}(lt);Mt.prototype.className="Image",a(Mt),w.addGetterSetter(Mt,"image"),w.addComponentsGetterSetter(Mt,"crop",["x","y","width","height"]),w.addGetterSetter(Mt,"cropX",0,y()),w.addGetterSetter(Mt,"cropY",0,y()),w.addGetterSetter(Mt,"cropWidth",0,y()),w.addGetterSetter(Mt,"cropHeight",0,y()),s.mapMethods(Mt);var Gt=["fontFamily","fontSize","fontStyle","padding","lineHeight","text","width","height"],Rt=Gt.length,Lt=function(t){function e(e){var i=t.call(this,e)||this;return i.on("add.konva",(function(t){this._addListeners(t.child),this._sync()})),i}return P(e,t),e.prototype.getText=function(){return this.find("Text")[0]},e.prototype.getTag=function(){return this.find("Tag")[0]},e.prototype._addListeners=function(t){var e,i=this,n=function(){i._sync()};for(e=0;el?h:l,g=h>l?1:h/l,v=h>l?l/h:1;t.translate(a,s),t.rotate(u),t.scale(g,v),t.arc(0,0,f,c,c+d,1-p),t.scale(1/g,1/v),t.rotate(-u),t.translate(-a,-s);break;case"z":i=!0,t.closePath()}}i||this.hasFill()?t.fillStrokeShape(this):t.strokeShape(this)},e.prototype.getSelfRect=function(){var t=[];this.dataArray.forEach((function(i){if("A"===i.command){var n=i.points[4],r=i.points[5],o=i.points[4]+r,a=Math.PI/180;if(Math.abs(n-o)o;s-=a){var h=e.getPointOnEllipticalArc(i.points[0],i.points[1],i.points[2],i.points[3],s,0);t.push(h.x,h.y)}else for(s=n+a;sthis.dataArray[n].pathLength;)t-=this.dataArray[n].pathLength,++n;if(n===r)return{x:(i=this.dataArray[n-1].points.slice(-2))[0],y:i[1]};if(t<.01)return{x:(i=this.dataArray[n].points.slice(0,2))[0],y:i[1]};var o=this.dataArray[n],a=o.points;switch(o.command){case"L":return e.getPointOnLine(t,o.start.x,o.start.y,a[0],a[1]);case"C":return e.getPointOnCubicBezier(t/o.pathLength,o.start.x,o.start.y,a[0],a[1],a[2],a[3],a[4],a[5]);case"Q":return e.getPointOnQuadraticBezier(t/o.pathLength,o.start.x,o.start.y,a[0],a[1],a[2],a[3]);case"A":var s=a[0],h=a[1],l=a[2],c=a[3],d=a[4],u=a[5],p=a[6];return d+=u*t/o.pathLength,e.getPointOnEllipticalArc(s,h,l,c,d,p)}return null},e.getLineLength=function(t,e,i,n){return Math.sqrt((i-t)*(i-t)+(n-e)*(n-e))},e.getPointOnLine=function(t,e,i,n,r,o,a){void 0===o&&(o=e),void 0===a&&(a=i);var s=(r-i)/(n-e+1e-8),h=Math.sqrt(t*t/(1+s*s));n0&&!isNaN(p[0]);){var y,m,_,b,x,S,w,C,P,k,T=null,A=[],M=h,G=l;switch(u){case"l":h+=p.shift(),l+=p.shift(),T="L",A.push(h,l);break;case"L":h=p.shift(),l=p.shift(),A.push(h,l);break;case"m":var R=p.shift(),L=p.shift();if(h+=R,l+=L,T="M",a.length>2&&"z"===a[a.length-1].command)for(var E=a.length-2;E>=0;E--)if("M"===a[E].command){h=a[E].points[0]+R,l=a[E].points[1]+L;break}A.push(h,l),u="l";break;case"M":h=p.shift(),l=p.shift(),T="M",A.push(h,l),u="L";break;case"h":h+=p.shift(),T="L",A.push(h,l);break;case"H":h=p.shift(),T="L",A.push(h,l);break;case"v":l+=p.shift(),T="L",A.push(h,l);break;case"V":l=p.shift(),T="L",A.push(h,l);break;case"C":A.push(p.shift(),p.shift(),p.shift(),p.shift()),h=p.shift(),l=p.shift(),A.push(h,l);break;case"c":A.push(h+p.shift(),l+p.shift(),h+p.shift(),l+p.shift()),h+=p.shift(),l+=p.shift(),T="C",A.push(h,l);break;case"S":m=h,_=l,"C"===(y=a[a.length-1]).command&&(m=h+(h-y.points[2]),_=l+(l-y.points[3])),A.push(m,_,p.shift(),p.shift()),h=p.shift(),l=p.shift(),T="C",A.push(h,l);break;case"s":m=h,_=l,"C"===(y=a[a.length-1]).command&&(m=h+(h-y.points[2]),_=l+(l-y.points[3])),A.push(m,_,h+p.shift(),l+p.shift()),h+=p.shift(),l+=p.shift(),T="C",A.push(h,l);break;case"Q":A.push(p.shift(),p.shift()),h=p.shift(),l=p.shift(),A.push(h,l);break;case"q":A.push(h+p.shift(),l+p.shift()),h+=p.shift(),l+=p.shift(),T="Q",A.push(h,l);break;case"T":m=h,_=l,"Q"===(y=a[a.length-1]).command&&(m=h+(h-y.points[0]),_=l+(l-y.points[1])),h=p.shift(),l=p.shift(),T="Q",A.push(m,_,h,l);break;case"t":m=h,_=l,"Q"===(y=a[a.length-1]).command&&(m=h+(h-y.points[0]),_=l+(l-y.points[1])),h+=p.shift(),l+=p.shift(),T="Q",A.push(m,_,h,l);break;case"A":b=p.shift(),x=p.shift(),S=p.shift(),w=p.shift(),C=p.shift(),P=h,k=l,h=p.shift(),l=p.shift(),T="A",A=this.convertEndpointToCenterParameterization(P,k,h,l,w,C,b,x,S);break;case"a":b=p.shift(),x=p.shift(),S=p.shift(),w=p.shift(),C=p.shift(),P=h,k=l,h+=p.shift(),l+=p.shift(),T="A",A=this.convertEndpointToCenterParameterization(P,k,h,l,w,C,b,x,S)}a.push({command:T||u,points:A,start:{x:M,y:G},pathLength:this.calcLength(M,G,T||u,A)})}"z"!==u&&"Z"!==u||a.push({command:"z",points:[],start:void 0,pathLength:0})}return a},e.calcLength=function(t,i,n,r){var o,a,s,h,l=e;switch(n){case"L":return l.getLineLength(t,i,r[0],r[1]);case"C":for(o=0,a=l.getPointOnCubicBezier(0,t,i,r[0],r[1],r[2],r[3],r[4],r[5]),h=.01;h<=1;h+=.01)s=l.getPointOnCubicBezier(h,t,i,r[0],r[1],r[2],r[3],r[4],r[5]),o+=l.getLineLength(a.x,a.y,s.x,s.y),a=s;return o;case"Q":for(o=0,a=l.getPointOnQuadraticBezier(0,t,i,r[0],r[1],r[2],r[3]),h=.01;h<=1;h+=.01)s=l.getPointOnQuadraticBezier(h,t,i,r[0],r[1],r[2],r[3]),o+=l.getLineLength(a.x,a.y,s.x,s.y),a=s;return o;case"A":o=0;var c=r[4],d=r[5],u=r[4]+d,p=Math.PI/180;if(Math.abs(c-u)u;h-=p)s=l.getPointOnEllipticalArc(r[0],r[1],r[2],r[3],h,0),o+=l.getLineLength(a.x,a.y,s.x,s.y),a=s;else for(h=c+p;h1&&(a*=Math.sqrt(u),s*=Math.sqrt(u));var p=Math.sqrt((a*a*(s*s)-a*a*(d*d)-s*s*(c*c))/(a*a*(d*d)+s*s*(c*c)));r===o&&(p*=-1),isNaN(p)&&(p=0);var f=p*a*d/s,g=p*-s*c/a,v=(t+i)/2+Math.cos(l)*f-Math.sin(l)*g,y=(e+n)/2+Math.sin(l)*f+Math.cos(l)*g,m=function(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1])},_=function(t,e){return(t[0]*e[0]+t[1]*e[1])/(m(t)*m(e))},b=function(t,e){return(t[0]*e[1]=1&&(C=0),0===o&&C>0&&(C-=2*Math.PI),1===o&&C<0&&(C+=2*Math.PI),[v,y,a,s,x,C,l,o]},e}(lt);Ot.prototype.className="Path",Ot.prototype._attrsAffectingSize=["data"],a(Ot),w.addGetterSetter(Ot,"data"),s.mapMethods(Ot);var Dt=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._sceneFunc=function(t){var e=this.cornerRadius(),i=this.width(),n=this.height();if(t.beginPath(),e){var r=0,o=0,a=0,s=0;"number"==typeof e?r=o=a=s=Math.min(e,i/2,n/2):(r=Math.min(e[0]||0,i/2,n/2),o=Math.min(e[1]||0,i/2,n/2),s=Math.min(e[2]||0,i/2,n/2),a=Math.min(e[3]||0,i/2,n/2)),t.moveTo(r,0),t.lineTo(i-o,0),t.arc(i-o,o,o,3*Math.PI/2,0,!1),t.lineTo(i,n-s),t.arc(i-s,n-s,s,0,Math.PI/2,!1),t.lineTo(a,n),t.arc(a,n-a,a,Math.PI/2,Math.PI,!1),t.lineTo(0,r),t.arc(r,r,r,Math.PI,3*Math.PI/2,!1)}else t.rect(0,0,i,n);t.closePath(),t.fillStrokeShape(this)},e}(lt);Dt.prototype.className="Rect",a(Dt),w.addGetterSetter(Dt,"cornerRadius",0,m(4)),s.mapMethods(Dt);var It=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._sceneFunc=function(t){var e=this._getPoints();t.beginPath(),t.moveTo(e[0].x,e[0].y);for(var i=1;i1&&(v+=a)}}},e.prototype._hitFunc=function(t){var e=this.getWidth(),i=this.getHeight();t.beginPath(),t.rect(0,0,e,i),t.closePath(),t.fillStrokeShape(this)},e.prototype.setText=function(t){var e=f._isString(t)?t:null==t?"":t+"";return this._setAttr("text",e),this},e.prototype.getWidth=function(){return"auto"===this.attrs.width||void 0===this.attrs.width?this.getTextWidth()+2*this.padding():this.attrs.width},e.prototype.getHeight=function(){return"auto"===this.attrs.height||void 0===this.attrs.height?this.fontSize()*this.textArr.length*this.lineHeight()+2*this.padding():this.attrs.height},e.prototype.getTextWidth=function(){return this.textWidth},e.prototype.getTextHeight=function(){return f.warn("text.getTextHeight() method is deprecated. Use text.height() - for full height and text.fontSize() - for one line height."),this.textHeight},e.prototype.measureSize=function(t){var e,i=jt(),n=this.fontSize();return i.save(),i.font=this._getContextFont(),e=i.measureText(t),i.restore(),{width:e.width,height:n}},e.prototype._getContextFont=function(){return r.UA.isIE?this.fontStyle()+" "+this.fontSize()+"px "+this.fontFamily():this.fontStyle()+" "+this.fontVariant()+" "+this.fontSize()+"px "+this.fontFamily().split(",").map((function(t){var e=(t=t.trim()).indexOf(" ")>=0,i=t.indexOf('"')>=0||t.indexOf("'")>=0;return e&&!i&&(t='"'+t+'"'),t})).join(", ")},e.prototype._addTextLine=function(t){"justify"===this.align()&&(t=t.trim());var e=this._getTextWidth(t);return this.textArr.push({text:t,width:e})},e.prototype._getTextWidth=function(t){var e=this.letterSpacing(),i=t.length;return jt().measureText(t).width+(i?e*(i-1):0)},e.prototype._setTextData=function(){var t=this.text().split("\n"),e=+this.fontSize(),i=0,n=this.lineHeight()*e,r=this.attrs.width,o=this.attrs.height,a="auto"!==r&&void 0!==r,s="auto"!==o&&void 0!==o,h=this.padding(),l=r-2*h,c=o-2*h,d=0,u=this.wrap(),p="none"!==u,f="char"!==u&&p,g=this.ellipsis();this.textArr=[],jt().font=this._getContextFont();for(var v=g?this._getTextWidth("…"):0,y=0,m=t.length;yl)for(;_.length>0;){for(var x=0,S=_.length,w="",C=0;x>>1,k=_.slice(0,P+1),T=this._getTextWidth(k)+v;T<=l?(x=P+1,w=k,C=T):S=P}if(!w)break;if(f){var A,M=_[w.length];(A=(" "===M||"-"===M)&&C<=l?w.length:Math.max(w.lastIndexOf(" "),w.lastIndexOf("-"))+1)>0&&(x=A,w=w.slice(0,x),C=this._getTextWidth(w))}if(w=w.trimRight(),this._addTextLine(w),i=Math.max(i,C),d+=n,!p||s&&d+n>c){var G=this.textArr[this.textArr.length-1];if(G)if(g)this._getTextWidth(G.text+"…")0&&(b=this._getTextWidth(_))<=l){this._addTextLine(_),d+=n,i=Math.max(i,b);break}}else this._addTextLine(_),d+=n,i=Math.max(i,b);if(s&&d+n>c)break}this.textHeight=e,this.textWidth=i},e.prototype.getStrokeScaleEnabled=function(){return!0},e}(lt);Ut.prototype._fillFunc=function(t){t.fillText(this._partialText,this._partialTextX,this._partialTextY)},Ut.prototype._strokeFunc=function(t){t.strokeText(this._partialText,this._partialTextX,this._partialTextY)},Ut.prototype.className="Text",Ut.prototype._attrsAffectingSize=["text","fontSize","padding","wrap","lineHeight","letterSpacing"],a(Ut),w.overWriteSetter(Ut,"width",_()),w.overWriteSetter(Ut,"height",_()),w.addGetterSetter(Ut,"fontFamily","Arial"),w.addGetterSetter(Ut,"fontSize",12,y()),w.addGetterSetter(Ut,"fontStyle","normal"),w.addGetterSetter(Ut,"fontVariant","normal"),w.addGetterSetter(Ut,"padding",0,y()),w.addGetterSetter(Ut,"align","left"),w.addGetterSetter(Ut,"verticalAlign","top"),w.addGetterSetter(Ut,"lineHeight",1,y()),w.addGetterSetter(Ut,"wrap","word"),w.addGetterSetter(Ut,"ellipsis",!1,S()),w.addGetterSetter(Ut,"letterSpacing",0,y()),w.addGetterSetter(Ut,"text","",b()),w.addGetterSetter(Ut,"textDecoration",""),s.mapMethods(Ut);function qt(t){t.fillText(this.partialText,0,0)}function Kt(t){t.strokeText(this.partialText,0,0)}var Vt=function(t){function e(e){var i=t.call(this,e)||this;return i.dummyCanvas=f.createCanvasElement(),i.dataArray=[],i.dataArray=Ot.parsePathData(i.attrs.data),i.on("dataChange.konva",(function(){this.dataArray=Ot.parsePathData(this.attrs.data),this._setTextData()})),i.on("textChange.konva alignChange.konva letterSpacingChange.konva kerningFuncChange.konva",i._setTextData),e&&e.getKerning&&(f.warn('getKerning TextPath API is deprecated. Please use "kerningFunc" instead.'),i.kerningFunc(e.getKerning)),i._setTextData(),i}return P(e,t),e.prototype._sceneFunc=function(t){t.setAttr("font",this._getContextFont()),t.setAttr("textBaseline",this.textBaseline()),t.setAttr("textAlign","left"),t.save();var e=this.textDecoration(),i=this.fill(),n=this.fontSize(),r=this.glyphInfo;"underline"===e&&t.beginPath();for(var o=0;o=1){var i=e[0].p0;t.moveTo(i.x,i.y)}for(var n=0;n0&&(a+=t.dataArray[s].pathLength);var h=0;"center"===n&&(h=Math.max(0,a/2-o/2)),"right"===n&&(h=Math.max(0,a-o));for(var l,c,d,u=Wt(this.text()),p=this.text().split(" ").length-1,f=-1,g=0,v=function(){g=0;for(var e=t.dataArray,i=f+1;i0)return f=i,e[i];"M"===e[i].command&&(l={x:e[i].points[0],y:e[i].points[1]})}return{}},y=function(e){var r=t._getTextSize(e).width+i;" "===e&&"justify"===n&&(r+=(a-o)/p);var s=0,h=0;for(c=void 0;Math.abs(r-s)/r>.01&&h<20;){h++;for(var u=s;void 0===d;)(d=v())&&u+d.pathLengthr?c=Ot.getPointOnLine(r,l.x,l.y,d.points[0],d.points[1],l.x,l.y):d=void 0;break;case"A":var y=d.points[4],m=d.points[5],_=d.points[4]+m;0===g?g=y+1e-8:r>s?g+=Math.PI/180*m/Math.abs(m):g-=Math.PI/360*m/Math.abs(m),(m<0&&g<_||m>=0&&g>_)&&(g=_,f=!0),c=Ot.getPointOnEllipticalArc(d.points[0],d.points[1],d.points[2],d.points[3],g,d.points[6]);break;case"C":0===g?g=r>d.pathLength?1e-8:r/d.pathLength:r>s?g+=(r-s)/d.pathLength/2:g=Math.max(g-(s-r)/d.pathLength/2,0),g>1&&(g=1,f=!0),c=Ot.getPointOnCubicBezier(g,d.start.x,d.start.y,d.points[0],d.points[1],d.points[2],d.points[3],d.points[4],d.points[5]);break;case"Q":0===g?g=r/d.pathLength:r>s?g+=(r-s)/d.pathLength:g-=(s-r)/d.pathLength,g>1&&(g=1,f=!0),c=Ot.getPointOnQuadraticBezier(g,d.start.x,d.start.y,d.points[0],d.points[1],d.points[2],d.points[3])}void 0!==c&&(s=Ot.getLineLength(l.x,l.y,c.x,c.y)),f&&(f=!1,d=void 0)}},m=h/(t._getTextSize("C").width+i)-1,_=0;_p.x?-1:1,g=this.findOne(".top-left").y()>p.y?-1:1;e=n*this.cos*f,i=n*this.sin*g,this.findOne(".top-left").x(p.x-e),this.findOne(".top-left").y(p.y-i)}}else if("top-center"===this._movingAnchorName)this.findOne(".top-left").y(o.y());else if("top-right"===this._movingAnchorName){if(d){p=u?{x:this.width()/2,y:this.height()/2}:{x:this.findOne(".bottom-left").x(),y:this.findOne(".bottom-left").y()};n=Math.sqrt(Math.pow(o.x()-p.x,2)+Math.pow(p.y-o.y(),2));f=this.findOne(".top-right").x()p.y?-1:1;e=n*this.cos*f,i=n*this.sin*g,this.findOne(".top-right").x(p.x+e),this.findOne(".top-right").y(p.y-i)}var v=o.position();this.findOne(".top-left").y(v.y),this.findOne(".bottom-right").x(v.x)}else if("middle-left"===this._movingAnchorName)this.findOne(".top-left").x(o.x());else if("middle-right"===this._movingAnchorName)this.findOne(".bottom-right").x(o.x());else if("bottom-left"===this._movingAnchorName){if(d){p=u?{x:this.width()/2,y:this.height()/2}:{x:this.findOne(".top-right").x(),y:this.findOne(".top-right").y()};n=Math.sqrt(Math.pow(p.x-o.x(),2)+Math.pow(o.y()-p.y,2));f=p.x=0){var a=o.point({x:2*-this.padding(),y:0});t.x+=a.x,t.y+=a.y,t.width+=2*this.padding(),this._movingAnchorName=this._movingAnchorName.replace("left","right"),this._anchorDragOffset.x-=a.x,this._anchorDragOffset.y-=a.y}else if(this._movingAnchorName&&t.width<0&&this._movingAnchorName.indexOf("right")>=0){a=o.point({x:2*this.padding(),y:0});this._movingAnchorName=this._movingAnchorName.replace("right","left"),this._anchorDragOffset.x-=a.x,this._anchorDragOffset.y-=a.y,t.width+=2*this.padding()}if(this._movingAnchorName&&t.height<0&&this._movingAnchorName.indexOf("top")>=0){a=o.point({x:0,y:2*-this.padding()});t.x+=a.x,t.y+=a.y,this._movingAnchorName=this._movingAnchorName.replace("top","bottom"),this._anchorDragOffset.x-=a.x,this._anchorDragOffset.y-=a.y,t.height+=2*this.padding()}else if(this._movingAnchorName&&t.height<0&&this._movingAnchorName.indexOf("bottom")>=0){a=o.point({x:0,y:2*this.padding()});this._movingAnchorName=this._movingAnchorName.replace("bottom","top"),this._anchorDragOffset.x-=a.x,this._anchorDragOffset.y-=a.y,t.height+=2*this.padding()}if(this.boundBoxFunc()){var s=this.boundBoxFunc()(n,t);s?t=s:f.warn("boundBoxFunc returned falsy. You should return new bound rect from it!")}var l=new h;l.translate(n.x,n.y),l.rotate(n.rotation),l.scale(n.width/1e7,n.height/1e7);var c=new h;c.translate(t.x,t.y),c.rotate(t.rotation),c.scale(t.width/1e7,t.height/1e7);var d=c.multiply(l.invert());this._nodes.forEach((function(t){var n,r=t.getParent().getAbsoluteTransform(),o=t.getTransform().copy();o.translate(t.offsetX(),t.offsetY());var a=new h;a.multiply(r.copy().invert()).multiply(d).multiply(r).multiply(o);var s=a.decompose();t.setAttrs(s),i._fire("transform",{evt:e,target:t}),t._fire("transform",{evt:e,target:t}),null===(n=t.getLayer())||void 0===n||n.batchDraw()})),this.rotation(f._getRotation(t.rotation)),this._resetTransformCache(),this.update(),this.getLayer().batchDraw()}},e.prototype.forceUpdate=function(){this._resetTransformCache(),this.update()},e.prototype._batchChangeChild=function(t,e){this.findOne(t).setAttrs(e)},e.prototype.update=function(){var t,e=this,i=this._getNodeRect();this.rotation(f._getRotation(i.rotation));var n=i.width,r=i.height,o=this.enabledAnchors(),a=this.resizeEnabled(),s=this.padding(),h=this.anchorSize();this.find("._anchor").each((function(t){t.setAttrs({width:h,height:h,offsetX:h/2,offsetY:h/2,stroke:e.anchorStroke(),strokeWidth:e.anchorStrokeWidth(),fill:e.anchorFill(),cornerRadius:e.anchorCornerRadius()})})),this._batchChangeChild(".top-left",{x:0,y:0,offsetX:h/2+s,offsetY:h/2+s,visible:a&&o.indexOf("top-left")>=0}),this._batchChangeChild(".top-center",{x:n/2,y:0,offsetY:h/2+s,visible:a&&o.indexOf("top-center")>=0}),this._batchChangeChild(".top-right",{x:n,y:0,offsetX:h/2-s,offsetY:h/2+s,visible:a&&o.indexOf("top-right")>=0}),this._batchChangeChild(".middle-left",{x:0,y:r/2,offsetX:h/2+s,visible:a&&o.indexOf("middle-left")>=0}),this._batchChangeChild(".middle-right",{x:n,y:r/2,offsetX:h/2-s,visible:a&&o.indexOf("middle-right")>=0}),this._batchChangeChild(".bottom-left",{x:0,y:r,offsetX:h/2+s,offsetY:h/2-s,visible:a&&o.indexOf("bottom-left")>=0}),this._batchChangeChild(".bottom-center",{x:n/2,y:r,offsetY:h/2-s,visible:a&&o.indexOf("bottom-center")>=0}),this._batchChangeChild(".bottom-right",{x:n,y:r,offsetX:h/2-s,offsetY:h/2-s,visible:a&&o.indexOf("bottom-right")>=0}),this._batchChangeChild(".rotater",{x:n/2,y:-this.rotateAnchorOffset()*f._sign(r)-s,visible:this.rotateEnabled()}),this._batchChangeChild(".back",{width:n,height:r,visible:this.borderEnabled(),stroke:this.borderStroke(),strokeWidth:this.borderStrokeWidth(),dash:this.borderDash(),x:0,y:0}),null===(t=this.getLayer())||void 0===t||t.batchDraw()},e.prototype.isTransforming=function(){return this._transforming},e.prototype.stopTransform=function(){if(this._transforming){this._removeEvents();var t=this.findOne("."+this._movingAnchorName);t&&t.stopDrag()}},e.prototype.destroy=function(){return this.getStage()&&this._cursorChange&&(this.getStage().content.style.cursor=""),ft.prototype.destroy.call(this),this.detach(),this._removeEvents(),this},e.prototype.toObject=function(){return X.prototype.toObject.call(this)},e}(ft);ne.prototype.className="Transformer",a(ne),w.addGetterSetter(ne,"enabledAnchors",te,(function(t){return t instanceof Array||f.warn("enabledAnchors value should be an array"),t instanceof Array&&t.forEach((function(t){-1===te.indexOf(t)&&f.warn("Unknown anchor name: "+t+". Available names are: "+te.join(", "))})),t||[]})),w.addGetterSetter(ne,"resizeEnabled",!0),w.addGetterSetter(ne,"anchorSize",10,y()),w.addGetterSetter(ne,"rotateEnabled",!0),w.addGetterSetter(ne,"rotationSnaps",[]),w.addGetterSetter(ne,"rotateAnchorOffset",50,y()),w.addGetterSetter(ne,"rotationSnapTolerance",5,y()),w.addGetterSetter(ne,"borderEnabled",!0),w.addGetterSetter(ne,"anchorStroke","rgb(0, 161, 255)"),w.addGetterSetter(ne,"anchorStrokeWidth",1,y()),w.addGetterSetter(ne,"anchorFill","white"),w.addGetterSetter(ne,"anchorCornerRadius",0,y()),w.addGetterSetter(ne,"borderStroke","rgb(0, 161, 255)"),w.addGetterSetter(ne,"borderStrokeWidth",1,y()),w.addGetterSetter(ne,"borderDash"),w.addGetterSetter(ne,"keepRatio",!0),w.addGetterSetter(ne,"centeredScaling",!1),w.addGetterSetter(ne,"ignoreStroke",!1),w.addGetterSetter(ne,"padding",0,y()),w.addGetterSetter(ne,"node"),w.addGetterSetter(ne,"nodes"),w.addGetterSetter(ne,"boundBoxFunc"),w.addGetterSetter(ne,"shouldOverdrawWholeArea",!1),w.backCompat(ne,{lineEnabled:"borderEnabled",rotateHandlerOffset:"rotateAnchorOffset",enabledHandlers:"enabledAnchors"}),s.mapMethods(ne);var re=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return P(e,t),e.prototype._sceneFunc=function(t){t.beginPath(),t.arc(0,0,this.radius(),0,r.getAngle(this.angle()),this.clockwise()),t.lineTo(0,0),t.closePath(),t.fillStrokeShape(this)},e.prototype.getWidth=function(){return 2*this.radius()},e.prototype.getHeight=function(){return 2*this.radius()},e.prototype.setWidth=function(t){this.radius(t/2)},e.prototype.setHeight=function(t){this.radius(t/2)},e}(lt);function oe(){this.r=0,this.g=0,this.b=0,this.a=0,this.next=null}re.prototype.className="Wedge",re.prototype._centroid=!0,re.prototype._attrsAffectingSize=["radius"],a(re),w.addGetterSetter(re,"radius",0,y()),w.addGetterSetter(re,"angle",0,y()),w.addGetterSetter(re,"clockwise",!1),w.backCompat(re,{angleDeg:"angle",getAngleDeg:"getAngle",setAngleDeg:"setAngle"}),s.mapMethods(re);var ae=[512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,289,287,285,282,280,278,275,273,271,269,267,265,263,261,259],se=[9,11,12,13,13,14,14,15,15,15,15,16,16,16,16,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24];w.addGetterSetter(X,"blurRadius",0,y(),w.afterSetFilter);w.addGetterSetter(X,"brightness",0,y(),w.afterSetFilter);w.addGetterSetter(X,"contrast",0,y(),w.afterSetFilter);function he(t,e,i,n,r){var o=i-e,a=r-n;return 0===o?n+a/2:0===a?n:a*((t-e)/o)+n}w.addGetterSetter(X,"embossStrength",.5,y(),w.afterSetFilter),w.addGetterSetter(X,"embossWhiteLevel",.5,y(),w.afterSetFilter),w.addGetterSetter(X,"embossDirection","top-left",null,w.afterSetFilter),w.addGetterSetter(X,"embossBlend",!1,null,w.afterSetFilter);w.addGetterSetter(X,"enhance",0,y(),w.afterSetFilter);w.addGetterSetter(X,"hue",0,y(),w.afterSetFilter),w.addGetterSetter(X,"saturation",0,y(),w.afterSetFilter),w.addGetterSetter(X,"luminance",0,y(),w.afterSetFilter);w.addGetterSetter(X,"hue",0,y(),w.afterSetFilter),w.addGetterSetter(X,"saturation",0,y(),w.afterSetFilter),w.addGetterSetter(X,"value",0,y(),w.afterSetFilter);function le(t,e,i){var n=4*(i*t.width+e),r=[];return r.push(t.data[n++],t.data[n++],t.data[n++],t.data[n++]),r}function ce(t,e){return Math.sqrt(Math.pow(t[0]-e[0],2)+Math.pow(t[1]-e[1],2)+Math.pow(t[2]-e[2],2))}w.addGetterSetter(X,"kaleidoscopePower",2,y(),w.afterSetFilter),w.addGetterSetter(X,"kaleidoscopeAngle",0,y(),w.afterSetFilter);w.addGetterSetter(X,"threshold",0,y(),w.afterSetFilter);w.addGetterSetter(X,"noise",.2,y(),w.afterSetFilter);w.addGetterSetter(X,"pixelSize",8,y(),w.afterSetFilter);w.addGetterSetter(X,"levels",.5,y(),w.afterSetFilter);w.addGetterSetter(X,"red",0,(function(t){return this._filterUpToDate=!1,t>255?255:t<0?0:Math.round(t)})),w.addGetterSetter(X,"green",0,(function(t){return this._filterUpToDate=!1,t>255?255:t<0?0:Math.round(t)})),w.addGetterSetter(X,"blue",0,v,w.afterSetFilter);w.addGetterSetter(X,"red",0,(function(t){return this._filterUpToDate=!1,t>255?255:t<0?0:Math.round(t)})),w.addGetterSetter(X,"green",0,(function(t){return this._filterUpToDate=!1,t>255?255:t<0?0:Math.round(t)})),w.addGetterSetter(X,"blue",0,v,w.afterSetFilter),w.addGetterSetter(X,"alpha",1,(function(t){return this._filterUpToDate=!1,t>1?1:t<0?0:t}));return w.addGetterSetter(X,"threshold",.5,y(),w.afterSetFilter),wt.Util._assign(wt,{Arc:Ct,Arrow:kt,Circle:Tt,Ellipse:At,Image:Mt,Label:Lt,Tag:Et,Line:Pt,Path:Ot,Rect:Dt,RegularPolygon:It,Ring:Bt,Sprite:Nt,Star:zt,Text:Ut,TextPath:Vt,Transformer:ne,Wedge:re,Filters:{Blur:function(t){var e=Math.round(this.blurRadius());e>0&&function(t,e){var i,n,r,o,a,s,h,l,c,d,u,p,f,g,v,y,m,_,b,x,S,w,C,P,k=t.data,T=t.width,A=t.height,M=e+e+1,G=T-1,R=A-1,L=e+1,E=L*(L+1)/2,O=new oe,D=null,I=O,F=null,B=null,N=ae[e],z=se[e];for(r=1;r>z,0!==C?(C=255/C,k[s]=(l*N>>z)*C,k[s+1]=(c*N>>z)*C,k[s+2]=(d*N>>z)*C):k[s]=k[s+1]=k[s+2]=0,l-=p,c-=f,d-=g,u-=v,p-=F.r,f-=F.g,g-=F.b,v-=F.a,o=h+((o=i+e+1)>z,C>0?(C=255/C,k[o]=(l*N>>z)*C,k[o+1]=(c*N>>z)*C,k[o+2]=(d*N>>z)*C):k[o]=k[o+1]=k[o+2]=0,l-=p,c-=f,d-=g,u-=v,p-=F.r,f-=F.g,g-=F.b,v-=F.a,o=i+((o=n+L)255?255:o,a=(a*=255)<0?0:a>255?255:a,s=(s*=255)<0?0:s>255?255:s,n[e]=o,n[e+1]=a,n[e+2]=s},Emboss:function(t){var e=10*this.embossStrength(),i=255*this.embossWhiteLevel(),n=this.embossDirection(),r=this.embossBlend(),o=0,a=0,s=t.data,h=t.width,l=t.height,c=4*h,d=l;switch(n){case"top-left":o=-1,a=-1;break;case"top":o=-1,a=0;break;case"top-right":o=-1,a=1;break;case"right":o=0,a=1;break;case"bottom-right":o=1,a=1;break;case"bottom":o=1,a=0;break;case"bottom-left":o=1,a=-1;break;case"left":o=0,a=-1;break;default:f.error("Unknown emboss direction: "+n)}do{var u=(d-1)*c,p=o;d+p<1&&(p=0),d+p>l&&(p=0);var g=(d-1+p)*h*4,v=h;do{var y=u+4*(v-1),m=a;v+m<1&&(m=0),v+m>h&&(m=0);var _=g+4*(v-1+m),b=s[y]-s[_],x=s[y+1]-s[_+1],S=s[y+2]-s[_+2],w=b,C=w>0?w:-w;if((x>0?x:-x)>C&&(w=x),(S>0?S:-S)>C&&(w=S),w*=e,r){var P=s[y]+w,k=s[y+1]+w,T=s[y+2]+w;s[y]=P>255?255:P<0?0:P,s[y+1]=k>255?255:k<0?0:k,s[y+2]=T>255?255:T<0?0:T}else{var A=i-w;A<0?A=0:A>255&&(A=255),s[y]=s[y+1]=s[y+2]=A}}while(--v)}while(--d)},Enhance:function(t){var e,i,n,r,o=t.data,a=o.length,s=o[0],h=s,l=o[1],c=l,d=o[2],u=d,p=this.enhance();if(0!==p){for(r=0;rh&&(h=e),(i=o[r+1])c&&(c=i),(n=o[r+2])u&&(u=n);var f,g,v,y,m,_,b,x,S;for(h===s&&(h=255,s=0),c===l&&(c=255,l=0),u===d&&(u=255,d=0),p>0?(g=h+p*(255-h),v=s-p*(s-0),m=c+p*(255-c),_=l-p*(l-0),x=u+p*(255-u),S=d-p*(d-0)):(g=h+p*(h-(f=.5*(h+s))),v=s+p*(s-f),m=c+p*(c-(y=.5*(c+l))),_=l+p*(l-y),x=u+p*(u-(b=.5*(u+d))),S=d+p*(d-b)),r=0;ry?a:y;var m,_,b,x,S=c,w=l,C=360/w*Math.PI/180;for(_=0;_c&&(b=_,x=0,S=-1),i=0;i_?h:_;var b,x,S,w=u,C=d,P=i.polarRotation||0;for(r=0;r=0&&p=0&&f=0&&p=0&&f=1020?255:0}return a}(e=function(t,e,i){for(var n=[1,1,1,1,0,1,1,1,1],r=Math.round(Math.sqrt(n.length)),o=Math.floor(r/2),a=[],s=0;s=0&&p=0&&f=y))for(i=c;i=m||(r+=x[(n=4*(y*i+e))+0],o+=x[n+1],a+=x[n+2],s+=x[n+3],g+=1);for(r/=g,o/=g,a/=g,s/=g,e=h;e=y))for(i=c;i=m||(x[(n=4*(y*i+e))+0]=r,x[n+1]=o,x[n+2]=a,x[n+3]=s)}},Posterize:function(t){var e,i=Math.round(254*this.levels())+1,n=t.data,r=n.length,o=255/i;for(e=0;e127&&(h=255-h),l>127&&(l=255-l),c>127&&(c=255-c),e[s]=h,e[s+1]=l,e[s+2]=c}while(--a)}while(--r)},Threshold:function(t){var e,i=255*this.threshold(),n=t.data,r=n.length;for(e=0;e - - Kavea - - -
- - - - diff --git a/src/web.go b/src/web.go deleted file mode 100644 index 8b509a4..0000000 --- a/src/web.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -// #cgo LDFLAGS: -lm -// #include "img.h" -import "C" -import ( - "fmt" - // "html/template" - "net/http" -) - -func GetHome(w http.ResponseWriter, r *http.Request) { - filename := C.CString("Skydusky.3d") - img := C.img_open_survey(filename, nil) - for true { - p := C.img_point{} - C.img_read_item(img, &p) - fmt.Printf(C.GoString(img.label)) - } - // - // // return index.html - // t, err := template.ParseFS(templatesHTML, "templates/index.html.tmpl") - // if !checkWebError(w, err) { - // return - // } - // - // err = t.Execute(w, nil) - // if !checkError(err) { - // return - // } -}