mirror of https://github.com/GNOME/gimp.git
772 lines
21 KiB
C
772 lines
21 KiB
C
![]() |
/*
|
||
|
* "$Id$"
|
||
|
*
|
||
|
* Softweave calculator for gimp-print.
|
||
|
*
|
||
|
* Copyright 2000 Charles Briscoe-Smith <cpbs@debian.org>
|
||
|
*
|
||
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#if 0
|
||
|
#define TEST_RAW
|
||
|
#endif
|
||
|
#if 0
|
||
|
#define TEST_COOKED
|
||
|
#endif
|
||
|
#if 0
|
||
|
#define ACCUMULATE
|
||
|
#endif
|
||
|
#if 1
|
||
|
#define ASSERTIONS
|
||
|
#endif
|
||
|
|
||
|
#if defined(TEST_RAW) || defined(TEST_COOKED)
|
||
|
#define TEST
|
||
|
#endif
|
||
|
|
||
|
#ifdef ASSERTIONS
|
||
|
#define assert(x) if (!(x)) { fprintf(stderr, "ASSERTION FAILURE! \"%s\", line %d.\n", __FILE__, __LINE__); exit(1); }
|
||
|
#else
|
||
|
#define assert(x) /* nothing */
|
||
|
#endif
|
||
|
|
||
|
#ifdef TEST
|
||
|
#define MAXCOLLECT (1000)
|
||
|
#endif
|
||
|
|
||
|
static int
|
||
|
gcd(int x, int y)
|
||
|
{
|
||
|
assert (x >= 0);
|
||
|
assert (y >= 0);
|
||
|
if (y == 0)
|
||
|
return x;
|
||
|
while (x != 0) {
|
||
|
if (y > x) {
|
||
|
int t = x;
|
||
|
x = y;
|
||
|
y = t;
|
||
|
}
|
||
|
x %= y;
|
||
|
}
|
||
|
return y;
|
||
|
}
|
||
|
|
||
|
/* RAW WEAVE */
|
||
|
|
||
|
typedef struct raw {
|
||
|
int separation;
|
||
|
int jets;
|
||
|
int oversampling;
|
||
|
int advancebasis;
|
||
|
int subblocksperpassblock;
|
||
|
int passespersubblock;
|
||
|
} raw_t;
|
||
|
|
||
|
static void
|
||
|
initialize_raw_weave(raw_t *w, /* I - weave struct to be filled in */
|
||
|
int S, /* I - jet separation */
|
||
|
int J, /* I - number of jets */
|
||
|
int H) /* I - oversampling factor */
|
||
|
{
|
||
|
w->separation = S;
|
||
|
w->jets = J;
|
||
|
w->oversampling = H;
|
||
|
w->advancebasis = J / H;
|
||
|
w->subblocksperpassblock = gcd(S, w->advancebasis);
|
||
|
w->passespersubblock = S / w->subblocksperpassblock;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
calculate_raw_pass_parameters(raw_t *w, /* I - weave parameters */
|
||
|
int pass, /* I - pass number ( >= 0) */
|
||
|
int *startrow, /* O - print head position */
|
||
|
int *subpass) /* O - subpass number */
|
||
|
{
|
||
|
int band, passinband, subpassblock, subpassoffset;
|
||
|
|
||
|
band = pass / (w->separation * w->oversampling);
|
||
|
passinband = pass % (w->separation * w->oversampling);
|
||
|
subpassblock = pass % w->separation
|
||
|
* w->subblocksperpassblock / w->separation;
|
||
|
|
||
|
if (subpassblock * 2 < w->subblocksperpassblock)
|
||
|
subpassoffset = 2 * subpassblock;
|
||
|
else
|
||
|
subpassoffset = 2 * (w->subblocksperpassblock - subpassblock)
|
||
|
- 1;
|
||
|
|
||
|
*startrow = w->separation * w->jets * band
|
||
|
+ w->advancebasis * passinband + subpassoffset;
|
||
|
*subpass = passinband / w->separation;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
calculate_raw_row_parameters(raw_t *w, /* I - weave parameters */
|
||
|
int row, /* I - row number */
|
||
|
int subpass, /* I - subpass number */
|
||
|
int *pass, /* O - pass number */
|
||
|
int *jet, /* O - jet number in pass */
|
||
|
int *startrow) /* O - starting row of pass */
|
||
|
{
|
||
|
int subblockoffset, subpassblock, band, baserow, passinband, offset;
|
||
|
|
||
|
subblockoffset = row % w->subblocksperpassblock;
|
||
|
if (subblockoffset % 2 == 0)
|
||
|
subpassblock = subblockoffset / 2;
|
||
|
else
|
||
|
subpassblock = w->subblocksperpassblock
|
||
|
- (subblockoffset + 1) / 2;
|
||
|
|
||
|
band = row / (w->separation * w->jets);
|
||
|
baserow = row - subblockoffset - band * w->separation * w->jets;
|
||
|
passinband = baserow / w->advancebasis;
|
||
|
offset = baserow % w->advancebasis;
|
||
|
|
||
|
while (offset % w->separation != 0
|
||
|
|| passinband / w->separation != subpass
|
||
|
|| passinband % w->separation / w->passespersubblock
|
||
|
!= subpassblock)
|
||
|
{
|
||
|
offset += w->advancebasis;
|
||
|
passinband--;
|
||
|
if (passinband < 0) {
|
||
|
const int roundedjets = w->advancebasis
|
||
|
* w->oversampling;
|
||
|
band--;
|
||
|
passinband += w->separation * w->oversampling;
|
||
|
offset += w->separation * (w->jets - roundedjets);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*pass = band * w->oversampling * w->separation + passinband;
|
||
|
*jet = offset / w->separation;
|
||
|
*startrow = row - (*jet * w->separation);
|
||
|
}
|
||
|
|
||
|
/* COOKED WEAVE */
|
||
|
|
||
|
typedef struct cooked {
|
||
|
raw_t rw;
|
||
|
int first_row_printed;
|
||
|
int last_row_printed;
|
||
|
|
||
|
int first_premapped_pass; /* First raw pass used by this page */
|
||
|
int first_normal_pass;
|
||
|
int first_postmapped_pass;
|
||
|
int first_unused_pass;
|
||
|
|
||
|
int *pass_premap;
|
||
|
int *stagger_premap;
|
||
|
int *pass_postmap;
|
||
|
int *stagger_postmap;
|
||
|
} cooked_t;
|
||
|
|
||
|
static void
|
||
|
sort_by_start_row(int *map, int *startrows, int count)
|
||
|
{
|
||
|
/*
|
||
|
* Yes, it's a bubble sort, but we do it no more than 4 times
|
||
|
* per page, and we are only sorting a small number of items.
|
||
|
*/
|
||
|
|
||
|
int dirty;
|
||
|
|
||
|
do {
|
||
|
int x;
|
||
|
dirty = 0;
|
||
|
for (x = 1; x < count; x++) {
|
||
|
if (startrows[x - 1] > startrows[x]) {
|
||
|
int temp = startrows[x - 1];
|
||
|
startrows[x - 1] = startrows[x];
|
||
|
startrows[x] = temp;
|
||
|
temp = map[x - 1];
|
||
|
map[x - 1] = map[x];
|
||
|
map[x] = temp;
|
||
|
dirty = 1;
|
||
|
}
|
||
|
}
|
||
|
} while (dirty);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
calculate_stagger(raw_t *w, int *map, int *startrows_stagger, int count)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < count; i++) {
|
||
|
int startrow, subpass;
|
||
|
calculate_raw_pass_parameters(w, map[i], &startrow, &subpass);
|
||
|
startrow -= w->separation * w->jets;
|
||
|
startrows_stagger[i] = (startrows_stagger[i] - startrow)
|
||
|
/ w->separation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
invert_map(int *map, int *stagger, int count, int oldfirstpass,
|
||
|
int newfirstpass)
|
||
|
{
|
||
|
int newmap[count], newstagger[count];
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < count; i++) {
|
||
|
newmap[map[i] - oldfirstpass] = i + newfirstpass;
|
||
|
newstagger[map[i] - oldfirstpass] = stagger[i];
|
||
|
}
|
||
|
|
||
|
memcpy(map, newmap, count * sizeof(int));
|
||
|
memcpy(stagger, newstagger, count * sizeof(int));
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
make_passmap(raw_t *w, int **map, int **starts, int first_pass_number,
|
||
|
int first_pass_to_map, int first_pass_after_map,
|
||
|
int first_pass_to_stagger, int first_pass_after_stagger,
|
||
|
int first_row_of_maximal_pass, int separations_to_distribute)
|
||
|
{
|
||
|
int *passmap, *startrows;
|
||
|
int passes_to_map = first_pass_after_map - first_pass_to_map;
|
||
|
int i;
|
||
|
|
||
|
assert(first_pass_to_map <= first_pass_after_map);
|
||
|
assert(first_pass_to_stagger <= first_pass_after_stagger);
|
||
|
|
||
|
*map = passmap = malloc(passes_to_map * sizeof(int));
|
||
|
*starts = startrows = malloc(passes_to_map * sizeof(int));
|
||
|
|
||
|
for (i = 0; i < passes_to_map; i++) {
|
||
|
int startrow, subpass;
|
||
|
int pass = i + first_pass_to_map;
|
||
|
calculate_raw_pass_parameters(w, pass, &startrow, &subpass);
|
||
|
passmap[i] = pass;
|
||
|
if (first_row_of_maximal_pass >= 0)
|
||
|
startrow = first_row_of_maximal_pass - startrow
|
||
|
+ w->separation * w->jets;
|
||
|
else
|
||
|
startrow -= w->separation * w->jets;
|
||
|
while (startrow < 0)
|
||
|
startrow += w->separation;
|
||
|
startrows[i] = startrow;
|
||
|
}
|
||
|
|
||
|
sort_by_start_row(passmap, startrows, passes_to_map);
|
||
|
|
||
|
separations_to_distribute++;
|
||
|
|
||
|
for (i = 0; i < first_pass_after_stagger - first_pass_to_stagger; i++) {
|
||
|
int offset = first_pass_to_stagger - first_pass_to_map;
|
||
|
if (startrows[i + offset] / w->separation
|
||
|
< i % separations_to_distribute)
|
||
|
{
|
||
|
startrows[i + offset]
|
||
|
= startrows[i + offset] % w->separation
|
||
|
+ w->separation * (i % separations_to_distribute);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (first_row_of_maximal_pass >= 0) {
|
||
|
for (i = 0; i < passes_to_map; i++) {
|
||
|
startrows[i] = first_row_of_maximal_pass - startrows[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sort_by_start_row(passmap, startrows, passes_to_map);
|
||
|
calculate_stagger(w, passmap, startrows, passes_to_map);
|
||
|
|
||
|
invert_map(passmap, startrows, passes_to_map, first_pass_to_map,
|
||
|
first_pass_to_map - first_pass_number);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
calculate_pass_map(cooked_t *w, /* I - weave parameters */
|
||
|
int pagelength, /* I - number of rows on page */
|
||
|
int firstrow, /* I - first printed row */
|
||
|
int lastrow) /* I - last printed row */
|
||
|
{
|
||
|
int startrow, subpass;
|
||
|
int pass = -1;
|
||
|
|
||
|
w->first_row_printed = firstrow;
|
||
|
w->last_row_printed = lastrow;
|
||
|
|
||
|
if (pagelength <= lastrow)
|
||
|
pagelength = lastrow + 1;
|
||
|
|
||
|
do {
|
||
|
calculate_raw_pass_parameters(&w->rw, ++pass,
|
||
|
&startrow, &subpass);
|
||
|
} while (startrow - w->rw.separation < firstrow);
|
||
|
|
||
|
w->first_premapped_pass = pass;
|
||
|
|
||
|
while (startrow < w->rw.separation * w->rw.jets
|
||
|
&& startrow - w->rw.separation < pagelength
|
||
|
&& startrow <= lastrow + w->rw.separation * w->rw.jets)
|
||
|
{
|
||
|
calculate_raw_pass_parameters(&w->rw, ++pass,
|
||
|
&startrow, &subpass);
|
||
|
}
|
||
|
w->first_normal_pass = pass;
|
||
|
|
||
|
while (startrow - w->rw.separation < pagelength
|
||
|
&& startrow <= lastrow + w->rw.separation * w->rw.jets)
|
||
|
{
|
||
|
calculate_raw_pass_parameters(&w->rw, ++pass,
|
||
|
&startrow, &subpass);
|
||
|
}
|
||
|
w->first_postmapped_pass = pass;
|
||
|
|
||
|
while (startrow <= lastrow + w->rw.separation * w->rw.jets) {
|
||
|
calculate_raw_pass_parameters(&w->rw, ++pass,
|
||
|
&startrow, &subpass);
|
||
|
}
|
||
|
w->first_unused_pass = pass;
|
||
|
|
||
|
/*
|
||
|
* FIXME: make sure first_normal_pass doesn't advance beyond
|
||
|
* first_postmapped_pass, or first_postmapped_pass doesn't
|
||
|
* retreat before first_normal_pass.
|
||
|
*/
|
||
|
|
||
|
if (w->first_normal_pass > w->first_premapped_pass) {
|
||
|
int spread, separations_to_distribute, normal_passes_mapped;
|
||
|
separations_to_distribute = firstrow / w->rw.separation;
|
||
|
spread = (separations_to_distribute + 1) * w->rw.separation;
|
||
|
normal_passes_mapped = (spread + w->rw.advancebasis - 1)
|
||
|
/ w->rw.advancebasis;
|
||
|
w->first_normal_pass += normal_passes_mapped;
|
||
|
make_passmap(&w->rw, &w->pass_premap, &w->stagger_premap,
|
||
|
w->first_premapped_pass,
|
||
|
w->first_premapped_pass, w->first_normal_pass,
|
||
|
w->first_premapped_pass,
|
||
|
w->first_normal_pass - normal_passes_mapped,
|
||
|
-1, separations_to_distribute);
|
||
|
} else {
|
||
|
w->pass_premap = 0;
|
||
|
w->stagger_premap = 0;
|
||
|
}
|
||
|
|
||
|
if (w->first_unused_pass > w->first_postmapped_pass) {
|
||
|
int spread, separations_to_distribute, normal_passes_mapped;
|
||
|
separations_to_distribute = (pagelength - lastrow - 1)
|
||
|
/ w->rw.separation;
|
||
|
spread = (separations_to_distribute + 1) * w->rw.separation;
|
||
|
normal_passes_mapped = (spread + w->rw.advancebasis)
|
||
|
/ w->rw.advancebasis;
|
||
|
w->first_postmapped_pass -= normal_passes_mapped;
|
||
|
make_passmap(&w->rw, &w->pass_postmap, &w->stagger_postmap,
|
||
|
w->first_premapped_pass,
|
||
|
w->first_postmapped_pass, w->first_unused_pass,
|
||
|
w->first_postmapped_pass + normal_passes_mapped,
|
||
|
w->first_unused_pass,
|
||
|
pagelength - 1
|
||
|
- w->rw.separation * (w->rw.jets - 1),
|
||
|
separations_to_distribute);
|
||
|
} else {
|
||
|
w->pass_postmap = 0;
|
||
|
w->stagger_postmap = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void * /* O - weave parameter block */
|
||
|
initialize_weave_params(int S, /* I - jet separation */
|
||
|
int J, /* I - number of jets */
|
||
|
int H, /* I - oversampling factor */
|
||
|
int firstrow, /* I - first row number to print */
|
||
|
int lastrow, /* I - last row number to print */
|
||
|
int pagelength) /* I - number of rows on the whole
|
||
|
page, without using any
|
||
|
expanded margin facilities */
|
||
|
{
|
||
|
cooked_t *w = malloc(sizeof(cooked_t));
|
||
|
if (w) {
|
||
|
initialize_raw_weave(&w->rw, S, J, H);
|
||
|
calculate_pass_map(w, pagelength, firstrow, lastrow);
|
||
|
}
|
||
|
return w;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
destroy_weave_params(void *vw)
|
||
|
{
|
||
|
cooked_t *w = (cooked_t *) vw;
|
||
|
|
||
|
if (w->pass_premap) free(w->pass_premap);
|
||
|
if (w->stagger_premap) free(w->stagger_premap);
|
||
|
if (w->pass_postmap) free(w->pass_postmap);
|
||
|
if (w->stagger_postmap) free(w->stagger_postmap);
|
||
|
free(w);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
calculate_row_parameters(void *vw, /* I - weave parameters */
|
||
|
int row, /* I - row number */
|
||
|
int subpass, /* I - subpass */
|
||
|
int *pass, /* O - pass containing row */
|
||
|
int *jetnum, /* O - jet number of row */
|
||
|
int *startingrow, /* O - phys start row of pass */
|
||
|
int *ophantomrows, /* O - missing rows at start */
|
||
|
int *ojetsused) /* O - jets used by pass */
|
||
|
{
|
||
|
cooked_t *w = (cooked_t *) vw;
|
||
|
int raw_pass, jet, startrow, phantomrows, jetsused;
|
||
|
int stagger = 0;
|
||
|
int extra;
|
||
|
|
||
|
assert(row >= w->first_row_printed);
|
||
|
assert(row <= w->last_row_printed);
|
||
|
calculate_raw_row_parameters(&w->rw,
|
||
|
row + w->rw.separation * w->rw.jets,
|
||
|
subpass, &raw_pass, &jet, &startrow);
|
||
|
startrow -= w->rw.separation * w->rw.jets;
|
||
|
jetsused = w->rw.jets;
|
||
|
phantomrows = 0;
|
||
|
|
||
|
if (raw_pass < w->first_normal_pass) {
|
||
|
*pass = w->pass_premap[raw_pass - w->first_premapped_pass];
|
||
|
stagger = w->stagger_premap[raw_pass - w->first_premapped_pass];
|
||
|
} else if (raw_pass >= w->first_postmapped_pass) {
|
||
|
*pass = w->pass_postmap[raw_pass - w->first_postmapped_pass];
|
||
|
stagger = w->stagger_postmap[raw_pass
|
||
|
- w->first_postmapped_pass];
|
||
|
} else {
|
||
|
*pass = raw_pass - w->first_premapped_pass;
|
||
|
}
|
||
|
|
||
|
startrow += stagger * w->rw.separation;
|
||
|
*jetnum = jet - stagger;
|
||
|
if (stagger < 0) {
|
||
|
stagger = -stagger;
|
||
|
phantomrows += stagger;
|
||
|
}
|
||
|
jetsused -= stagger;
|
||
|
|
||
|
extra = w->first_row_printed
|
||
|
- (startrow + w->rw.separation * phantomrows);
|
||
|
if (extra > 0) {
|
||
|
extra = (extra + w->rw.separation - 1) / w->rw.separation;
|
||
|
jetsused -= extra;
|
||
|
phantomrows += extra;
|
||
|
}
|
||
|
|
||
|
extra = startrow + w->rw.separation * (phantomrows + jetsused - 1)
|
||
|
- w->last_row_printed;
|
||
|
if (extra > 0) {
|
||
|
extra = (extra + w->rw.separation - 1) / w->rw.separation;
|
||
|
jetsused -= extra;
|
||
|
}
|
||
|
|
||
|
*startingrow = startrow;
|
||
|
*ophantomrows = phantomrows;
|
||
|
*ojetsused = jetsused;
|
||
|
}
|
||
|
|
||
|
#ifdef TEST_COOKED
|
||
|
static void
|
||
|
calculate_pass_parameters(cooked_t *w, /* I - weave parameters */
|
||
|
int pass, /* I - pass number ( >= 0) */
|
||
|
int *startrow, /* O - print head position */
|
||
|
int *subpass, /* O - subpass number */
|
||
|
int *phantomrows, /* O - missing rows */
|
||
|
int *jetsused) /* O - jets used to print */
|
||
|
{
|
||
|
int raw_pass = pass + w->first_premapped_pass;
|
||
|
int stagger = 0;
|
||
|
int extra;
|
||
|
|
||
|
if (raw_pass < w->first_normal_pass) {
|
||
|
int i = 0;
|
||
|
while (i + w->first_premapped_pass < w->first_normal_pass) {
|
||
|
if (w->pass_premap[i] == pass) {
|
||
|
raw_pass = i + w->first_premapped_pass;
|
||
|
stagger = w->stagger_premap[i];
|
||
|
break;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
} else if (raw_pass >= w->first_postmapped_pass) {
|
||
|
int i = 0;
|
||
|
while (i + w->first_postmapped_pass < w->first_unused_pass) {
|
||
|
if (w->pass_postmap[i] == pass) {
|
||
|
raw_pass = i + w->first_postmapped_pass;
|
||
|
stagger = w->stagger_postmap[i];
|
||
|
break;
|
||
|
}
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
calculate_raw_pass_parameters(&w->rw, raw_pass, startrow, subpass);
|
||
|
*startrow -= w->rw.separation * w->rw.jets;
|
||
|
*jetsused = w->rw.jets;
|
||
|
*phantomrows = 0;
|
||
|
|
||
|
*startrow += stagger * w->rw.separation;
|
||
|
if (stagger < 0) {
|
||
|
stagger = -stagger;
|
||
|
*phantomrows += stagger;
|
||
|
}
|
||
|
*jetsused -= stagger;
|
||
|
|
||
|
extra = w->first_row_printed - (*startrow + w->rw.separation * *phantomrows);
|
||
|
extra = (extra + w->rw.separation - 1) / w->rw.separation;
|
||
|
if (extra > 0) {
|
||
|
*jetsused -= extra;
|
||
|
*phantomrows += extra;
|
||
|
}
|
||
|
|
||
|
extra = *startrow + w->rw.separation * (*phantomrows + *jetsused - 1)
|
||
|
- w->last_row_printed;
|
||
|
extra = (extra + w->rw.separation - 1) / w->rw.separation;
|
||
|
if (extra > 0) {
|
||
|
*jetsused -= extra;
|
||
|
}
|
||
|
}
|
||
|
#endif /* TEST_COOKED */
|
||
|
|
||
|
#ifdef TEST
|
||
|
|
||
|
#ifdef ACCUMULATE
|
||
|
#define PUTCHAR(x) /* nothing */
|
||
|
#else
|
||
|
#define PUTCHAR(x) putchar(x)
|
||
|
#endif
|
||
|
|
||
|
static void
|
||
|
plotpass(int startrow, int phantomjets, int jetsused, int totaljets,
|
||
|
int separation, int subpass, int *collect, int *prints)
|
||
|
{
|
||
|
int hpos, i;
|
||
|
|
||
|
for (hpos = 0; hpos < startrow; hpos++)
|
||
|
PUTCHAR(' ');
|
||
|
|
||
|
for (i = 0; i < phantomjets; i++) {
|
||
|
int j;
|
||
|
PUTCHAR('X');
|
||
|
hpos++;
|
||
|
for (j = 1; j < separation; j++) {
|
||
|
PUTCHAR(' ');
|
||
|
hpos++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (; i < phantomjets + jetsused; i++) {
|
||
|
if (i > phantomjets) {
|
||
|
int j;
|
||
|
for (j = 1; j < separation; j++) {
|
||
|
PUTCHAR('-');
|
||
|
hpos++;
|
||
|
}
|
||
|
}
|
||
|
if (hpos < MAXCOLLECT) {
|
||
|
if (collect[hpos] & 1 << subpass)
|
||
|
PUTCHAR('^');
|
||
|
else if (subpass < 10)
|
||
|
PUTCHAR('0' + subpass);
|
||
|
else
|
||
|
PUTCHAR('A' + subpass - 10);
|
||
|
collect[hpos] |= 1 << subpass;
|
||
|
prints[hpos]++;
|
||
|
} else {
|
||
|
PUTCHAR('0' + subpass);
|
||
|
}
|
||
|
hpos++;
|
||
|
}
|
||
|
|
||
|
while (i++ < totaljets) {
|
||
|
int j;
|
||
|
for (j = 1; j < separation; j++) {
|
||
|
PUTCHAR(' ');
|
||
|
hpos++;
|
||
|
}
|
||
|
PUTCHAR('X');
|
||
|
}
|
||
|
#ifdef ACCUMULATE
|
||
|
for (i=0; i<=MAXCOLLECT; i++) {
|
||
|
if (collect[i] == 0)
|
||
|
putchar(' ');
|
||
|
else if (collect[i] < 10)
|
||
|
putchar('0'+collect[i]);
|
||
|
else
|
||
|
putchar('A'+collect[i]-10);
|
||
|
}
|
||
|
#endif
|
||
|
putchar('\n');
|
||
|
}
|
||
|
#endif /* TEST */
|
||
|
|
||
|
#ifdef TEST_COOKED
|
||
|
int
|
||
|
main(int ac, char *av[])
|
||
|
{
|
||
|
int S =ac>1 ? atoi(av[1]) : 4;
|
||
|
int J =ac>2 ? atoi(av[2]) : 12;
|
||
|
int H =ac>3 ? atoi(av[3]) : 1;
|
||
|
int firstrow =ac>4 ? atoi(av[4]) : 1;
|
||
|
int lastrow =ac>5 ? atoi(av[5]) : 100;
|
||
|
int pagelength=ac>6 ? atoi(av[6]) : 1000;
|
||
|
cooked_t *weave;
|
||
|
int passes;
|
||
|
|
||
|
int pass, x;
|
||
|
int collect[MAXCOLLECT];
|
||
|
int prints[MAXCOLLECT];
|
||
|
|
||
|
memset(collect, 0, MAXCOLLECT*sizeof(int));
|
||
|
memset(prints, 0, MAXCOLLECT*sizeof(int));
|
||
|
printf("S=%d J=%d H=%d firstrow=%d lastrow=%d pagelength=%d\n",
|
||
|
S, J, H, firstrow, lastrow, pagelength);
|
||
|
|
||
|
weave = initialize_weave_params(S, J, H, firstrow, lastrow, pagelength);
|
||
|
passes = weave->first_unused_pass - weave->first_premapped_pass;
|
||
|
|
||
|
for (pass = 0; pass < passes; pass++) {
|
||
|
int startrow, subpass, phantomjets, jetsused;
|
||
|
|
||
|
calculate_pass_parameters(weave, pass, &startrow, &subpass,
|
||
|
&phantomjets, &jetsused);
|
||
|
|
||
|
plotpass(startrow, phantomjets, jetsused, J, S, subpass,
|
||
|
collect, prints);
|
||
|
}
|
||
|
|
||
|
for (pass=MAXCOLLECT - 1; prints[pass] == 0; pass--)
|
||
|
;
|
||
|
|
||
|
for (x=0; x<=pass; x++) {
|
||
|
if (collect[x] < 10)
|
||
|
putchar('0'+collect[x]);
|
||
|
else
|
||
|
putchar('A'+collect[x]-10);
|
||
|
}
|
||
|
putchar('\n');
|
||
|
|
||
|
for (x=0; x<=pass; x++) {
|
||
|
if (prints[x] < 10)
|
||
|
putchar('0'+prints[x]);
|
||
|
else
|
||
|
putchar('A'+prints[x]-10);
|
||
|
}
|
||
|
putchar('\n');
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif /* TEST_COOKED */
|
||
|
|
||
|
#ifdef TEST_RAW
|
||
|
int
|
||
|
main(int ac, char *av[])
|
||
|
{
|
||
|
int S =ac>1 ? atoi(av[1]) : 4;
|
||
|
int J =ac>2 ? atoi(av[2]) : 12;
|
||
|
int h_pos =ac>3 ? atoi(av[3]) : 1;
|
||
|
int h_over=ac>4 ? atoi(av[4]) : 1;
|
||
|
int v_over=ac>5 ? atoi(av[5]) : 1;
|
||
|
int H = h_pos * h_over * v_over;
|
||
|
|
||
|
int pass, passes, x;
|
||
|
int collect[MAXCOLLECT];
|
||
|
int prints[MAXCOLLECT];
|
||
|
raw_t raw;
|
||
|
|
||
|
memset(collect, 0, MAXCOLLECT*sizeof(int));
|
||
|
memset(prints, 0, MAXCOLLECT*sizeof(int));
|
||
|
printf("S=%d J=%d H=%d\n", S, J, H);
|
||
|
|
||
|
if (H > J) {
|
||
|
printf("H > J, so this weave will not work!\n");
|
||
|
}
|
||
|
passes = S * H * 3;
|
||
|
|
||
|
initialize_raw_weave(&raw, S, J, H);
|
||
|
|
||
|
for (pass=0; pass<passes + S * H; pass++) {
|
||
|
int startrow, subpass, phantomjets, jetsused;
|
||
|
|
||
|
calculate_raw_pass_parameters(&raw, pass, &startrow, &subpass);
|
||
|
phantomjets = 0;
|
||
|
jetsused = J;
|
||
|
|
||
|
plotpass(startrow, phantomjets, jetsused, J, S, subpass,
|
||
|
collect, prints);
|
||
|
}
|
||
|
for (pass=MAXCOLLECT - 1; prints[pass] == 0; pass--)
|
||
|
;
|
||
|
|
||
|
for (x=0; x<=pass; x++) {
|
||
|
if (collect[x] < 10)
|
||
|
putchar('0'+collect[x]);
|
||
|
else
|
||
|
putchar('A'+collect[x]-10);
|
||
|
}
|
||
|
putchar('\n');
|
||
|
|
||
|
for (x=0; x<=pass; x++) {
|
||
|
if (prints[x] < 10)
|
||
|
putchar('0'+prints[x]);
|
||
|
else
|
||
|
putchar('A'+prints[x]-10);
|
||
|
}
|
||
|
putchar('\n');
|
||
|
|
||
|
printf(" A first row given by pass lookup doesn't match row lookup\n"
|
||
|
" B jet out of range\n"
|
||
|
" C given jet number of pass doesn't print this row\n"
|
||
|
" D subpass given by reverse lookup doesn't match requested subpass\n");
|
||
|
|
||
|
for (x = S * J; x < S * J * 20; x++) {
|
||
|
int h;
|
||
|
for (h = 0; h < H; h++) {
|
||
|
int pass, jet, start, first, subpass, z;
|
||
|
int a=0, b=0, c=0, d=0;
|
||
|
calculate_raw_row_parameters(&raw, x, h, &pass, &jet, &start);
|
||
|
for (z=0; z < pass; z++) {
|
||
|
putchar(' ');
|
||
|
}
|
||
|
printf("%d", jet);
|
||
|
calculate_raw_pass_parameters(&raw, pass, &first, &subpass);
|
||
|
if (first != start)
|
||
|
a=1;
|
||
|
if (jet < 0 || jet >= J)
|
||
|
b=1;
|
||
|
if (x != first + jet * S)
|
||
|
c=1;
|
||
|
if (subpass != h)
|
||
|
d=1;
|
||
|
if (a || b || c || d) {
|
||
|
printf(" (");
|
||
|
if (a) putchar('A');
|
||
|
if (b) putchar('B');
|
||
|
if (c) putchar('C');
|
||
|
if (d) putchar('D');
|
||
|
putchar(')');
|
||
|
printf("\npass=%d first=%d start=%d jet=%d subpass=%d", pass, first, start, jet, subpass);
|
||
|
}
|
||
|
putchar('\n');
|
||
|
}
|
||
|
//putchar('\n');
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif /* TEST_RAW */
|