summaryrefslogtreecommitdiff
path: root/src/cd_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cd_util.c')
-rw-r--r--src/cd_util.c285
1 files changed, 285 insertions, 0 deletions
diff --git a/src/cd_util.c b/src/cd_util.c
new file mode 100644
index 0000000..033fac6
--- /dev/null
+++ b/src/cd_util.c
@@ -0,0 +1,285 @@
+/** \file
+ * \brief Utilities
+ *
+ * See Copyright Notice in cd.h
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <memory.h>
+#include <math.h>
+
+
+#include "cd.h"
+
+#include "cd_private.h"
+
+
+int cdRound(double x)
+{
+ return _cdRound(x);
+}
+
+/* Returns a table to speed up zoom in discrete zoom rotines.
+ Adds the min parameter and allocates the table using malloc.
+ The table should be used when mapping from destiny coordinates to
+ source coordinates (src_pos = tab[dst_pos]).
+ dst_len is the full destiny size range.
+ src_len is only the zoomed region size, usually max-min+1.
+*/
+int* cdGetZoomTable(int dst_len, int src_len, int src_min)
+{
+ int dst_i, src_i;
+ double factor;
+ int* tab = (int*)malloc(dst_len*sizeof(int));
+
+ factor = (double)(src_len) / (double)(dst_len);
+
+ for(dst_i = 0; dst_i < dst_len; dst_i++)
+ {
+ src_i = cdRound((factor*(dst_i + 0.5)) - 0.5);
+ tab[dst_i] = src_i + src_min;
+ }
+
+ return tab;
+}
+
+/* funcao usada para calcular os retangulos efetivos de zoom
+ de imagens clientes. Pode ser usada para os eixos X e Y.
+
+ canvas_size - tamanho do canvas (canvas->w, canvas->h)
+ cnv_rect_pos - posicao no canvas onde a regiao sera´ desenhada (x, y)
+ cnv_rect_size - tamanho da regiao no canvas com zoom (w, h)
+ img_rect_pos - posicao na imagem da regiao a ser desenhada (min)
+ img_rect_size - tamanho da regiao na imagem (max-min+1)
+
+ calcula o melhor tamanho a ser usado
+ retorna 0 se o retangulo resultante e´ nulo
+*/
+int cdCalcZoom(int canvas_size,
+ int cnv_rect_pos, int cnv_rect_size,
+ int *new_cnv_rect_pos, int *new_cnv_rect_size,
+ int img_rect_pos, int img_rect_size,
+ int *new_img_rect_pos, int *new_img_rect_size,
+ int is_horizontal)
+{
+ int offset;
+ float zoom_factor = (float)img_rect_size / (float)cnv_rect_size;
+
+ /* valores default sem otimizacao */
+ *new_cnv_rect_size = cnv_rect_size, *new_cnv_rect_pos = cnv_rect_pos;
+ *new_img_rect_size = img_rect_size, *new_img_rect_pos = img_rect_pos;
+
+ if (cnv_rect_size > 0)
+ {
+ /* se posicao no canvas > tamanho do canvas, fora da janela, nao desenha nada */
+ if (cnv_rect_pos >= canvas_size)
+ return 0;
+
+ /* se posicao no canvas + tamanho da regiao no canvas < 0, fora da janela, nao desenha nada */
+ if (cnv_rect_pos+cnv_rect_size < 0)
+ return 0;
+
+ /* se posicao no canvas < 0, entao comeca fora do canvas melhor posicao no canvas e' 0
+ E o tamanho e' reduzido do valor negativo */
+ if (cnv_rect_pos < 0)
+ {
+ /* valores ajustados para cair numa vizinhanca de um pixel da imagem */
+ offset = (int)ceil(cnv_rect_pos*zoom_factor); /* offset is <0 */
+ offset = (int)ceil(offset/zoom_factor);
+ *new_cnv_rect_pos -= offset;
+ *new_cnv_rect_size += offset;
+ }
+
+ /* se posicao no canvas + tamanho da regiao no canvas > tamanho do canvas,
+ termina fora do canvas entao
+ o tamanho da regiao no canvas e' o tamanho do canvas reduzido da posicao */
+ if (*new_cnv_rect_pos+*new_cnv_rect_size > canvas_size)
+ {
+ offset = (int)((*new_cnv_rect_pos+*new_cnv_rect_size - canvas_size)*zoom_factor);
+ *new_cnv_rect_size -= (int)(offset/zoom_factor); /* offset is >0 */
+ }
+ }
+ else
+ {
+ /* cnv_rect_size tamanho negativo, significa imagem top down */
+ /* calculos adicionados pela Paula */
+
+ /* se posicao no canvas + tamanho no canvas (xmin+1) >= tamanho do canvas, fora da janela, nao desenha nada */
+ if (cnv_rect_pos+cnv_rect_size >= canvas_size)
+ return 0;
+
+ /* se posicao da imagem com zoom (xmax) < 0, fora da janela, nao desenha nada */
+ if (cnv_rect_pos < 0)
+ return 0;
+
+ /* se posicao com zoom (xmax) >= tamanho do canvas, posicao da imagem com zoom e' o tamanho do canvas menos um
+ tambem o tamanho e' reduzido do valor negativo */
+ if (cnv_rect_pos >= canvas_size)
+ {
+ *new_cnv_rect_pos = canvas_size-1;
+ *new_cnv_rect_size = cnv_rect_size + (cnv_rect_pos - *new_cnv_rect_pos);
+ }
+
+ /* se posicao + tamanho com zoom (xmin+1) < 0,
+ entao o tamanho com zoom e' a posição + 1 */
+ if (cnv_rect_pos+cnv_rect_size < 0)
+ *new_cnv_rect_size = -(*new_cnv_rect_pos + 1);
+ }
+
+ /* agora ja' tenho tamanho e posicao da regiao no canvas,
+ tenho que obter tamanho e posicao dentro da imagem original,
+ baseado nos novos valores */
+
+ /* tamanho da regiao na imagem e' a conversao de zoom para real do tamanho no canvas */
+ *new_img_rect_size = (int)(*new_cnv_rect_size * zoom_factor + 0.5);
+
+ if (is_horizontal)
+ {
+ /* em X, o offset dentro da imagem so' existe se houver diferenca entre a posicao inicial da
+ imagem e a posicao otimizada (ambas da imagem com zoom) */
+ if (*new_cnv_rect_pos != cnv_rect_pos)
+ {
+ offset = *new_cnv_rect_pos - cnv_rect_pos; /* offset is >0 */
+ *new_img_rect_pos += (int)(offset*zoom_factor);
+ }
+ }
+ else
+ {
+ /* em Y, o offset dentro da imagem so' existe se houver diferenca entre a posicao
+ final (posição inicial + tamanho) da imagem e a posicao otimizada (ambas da
+ imagem com zoom) */
+ if ((cnv_rect_pos + cnv_rect_size) != (*new_cnv_rect_pos + *new_cnv_rect_size))
+ {
+ /* offset is >0, because Y axis is from top to bottom */
+ offset = (cnv_rect_pos + cnv_rect_size) - (*new_cnv_rect_pos + *new_cnv_rect_size);
+ *new_img_rect_pos += (int)(offset*zoom_factor);
+ }
+ }
+
+ return 1;
+}
+
+int cdGetFileName(const char* strdata, char* filename)
+{
+ const char* start = strdata;
+ if (!strdata || strdata[0] == 0) return 0;
+
+ if (strdata[0] == '\"')
+ {
+ strdata++; /* the first " */
+ while(*strdata && *strdata != '\"')
+ *filename++ = *strdata++;
+ strdata++; /* the last " */
+ }
+ else
+ {
+ while(*strdata && *strdata != ' ')
+ *filename++ = *strdata++;
+ }
+
+ if (*strdata == ' ')
+ strdata++;
+
+ *filename = 0;
+ return (int)(strdata - start);
+}
+
+void cdNormalizeLimits(int w, int h, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ *xmin = *xmin < 0? 0: *xmin < w? *xmin: (w - 1);
+ *ymin = *ymin < 0? 0: *ymin < h? *ymin: (h - 1);
+ *xmax = *xmax < 0? 0: *xmax < w? *xmax: (w - 1);
+ *ymax = *ymax < 0? 0: *ymax < h? *ymax: (h - 1);
+}
+
+int cdCheckBoxSize(int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ if (*xmin > *xmax) _cdSwapInt(*xmin, *xmax);
+ if (*ymin > *ymax) _cdSwapInt(*ymin, *ymax);
+
+ if ((*xmax-*xmin+1) <= 0)
+ return 0;
+
+ if ((*ymax-*ymin+1) <= 0)
+ return 0;
+
+ return 1;
+}
+
+int cdfCheckBoxSize(double *xmin, double *xmax, double *ymin, double *ymax)
+{
+ if (*xmin > *xmax) _cdSwapDouble(*xmin, *xmax);
+ if (*ymin > *ymax) _cdSwapDouble(*ymin, *ymax);
+
+ if ((*xmax-*xmin+1) <= 0)
+ return 0;
+
+ if ((*ymax-*ymin+1) <= 0)
+ return 0;
+
+ return 1;
+}
+
+void cdRotatePoint(cdCanvas* canvas, int x, int y, int cx, int cy, int *rx, int *ry, double sin_theta, double cos_theta)
+{
+ double t;
+
+ /* translate to (cx,cy) */
+ x = x - cx;
+ y = y - cy;
+
+ /* rotate */
+ if (canvas->invert_yaxis)
+ {
+ t = (x * cos_theta) + (y * sin_theta); *rx = _cdRound(t);
+ t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+ else
+ {
+ t = (x * cos_theta) - (y * sin_theta); *rx = _cdRound(t);
+ t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+
+ /* translate back */
+ *rx = *rx + cx;
+ *ry = *ry + cy;
+}
+
+void cdRotatePointY(cdCanvas* canvas, int x, int y, int cx, int cy, int *ry, double sin_theta, double cos_theta)
+{
+ double t;
+
+ /* translate to (cx,cy) */
+ x = x - cx;
+ y = y - cy;
+
+ /* rotate */
+ if (canvas->invert_yaxis)
+ {
+ t = -(x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+ else
+ {
+ t = (x * sin_theta) + (y * cos_theta); *ry = _cdRound(t);
+ }
+
+ /* translate back */
+ *ry = *ry + cy;
+}
+
+int cdStrEqualNoCase(const char* str1, const char* str2)
+{
+ int i = 0;
+ if (str1 == str2) return 1;
+ if (!str1 || !str2 || tolower(*str1) != tolower(*str2)) return 0;
+
+ while (str1[i] && str2[i] && tolower(str1[i])==tolower(str2[i]))
+ i++;
+ if (str1[i] == str2[i]) return 1;
+
+ return 0;
+}
+