Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/engine/zoomd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/zoomd.c')
-rw-r--r--src/engine/zoomd.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/engine/zoomd.c b/src/engine/zoomd.c
new file mode 100644
index 0000000..ef3b965
--- /dev/null
+++ b/src/engine/zoomd.c
@@ -0,0 +1,309 @@
+#ifndef UNSUPPORTED
+
+/* this two routines implements solid guessing. They are almost same. One
+ * caluclates lines, second rows.
+ *
+ * The heruistic is as follows:
+ *
+ * ---1------6------5------- (vbuffu)
+ * | | |
+ * ===7======X======8======= (vbuff1)
+ * | | |
+ * ---2------3------4------- (vbuffd)
+ * distdown rx distup
+ *
+ * -- and | means calculated lines. == is current line, names are pointers to
+ * them. Note that naming is quite confusing, because it is same in lines and
+ * rows.
+ *
+ * we do solid guessing as folows:
+ * |distl-vbuff1| < range
+ * |distr-vbuff1| < range
+ * the distance of distup and distdown is not limited, because we already
+ * have exact enought guesses 3 and 6
+ *
+ * points 1 2 3 4 5 6 8 must be the same (point 8 is not yet calculated)
+ *
+ */
+static void calcline(realloc_t * RESTRICT ry) REGISTERS(3);
+REGISTERS(3)
+static void calcline(realloc_t * RESTRICT ry)
+{
+ number_t y;
+ int range = cfractalc.range;
+ realloc_t *RESTRICT rx, *rend, *rend1, *ryl, *ryr;
+ int distl, distr, distup, distdown;
+ cpixel_t *RESTRICT vbuff, *RESTRICT vbuffu, *RESTRICT vbuffd;
+ cpixeldata_t inset = (cpixeldata_t) cpalette.pixels[0];
+ cpixeldata_t c;
+ cppixel_t *vbuff1 =
+ (cpixel_t **) cimage.currlines + (ry - czoomc.reallocy);
+ assert(ry >= czoomc.reallocy);
+ assert(ry < czoomc.reallocy + cimage.height);
+ y = ry->possition;
+ rend = ry - range - 1;
+ if (czoomc.reallocy > rend)
+ rend = czoomc.reallocy;
+ for (ryl = ry - 1; rend <= ryl && ryl->dirty; ryl--);
+ distl = (int) (ryl - ry);
+ rend = ry + range;
+ if (czoomc.reallocy + cimage.height < rend)
+ rend = czoomc.reallocy + cimage.height;
+ for (ryr = ry + 1; rend > ryr && ryr->dirty; ryr++);
+ distr = (int) (ryr - ry);
+ rend = czoomc.reallocy + cimage.height;
+ if (ryr == czoomc.reallocy + cimage.height || ryl < czoomc.reallocy
+ || ryr->dirty || ryl->dirty) {
+ for (rx = czoomc.reallocx, vbuff = *vbuff1,
+ rend1 = czoomc.reallocx + cimage.width; rx < rend1; rx++) {
+ if (!rx->dirty) {
+ STAT(tocalculate++);
+ p_set(vbuff,
+ (cpixeldata_t) calculate(rx->possition, y,
+ cfractalc.periodicity));
+#ifdef DRAW
+ vga_setcolor(0xff0000);
+ vga_drawpixel(rx - czoomc.reallocx, ry - czoomc.reallocy);
+#endif
+ }
+ p_inc(vbuff, 1);
+ }
+ } else {
+ distup = INT_MAX / 2;
+ distdown = 0;
+ for (rx = czoomc.reallocx,
+ vbuff = vbuff1[0], vbuffu = vbuff1[distl], vbuffd =
+ vbuff1[distr], rend1 = czoomc.reallocx + cimage.width;
+ rx < rend1; rx++) {
+ assert(rx < czoomc.reallocx + cimage.width);
+ assert(rx >= czoomc.reallocx);
+ if (!rx->dirty) {
+ STAT(tocalculate++);
+ if (distdown <= 0) {
+ for (ryr = rx + 1; ryr < rend1 && ryr->dirty; ryr++);
+ distdown = (int) (ryr - rx);
+ if (ryr == rend1)
+ distdown = INT_MAX / 2;
+ }
+ if (distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
+ (p_get(vbuffu) == (c = p_get(vbuffd)) &&
+ c == p_getp(vbuff, -distup) &&
+ c == p_getp(vbuffu, -distup) &&
+ c == p_getp(vbuffu, distdown) &&
+ c == p_getp(vbuffd, distdown) &&
+ c == p_getp(vbuffd, -distup))) {
+ p_set(vbuff, c);
+ STAT(avoided++);
+ } else {
+ if (cfractalc.periodicity &&
+ distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
+ (p_get(vbuffu) != inset &&
+ p_get(vbuffd) != inset &&
+ p_getp(vbuff, -distup) != inset &&
+ p_getp(vbuffu, -distup) != inset &&
+ p_getp(vbuffu, +distdown) != inset &&
+ p_getp(vbuffd, -distup) != inset &&
+ p_getp(vbuffd, +distdown) != inset))
+ p_set(vbuff,
+ (cpixeldata_t) calculate(rx->possition, y,
+ 0));
+ else
+ p_set(vbuff,
+ (cpixeldata_t) calculate(rx->possition, y,
+ cfractalc.
+ periodicity));
+#ifdef DRAW
+ vga_setcolor(0xffffff);
+ vga_drawpixel(rx - czoomc.reallocx,
+ ry - czoomc.reallocy);
+#endif
+ }
+ distup = 0;
+ }
+ p_inc(vbuff, 1);
+ p_inc(vbuffu, 1);
+ p_inc(vbuffd, 1);
+ distdown--;
+ distup++;
+ }
+ }
+ ry->recalculate = 0;
+ ry->dirty = 0;
+}
+
+static void calccolumn(realloc_t * RESTRICT rx) REGISTERS(3);
+REGISTERS(3)
+static void calccolumn(realloc_t * RESTRICT rx)
+{
+ number_t x;
+ int range = cfractalc.range;
+ realloc_t *RESTRICT ry, *rend, *rend1, *rxl, *rxr;
+ int pos, distl, distr, distup, distdown;
+ cpixeldata_t c;
+ cpixeldata_t inset = (cpixeldata_t) cpalette.pixels[0];
+ cppixel_t *RESTRICT vbuff;
+ pos = (int) (rx - czoomc.reallocx);
+ assert(pos >= 0);
+ assert(pos < cimage.width);
+ rend = rx - range + 1;
+ if (czoomc.reallocx > rend)
+ rend = czoomc.reallocx;
+ for (rxl = rx - 1; rend <= rxl && rxl->dirty; rxl--);
+ distl = (int) (rx - rxl);
+ rend = rx + range;
+ if (czoomc.reallocx + cimage.width < rend)
+ rend = czoomc.reallocx + cimage.width;
+ for (rxr = rx + 1; rxr < rend && rxr->dirty; rxr++);
+ distr = (int) (rxr - rx);
+ x = rx->possition;
+ rend = czoomc.reallocx + cimage.width;
+ if (rxr >= czoomc.reallocx + cimage.width || rxl < czoomc.reallocx
+ || rxr->dirty || rxl->dirty) {
+ for (ry = czoomc.reallocy, vbuff =
+ (cppixel_t *) cimage.currlines, rend1 =
+ czoomc.reallocy + cimage.height; ry < rend1; ry++, vbuff++) {
+ if (!ry->dirty) {
+ STAT(tocalculate++);
+ p_setp((*vbuff), pos,
+ (cpixeldata_t) calculate(x, ry->possition,
+ cfractalc.periodicity));
+#ifdef DRAW
+ vga_setcolor(0xff0000);
+ vga_drawpixel(rx - czoomc.reallocx, ry - czoomc.reallocy);
+#endif
+ }
+ }
+ } else {
+ distl = pos - distl;
+ distr = pos + distr;
+ assert(distl >= 0);
+ assert(distr < cimage.width);
+ distup = INT_MAX / 2;
+ distdown = 0;
+ for (ry = czoomc.reallocy, vbuff =
+ (cppixel_t *) cimage.currlines, rend1 =
+ czoomc.reallocy + cimage.height; ry < rend1; ry++) {
+ /*if (ry->symto == -1) { */
+ assert(ry < czoomc.reallocy + cimage.height);
+ if (!ry->dirty) {
+ STAT(tocalculate++);
+ if (distdown <= 0) {
+ for (rxr = ry + 1; rxr < rend1 && rxr->dirty; rxr++);
+ distdown = (int) (rxr - ry);
+ if (rxr == rend1)
+ distdown = INT_MAX / 2;
+ }
+ if (distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
+ (p_getp(vbuff[0], distl) ==
+ (c = p_getp(vbuff[0], distr))
+ && p_getp(vbuff[-distup], distl) == c
+ && p_getp(vbuff[-distup], distr) == c
+ && p_getp(vbuff[-distup], pos) == c
+ && p_getp(vbuff[distdown], distr) == c
+ && p_getp(vbuff[distdown], distl) == c)) {
+ STAT(avoided++);
+ p_setp(vbuff[0], pos, c);
+ } else {
+ if (cfractalc.periodicity &&
+ distdown < INT_MAX / 4 && distup < INT_MAX / 4 &&
+ (p_getp(vbuff[0], distl) != inset &&
+ p_getp(vbuff[0], distr) != inset &&
+ p_getp(vbuff[distdown], distr) != inset &&
+ p_getp(vbuff[distdown], distl) != inset &&
+ p_getp(vbuff[-distup], distl) != inset &&
+ p_getp(vbuff[-distup], pos) != inset &&
+ p_getp(vbuff[-distup], distr) != inset))
+ p_setp(vbuff[0], pos,
+ (cpixeldata_t) calculate(x, ry->possition,
+ 0));
+ else
+ p_setp(vbuff[0], pos,
+ (cpixeldata_t) calculate(x, ry->possition,
+ cfractalc.
+ periodicity));
+#ifdef DRAW
+ vga_setcolor(0xffffff);
+ vga_drawpixel(rx - czoomc.reallocx,
+ ry - czoomc.reallocy);
+#endif
+ }
+ distup = 0;
+ }
+ vbuff++;
+ distdown--;
+ distup++;
+ }
+ }
+ rx->recalculate = 0;
+ rx->dirty = 0;
+}
+
+static /*INLINE */ void
+dosymetry2(void /*@unused@ */ *data, struct taskinfo /*@unused@ */ *task,
+ int r1, int r2)
+{
+ cpixel_t **vbuff = (cpixel_t **) cimage.currlines;
+ realloc_t *rx, *rend;
+ cpixel_t **vend = (cpixel_t **) cimage.currlines + cimage.height;
+ for (rx = czoomc.reallocx + r1, rend = czoomc.reallocx + r2; rx < rend;
+ rx++) {
+ assert(rx->symto >= 0 || rx->symto == -1);
+ if (rx->symto >= 0) {
+ assert(rx->symto < cimage.width);
+ if (!czoomc.reallocx[rx->symto].dirty) {
+ int pos = (int) (rx - czoomc.reallocx);
+ int pos1 = rx->symto;
+ vbuff = (cpixel_t **) cimage.currlines;
+ for (; vbuff < vend; vbuff++)
+ p_copy(vbuff[0], pos, vbuff[0], pos1);
+ rx->dirty = 0;
+ }
+ }
+ }
+}
+
+#ifndef USE_i386ASM
+/*
+ * Fill - bitmap depended part.
+ *
+ * This function is called, when calculation was interrupted because of
+ * timeout. It fills uncalculated rows by nearest one
+ *
+ * This function is very time critical in higher resultions I am shooting
+ * for.
+ */
+#ifndef __GNUC__
+#undef bpp1
+#endif
+#ifndef __i386__
+#undef bpp1
+#endif
+#undef bpp1
+
+static INLINE void fillline(int line)
+{
+ register unsigned char *RESTRICT vbuff = cimage.currlines[line];
+ CONST struct filltable *RESTRICT table = (struct filltable *) tmpdata;
+ while (table->length) {
+ register cpixeldata_t s =
+ p_get((cpixel_t *) (vbuff + table->from));
+ register cpixel_t *vcurr = (cpixel_t *) (vbuff + table->to);
+#ifdef bpp1
+ memset(vcurr, s, table->length);
+#else
+ register cpixel_t *vend = (cpixel_t *) (vbuff + table->end);
+ while (vcurr < vend) {
+ p_set(vcurr, s);
+ p_inc(vcurr, 1);
+ }
+#endif
+ table++;
+ }
+}
+#endif
+#endif
+#undef dosymetry2
+#undef calcline
+#undef calccolumn
+#undef fillline
+#undef rend