00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 #include <string.h>
00032 #include <gimp-print/gimp-print.h>
00033 #include "gimp-print-internal.h"
00034 #include <gimp-print/gimp-print-intl-internal.h>
00035 #ifdef HAVE_LIMITS_H
00036 #include <limits.h>
00037 #endif
00038
00039 #if 1
00040 #define ASSERTIONS
00041 #endif
00042
00043 #ifdef ASSERTIONS
00044 #define assert(x,v) \
00045 do \
00046 { \
00047 if (!(x)) \
00048 { \
00049 stp_eprintf(v, "Assertion %s failed! file %s, line %d.\n", \
00050 #x, __FILE__, __LINE__); \
00051 stp_abort(); \
00052 } \
00053 } while (0)
00054 #else
00055 #define assert(x,v) do {} while (0)
00056 #endif
00057
00058 static int
00059 gcd(int x, int y)
00060 {
00061 if (y == 0)
00062 return x;
00063 while (x != 0) {
00064 if (y > x) {
00065 int t = x;
00066 x = y;
00067 y = t;
00068 }
00069 x %= y;
00070 }
00071 return y;
00072 }
00073
00074 typedef struct stpi_softweave
00075 {
00076 stp_linebufs_t *linebases;
00077 stp_lineoff_t *lineoffsets;
00078 stp_lineactive_t *lineactive;
00079 stp_linecount_t *linecounts;
00080 stp_linebounds_t *linebounds;
00081 stp_pass_t *passes;
00082 int last_pass_offset;
00083
00084
00085
00086 int last_pass;
00087
00088 int jets;
00089 int virtual_jets;
00090
00091 int separation;
00092 void *weaveparm;
00093
00094 int horizontal_weave;
00095
00096
00097 int vertical_subpasses;
00098
00099 int vmod;
00100 int oversample;
00101 int repeat_count;
00102 int ncolors;
00103 int linewidth;
00104 int vertical_height;
00105 int firstline;
00106
00107 int bitwidth;
00108 int lineno;
00109 int vertical_oversample;
00110 int current_vertical_subpass;
00111 int horizontal_width;
00112 int *head_offset;
00113 unsigned char *s[STP_MAX_WEAVE];
00114 unsigned char *fold_buf;
00115 unsigned char *comp_buf;
00116 stp_weave_t wcache;
00117 int rcache;
00118 int vcache;
00119 stp_flushfunc *flushfunc;
00120 stp_fillfunc *fillfunc;
00121 stp_packfunc *pack;
00122 stp_compute_linewidth_func *compute_linewidth;
00123 } stpi_softweave_t;
00124
00125
00126
00127 typedef struct raw {
00128 int separation;
00129 int jets;
00130 int oversampling;
00131 int advancebasis;
00132 int subblocksperpassblock;
00133 int passespersubblock;
00134 stp_weave_strategy_t strategy;
00135 stp_vars_t *v;
00136 } raw_t;
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static void
00155 initialize_raw_weave(raw_t *w,
00156 int separation,
00157 int jets,
00158 int oversample,
00159 stp_weave_strategy_t strat,
00160 stp_vars_t *v)
00161 {
00162 w->separation = separation;
00163 w->jets = jets;
00164 w->oversampling = oversample;
00165 w->advancebasis = jets / oversample;
00166 if (w->advancebasis == 0)
00167 w->advancebasis++;
00168 w->subblocksperpassblock = gcd(separation, w->advancebasis);
00169 w->passespersubblock = separation / w->subblocksperpassblock;
00170 w->strategy = strat;
00171 w->v = v;
00172 }
00173
00174 static void
00175 calculate_raw_pass_parameters(raw_t *w,
00176 int pass,
00177 int *startrow,
00178 int *subpass)
00179 {
00180 int band, passinband, subpassblock, subpassoffset;
00181
00182 band = pass / (w->separation * w->oversampling);
00183 passinband = pass % (w->separation * w->oversampling);
00184 subpassblock = pass % w->separation
00185 * w->subblocksperpassblock / w->separation;
00186
00187 switch (w->strategy) {
00188 case STP_WEAVE_ZIGZAG:
00189 if (subpassblock * 2 < w->subblocksperpassblock)
00190 subpassoffset = 2 * subpassblock;
00191 else
00192 subpassoffset = 2 * (w->subblocksperpassblock
00193 - subpassblock) - 1;
00194 break;
00195 case STP_WEAVE_ASCENDING:
00196 subpassoffset = subpassblock;
00197 break;
00198 case STP_WEAVE_DESCENDING:
00199 subpassoffset = w->subblocksperpassblock - 1 - subpassblock;
00200 break;
00201 case STP_WEAVE_ASCENDING_2X:
00202 if (subpassblock * 2 < w->subblocksperpassblock)
00203 subpassoffset = 2 * subpassblock;
00204 else
00205 subpassoffset = 1 + 2 * (subpassblock
00206 - (w->subblocksperpassblock
00207 + 1) / 2);
00208 break;
00209 case STP_WEAVE_ASCENDING_3X:
00210 if (subpassblock * 3 < w->subblocksperpassblock)
00211 subpassoffset = 3 * subpassblock;
00212 else if (3 * (subpassblock - (w->subblocksperpassblock + 2) / 3)
00213 < w->subblocksperpassblock - 2)
00214 subpassoffset = 2 + 3 * (subpassblock
00215 - (w->subblocksperpassblock
00216 + 2) / 3);
00217 else
00218 subpassoffset = 1 + 3 * (subpassblock
00219 - (w->subblocksperpassblock
00220 + 2) / 3
00221 - w->subblocksperpassblock
00222 / 3);
00223 break;
00224 case STP_WEAVE_STAGGERED:
00225 if (subpassblock * 2 < w->subblocksperpassblock)
00226 subpassoffset = 2 * subpassblock;
00227 else if (subpassblock * 2 < w->subblocksperpassblock + 2)
00228 subpassoffset = 1;
00229 else
00230 subpassoffset = 2 * (w->subblocksperpassblock
00231 - subpassblock) + 1;
00232 break;
00233 default:
00234 subpassoffset = subpassblock;
00235 break;
00236 }
00237
00238 *startrow = w->separation * w->jets * band
00239 + w->advancebasis * passinband + subpassoffset;
00240 *subpass = passinband / w->separation;
00241 }
00242
00243 static void
00244 calculate_raw_row_parameters(raw_t *w,
00245 int row,
00246 int subpass,
00247 int *pass,
00248 int *jet,
00249 int *startrow)
00250 {
00251 int subblockoffset, subpassblock, band, baserow, passinband, offset;
00252 int pass_div_separation;
00253 int pass_mod_separation;
00254 int off_mod_separation;
00255
00256 subblockoffset = row % w->subblocksperpassblock;
00257 switch (w->strategy) {
00258 case STP_WEAVE_ZIGZAG:
00259 if (subblockoffset % 2 == 0)
00260 subpassblock = subblockoffset / 2;
00261 else
00262 subpassblock = w->subblocksperpassblock
00263 - (subblockoffset + 1) / 2;
00264 break;
00265 case STP_WEAVE_ASCENDING:
00266 subpassblock = subblockoffset;
00267 break;
00268 case STP_WEAVE_DESCENDING:
00269 subpassblock = w->subblocksperpassblock - 1 - subblockoffset;
00270 break;
00271 case STP_WEAVE_ASCENDING_2X:
00272 if (subblockoffset % 2 == 0)
00273 subpassblock = subblockoffset / 2;
00274 else
00275 subpassblock = (subblockoffset - 1) / 2
00276 + (w->subblocksperpassblock + 1) / 2;
00277 break;
00278 case STP_WEAVE_ASCENDING_3X:
00279 if (subblockoffset % 3 == 0)
00280 subpassblock = subblockoffset / 3;
00281 else if (subblockoffset % 3 == 1)
00282 subpassblock = (subblockoffset - 1) / 3
00283 + (w->subblocksperpassblock + 2) / 3;
00284 else
00285 subpassblock = (subblockoffset - 2) / 3
00286 + (w->subblocksperpassblock + 2) / 3
00287 + (w->subblocksperpassblock + 1) / 3;
00288 break;
00289 case STP_WEAVE_STAGGERED:
00290 if (subblockoffset % 2 == 0)
00291 subpassblock = subblockoffset / 2;
00292 else if (subblockoffset == 1)
00293 subpassblock = (w->subblocksperpassblock + 1) / 2;
00294 else
00295 subpassblock = w->subblocksperpassblock
00296 - (subblockoffset - 1) / 2;
00297 break;
00298 default:
00299 subpassblock = subblockoffset;
00300 break;
00301 }
00302
00303 band = row / (w->separation * w->jets);
00304 baserow = row - subblockoffset - band * w->separation * w->jets;
00305 passinband = baserow / w->advancebasis;
00306 offset = baserow % w->advancebasis;
00307 pass_div_separation = passinband / w->separation;
00308 pass_mod_separation = passinband % w->separation;
00309 off_mod_separation = offset % w->separation;
00310
00311 while (off_mod_separation != 0
00312 || pass_div_separation != subpass
00313 || pass_mod_separation / w->passespersubblock
00314 != subpassblock)
00315 {
00316 offset += w->advancebasis;
00317 passinband--;
00318 if (passinband >= 0)
00319 {
00320 pass_mod_separation--;
00321 if (pass_mod_separation < 0)
00322 {
00323 pass_mod_separation += w->separation;
00324 pass_div_separation--;
00325 }
00326 if (w->advancebasis < w->separation)
00327 {
00328 off_mod_separation += w->advancebasis;
00329 if (off_mod_separation >= w->separation)
00330 off_mod_separation -= w->separation;
00331 }
00332 else if (w->advancebasis > w->separation)
00333 off_mod_separation = offset % w->separation;
00334 }
00335 else
00336 {
00337 const int roundedjets =
00338 (w->advancebasis * w->oversampling) % w->jets;
00339 band--;
00340 passinband += w->separation * w->oversampling;
00341 offset += w->separation * (w->jets - roundedjets);
00342 pass_div_separation = passinband / w->separation;
00343 pass_mod_separation = passinband % w->separation;
00344 off_mod_separation = offset % w->separation;
00345 }
00346 }
00347
00348 *pass = band * w->oversampling * w->separation + passinband;
00349 *jet = (offset / w->separation) % w->jets;
00350 *startrow = row - (*jet * w->separation);
00351 }
00352
00353
00354
00355 typedef struct cooked {
00356 raw_t rw;
00357 int first_row_printed;
00358 int last_row_printed;
00359
00360 int first_premapped_pass;
00361 int first_normal_pass;
00362 int first_postmapped_pass;
00363 int first_unused_pass;
00364
00365 int *pass_premap;
00366 int *stagger_premap;
00367 int *pass_postmap;
00368 int *stagger_postmap;
00369 } cooked_t;
00370
00371 static void
00372 sort_by_start_row(int *map, int *startrows, int count)
00373 {
00374
00375
00376
00377
00378
00379 int dirty;
00380
00381 do {
00382 int x;
00383 dirty = 0;
00384 for (x = 1; x < count; x++) {
00385 if (startrows[x - 1] > startrows[x]) {
00386 int temp = startrows[x - 1];
00387 startrows[x - 1] = startrows[x];
00388 startrows[x] = temp;
00389 temp = map[x - 1];
00390 map[x - 1] = map[x];
00391 map[x] = temp;
00392 dirty = 1;
00393 }
00394 }
00395 } while (dirty);
00396 }
00397
00398 static void
00399 calculate_stagger(raw_t *w, int *map, int *startrows_stagger, int count)
00400 {
00401 int i;
00402
00403 for (i = 0; i < count; i++) {
00404 int startrow, subpass;
00405 calculate_raw_pass_parameters(w, map[i], &startrow, &subpass);
00406 startrow -= w->separation * w->jets;
00407 startrows_stagger[i] = (startrows_stagger[i] - startrow)
00408 / w->separation;
00409 }
00410 }
00411
00412 static void
00413 invert_map(int *map, int *stagger, int count, int oldfirstpass,
00414 int newfirstpass)
00415 {
00416 int i;
00417 int *newmap, *newstagger;
00418 newmap = stp_malloc(count * sizeof(int));
00419 newstagger = stp_malloc(count * sizeof(int));
00420
00421 for (i = 0; i < count; i++) {
00422 newmap[map[i] - oldfirstpass] = i + newfirstpass;
00423 newstagger[map[i] - oldfirstpass] = stagger[i];
00424 }
00425
00426 memcpy(map, newmap, count * sizeof(int));
00427 memcpy(stagger, newstagger, count * sizeof(int));
00428 stp_free(newstagger);
00429 stp_free(newmap);
00430 }
00431
00432 static void
00433 make_passmap(raw_t *w, int **map, int **starts, int first_pass_number,
00434 int first_pass_to_map, int first_pass_after_map,
00435 int first_pass_to_stagger, int first_pass_after_stagger,
00436 int first_row_of_maximal_pass, int separations_to_distribute)
00437 {
00438 int *passmap, *startrows;
00439 int passes_to_map = first_pass_after_map - first_pass_to_map;
00440 int i;
00441
00442 assert(first_pass_to_map <= first_pass_after_map, w->v);
00443 assert(first_pass_to_stagger <= first_pass_after_stagger, w->v);
00444
00445 *map = passmap = stp_malloc(passes_to_map * sizeof(int));
00446 *starts = startrows = stp_malloc(passes_to_map * sizeof(int));
00447
00448 for (i = 0; i < passes_to_map; i++) {
00449 int startrow, subpass;
00450 int pass = i + first_pass_to_map;
00451 calculate_raw_pass_parameters(w, pass, &startrow, &subpass);
00452 passmap[i] = pass;
00453 if (first_row_of_maximal_pass >= 0)
00454 startrow = first_row_of_maximal_pass - startrow
00455 + w->separation * w->jets;
00456 else
00457 startrow -= w->separation * w->jets;
00458 while (startrow < 0)
00459 startrow += w->separation;
00460 startrows[i] = startrow;
00461 }
00462
00463 sort_by_start_row(passmap, startrows, passes_to_map);
00464
00465 separations_to_distribute++;
00466
00467 for (i = 0; i < first_pass_after_stagger - first_pass_to_stagger; i++) {
00468 int offset = first_pass_to_stagger - first_pass_to_map;
00469 if (startrows[i + offset] / w->separation
00470 < i % separations_to_distribute)
00471 {
00472 startrows[i + offset]
00473 = startrows[i + offset] % w->separation
00474 + w->separation * (i % separations_to_distribute);
00475 }
00476 }
00477
00478 if (first_row_of_maximal_pass >= 0) {
00479 for (i = 0; i < passes_to_map; i++) {
00480 startrows[i] = first_row_of_maximal_pass - startrows[i];
00481 }
00482 }
00483
00484 sort_by_start_row(passmap, startrows, passes_to_map);
00485 calculate_stagger(w, passmap, startrows, passes_to_map);
00486
00487 invert_map(passmap, startrows, passes_to_map, first_pass_to_map,
00488 first_pass_to_map - first_pass_number);
00489 }
00490
00491 static void
00492 calculate_pass_map(stp_vars_t *v,
00493 cooked_t *w,
00494 int pageheight,
00495 int firstrow,
00496 int lastrow)
00497 {
00498 int startrow, subpass;
00499 int pass = -1;
00500
00501 w->first_row_printed = firstrow;
00502 w->last_row_printed = lastrow;
00503
00504 if (pageheight <= lastrow)
00505 pageheight = lastrow + 1;
00506
00507 do {
00508 calculate_raw_pass_parameters(&w->rw, ++pass,
00509 &startrow, &subpass);
00510 } while (startrow - w->rw.separation < firstrow);
00511
00512 w->first_premapped_pass = pass;
00513
00514 while (startrow < w->rw.separation * w->rw.jets
00515 && startrow - w->rw.separation < pageheight
00516 && startrow <= lastrow + w->rw.separation * w->rw.jets)
00517 {
00518 calculate_raw_pass_parameters(&w->rw, ++pass,
00519 &startrow, &subpass);
00520 }
00521 w->first_normal_pass = pass;
00522
00523 while (startrow - w->rw.separation < pageheight
00524 && startrow <= lastrow + w->rw.separation * w->rw.jets)
00525 {
00526 calculate_raw_pass_parameters(&w->rw, ++pass,
00527 &startrow, &subpass);
00528 }
00529 w->first_postmapped_pass = pass;
00530
00531 while (startrow <= lastrow + w->rw.separation * w->rw.jets) {
00532 calculate_raw_pass_parameters(&w->rw, ++pass,
00533 &startrow, &subpass);
00534 }
00535 w->first_unused_pass = pass;
00536
00537 stp_dprintf(STP_DBG_WEAVE_PARAMS, v,
00538 "first premapped %d first normal %d first postmapped %d "
00539 "first unused %d\n",
00540 w->first_premapped_pass, w->first_normal_pass,
00541 w->first_postmapped_pass, w->first_unused_pass);
00542
00543
00544
00545
00546
00547
00548 if (w->first_normal_pass > w->first_premapped_pass) {
00549 int spread, separations_to_distribute, normal_passes_mapped;
00550 separations_to_distribute = firstrow / w->rw.separation;
00551 spread = (separations_to_distribute + 1) * w->rw.separation;
00552 normal_passes_mapped = (spread + w->rw.advancebasis - 1)
00553 / w->rw.advancebasis;
00554 w->first_normal_pass += normal_passes_mapped;
00555 make_passmap(&w->rw, &w->pass_premap, &w->stagger_premap,
00556 w->first_premapped_pass,
00557 w->first_premapped_pass, w->first_normal_pass,
00558 w->first_premapped_pass,
00559 w->first_normal_pass - normal_passes_mapped,
00560 -1, separations_to_distribute);
00561 } else {
00562 w->pass_premap = 0;
00563 w->stagger_premap = 0;
00564 }
00565
00566 if (w->first_unused_pass >= w->first_postmapped_pass) {
00567 int spread, separations_to_distribute, normal_passes_mapped;
00568 separations_to_distribute = (pageheight - lastrow - 1)
00569 / w->rw.separation;
00570 spread = (separations_to_distribute + 1) * w->rw.separation;
00571 normal_passes_mapped = (spread + w->rw.advancebasis)
00572 / w->rw.advancebasis;
00573 w->first_postmapped_pass -= normal_passes_mapped;
00574 make_passmap(&w->rw, &w->pass_postmap, &w->stagger_postmap,
00575 w->first_premapped_pass,
00576 w->first_postmapped_pass, w->first_unused_pass,
00577 w->first_postmapped_pass + normal_passes_mapped,
00578 w->first_unused_pass,
00579 pageheight - 1
00580 - w->rw.separation * (w->rw.jets - 1),
00581 separations_to_distribute);
00582 } else {
00583 w->pass_postmap = 0;
00584 w->stagger_postmap = 0;
00585 }
00586 }
00587
00588 static void *
00589 initialize_weave_params(int separation,
00590 int jets,
00591 int oversample,
00592 int firstrow,
00593 int lastrow,
00594 int pageheight,
00595
00596
00597 stp_weave_strategy_t strategy,
00598 stp_vars_t *v)
00599 {
00600 cooked_t *w = stp_malloc(sizeof(cooked_t));
00601 if (w) {
00602 initialize_raw_weave(&w->rw, separation, jets, oversample, strategy, v);
00603 calculate_pass_map(v, w, pageheight, firstrow, lastrow);
00604 }
00605 return w;
00606 }
00607
00608 static void
00609 stpi_destroy_weave_params(void *vw)
00610 {
00611 cooked_t *w = (cooked_t *) vw;
00612
00613 if (w->pass_premap) stp_free(w->pass_premap);
00614 if (w->stagger_premap) stp_free(w->stagger_premap);
00615 if (w->pass_postmap) stp_free(w->pass_postmap);
00616 if (w->stagger_postmap) stp_free(w->stagger_postmap);
00617 stp_free(w);
00618 }
00619
00620 static void
00621 stpi_calculate_row_parameters(void *vw,
00622 int row,
00623 int subpass,
00624 int *pass,
00625 int *jetnum,
00626 int *startingrow,
00627 int *ophantomrows,
00628 int *ojetsused)
00629 {
00630 cooked_t *w = (cooked_t *) vw;
00631 int raw_pass, jet, startrow, phantomrows, jetsused;
00632 int stagger = 0;
00633 int extra;
00634
00635 assert(row >= w->first_row_printed, w->rw.v);
00636 assert(row <= w->last_row_printed, w->rw.v);
00637 calculate_raw_row_parameters(&w->rw,
00638 row + w->rw.separation * w->rw.jets,
00639 subpass, &raw_pass, &jet, &startrow);
00640 startrow -= w->rw.separation * w->rw.jets;
00641 jetsused = w->rw.jets;
00642 phantomrows = 0;
00643
00644 if (raw_pass < w->first_normal_pass) {
00645 assert(raw_pass >= w->first_premapped_pass, w->rw.v);
00646 *pass = w->pass_premap[raw_pass - w->first_premapped_pass];
00647 stagger = w->stagger_premap[raw_pass - w->first_premapped_pass];
00648 } else if (raw_pass >= w->first_postmapped_pass) {
00649 assert(raw_pass >= w->first_postmapped_pass, w->rw.v);
00650 *pass = w->pass_postmap[raw_pass - w->first_postmapped_pass];
00651 stagger = w->stagger_postmap[raw_pass
00652 - w->first_postmapped_pass];
00653 } else {
00654 *pass = raw_pass - w->first_premapped_pass;
00655 }
00656
00657 startrow += stagger * w->rw.separation;
00658 *jetnum = jet - stagger;
00659 if (stagger < 0) {
00660 stagger = -stagger;
00661 phantomrows += stagger;
00662 }
00663 jetsused -= stagger;
00664
00665 extra = w->first_row_printed
00666 - (startrow + w->rw.separation * phantomrows);
00667 if (extra > 0) {
00668 extra = (extra + w->rw.separation - 1) / w->rw.separation;
00669 jetsused -= extra;
00670 phantomrows += extra;
00671 }
00672
00673 extra = startrow + w->rw.separation * (phantomrows + jetsused - 1)
00674 - w->last_row_printed;
00675 if (extra > 0) {
00676 extra = (extra + w->rw.separation - 1) / w->rw.separation;
00677 jetsused -= extra;
00678 }
00679
00680 *startingrow = startrow;
00681 *ophantomrows = phantomrows;
00682 *ojetsused = jetsused;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 static stp_lineoff_t *
00891 allocate_lineoff(int count, int ncolors)
00892 {
00893 int i;
00894 stp_lineoff_t *retval = stp_malloc(count * sizeof(stp_lineoff_t));
00895 for (i = 0; i < count; i++)
00896 {
00897 retval[i].ncolors = ncolors;
00898 retval[i].v = stp_zalloc(ncolors * sizeof(unsigned long));
00899 }
00900 return (retval);
00901 }
00902
00903 static stp_lineactive_t *
00904 allocate_lineactive(int count, int ncolors)
00905 {
00906 int i;
00907 stp_lineactive_t *retval = stp_malloc(count * sizeof(stp_lineactive_t));
00908 for (i = 0; i < count; i++)
00909 {
00910 retval[i].ncolors = ncolors;
00911 retval[i].v = stp_zalloc(ncolors * sizeof(char));
00912 }
00913 return (retval);
00914 }
00915
00916 static stp_linecount_t *
00917 allocate_linecount(int count, int ncolors)
00918 {
00919 int i;
00920 stp_linecount_t *retval = stp_malloc(count * sizeof(stp_linecount_t));
00921 for (i = 0; i < count; i++)
00922 {
00923 retval[i].ncolors = ncolors;
00924 retval[i].v = stp_zalloc(ncolors * sizeof(int));
00925 }
00926 return (retval);
00927 }
00928
00929 static stp_linebounds_t *
00930 allocate_linebounds(int count, int ncolors)
00931 {
00932 int i;
00933 stp_linebounds_t *retval = stp_malloc(count * sizeof(stp_linebounds_t));
00934 for (i = 0; i < count; i++)
00935 {
00936 retval[i].ncolors = ncolors;
00937 retval[i].start_pos = stp_zalloc(ncolors * sizeof(int));
00938 retval[i].end_pos = stp_zalloc(ncolors * sizeof(int));
00939 }
00940 return (retval);
00941 }
00942
00943 static stp_linebufs_t *
00944 allocate_linebuf(int count, int ncolors)
00945 {
00946 int i;
00947 stp_linebufs_t *retval = stp_malloc(count * sizeof(stp_linebufs_t));
00948 for (i = 0; i < count; i++)
00949 {
00950 retval[i].ncolors = ncolors;
00951 retval[i].v = stp_zalloc(ncolors * sizeof(unsigned char *));
00952 }
00953 return (retval);
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 static void
00972 stpi_destroy_weave(void *vsw)
00973 {
00974 int i, j;
00975 stpi_softweave_t *sw = (stpi_softweave_t *) vsw;
00976 stp_free(sw->passes);
00977 if (sw->fold_buf)
00978 stp_free(sw->fold_buf);
00979 if (sw->comp_buf)
00980 stp_free(sw->comp_buf);
00981 for (i = 0; i < STP_MAX_WEAVE; i++)
00982 if (sw->s[i])
00983 stp_free(sw->s[i]);
00984 for (i = 0; i < sw->vmod; i++)
00985 {
00986 for (j = 0; j < sw->ncolors; j++)
00987 {
00988 if (sw->linebases[i].v[j])
00989 stp_free(sw->linebases[i].v[j]);
00990 }
00991 stp_free(sw->linecounts[i].v);
00992 stp_free(sw->linebases[i].v);
00993 stp_free(sw->lineactive[i].v);
00994 stp_free(sw->lineoffsets[i].v);
00995 stp_free(sw->linebounds[i].start_pos);
00996 stp_free(sw->linebounds[i].end_pos);
00997 }
00998 stp_free(sw->linecounts);
00999 stp_free(sw->lineactive);
01000 stp_free(sw->lineoffsets);
01001 stp_free(sw->linebases);
01002 stp_free(sw->linebounds);
01003 stp_free(sw->head_offset);
01004 stpi_destroy_weave_params(sw->weaveparm);
01005 stp_free(vsw);
01006 }
01007
01008 void
01009 stp_initialize_weave(stp_vars_t *v,
01010 int jets,
01011 int sep,
01012 int osample,
01013 int v_subpasses,
01014 int v_subsample,
01015 int ncolors,
01016 int bitwidth,
01017 int linewidth,
01018 int line_count,
01019 int first_line,
01020 int page_height,
01021 const int *head_offset,
01022 stp_weave_strategy_t weave_strategy,
01023 stp_flushfunc flushfunc,
01024 stp_fillfunc fillfunc,
01025 stp_packfunc pack,
01026 stp_compute_linewidth_func compute_linewidth)
01027 {
01028 int i;
01029 int last_line, maxHeadOffset;
01030 stpi_softweave_t *sw = stp_zalloc(sizeof (stpi_softweave_t));
01031
01032 if (jets < 1)
01033 jets = 1;
01034 if (jets == 1 || sep < 1)
01035 sep = 1;
01036 if (v_subpasses < 1)
01037 v_subpasses = 1;
01038 if (v_subsample < 1)
01039 v_subsample = 1;
01040
01041 sw->separation = sep;
01042 sw->jets = jets;
01043 sw->horizontal_weave = osample;
01044 sw->oversample = osample * v_subpasses * v_subsample;
01045 if (sw->oversample > jets)
01046 {
01047 int found = 0;
01048 for (i = 2; i <= osample; i++)
01049 {
01050 if ((osample % i == 0) && (sw->oversample / i <= jets))
01051 {
01052 sw->repeat_count = i;
01053 osample /= i;
01054 found = 1;
01055 break;
01056 }
01057 }
01058 if (!found)
01059 {
01060 stp_eprintf(v, "Weave error: oversample (%d) > jets (%d)\n",
01061 sw->oversample, jets);
01062 stp_free(sw);
01063 return;
01064 }
01065 }
01066 else
01067 sw->repeat_count = 1;
01068
01069 sw->vertical_oversample = v_subsample;
01070 sw->vertical_subpasses = v_subpasses;
01071 sw->oversample = osample * v_subpasses * v_subsample;
01072 sw->firstline = first_line;
01073 sw->lineno = first_line;
01074 sw->flushfunc = flushfunc;
01075
01076 if (sw->oversample > jets)
01077 {
01078 stp_eprintf(v, "Weave error: oversample (%d) > jets (%d)\n",
01079 sw->oversample, jets);
01080 stp_free(sw);
01081 return;
01082 }
01083
01084
01085
01086
01087
01088 sw->head_offset = stp_zalloc(ncolors * sizeof(int));
01089 if (ncolors > 1)
01090 for(i = 0; i < ncolors; i++)
01091 sw->head_offset[i] = head_offset[i];
01092
01093 maxHeadOffset = 0;
01094 for (i = 0; i < ncolors; i++)
01095 if (sw->head_offset[i] > maxHeadOffset)
01096 maxHeadOffset = sw->head_offset[i];
01097
01098 sw->virtual_jets = sw->jets;
01099 if (maxHeadOffset > 0)
01100 sw->virtual_jets += (maxHeadOffset + sw->separation - 1) / sw->separation;
01101 last_line = first_line + line_count - 1 + maxHeadOffset;
01102
01103 sw->weaveparm = initialize_weave_params(sw->separation, sw->jets,
01104 sw->oversample, first_line, last_line,
01105 page_height, weave_strategy, v);
01106
01107
01108
01109
01110
01111
01112
01113 sw->vmod = 2 * sw->separation * sw->oversample * sw->repeat_count;
01114 if (sw->virtual_jets > sw->jets)
01115 sw->vmod *= (sw->virtual_jets + sw->jets - 1) / sw->jets;
01116
01117 sw->bitwidth = bitwidth;
01118 sw->last_pass_offset = 0;
01119 sw->last_pass = -1;
01120 sw->current_vertical_subpass = 0;
01121 sw->ncolors = ncolors;
01122 sw->linewidth = linewidth;
01123 sw->vertical_height = line_count;
01124 sw->lineoffsets = allocate_lineoff(sw->vmod, ncolors);
01125 sw->lineactive = allocate_lineactive(sw->vmod, ncolors);
01126 sw->linebases = allocate_linebuf(sw->vmod, ncolors);
01127 sw->linebounds = allocate_linebounds(sw->vmod, ncolors);
01128 sw->passes = stp_zalloc(sw->vmod * sizeof(stp_pass_t));
01129 sw->linecounts = allocate_linecount(sw->vmod, ncolors);
01130 sw->rcache = -2;
01131 sw->vcache = -2;
01132 sw->fillfunc = fillfunc;
01133 sw->compute_linewidth = compute_linewidth;
01134 sw->pack = pack;
01135 sw->horizontal_width =
01136 (sw->compute_linewidth)(v, ((sw->linewidth + sw->horizontal_weave - 1) /
01137 sw->horizontal_weave));
01138 sw->horizontal_width = ((sw->horizontal_width + 7) / 8);
01139
01140 for (i = 0; i < sw->vmod; i++)
01141 {
01142 int j;
01143 sw->passes[i].pass = -1;
01144 for (j = 0; j < sw->ncolors; j++)
01145 {
01146 sw->linebases[i].v[j] = NULL;
01147 }
01148 }
01149 stp_allocate_component_data(v, "Weave", NULL, stpi_destroy_weave, sw);
01150 return;
01151 }
01152
01153 static void
01154 weave_parameters_by_row(const stp_vars_t *v, const stpi_softweave_t *sw,
01155 int row, int vertical_subpass, stp_weave_t *w)
01156 {
01157 int jetsused;
01158 int sub_repeat_count = vertical_subpass % sw->repeat_count;
01159
01160
01161
01162
01163 stpi_softweave_t *wsw = (stpi_softweave_t *) sw;
01164 vertical_subpass /= sw->repeat_count;
01165
01166 if (sw->rcache == row && sw->vcache == vertical_subpass)
01167 {
01168 memcpy(w, &sw->wcache, sizeof(stp_weave_t));
01169 w->pass = (w->pass * sw->repeat_count) + sub_repeat_count;
01170 return;
01171 }
01172 wsw->rcache = row;
01173 wsw->vcache = vertical_subpass;
01174
01175 w->row = row;
01176 stpi_calculate_row_parameters(sw->weaveparm, row, vertical_subpass,
01177 &w->pass, &w->jet, &w->logicalpassstart,
01178 &w->missingstartrows, &jetsused);
01179
01180 w->physpassstart = w->logicalpassstart + sw->separation * w->missingstartrows;
01181 w->physpassend = w->physpassstart + sw->separation * (jetsused - 1);
01182
01183 memcpy(&(((stpi_softweave_t *) wsw)->wcache), w, sizeof(stp_weave_t));
01184 w->pass = (w->pass * sw->repeat_count) + sub_repeat_count;
01185 stp_dprintf(STP_DBG_WEAVE_PARAMS, v, "row %d, jet %d of pass %d "
01186 "(pos %d, start %d, end %d, missing rows %d)\n",
01187 w->row, w->jet, w->pass, w->logicalpassstart, w->physpassstart,
01188 w->physpassend, w->missingstartrows);
01189 }
01190
01191 void
01192 stp_weave_parameters_by_row(const stp_vars_t *v, int row,
01193 int vertical_subpass, stp_weave_t *w)
01194 {
01195 const stpi_softweave_t *sw =
01196 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01197 weave_parameters_by_row(v, sw, row, vertical_subpass, w);
01198 }
01199
01200
01201 static stp_lineoff_t *
01202 stpi_get_lineoffsets(const stp_vars_t *v, const stpi_softweave_t *sw,
01203 int row, int subpass, int offset)
01204 {
01205 stp_weave_t w;
01206 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01207 return &(sw->lineoffsets[w.pass % sw->vmod]);
01208 }
01209
01210 static stp_lineactive_t *
01211 stpi_get_lineactive(const stp_vars_t *v, const stpi_softweave_t *sw,
01212 int row, int subpass, int offset)
01213 {
01214 stp_weave_t w;
01215 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01216 return &(sw->lineactive[w.pass % sw->vmod]);
01217 }
01218
01219 static stp_linecount_t *
01220 stpi_get_linecount(const stp_vars_t *v, const stpi_softweave_t *sw,
01221 int row, int subpass, int offset)
01222 {
01223 stp_weave_t w;
01224 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01225 return &(sw->linecounts[w.pass % sw->vmod]);
01226 }
01227
01228 static stp_linebufs_t *
01229 stpi_get_linebases(const stp_vars_t *v, const stpi_softweave_t *sw,
01230 int row, int subpass, int offset)
01231 {
01232 stp_weave_t w;
01233 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01234 return &(sw->linebases[w.pass % sw->vmod]);
01235 }
01236
01237 static stp_linebounds_t *
01238 stpi_get_linebounds(const stp_vars_t *v, const stpi_softweave_t *sw,
01239 int row, int subpass, int offset)
01240 {
01241 stp_weave_t w;
01242 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01243 return &(sw->linebounds[w.pass % sw->vmod]);
01244 }
01245
01246 static stp_pass_t *
01247 stpi_get_pass_by_row(stp_vars_t *v, const stpi_softweave_t *sw,
01248 int row, int subpass,int offset)
01249 {
01250 stp_weave_t w;
01251 weave_parameters_by_row(v, sw, row + offset, subpass, &w);
01252 return &(sw->passes[w.pass % sw->vmod]);
01253 }
01254
01255 stp_lineoff_t *
01256 stp_get_lineoffsets_by_pass(const stp_vars_t *v, int pass)
01257 {
01258 const stpi_softweave_t *sw =
01259 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01260 return &(sw->lineoffsets[pass % sw->vmod]);
01261 }
01262
01263 stp_lineactive_t *
01264 stp_get_lineactive_by_pass(const stp_vars_t *v, int pass)
01265 {
01266 const stpi_softweave_t *sw =
01267 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01268 return &(sw->lineactive[pass % sw->vmod]);
01269 }
01270
01271 stp_linecount_t *
01272 stp_get_linecount_by_pass(const stp_vars_t *v, int pass)
01273 {
01274 const stpi_softweave_t *sw =
01275 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01276 return &(sw->linecounts[pass % sw->vmod]);
01277 }
01278
01279 const stp_linebufs_t *
01280 stp_get_linebases_by_pass(const stp_vars_t *v, int pass)
01281 {
01282 const stpi_softweave_t *sw =
01283 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01284 return &(sw->linebases[pass % sw->vmod]);
01285 }
01286
01287 stp_pass_t *
01288 stp_get_pass_by_pass(const stp_vars_t *v, int pass)
01289 {
01290 const stpi_softweave_t *sw =
01291 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01292 return &(sw->passes[pass % sw->vmod]);
01293 }
01294
01295 static void
01296 check_linebases(stp_vars_t *v, const stpi_softweave_t *sw,
01297 int row, int cpass, int head_offset, int color)
01298 {
01299 stp_linebufs_t *bufs =
01300 (stp_linebufs_t *) stpi_get_linebases(v, sw, row, cpass, head_offset);
01301 if (!(bufs[0].v[color]))
01302 bufs[0].v[color] =
01303 stp_zalloc (sw->virtual_jets * sw->bitwidth * sw->horizontal_width);
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316 void
01317 stp_fill_tiff(stp_vars_t *v, int row, int subpass,
01318 int width, int missingstartrows, int color)
01319 {
01320 stpi_softweave_t *sw =
01321 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01322 stp_lineoff_t *lineoffs;
01323 stp_linecount_t *linecount;
01324 const stp_linebufs_t *bufs;
01325 int i = 0;
01326 int k = 0;
01327
01328 width = sw->bitwidth * width * 8;
01329 for (k = 0; k < missingstartrows; k++)
01330 {
01331 int bytes_to_fill = width;
01332 int full_blocks = bytes_to_fill / (128 * 8);
01333 int leftover = (7 + (bytes_to_fill % (128 * 8))) / 8;
01334 int l = 0;
01335 bufs = stpi_get_linebases(v, sw, row, subpass, sw->head_offset[color]);
01336
01337 while (l < full_blocks)
01338 {
01339 (bufs[0].v[color][2 * i]) = 129;
01340 (bufs[0].v[color][2 * i + 1]) = 0;
01341 i++;
01342 l++;
01343 }
01344 if (leftover == 1)
01345 {
01346 (bufs[0].v[color][2 * i]) = 1;
01347 (bufs[0].v[color][2 * i + 1]) = 0;
01348 i++;
01349 }
01350 else if (leftover > 0)
01351 {
01352 (bufs[0].v[color][2 * i]) = 257 - leftover;
01353 (bufs[0].v[color][2 * i + 1]) = 0;
01354 i++;
01355 }
01356 }
01357
01358 lineoffs = stpi_get_lineoffsets(v, sw, row, subpass, sw->head_offset[color]);
01359 linecount = stpi_get_linecount(v, sw, row, subpass, sw->head_offset[color]);
01360 lineoffs[0].v[color] = 2 * i;
01361 linecount[0].v[color] = missingstartrows;
01362 }
01363
01364 void
01365 stp_fill_uncompressed(stp_vars_t *v, int row, int subpass,
01366 int width, int missingstartrows, int color)
01367 {
01368 stpi_softweave_t *sw =
01369 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01370 stp_lineoff_t *lineoffs;
01371 stp_linecount_t *linecount;
01372 const stp_linebufs_t *bufs;
01373
01374 bufs = stpi_get_linebases(v, sw, row, subpass, sw->head_offset[color]);
01375 lineoffs = stpi_get_lineoffsets(v, sw, row, subpass, sw->head_offset[color]);
01376 linecount = stpi_get_linecount(v, sw, row, subpass, sw->head_offset[color]);
01377 width *= sw->bitwidth * missingstartrows;
01378 memset(bufs[0].v[color], 0, width);
01379 lineoffs[0].v[color] = width;
01380 linecount[0].v[color] = missingstartrows;
01381 }
01382
01383 int
01384 stp_compute_tiff_linewidth(stp_vars_t *v, int n)
01385 {
01386
01387
01388
01389
01390 return ((n + 128 + 7) * 129 / 128);
01391 }
01392
01393 int
01394 stp_compute_uncompressed_linewidth(stp_vars_t *v, int n)
01395 {
01396 return (8 * ((n + 7) / 8));
01397 }
01398
01399 static void
01400 initialize_row(stp_vars_t *v, stpi_softweave_t *sw,
01401 int row, int width, unsigned char *const cols[])
01402 {
01403 stp_weave_t w;
01404 int i, j, jj;
01405 stp_pass_t *pass;
01406
01407 for (i = 0; i < sw->oversample; i++)
01408 {
01409 for (j = 0; j < sw->ncolors; j++)
01410 {
01411 if (cols[j])
01412 {
01413 stp_lineoff_t *lineoffs =
01414 stpi_get_lineoffsets(v, sw, row, i, sw->head_offset[j]);
01415 stp_lineactive_t *lineactive =
01416 stpi_get_lineactive(v, sw, row, i, sw->head_offset[j]);
01417 stp_linecount_t *linecount =
01418 stpi_get_linecount(v, sw, row, i, sw->head_offset[j]);
01419 stp_linebounds_t *linebounds =
01420 stpi_get_linebounds(v, sw, row, i, sw->head_offset[j]);
01421 check_linebases(v, sw, row, i, sw->head_offset[j], j);
01422 weave_parameters_by_row(v, sw, row+sw->head_offset[j], i, &w);
01423 pass = stpi_get_pass_by_row(v, sw, row, i, sw->head_offset[j]);
01424
01425
01426 if (pass->pass < 0)
01427 {
01428 pass->pass = w.pass;
01429 pass->missingstartrows = w.missingstartrows;
01430 pass->logicalpassstart = w.logicalpassstart;
01431 pass->physpassstart = w.physpassstart;
01432 pass->physpassend = w.physpassend;
01433 pass->subpass = i;
01434
01435 for(jj=0; jj<sw->ncolors; jj++)
01436 {
01437 if (lineoffs[0].v[jj] != 0)
01438 stp_eprintf(v, "WARNING: pass %d subpass %d row %d: "
01439 "lineoffs %ld should be zero!\n",
01440 w.pass, i, row, lineoffs[0].v[jj]);
01441 lineoffs[0].v[jj] = 0;
01442 lineactive[0].v[jj] = 0;
01443 if (linecount[0].v[jj] != 0)
01444 stp_eprintf(v, "WARNING: pass %d subpass %d row %d: "
01445 "linecount %d should be zero!\n",
01446 w.pass, i, row, linecount[0].v[jj]);
01447 linecount[0].v[jj] = 0;
01448 linebounds[0].start_pos[jj] = INT_MAX;
01449 linebounds[0].end_pos[jj] = -1;
01450 }
01451 }
01452
01453 if((linecount[0].v[j] == 0) && (w.jet > 0))
01454 {
01455 (sw->fillfunc)(v, row, i, width, w.jet, j);
01456 }
01457 }
01458 }
01459 }
01460 }
01461
01462 static void
01463 add_to_row(stp_vars_t *v, stpi_softweave_t *sw, int row, unsigned char *buf,
01464 size_t nbytes, int color, int setactive, int h_pass)
01465 {
01466 const stp_linebufs_t *bufs =
01467 stpi_get_linebases(v, sw, sw->lineno, h_pass, sw->head_offset[color]);
01468 stp_lineoff_t *lineoffs =
01469 stpi_get_lineoffsets(v, sw, sw->lineno, h_pass, sw->head_offset[color]);
01470 stp_lineactive_t *lineactive =
01471 stpi_get_lineactive(v, sw, sw->lineno, h_pass, sw->head_offset[color]);
01472 stp_linecount_t *linecount =
01473 stpi_get_linecount(v, sw, sw->lineno, h_pass, sw->head_offset[color]);
01474 size_t place = lineoffs[0].v[color];
01475 size_t count = linecount[0].v[color];
01476 if (place + nbytes > sw->virtual_jets * sw->bitwidth * sw->horizontal_width)
01477 {
01478 stp_eprintf(v, "Buffer overflow: limit %d, actual %d, count %d\n",
01479 sw->virtual_jets * sw->bitwidth * sw->horizontal_width,
01480 place + nbytes, count);
01481 stp_abort();
01482 }
01483 memcpy(bufs[0].v[color] + lineoffs[0].v[color], buf, nbytes);
01484 lineoffs[0].v[color] += nbytes;
01485 if (setactive)
01486 lineactive[0].v[color] = 1;
01487 }
01488
01489 static void
01490 stpi_flush_passes(stp_vars_t *v, int flushall)
01491 {
01492 stpi_softweave_t *sw =
01493 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01494 while (1)
01495 {
01496 stp_pass_t *pass = stp_get_pass_by_pass(v, sw->last_pass + 1);
01497
01498
01499
01500
01501 if (pass->pass < 0 || (!flushall && pass->physpassend >= sw->lineno))
01502 return;
01503 (sw->flushfunc)(v, pass->pass, pass->subpass);
01504 sw->last_pass = pass->pass;
01505 pass->pass = -1;
01506 }
01507 }
01508
01509 void
01510 stp_flush_all(stp_vars_t *v)
01511 {
01512 stpi_flush_passes(v, 1);
01513 }
01514
01515 static void
01516 finalize_row(stp_vars_t *v, int row)
01517 {
01518 stpi_softweave_t *sw =
01519 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01520 int i,j;
01521 stp_dprintf(STP_DBG_ROWS, v, "Finalizing row %d...\n", row);
01522 for (i = 0; i < sw->oversample; i++)
01523 {
01524 stp_weave_t w;
01525 stp_linecount_t *lines;
01526
01527 for(j=0; j<sw->ncolors; j++)
01528 {
01529 lines = stpi_get_linecount(v, sw, row, i, sw->head_offset[j]);
01530 lines[0].v[j]++;
01531 }
01532
01533 weave_parameters_by_row(v, sw, row, i, &w);
01534 if (w.physpassend == row)
01535 {
01536 stp_dprintf(STP_DBG_ROWS, v,
01537 "Pass=%d, physpassend=%d, row=%d, lineno=%d, flush..\n",
01538 w.pass, w.physpassend, row, sw->lineno);
01539 stpi_flush_passes(v, 0);
01540 }
01541 }
01542 }
01543
01544 void
01545 stp_write_weave(stp_vars_t *v, unsigned char *const cols[])
01546 {
01547 stpi_softweave_t *sw =
01548 (stpi_softweave_t *) stp_get_component_data(v, "Weave");
01549 int length = (sw->linewidth + 7) / 8;
01550 stp_lineoff_t *lineoffs[STP_MAX_WEAVE];
01551 stp_lineactive_t *lineactives[STP_MAX_WEAVE];
01552 stp_linecount_t *linecounts[STP_MAX_WEAVE];
01553 stp_linebounds_t *linebounds[STP_MAX_WEAVE];
01554 const stp_linebufs_t *bufs[STP_MAX_WEAVE];
01555 int xlength = (length + sw->horizontal_weave - 1) / sw->horizontal_weave;
01556 int ylength = xlength * sw->horizontal_weave;
01557 unsigned char *comp_ptr;
01558 int i, j;
01559 int setactive;
01560 int h_passes = sw->horizontal_weave * sw->vertical_subpasses;
01561 int cpass = sw->current_vertical_subpass * h_passes;
01562
01563 if (!sw->fold_buf)
01564 sw->fold_buf = stp_zalloc(sw->bitwidth * ylength);
01565 if (!sw->comp_buf)
01566 sw->comp_buf = stp_zalloc(sw->bitwidth *
01567 (sw->compute_linewidth)(v,ylength));
01568 if (sw->current_vertical_subpass == 0)
01569 initialize_row(v, sw, sw->lineno, xlength, cols);
01570
01571 for (j = 0; j < sw->ncolors; j++)
01572 {
01573 if (cols[j])
01574 {
01575 const unsigned char *in;
01576 int idx;
01577
01578 for (i = 0; i < h_passes; i++)
01579 {
01580 int offset = sw->head_offset[j];
01581 int pass = cpass + i;
01582 if (!sw->s[i])
01583 sw->s[i] = stp_zalloc(sw->bitwidth *
01584 (sw->compute_linewidth)(v, ylength));
01585 lineoffs[i] =
01586 stpi_get_lineoffsets(v, sw, sw->lineno, pass, offset);
01587 linecounts[i] =
01588 stpi_get_linecount(v, sw, sw->lineno, pass, offset);
01589 lineactives[i] =
01590 stpi_get_lineactive(v, sw, sw->lineno, pass,offset);
01591 linebounds[i] =
01592 stpi_get_linebounds(v, sw, sw->lineno, pass, offset);
01593 bufs[i] =
01594 stpi_get_linebases(v, sw, sw->lineno, pass, offset);
01595 }
01596
01597 if (sw->bitwidth == 2)
01598 {
01599 stp_fold(cols[j], length, sw->fold_buf);
01600 in = sw->fold_buf;
01601 }
01602 else
01603 in = cols[j];
01604 switch (sw->horizontal_weave)
01605 {
01606 case 1:
01607 memcpy(sw->s[0], in, length * sw->bitwidth);
01608 break;
01609 case 2:
01610 stp_unpack_2(length, sw->bitwidth, in, sw->s[0], sw->s[1]);
01611 break;
01612 case 4:
01613 stp_unpack_4(length, sw->bitwidth, in,
01614 sw->s[0], sw->s[1], sw->s[2], sw->s[3]);
01615 break;
01616 case 8:
01617 stp_unpack_8(length, sw->bitwidth, in,
01618 sw->s[0], sw->s[1], sw->s[2], sw->s[3],
01619 sw->s[4], sw->s[5], sw->s[6], sw->s[7]);
01620 break;
01621 }
01622 switch (sw->vertical_subpasses)
01623 {
01624 case 4:
01625 for (idx = 0; idx < sw->horizontal_weave; idx++)
01626 stp_split_4(length, sw->bitwidth, sw->s[idx], sw->s[idx],
01627 sw->s[idx + sw->horizontal_weave],
01628 sw->s[idx + sw->horizontal_weave * 2],
01629 sw->s[idx + sw->horizontal_weave * 3]);
01630 break;
01631 case 2:
01632 for (idx = 0; idx < sw->horizontal_weave; idx++)
01633 stp_split_2(length, sw->bitwidth, sw->s[idx], sw->s[idx],
01634 sw->s[idx + sw->horizontal_weave]);
01635 break;
01636
01637
01638 }
01639 for (i = 0; i < h_passes; i++)
01640 {
01641 int first, last;
01642 setactive = (sw->pack)(v, sw->s[i], sw->bitwidth * xlength,
01643 sw->comp_buf, &comp_ptr, &first, &last);
01644 if (first < linebounds[i]->start_pos[j])
01645 linebounds[i]->start_pos[j] = first;
01646 if (last > linebounds[i]->end_pos[j])
01647 linebounds[i]->end_pos[j] = last;
01648 add_to_row(v, sw, sw->lineno, sw->comp_buf,
01649 comp_ptr - sw->comp_buf, j, setactive, cpass + i);
01650 }
01651 }
01652 }
01653 sw->current_vertical_subpass++;
01654 if (sw->current_vertical_subpass >= sw->vertical_oversample)
01655 {
01656 finalize_row(v, sw->lineno);
01657 sw->lineno++;
01658 sw->current_vertical_subpass = 0;
01659 }
01660 }
01661
01662 #if 0
01663 #define TEST_RAW
01664 #endif
01665 #if 0
01666 #define TEST_COOKED
01667 #endif
01668 #if 0
01669 #define ACCUMULATE
01670 #endif
01671
01672 #if defined(TEST_RAW) || defined(TEST_COOKED)
01673 #define TEST
01674 #endif
01675
01676 #ifdef TEST
01677 #define MAXCOLLECT (1000)
01678 #endif
01679
01680 #ifdef TEST_COOKED
01681 static void
01682 calculate_pass_parameters(cooked_t *w,
01683 int pass,
01684 int *startrow,
01685 int *subpass,
01686 int *phantomrows,
01687 int *jetsused)
01688 {
01689 int raw_pass = pass + w->first_premapped_pass;
01690 int stagger = 0;
01691 int extra;
01692
01693 if (raw_pass < w->first_normal_pass) {
01694 int i = 0;
01695 while (i + w->first_premapped_pass < w->first_normal_pass) {
01696 if (w->pass_premap[i] == pass) {
01697 raw_pass = i + w->first_premapped_pass;
01698 stagger = w->stagger_premap[i];
01699 break;
01700 }
01701 i++;
01702 }
01703 } else if (raw_pass >= w->first_postmapped_pass) {
01704 int i = 0;
01705 while (i + w->first_postmapped_pass < w->first_unused_pass) {
01706 if (w->pass_postmap[i] == pass) {
01707 raw_pass = i + w->first_postmapped_pass;
01708 stagger = w->stagger_postmap[i];
01709 break;
01710 }
01711 i++;
01712 }
01713 }
01714
01715 calculate_raw_pass_parameters(&w->rw, raw_pass, startrow, subpass);
01716 *startrow -= w->rw.separation * w->rw.jets;
01717 *jetsused = w->rw.jets;
01718 *phantomrows = 0;
01719
01720 *startrow += stagger * w->rw.separation;
01721 if (stagger < 0) {
01722 stagger = -stagger;
01723 *phantomrows += stagger;
01724 }
01725 *jetsused -= stagger;
01726
01727 extra = w->first_row_printed - (*startrow + w->rw.separation * *phantomrows);
01728 extra = (extra + w->rw.separation - 1) / w->rw.separation;
01729 if (extra > 0) {
01730 *jetsused -= extra;
01731 *phantomrows += extra;
01732 }
01733
01734 extra = *startrow + w->rw.separation * (*phantomrows + *jetsused - 1)
01735 - w->last_row_printed;
01736 extra = (extra + w->rw.separation - 1) / w->rw.separation;
01737 if (extra > 0) {
01738 *jetsused -= extra;
01739 }
01740 }
01741 #endif
01742
01743 #ifdef TEST
01744
01745 #ifdef ACCUMULATE
01746 #define PUTCHAR(x)
01747 #else
01748 #define PUTCHAR(x) putchar(x)
01749 #endif
01750
01751 static void
01752 plotpass(int startrow, int phantomjets, int jetsused, int totaljets,
01753 int separation, int subpass, int *collect, int *prints)
01754 {
01755 int hpos, i;
01756
01757 for (hpos = 0; hpos < startrow; hpos++)
01758 PUTCHAR(' ');
01759
01760 for (i = 0; i < phantomjets; i++) {
01761 int j;
01762 PUTCHAR('X');
01763 hpos++;
01764 for (j = 1; j < separation; j++) {
01765 PUTCHAR(' ');
01766 hpos++;
01767 }
01768 }
01769
01770 for (; i < phantomjets + jetsused; i++) {
01771 if (i > phantomjets) {
01772 int j;
01773 for (j = 1; j < separation; j++) {
01774 PUTCHAR('-');
01775 hpos++;
01776 }
01777 }
01778 if (hpos < MAXCOLLECT) {
01779 if (collect[hpos] & 1 << subpass)
01780 PUTCHAR('^');
01781 else if (subpass < 10)
01782 PUTCHAR('0' + subpass);
01783 else
01784 PUTCHAR('A' + subpass - 10);
01785 collect[hpos] |= 1 << subpass;
01786 prints[hpos]++;
01787 } else {
01788 PUTCHAR('0' + subpass);
01789 }
01790 hpos++;
01791 }
01792
01793 while (i++ < totaljets) {
01794 int j;
01795 for (j = 1; j < separation; j++) {
01796 PUTCHAR(' ');
01797 hpos++;
01798 }
01799 PUTCHAR('X');
01800 }
01801 #ifdef ACCUMULATE
01802 for (i=0; i<=MAXCOLLECT; i++) {
01803 if (collect[i] == 0)
01804 putchar(' ');
01805 else if (collect[i] < 10)
01806 putchar('0'+collect[i]);
01807 else
01808 putchar('A'+collect[i]-10);
01809 }
01810 #endif
01811 putchar('\n');
01812 }
01813 #endif
01814
01815 #ifdef TEST_COOKED
01816 int
01817 main(int ac, char *av[])
01818 {
01819 int S =ac>1 ? atoi(av[1]) : 4;
01820 int J =ac>2 ? atoi(av[2]) : 12;
01821 int H =ac>3 ? atoi(av[3]) : 1;
01822 int firstrow =ac>4 ? atoi(av[4]) : 1;
01823 int lastrow =ac>5 ? atoi(av[5]) : 100;
01824 int pageheight=ac>6 ? atoi(av[6]) : 1000;
01825 stp_weave_strategy_t strategy =ac>7 ? atoi(av[7]) : 1;
01826 cooked_t *weave;
01827 int passes;
01828
01829 int pass, x;
01830 int collect[MAXCOLLECT];
01831 int prints[MAXCOLLECT];
01832
01833 memset(collect, 0, MAXCOLLECT*sizeof(int));
01834 memset(prints, 0, MAXCOLLECT*sizeof(int));
01835 printf("S=%d J=%d H=%d firstrow=%d lastrow=%d "
01836 "pageheight=%d strategy=%d\n",
01837 S, J, H, firstrow, lastrow, pageheight, strategy);
01838
01839 weave = initialize_weave_params(S, J, H, firstrow, lastrow,
01840 pageheight, strategy);
01841 passes = weave->first_unused_pass - weave->first_premapped_pass;
01842
01843 for (pass = 0; pass < passes; pass++) {
01844 int startrow, subpass, phantomjets, jetsused;
01845
01846 calculate_pass_parameters(weave, pass, &startrow, &subpass,
01847 &phantomjets, &jetsused);
01848
01849 plotpass(startrow, phantomjets, jetsused, J, S, subpass,
01850 collect, prints);
01851 }
01852
01853 for (pass=MAXCOLLECT - 1; prints[pass] == 0; pass--)
01854 ;
01855
01856 for (x=0; x<=pass; x++) {
01857 if (collect[x] < 10)
01858 putchar('0'+collect[x]);
01859 else
01860 putchar('A'+collect[x]-10);
01861 }
01862 putchar('\n');
01863
01864 for (x=0; x<=pass; x++) {
01865 if (prints[x] < 10)
01866 putchar('0'+prints[x]);
01867 else
01868 putchar('A'+prints[x]-10);
01869 }
01870 putchar('\n');
01871
01872 return 0;
01873 }
01874 #endif
01875
01876 #ifdef TEST_RAW
01877 int
01878 main(int ac, char *av[])
01879 {
01880 int S =ac>1 ? atoi(av[1]) : 4;
01881 int J =ac>2 ? atoi(av[2]) : 12;
01882 int h_pos =ac>3 ? atoi(av[3]) : 1;
01883 int h_over=ac>4 ? atoi(av[4]) : 1;
01884 int v_over=ac>5 ? atoi(av[5]) : 1;
01885 int H = h_pos * h_over * v_over;
01886
01887 int pass, passes, x;
01888 int collect[MAXCOLLECT];
01889 int prints[MAXCOLLECT];
01890 raw_t raw;
01891
01892 memset(collect, 0, MAXCOLLECT*sizeof(int));
01893 memset(prints, 0, MAXCOLLECT*sizeof(int));
01894 printf("S=%d J=%d H=%d\n", S, J, H);
01895
01896 if (H > J) {
01897 printf("H > J, so this weave will not work!\n");
01898 }
01899 passes = S * H * 3;
01900
01901 initialize_raw_weave(&raw, S, J, H);
01902
01903 for (pass=0; pass<passes + S * H; pass++) {
01904 int startrow, subpass, phantomjets, jetsused;
01905
01906 calculate_raw_pass_parameters(&raw, pass, &startrow, &subpass);
01907 phantomjets = 0;
01908 jetsused = J;
01909
01910 plotpass(startrow, phantomjets, jetsused, J, S, subpass,
01911 collect, prints);
01912 }
01913 for (pass=MAXCOLLECT - 1; prints[pass] == 0; pass--)
01914 ;
01915
01916 for (x=0; x<=pass; x++) {
01917 if (collect[x] < 10)
01918 putchar('0'+collect[x]);
01919 else
01920 putchar('A'+collect[x]-10);
01921 }
01922 putchar('\n');
01923
01924 for (x=0; x<=pass; x++) {
01925 if (prints[x] < 10)
01926 putchar('0'+prints[x]);
01927 else
01928 putchar('A'+prints[x]-10);
01929 }
01930 putchar('\n');
01931
01932 printf(" A first row given by pass lookup doesn't match row lookup\n"
01933 " B jet out of range\n"
01934 " C given jet number of pass doesn't print this row\n"
01935 " D subpass given by reverse lookup doesn't match requested subpass\n");
01936
01937 for (x = S * J; x < S * J * 20; x++) {
01938 int h;
01939 for (h = 0; h < H; h++) {
01940 int pass, jet, start, first, subpass, z;
01941 int a=0, b=0, c=0, d=0;
01942 calculate_raw_row_parameters(&raw, x, h, &pass, &jet, &start);
01943 for (z=0; z < pass; z++) {
01944 putchar(' ');
01945 }
01946 printf("%d", jet);
01947 calculate_raw_pass_parameters(&raw, pass, &first, &subpass);
01948 if (first != start)
01949 a=1;
01950 if (jet < 0 || jet >= J)
01951 b=1;
01952 if (x != first + jet * S)
01953 c=1;
01954 if (subpass != h)
01955 d=1;
01956 if (a || b || c || d) {
01957 printf(" (");
01958 if (a) putchar('A');
01959 if (b) putchar('B');
01960 if (c) putchar('C');
01961 if (d) putchar('D');
01962 putchar(')');
01963 printf("\npass=%d first=%d start=%d jet=%d subpass=%d", pass, first, start, jet, subpass);
01964 }
01965 putchar('\n');
01966 }
01967
01968 }
01969
01970 return 0;
01971 }
01972
01973 #endif