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
00029
00030
00031 #ifdef HAVE_CONFIG_H
00032 #include <config.h>
00033 #endif
00034 #include <gimp-print/gimp-print.h>
00035 #include "gimp-print-internal.h"
00036 #include <gimp-print/gimp-print-intl-internal.h>
00037 #include <string.h>
00038 #include <stdio.h>
00039
00040 #ifdef __GNUC__
00041 #define inline __inline__
00042 #endif
00043
00044 #define OLYMPUS_INTERLACE_NONE 0
00045 #define OLYMPUS_INTERLACE_LINE 1
00046 #define OLYMPUS_INTERLACE_PLANE 2
00047
00048 #define OLYMPUS_FEATURE_FULL_WIDTH 0x00000001
00049 #define OLYMPUS_FEATURE_FULL_HEIGHT 0x00000002
00050 #define OLYMPUS_FEATURE_BLOCK_ALIGN 0x00000004
00051 #define OLYMPUS_FEATURE_BORDERLESS 0x00000008
00052 #define OLYMPUS_FEATURE_WHITE_BORDER 0x00000010
00053
00054 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
00055 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
00056
00057 static const char *zero = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
00058
00059 typedef struct
00060 {
00061 const char *output_type;
00062 int output_channels;
00063 const char *name;
00064 } ink_t;
00065
00066 typedef struct {
00067 const ink_t *item;
00068 size_t n_items;
00069 } ink_list_t;
00070
00071 typedef struct
00072 {
00073 int xdpi, ydpi;
00074 int xsize, ysize;
00075 char plane;
00076 int block_min_x, block_min_y;
00077 int block_max_x, block_max_y;
00078 } olympus_privdata_t;
00079
00080 static olympus_privdata_t privdata;
00081
00082 typedef struct {
00083 const char* name;
00084 int xdpi;
00085 int ydpi;
00086 } olymp_resolution_t;
00087
00088 typedef struct {
00089 const olymp_resolution_t *item;
00090 size_t n_items;
00091 } olymp_resolution_list_t;
00092
00093 typedef struct {
00094 const char* name;
00095 const char* text;
00096 int width_pt;
00097 int height_pt;
00098 int border_pt_left;
00099 int border_pt_right;
00100 int border_pt_top;
00101 int border_pt_bottom;
00102 } olymp_pagesize_t;
00103
00104 typedef struct {
00105 const olymp_pagesize_t *item;
00106 size_t n_items;
00107 } olymp_pagesize_list_t;
00108
00109 typedef struct {
00110 const char* res_name;
00111 const char* pagesize_name;
00112 int width_px;
00113 int height_px;
00114 } olymp_printsize_t;
00115
00116 typedef struct {
00117 const olymp_printsize_t *item;
00118 size_t n_items;
00119 } olymp_printsize_list_t;
00120
00121
00122 typedef struct {
00123 const char *name;
00124 const char *text;
00125 const stp_raw_t seq;
00126 } laminate_t;
00127
00128 typedef struct {
00129 const laminate_t *item;
00130 size_t n_items;
00131 } laminate_list_t;
00132
00133 typedef struct
00134 {
00135 int model;
00136 const ink_list_t *inks;
00137 const olymp_resolution_list_t *resolution;
00138 const olymp_pagesize_list_t *pages;
00139 const olymp_printsize_list_t *printsize;
00140 int interlacing;
00141 const char *planes;
00142 int block_size;
00143 int features;
00144 void (*printer_init_func)(stp_vars_t *);
00145 void (*printer_end_func)(stp_vars_t *);
00146 void (*plane_init_func)(stp_vars_t *);
00147 void (*plane_end_func)(stp_vars_t *);
00148 void (*block_init_func)(stp_vars_t *);
00149 void (*block_end_func)(stp_vars_t *);
00150 const char *adj_cyan;
00151 const char *adj_magenta;
00152 const char *adj_yellow;
00153 const laminate_list_t *laminate;
00154 } olympus_cap_t;
00155
00156
00157 static const olympus_cap_t* olympus_get_model_capabilities(int model);
00158
00159
00160 static const ink_t cmy_inks[] =
00161 {
00162 { "CMY", 3, "CMY" },
00163 };
00164
00165 static const ink_list_t cmy_ink_list =
00166 {
00167 cmy_inks, sizeof(cmy_inks) / sizeof(ink_t)
00168 };
00169
00170 static const ink_t rgb_inks[] =
00171 {
00172 { "RGB", 3, "RGB" },
00173 };
00174
00175 static const ink_list_t rgb_ink_list =
00176 {
00177 rgb_inks, sizeof(rgb_inks) / sizeof(ink_t)
00178 };
00179
00180
00181
00182 static const olymp_resolution_t p300_res[] =
00183 {
00184 { "306x306", 306, 306},
00185 { "153x153", 153, 153},
00186 };
00187
00188 static const olymp_resolution_list_t p300_res_list =
00189 {
00190 p300_res, sizeof(p300_res) / sizeof(olymp_resolution_t)
00191 };
00192
00193 static const olymp_pagesize_t p300_page[] =
00194 {
00195 { "Custom", NULL, -1, -1, 28, 28, 48, 48},
00196 { "A6", NULL, -1, -1, 28, 28, 48, 48},
00197 };
00198
00199 static const olymp_pagesize_list_t p300_page_list =
00200 {
00201 p300_page, sizeof(p300_page) / sizeof(olymp_pagesize_t)
00202 };
00203
00204 static const olymp_printsize_t p300_printsize[] =
00205 {
00206 { "306x306", "Custom", 1024, 1376},
00207 { "153x153", "Custom", 1024, 1376},
00208 { "306x306", "A6", 1024, 1376},
00209 { "153x153", "A6", 512, 688},
00210 };
00211
00212 static const olymp_printsize_list_t p300_printsize_list =
00213 {
00214 p300_printsize, sizeof(p300_printsize) / sizeof(olymp_printsize_t)
00215 };
00216
00217 static void p300_printer_init_func(stp_vars_t *v)
00218 {
00219 stp_zfwrite("\033\033\033C\033N\1\033F\0\1\033MS\xff\xff\xff"
00220 "\033Z", 1, 19, v);
00221 stp_put16_be(privdata.xdpi, v);
00222 stp_put16_be(privdata.ydpi, v);
00223 }
00224
00225 static void p300_plane_end_func(stp_vars_t *v)
00226 {
00227 stp_zprintf(v, "\033\033\033P%cS", privdata.plane);
00228 }
00229
00230 static void p300_block_init_func(stp_vars_t *v)
00231 {
00232 stp_zprintf(v, "\033\033\033W%c", privdata.plane);
00233 stp_put16_be(privdata.block_min_y, v);
00234 stp_put16_be(privdata.block_min_x, v);
00235 stp_put16_be(privdata.block_max_y, v);
00236 stp_put16_be(privdata.block_max_x, v);
00237 }
00238
00239 static const char p300_adj_cyan[] =
00240 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00241 "<gimp-print>\n"
00242 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00243 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00244 "0.078431 0.211765 0.250980 0.282353 0.309804 0.333333 0.352941 0.368627\n"
00245 "0.388235 0.403922 0.427451 0.443137 0.458824 0.478431 0.498039 0.513725\n"
00246 "0.529412 0.545098 0.556863 0.576471 0.592157 0.611765 0.627451 0.647059\n"
00247 "0.666667 0.682353 0.701961 0.713725 0.725490 0.729412 0.733333 0.737255\n"
00248 "</sequence>\n"
00249 "</curve>\n"
00250 "</gimp-print>\n";
00251
00252 static const char p300_adj_magenta[] =
00253 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00254 "<gimp-print>\n"
00255 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00256 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00257 "0.047059 0.211765 0.250980 0.278431 0.305882 0.333333 0.349020 0.364706\n"
00258 "0.380392 0.396078 0.415686 0.435294 0.450980 0.466667 0.482353 0.498039\n"
00259 "0.513725 0.525490 0.541176 0.556863 0.572549 0.592157 0.611765 0.631373\n"
00260 "0.650980 0.670588 0.694118 0.705882 0.721569 0.741176 0.745098 0.756863\n"
00261 "</sequence>\n"
00262 "</curve>\n"
00263 "</gimp-print>\n";
00264
00265 static const char p300_adj_yellow[] =
00266 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00267 "<gimp-print>\n"
00268 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00269 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00270 "0.047059 0.117647 0.203922 0.250980 0.274510 0.301961 0.321569 0.337255\n"
00271 "0.352941 0.364706 0.380392 0.396078 0.407843 0.423529 0.439216 0.450980\n"
00272 "0.466667 0.482353 0.498039 0.513725 0.533333 0.552941 0.572549 0.596078\n"
00273 "0.615686 0.635294 0.650980 0.666667 0.682353 0.690196 0.701961 0.713725\n"
00274 "</sequence>\n"
00275 "</curve>\n"
00276 "</gimp-print>\n";
00277
00278
00279
00280 static const olymp_resolution_t res_314dpi[] =
00281 {
00282 { "314x314", 314, 314},
00283 };
00284
00285 static const olymp_resolution_list_t res_314dpi_list =
00286 {
00287 res_314dpi, sizeof(res_314dpi) / sizeof(olymp_resolution_t)
00288 };
00289
00290 static const olymp_pagesize_t p400_page[] =
00291 {
00292 { "A4", NULL, -1, -1, 22, 22, 54, 54},
00293 { "c8x10", "A5 wide", -1, -1, 58, 59, 84, 85},
00294 { "C6", "2 Postcards (A4)", -1, -1, 9, 9, 9, 9},
00295 { "Custom", NULL, -1, -1, 22, 22, 54, 54},
00296 };
00297
00298 static const olymp_pagesize_list_t p400_page_list =
00299 {
00300 p400_page, sizeof(p400_page) / sizeof(olymp_pagesize_t)
00301 };
00302
00303 static const olymp_printsize_t p400_printsize[] =
00304 {
00305 { "314x314", "A4", 2400, 3200},
00306 { "314x314", "c8x10", 2000, 2400},
00307 { "314x314", "C6", 1328, 1920},
00308 { "314x314", "Custom", 2400, 3200},
00309 };
00310
00311 static const olymp_printsize_list_t p400_printsize_list =
00312 {
00313 p400_printsize, sizeof(p400_printsize) / sizeof(olymp_printsize_t)
00314 };
00315
00316 static void p400_printer_init_func(stp_vars_t *v)
00317 {
00318 const char *p = stp_get_string_parameter(v, "PageSize");
00319 int wide = (strcmp(p, "c8x10") == 0 || strcmp(p, "C6") == 0);
00320
00321 stp_zprintf(v, "\033ZQ"); stp_zfwrite(zero, 1, 61, v);
00322 stp_zprintf(v, "\033FP"); stp_zfwrite(zero, 1, 61, v);
00323 stp_zprintf(v, "\033ZF");
00324 stp_putc((wide ? '\x40' : '\x00'), v); stp_zfwrite(zero, 1, 60, v);
00325 stp_zprintf(v, "\033ZS");
00326 if (wide)
00327 {
00328 stp_put16_be(privdata.ysize, v);
00329 stp_put16_be(privdata.xsize, v);
00330 }
00331 else
00332 {
00333 stp_put16_be(privdata.xsize, v);
00334 stp_put16_be(privdata.ysize, v);
00335 }
00336 stp_zfwrite(zero, 1, 57, v);
00337 stp_zprintf(v, "\033ZP"); stp_zfwrite(zero, 1, 61, v);
00338 }
00339
00340 static void p400_plane_init_func(stp_vars_t *v)
00341 {
00342 stp_zprintf(v, "\033ZC"); stp_zfwrite(zero, 1, 61, v);
00343 }
00344
00345 static void p400_plane_end_func(stp_vars_t *v)
00346 {
00347 stp_zprintf(v, "\033P"); stp_zfwrite(zero, 1, 62, v);
00348 }
00349
00350 static void p400_block_init_func(stp_vars_t *v)
00351 {
00352 const char *p = stp_get_string_parameter(v, "PageSize");
00353 int wide = (strcmp(p, "c8x10") == 0 || strcmp(p, "C6") == 0);
00354
00355 stp_zprintf(v, "\033Z%c", privdata.plane);
00356 if (wide)
00357 {
00358 stp_put16_be(privdata.ysize - privdata.block_max_y - 1, v);
00359 stp_put16_be(privdata.xsize - privdata.block_max_x - 1, v);
00360 stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
00361 stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
00362 }
00363 else
00364 {
00365 stp_put16_be(privdata.block_min_x, v);
00366 stp_put16_be(privdata.block_min_y, v);
00367 stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
00368 stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
00369 }
00370 stp_zfwrite(zero, 1, 53, v);
00371 }
00372
00373 static const char p400_adj_cyan[] =
00374 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00375 "<gimp-print>\n"
00376 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00377 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00378 "0.003922 0.031373 0.058824 0.090196 0.125490 0.156863 0.184314 0.219608\n"
00379 "0.250980 0.278431 0.309804 0.341176 0.376471 0.403922 0.439216 0.470588\n"
00380 "0.498039 0.517647 0.533333 0.545098 0.564706 0.576471 0.596078 0.615686\n"
00381 "0.627451 0.647059 0.658824 0.678431 0.690196 0.705882 0.721569 0.737255\n"
00382 "</sequence>\n"
00383 "</curve>\n"
00384 "</gimp-print>\n";
00385
00386 static const char p400_adj_magenta[] =
00387 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00388 "<gimp-print>\n"
00389 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00390 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00391 "0.003922 0.031373 0.062745 0.098039 0.125490 0.156863 0.188235 0.215686\n"
00392 "0.250980 0.282353 0.309804 0.345098 0.376471 0.407843 0.439216 0.470588\n"
00393 "0.501961 0.521569 0.549020 0.572549 0.592157 0.619608 0.643137 0.662745\n"
00394 "0.682353 0.713725 0.737255 0.756863 0.784314 0.807843 0.827451 0.850980\n"
00395 "</sequence>\n"
00396 "</curve>\n"
00397 "</gimp-print>\n";
00398
00399 static const char p400_adj_yellow[] =
00400 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00401 "<gimp-print>\n"
00402 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00403 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00404 "0.003922 0.027451 0.054902 0.090196 0.121569 0.156863 0.184314 0.215686\n"
00405 "0.250980 0.282353 0.309804 0.345098 0.372549 0.400000 0.435294 0.466667\n"
00406 "0.498039 0.525490 0.552941 0.580392 0.607843 0.631373 0.658824 0.678431\n"
00407 "0.698039 0.725490 0.760784 0.784314 0.811765 0.839216 0.866667 0.890196\n"
00408 "</sequence>\n"
00409 "</curve>\n"
00410 "</gimp-print>\n";
00411
00412
00413
00414 static const olymp_pagesize_t cpx00_page[] =
00415 {
00416 { "Postcard", "Postcard 148x100mm", -1, -1, 13, 13, 16, 18},
00417 { "w253h337", "CP_L 89x119mm", -1, -1, 13, 13, 15, 15},
00418 { "w155h244", "Card 54x86mm", -1, -1, 13, 13, 15, 15},
00419 { "Custom", NULL, -1, -1, 13, 13, 16, 18},
00420 };
00421
00422 static const olymp_pagesize_list_t cpx00_page_list =
00423 {
00424 cpx00_page, sizeof(cpx00_page) / sizeof(olymp_pagesize_t)
00425 };
00426
00427 static const olymp_printsize_t cpx00_printsize[] =
00428 {
00429 { "314x314", "Postcard", 1232, 1808},
00430 { "314x314", "w253h337", 1100, 1456},
00431 { "314x314", "w155h244", 672, 1040},
00432 { "314x314", "Custom", 1232, 1808},
00433 };
00434
00435 static const olymp_printsize_list_t cpx00_printsize_list =
00436 {
00437 cpx00_printsize, sizeof(cpx00_printsize) / sizeof(olymp_printsize_t)
00438 };
00439
00440 static void cpx00_printer_init_func(stp_vars_t *v)
00441 {
00442 stp_put16_be(0x4000, v);
00443 stp_put16_be(0x0001, v);
00444 stp_zfwrite(zero, 1, 8, v);
00445 }
00446
00447 static void cpx00_plane_init_func(stp_vars_t *v)
00448 {
00449 stp_put16_be(0x4001, v);
00450 stp_put16_le(privdata.plane - '1', v);
00451 stp_put32_le(privdata.xsize * privdata.ysize, v);
00452 stp_zfwrite(zero, 1, 4, v);
00453 }
00454
00455 static const char cpx00_adj_cyan[] =
00456 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00457 "<gimp-print>\n"
00458 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00459 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00460 "0.000000 0.035294 0.070588 0.101961 0.117647 0.168627 0.180392 0.227451\n"
00461 "0.258824 0.286275 0.317647 0.341176 0.376471 0.411765 0.427451 0.478431\n"
00462 "0.505882 0.541176 0.576471 0.611765 0.654902 0.678431 0.705882 0.737255\n"
00463 "0.764706 0.792157 0.811765 0.839216 0.862745 0.894118 0.909804 0.925490\n"
00464 "</sequence>\n"
00465 "</curve>\n"
00466 "</gimp-print>\n";
00467
00468 static const char cpx00_adj_magenta[] =
00469 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00470 "<gimp-print>\n"
00471 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00472 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00473 "0.011765 0.019608 0.035294 0.047059 0.054902 0.101961 0.133333 0.156863\n"
00474 "0.192157 0.235294 0.274510 0.321569 0.360784 0.403922 0.443137 0.482353\n"
00475 "0.521569 0.549020 0.584314 0.619608 0.658824 0.705882 0.749020 0.792157\n"
00476 "0.831373 0.890196 0.933333 0.964706 0.988235 0.992157 0.992157 0.996078\n"
00477 "</sequence>\n"
00478 "</curve>\n"
00479 "</gimp-print>\n";
00480
00481 static const char cpx00_adj_yellow[] =
00482 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
00483 "<gimp-print>\n"
00484 "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
00485 "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
00486 "0.003922 0.015686 0.015686 0.023529 0.027451 0.054902 0.094118 0.129412\n"
00487 "0.180392 0.219608 0.250980 0.286275 0.317647 0.341176 0.388235 0.427451\n"
00488 "0.470588 0.509804 0.552941 0.596078 0.627451 0.682353 0.768627 0.796078\n"
00489 "0.890196 0.921569 0.949020 0.968627 0.984314 0.992157 0.992157 1.000000\n"
00490 "</sequence>\n"
00491 "</curve>\n"
00492 "</gimp-print>\n";
00493
00494
00495
00496 static const olymp_resolution_t updp10_res[] =
00497 {
00498 { "300x300", 300, 300},
00499 };
00500
00501 static const olymp_resolution_list_t updp10_res_list =
00502 {
00503 updp10_res, sizeof(updp10_res) / sizeof(olymp_resolution_t)
00504 };
00505
00506 static const olymp_pagesize_t updp10_page[] =
00507 {
00508 { "w288h432", "UPC-10P23 (2:3)", -1, -1, 12, 12, 18, 18},
00509 { "w288h387", "UPC-10P34 (3:4)", -1, -1, 12, 12, 16, 16},
00510 { "w288h432", "UPC-10S01 (Sticker)", -1, -1, 12, 12, 18, 18},
00511 { "Custom", NULL, -1, -1, 12, 12, 0, 0},
00512 };
00513
00514 static const olymp_pagesize_list_t updp10_page_list =
00515 {
00516 updp10_page, sizeof(updp10_page) / sizeof(olymp_pagesize_t)
00517 };
00518
00519 static const olymp_printsize_t updp10_printsize[] =
00520 {
00521 { "300x300", "w288h432", 1200, 1800},
00522 { "300x300", "w288h387", 1200, 1600},
00523 { "300x300", "Custom", 1200, 1800},
00524 };
00525
00526 static const olymp_printsize_list_t updp10_printsize_list =
00527 {
00528 updp10_printsize, sizeof(updp10_printsize) / sizeof(olymp_printsize_t)
00529 };
00530
00531 static void updp10_printer_init_func(stp_vars_t *v)
00532 {
00533 stp_zfwrite("\x98\xff\xff\xff\xff\xff\xff\xff"
00534 "\x14\x00\x00\x00\x1b\x15\x00\x00"
00535 "\x00\x0d\x00\x00\x00\x00\x00\xc7"
00536 "\x00\x00\x00\x00", 1, 28, v);
00537 stp_put16_be(privdata.xsize, v);
00538 stp_put16_be(privdata.ysize, v);
00539 stp_put32_le(privdata.xsize*privdata.ysize*3+11, v);
00540 stp_zfwrite("\x1b\xea\x00\x00\x00\x00", 1, 6, v);
00541 stp_put32_be(privdata.xsize*privdata.ysize*3, v);
00542 stp_zfwrite("\x00", 1, 1, v);
00543 }
00544
00545 static void updp10_printer_end_func(stp_vars_t *v)
00546 {
00547 const char *lpar = stp_get_string_parameter(v, "Laminate");
00548 const olympus_cap_t *caps = olympus_get_model_capabilities(
00549 stp_get_model_id(v));
00550 const laminate_list_t *llist = caps->laminate;
00551 const laminate_t *l = NULL;
00552 int i;
00553
00554 for (i = 0; i < llist->n_items; i++)
00555 {
00556 l = &(llist->item[i]);
00557 if (strcmp(l->name, lpar) == 0)
00558 break;
00559 }
00560 stp_zfwrite("\x12\x00\x00\x00\x1b\xe1\x00\x00"
00561 "\x00\xb0\x00\x00\04", 1, 13, v);
00562 stp_zfwrite((l->seq).data, 1, (l->seq).bytes, v);
00563 stp_zfwrite("\x00\x00\x00\x00" , 1, 4, v);
00564 stp_put16_be(privdata.ysize, v);
00565 stp_put16_be(privdata.xsize, v);
00566 stp_zfwrite("\xff\xff\xff\xff\x09\x00\x00\x00"
00567 "\x1b\xee\x00\x00\x00\x02\x00\x00"
00568 "\x01\x07\x00\x00\x00\x1b\x0a\x00"
00569 "\x00\x00\x00\x00\xfd\xff\xff\xff"
00570 "\xff\xff\xff\xff\xf8\xff\xff\xff"
00571 , 1, 40, v);
00572 }
00573
00574 static const laminate_t updp10_laminate[] =
00575 {
00576 {"Glossy", N_("Glossy"), {1, "\x00"}},
00577 {"Texture", N_("Texture"), {1, "\x08"}},
00578 {"Matte", N_("Matte"), {1, "\x0c"}},
00579 };
00580
00581 static const laminate_list_t updp10_laminate_list =
00582 {
00583 updp10_laminate, sizeof(updp10_laminate) / sizeof(laminate_t)
00584 };
00585
00586
00587
00588 static const olymp_resolution_t cx400_res[] =
00589 {
00590 { "317x316", 317, 316},
00591 };
00592
00593 static const olymp_resolution_list_t cx400_res_list =
00594 {
00595 cx400_res, sizeof(cx400_res) / sizeof(olymp_resolution_t)
00596 };
00597
00598 static const olymp_pagesize_t cx400_page[] =
00599 {
00600 { "w288h387", "4x5 3/8 (Digital Camera 3:4)", -1, -1, 23, 23, 27, 26},
00601 { "w288h432", NULL, -1, -1, 23, 23, 28, 28},
00602 { "w288h504", NULL, -1, -1, 23, 23, 23, 22},
00603 { "Custom", NULL, -1, -1, 0, 0, 0, 0},
00604 };
00605
00606 static const olymp_pagesize_list_t cx400_page_list =
00607 {
00608 cx400_page, sizeof(cx400_page) / sizeof(olymp_pagesize_t)
00609 };
00610
00611 static const olymp_printsize_t cx400_printsize[] =
00612 {
00613 { "317x316", "w288h387", 1268, 1658},
00614 { "317x316", "w288h432", 1268, 1842},
00615 { "317x316", "w288h504", 1268, 2208},
00616 { "317x316", "Custom", 1268, 1842},
00617 };
00618
00619 static const olymp_printsize_list_t cx400_printsize_list =
00620 {
00621 cx400_printsize, sizeof(cx400_printsize) / sizeof(olymp_printsize_t)
00622 };
00623
00624 static void cx400_printer_init_func(stp_vars_t *v)
00625 {
00626 const char *p = stp_get_string_parameter(v, "PageSize");
00627 char pg = '\0';
00628
00629 stp_zfwrite("FUJIFILMNX1000\0", 1, 15, v);
00630 stp_put16_le(privdata.xsize, v);
00631 stp_put16_le(privdata.ysize, v);
00632 if (strcmp(p,"w288h504") == 0)
00633 pg = '\x0d';
00634 else if (strcmp(p,"w288h432") == 0)
00635 pg = '\x0c';
00636 else if (strcmp(p,"w288h387") == 0)
00637 pg = '\x0b';
00638 stp_putc(pg, v);
00639 stp_zfwrite("\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00"
00640 "\x00\x00\x2d\x00\x00\x00\x00", 1, 19, v);
00641 stp_zfwrite("FUJIFILMNX1000\1", 1, 15, v);
00642 }
00643
00644 static const olymp_resolution_t all_resolutions[] =
00645 {
00646 { "306x306", 306, 306},
00647 { "153x153", 153, 153},
00648 { "314x314", 314, 314},
00649 { "300x300", 300, 300},
00650 { "317x316", 317, 316},
00651 };
00652
00653 static const olymp_resolution_list_t all_res_list =
00654 {
00655 all_resolutions, sizeof(all_resolutions) / sizeof(olymp_resolution_t)
00656 };
00657
00658 static const olympus_cap_t olympus_model_capabilities[] =
00659 {
00660 {
00661 0,
00662 &cmy_ink_list,
00663 &p300_res_list,
00664 &p300_page_list,
00665 &p300_printsize_list,
00666 OLYMPUS_INTERLACE_PLANE, "YMC",
00667 16,
00668 OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_BLOCK_ALIGN,
00669 &p300_printer_init_func, NULL,
00670 NULL, &p300_plane_end_func,
00671 &p300_block_init_func, NULL,
00672 p300_adj_cyan, p300_adj_magenta, p300_adj_yellow,
00673 NULL,
00674 },
00675 {
00676 1,
00677 &cmy_ink_list,
00678 &res_314dpi_list,
00679 &p400_page_list,
00680 &p400_printsize_list,
00681 OLYMPUS_INTERLACE_PLANE, "123",
00682 180,
00683 OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT,
00684 &p400_printer_init_func, NULL,
00685 &p400_plane_init_func, &p400_plane_end_func,
00686 &p400_block_init_func, NULL,
00687 p400_adj_cyan, p400_adj_magenta, p400_adj_yellow,
00688 NULL,
00689 },
00690 {
00691 1000,
00692 &cmy_ink_list,
00693 &res_314dpi_list,
00694 &cpx00_page_list,
00695 &cpx00_printsize_list,
00696 OLYMPUS_INTERLACE_PLANE, "123",
00697 1808,
00698 OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
00699 | OLYMPUS_FEATURE_BORDERLESS | OLYMPUS_FEATURE_WHITE_BORDER,
00700 &cpx00_printer_init_func, NULL,
00701 &cpx00_plane_init_func, NULL,
00702 NULL, NULL,
00703 cpx00_adj_cyan, cpx00_adj_magenta, cpx00_adj_yellow,
00704 NULL,
00705 },
00706 {
00707 2000,
00708 &cmy_ink_list,
00709 &updp10_res_list,
00710 &updp10_page_list,
00711 &updp10_printsize_list,
00712 OLYMPUS_INTERLACE_NONE, "123",
00713 1800,
00714 OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
00715 | OLYMPUS_FEATURE_BORDERLESS,
00716 &updp10_printer_init_func, &updp10_printer_end_func,
00717 NULL, NULL,
00718 NULL, NULL,
00719 NULL, NULL, NULL,
00720 &updp10_laminate_list,
00721 },
00722 {
00723 3000,
00724 &rgb_ink_list,
00725 &cx400_res_list,
00726 &cx400_page_list,
00727 &cx400_printsize_list,
00728 OLYMPUS_INTERLACE_NONE, "CMY",
00729 2208,
00730 OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
00731 | OLYMPUS_FEATURE_BORDERLESS,
00732 &cx400_printer_init_func, NULL,
00733 NULL, NULL,
00734 NULL, NULL,
00735 NULL, NULL, NULL,
00736 NULL,
00737 },
00738 };
00739
00740 static const stp_parameter_t the_parameters[] =
00741 {
00742 {
00743 "PageSize", N_("Page Size"), N_("Basic Printer Setup"),
00744 N_("Size of the paper being printed to"),
00745 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
00746 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00747 },
00748 {
00749 "MediaType", N_("Media Type"), N_("Basic Printer Setup"),
00750 N_("Type of media (plain paper, photo paper, etc.)"),
00751 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00752 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00753 },
00754 {
00755 "InputSlot", N_("Media Source"), N_("Basic Printer Setup"),
00756 N_("Source (input slot) of the media"),
00757 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00758 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00759 },
00760 {
00761 "Resolution", N_("Resolution"), N_("Basic Printer Setup"),
00762 N_("Resolution and quality of the print"),
00763 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00764 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00765 },
00766 {
00767 "InkType", N_("Ink Type"), N_("Advanced Printer Setup"),
00768 N_("Type of ink in the printer"),
00769 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00770 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00771 },
00772 {
00773 "Laminate", N_("Laminate Pattern"), N_("Advanced Printer Setup"),
00774 N_("Laminate Pattern"),
00775 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
00776 STP_PARAMETER_LEVEL_BASIC, 1, 0, -1, 1, 0
00777 },
00778 {
00779 "Borderless", N_("Borderless"), N_("Advanced Printer Setup"),
00780 N_("Print without borders"),
00781 STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
00782 STP_PARAMETER_LEVEL_BASIC, 1, 0, -1, 1, 0
00783 },
00784 {
00785 "PrintingMode", N_("Printing Mode"), N_("Core Parameter"),
00786 N_("Printing Output Mode"),
00787 STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
00788 STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
00789 },
00790 };
00791
00792 static int the_parameter_count =
00793 sizeof(the_parameters) / sizeof(const stp_parameter_t);
00794
00795 typedef struct
00796 {
00797 const stp_parameter_t param;
00798 double min;
00799 double max;
00800 double defval;
00801 int color_only;
00802 } float_param_t;
00803
00804 static const float_param_t float_parameters[] =
00805 {
00806 {
00807 {
00808 "CyanDensity", N_("Cyan Balance"), N_("Output Level Adjustment"),
00809 N_("Adjust the cyan balance"),
00810 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00811 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
00812 }, 0.0, 2.0, 1.0, 1
00813 },
00814 {
00815 {
00816 "MagentaDensity", N_("Magenta Balance"), N_("Output Level Adjustment"),
00817 N_("Adjust the magenta balance"),
00818 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00819 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
00820 }, 0.0, 2.0, 1.0, 1
00821 },
00822 {
00823 {
00824 "YellowDensity", N_("Yellow Balance"), N_("Output Level Adjustment"),
00825 N_("Adjust the yellow balance"),
00826 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00827 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
00828 }, 0.0, 2.0, 1.0, 1
00829 },
00830 {
00831 {
00832 "BlackDensity", N_("Black Balance"), N_("Output Level Adjustment"),
00833 N_("Adjust the black balance"),
00834 STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
00835 STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
00836 }, 0.0, 2.0, 1.0, 1
00837 },
00838 };
00839
00840 static const int float_parameter_count =
00841 sizeof(float_parameters) / sizeof(const float_param_t);
00842
00843 static const olympus_cap_t* olympus_get_model_capabilities(int model)
00844 {
00845 int i;
00846 int models = sizeof(olympus_model_capabilities) / sizeof(olympus_cap_t);
00847
00848 for (i=0; i<models; i++)
00849 {
00850 if (olympus_model_capabilities[i].model == model)
00851 return &(olympus_model_capabilities[i]);
00852 }
00853 stp_deprintf(STP_DBG_OLYMPUS,
00854 "olympus: model %d not found in capabilities list.\n", model);
00855 return &(olympus_model_capabilities[0]);
00856 }
00857
00858 static void
00859 olympus_printsize(const stp_vars_t *v,
00860 int *width,
00861 int *height)
00862 {
00863 int i;
00864 const char *page = stp_get_string_parameter(v, "PageSize");
00865 const char *resolution = stp_get_string_parameter(v, "Resolution");
00866 const olympus_cap_t *caps = olympus_get_model_capabilities(
00867 stp_get_model_id(v));
00868 const olymp_printsize_list_t *p = caps->printsize;
00869
00870 for (i = 0; i < p->n_items; i++)
00871 {
00872 if (strcmp(p->item[i].res_name,resolution) == 0 &&
00873 strcmp(p->item[i].pagesize_name,page) == 0)
00874 {
00875 *width = p->item[i].width_px;
00876 *height = p->item[i].height_px;
00877 return;
00878 }
00879 }
00880 stp_erprintf("olympus_printsize: printsize not found (%s, %s)\n",
00881 page, resolution);
00882 }
00883
00884 static int
00885 olympus_feature(const olympus_cap_t *caps, int feature)
00886 {
00887 return ((caps->features & feature) == feature);
00888 }
00889
00890 static stp_parameter_list_t
00891 olympus_list_parameters(const stp_vars_t *v)
00892 {
00893 stp_parameter_list_t *ret = stp_parameter_list_create();
00894 int i;
00895
00896 for (i = 0; i < the_parameter_count; i++)
00897 stp_parameter_list_add_param(ret, &(the_parameters[i]));
00898 for (i = 0; i < float_parameter_count; i++)
00899 stp_parameter_list_add_param(ret, &(float_parameters[i].param));
00900 return ret;
00901 }
00902
00903 static void
00904 olympus_parameters(const stp_vars_t *v, const char *name,
00905 stp_parameter_t *description)
00906 {
00907 int i;
00908 const olympus_cap_t *caps = olympus_get_model_capabilities(
00909 stp_get_model_id(v));
00910
00911 description->p_type = STP_PARAMETER_TYPE_INVALID;
00912 if (name == NULL)
00913 return;
00914
00915 description->deflt.str = NULL;
00916 for (i = 0; i < float_parameter_count; i++)
00917 if (strcmp(name, float_parameters[i].param.name) == 0)
00918 {
00919 stp_fill_parameter_settings(description,
00920 &(float_parameters[i].param));
00921 description->deflt.dbl = float_parameters[i].defval;
00922 description->bounds.dbl.upper = float_parameters[i].max;
00923 description->bounds.dbl.lower = float_parameters[i].min;
00924 }
00925
00926 for (i = 0; i < the_parameter_count; i++)
00927 if (strcmp(name, the_parameters[i].name) == 0)
00928 {
00929 stp_fill_parameter_settings(description, &(the_parameters[i]));
00930 break;
00931 }
00932 if (strcmp(name, "PageSize") == 0)
00933 {
00934 int default_specified = 0;
00935 const olymp_pagesize_list_t *p = caps->pages;
00936 const char* text;
00937
00938 description->bounds.str = stp_string_list_create();
00939 for (i = 0; i < p->n_items; i++)
00940 {
00941 const stp_papersize_t *pt = stp_get_papersize_by_name(
00942 p->item[i].name);
00943
00944 text = (p->item[i].text ? p->item[i].text : pt->text);
00945 stp_string_list_add_string(description->bounds.str,
00946 p->item[i].name, text);
00947 if (! default_specified && pt && pt->width > 0 && pt->height > 0)
00948 {
00949 description->deflt.str = p->item[i].name;
00950 default_specified = 1;
00951 }
00952 }
00953 if (!default_specified)
00954 description->deflt.str =
00955 stp_string_list_param(description->bounds.str, 0)->name;
00956 }
00957 else if (strcmp(name, "MediaType") == 0)
00958 {
00959 description->bounds.str = stp_string_list_create();
00960 description->is_active = 0;
00961 }
00962 else if (strcmp(name, "InputSlot") == 0)
00963 {
00964 description->bounds.str = stp_string_list_create();
00965 description->is_active = 0;
00966 }
00967 else if (strcmp(name, "Resolution") == 0)
00968 {
00969 char res_text[24];
00970 const olymp_resolution_list_t *r = caps->resolution;
00971
00972 description->bounds.str = stp_string_list_create();
00973 for (i = 0; i < r->n_items; i++)
00974 {
00975 sprintf(res_text, "%s DPI", r->item[i].name);
00976 stp_string_list_add_string(description->bounds.str,
00977 r->item[i].name, _(res_text));
00978 }
00979 if (r->n_items < 1)
00980 description->is_active = 0;
00981 description->deflt.str =
00982 stp_string_list_param(description->bounds.str, 0)->name;
00983 }
00984 else if (strcmp(name, "InkType") == 0)
00985 {
00986 description->bounds.str = stp_string_list_create();
00987 for (i = 0; i < caps->inks->n_items; i++)
00988 stp_string_list_add_string(description->bounds.str,
00989 caps->inks->item[i].name, caps->inks->item[i].name);
00990 description->deflt.str =
00991 stp_string_list_param(description->bounds.str, 0)->name;
00992 if (caps->inks->n_items < 2)
00993 description->is_active = 0;
00994 }
00995 else if (strcmp(name, "Laminate") == 0)
00996 {
00997 description->bounds.str = stp_string_list_create();
00998 if (caps->laminate)
00999 {
01000 const laminate_list_t *llist = caps->laminate;
01001
01002 for (i = 0; i < llist->n_items; i++)
01003 {
01004 const laminate_t *l = &(llist->item[i]);
01005 stp_string_list_add_string(description->bounds.str,
01006 l->name, l->text);
01007 }
01008 description->deflt.str =
01009 stp_string_list_param(description->bounds.str, 0)->name;
01010 description->is_active = 1;
01011 }
01012 }
01013 else if (strcmp(name, "Borderless") == 0)
01014 {
01015 if (olympus_feature(caps, OLYMPUS_FEATURE_BORDERLESS))
01016 description->is_active = 1;
01017 }
01018 else if (strcmp(name, "PrintingMode") == 0)
01019 {
01020 description->bounds.str = stp_string_list_create();
01021 stp_string_list_add_string
01022 (description->bounds.str, "Color", _("Color"));
01023 description->deflt.str =
01024 stp_string_list_param(description->bounds.str, 0)->name;
01025 }
01026 else
01027 description->is_active = 0;
01028 }
01029
01030
01031 static void
01032 olympus_imageable_area(const stp_vars_t *v,
01033 int *left,
01034 int *right,
01035 int *bottom,
01036 int *top)
01037 {
01038 int width, height;
01039 int i;
01040 const char *page = stp_get_string_parameter(v, "PageSize");
01041 const stp_papersize_t *pt = stp_get_papersize_by_name(page);
01042 const olympus_cap_t *caps = olympus_get_model_capabilities(
01043 stp_get_model_id(v));
01044 const olymp_pagesize_list_t *p = caps->pages;
01045
01046 for (i = 0; i < p->n_items; i++)
01047 {
01048 if (strcmp(p->item[i].name,pt->name) == 0)
01049 {
01050
01051
01052
01053
01054
01055
01056
01057 stp_default_media_size(v, &width, &height);
01058
01059
01060 if (olympus_feature(caps, OLYMPUS_FEATURE_BORDERLESS)
01061 && stp_get_boolean_parameter(v, "Borderless"))
01062 {
01063 *left = 0;
01064 *top = 0;
01065 *right = width;
01066 *bottom = height;
01067 }
01068 else
01069 {
01070 *left = p->item[i].border_pt_left;
01071 *top = p->item[i].border_pt_top;
01072 *right = width - p->item[i].border_pt_right;
01073 *bottom = height - p->item[i].border_pt_bottom;
01074 }
01075 break;
01076 }
01077 }
01078 }
01079
01080 static void
01081 olympus_limit(const stp_vars_t *v,
01082 int *width, int *height,
01083 int *min_width, int *min_height)
01084 {
01085 *width = 65535;
01086 *height = 65535;
01087 *min_width = 1;
01088 *min_height = 1;
01089 }
01090
01091 static void
01092 olympus_describe_resolution(const stp_vars_t *v, int *x, int *y)
01093 {
01094 const char *resolution = stp_get_string_parameter(v, "Resolution");
01095 int i;
01096
01097 *x = -1;
01098 *y = -1;
01099 if (resolution)
01100 {
01101 for (i = 0; i < all_res_list.n_items; i++)
01102 {
01103 if (strcmp(resolution, all_res_list.item[i].name) == 0)
01104 {
01105 *x = all_res_list.item[i].xdpi;
01106 *y = all_res_list.item[i].ydpi;
01107 }
01108 }
01109 }
01110 return;
01111 }
01112
01113 static const char *
01114 olympus_describe_output(const stp_vars_t *v)
01115 {
01116 return "CMY";
01117 }
01118
01119
01120
01121
01122 static int
01123 olympus_do_print(stp_vars_t *v, stp_image_t *image)
01124 {
01125 int i, j;
01126 int y, min_y, max_y;
01127 int min_x, max_x;
01128 int out_channels, out_bytes;
01129 unsigned short *final_out = NULL;
01130 unsigned char *char_out = NULL;
01131 unsigned short *real_out = NULL;
01132 unsigned short *err_out = NULL;
01133 int char_out_width;
01134 int status = 1;
01135 int ink_channels = 1;
01136 stp_curve_t *adjustment = NULL;
01137
01138 int r_errdiv, r_errmod;
01139 int r_errval = 0;
01140 int r_errlast = -1;
01141 int r_errline = 0;
01142 int c_errdiv, c_errmod;
01143 int c_errval = 0;
01144 int c_errlast = -1;
01145 int c_errcol = 0;
01146
01147 const int model = stp_get_model_id(v);
01148 const char *ink_type = stp_get_string_parameter(v, "InkType");
01149 const olympus_cap_t *caps = olympus_get_model_capabilities(model);
01150 int max_print_px_width, max_print_px_height;
01151 int xdpi, ydpi;
01152
01153
01154 unsigned short image_px_width = stp_image_width(image);
01155 unsigned short image_px_height = stp_image_height(image);
01156
01157
01158 int out_pt_width = stp_get_width(v);
01159 int out_pt_height = stp_get_height(v);
01160 int out_pt_left = stp_get_left(v);
01161 int out_pt_top = stp_get_top(v);
01162
01163
01164 int out_px_width, out_px_height;
01165 int out_px_left, out_px_right, out_px_top, out_px_bottom;
01166
01167
01168 #if 0
01169 int page_pt_width = stp_get_page_width(v);
01170 int page_pt_height = stp_get_page_height(v);
01171 #endif
01172 int page_pt_left = 0;
01173 int page_pt_right = 0;
01174 int page_pt_top = 0;
01175 int page_pt_bottom = 0;
01176
01177
01178 int print_px_width;
01179 int print_px_height;
01180
01181 const char *l;
01182 unsigned char *zeros = NULL;
01183
01184 if (!stp_verify(v))
01185 {
01186 stp_eprintf(v, _("Print options not verified; cannot print.\n"));
01187 return 0;
01188 }
01189
01190 stp_describe_resolution(v, &xdpi, &ydpi);
01191 olympus_printsize(v, &max_print_px_width, &max_print_px_height);
01192
01193 if (olympus_feature(caps, OLYMPUS_FEATURE_WHITE_BORDER))
01194 stp_default_media_size(v, &page_pt_right, &page_pt_bottom);
01195 else
01196 olympus_imageable_area(v, &page_pt_left, &page_pt_right,
01197 &page_pt_bottom, &page_pt_top);
01198
01199 print_px_width = MIN(max_print_px_width,
01200 (page_pt_right - page_pt_left) * xdpi / 72);
01201 print_px_height = MIN(max_print_px_height,
01202 (page_pt_bottom - page_pt_top) * ydpi / 72);
01203 out_px_width = out_pt_width * xdpi / 72;
01204 out_px_height = out_pt_height * ydpi / 72;
01205
01206
01207
01208 if (out_px_width - image_px_width > -5
01209 && out_px_width - image_px_width < 5
01210 && out_px_height - image_px_height > -5
01211 && out_px_height - image_px_height < 5)
01212 {
01213 out_px_width = image_px_width;
01214 out_px_height = image_px_height;
01215 }
01216
01217 out_px_width = MIN(out_px_width, print_px_width);
01218 out_px_height = MIN(out_px_height, print_px_height);
01219 out_px_left = MIN(((out_pt_left - page_pt_left) * xdpi / 72),
01220 print_px_width - out_px_width);
01221 out_px_top = MIN(((out_pt_top - page_pt_top) * ydpi / 72),
01222 print_px_height - out_px_height);
01223 out_px_right = out_px_left + out_px_width;
01224 out_px_bottom = out_px_top + out_px_height;
01225
01226 #if 0
01227 stp_eprintf(v, "paper (pt) %d x %d\n"
01228 "image (px) %d x %d\n"
01229 "image (pt) %d x %d\n"
01230 "* out (pt) %d x %d\n"
01231 "* out (px) %d x %d\n"
01232 "* left x top (pt) %d x %d\n"
01233 "* left x top (px) %d x %d\n"
01234 "border (pt) (%d - %d) = %d x (%d - %d) = %d\n"
01235 "printable pixels (px) %d x %d\n"
01236 "res (dpi) %d x %d\n",
01237 page_pt_width, page_pt_height,
01238 image_px_width, image_px_height,
01239 image_px_width * 72 / xdpi, image_px_height * 72 / ydpi,
01240 out_pt_width, out_pt_height,
01241 out_px_width, out_px_height,
01242 out_pt_left, out_pt_top,
01243 out_px_left, out_px_top,
01244 page_pt_right, page_pt_left, page_pt_right - page_pt_left,
01245 page_pt_bottom, page_pt_top, page_pt_bottom - page_pt_top,
01246 print_px_width, print_px_height,
01247 xdpi, ydpi
01248 );
01249 #endif
01250 privdata.xdpi = xdpi;
01251 privdata.ydpi = ydpi;
01252 privdata.xsize = print_px_width;
01253 privdata.ysize = print_px_height;
01254
01255 stp_set_string_parameter(v, "STPIOutputType", "CMY");
01256
01257 if (caps->adj_cyan &&
01258 !stp_check_curve_parameter(v, "CyanCurve", STP_PARAMETER_ACTIVE))
01259 {
01260 adjustment = stp_curve_create_from_string(caps->adj_cyan);
01261 stp_set_curve_parameter(v, "CyanCurve", adjustment);
01262 stp_set_curve_parameter_active(v, "CyanCurve", STP_PARAMETER_ACTIVE);
01263 stp_curve_destroy(adjustment);
01264 }
01265 if (caps->adj_magenta &&
01266 !stp_check_curve_parameter(v, "MagentaCurve", STP_PARAMETER_ACTIVE))
01267 {
01268 adjustment = stp_curve_create_from_string(caps->adj_magenta);
01269 stp_set_curve_parameter(v, "MagentaCurve", adjustment);
01270 stp_set_curve_parameter_active(v, "MagentaCurve", STP_PARAMETER_ACTIVE);
01271 stp_curve_destroy(adjustment);
01272 }
01273 if (caps->adj_yellow &&
01274 !stp_check_curve_parameter(v, "YellowCurve", STP_PARAMETER_ACTIVE))
01275 {
01276 adjustment = stp_curve_create_from_string(caps->adj_yellow);
01277 stp_set_curve_parameter(v, "YellowCurve", adjustment);
01278 stp_set_curve_parameter_active(v, "YellowCurve", STP_PARAMETER_ACTIVE);
01279 stp_curve_destroy(adjustment);
01280 }
01281
01282 if (ink_type)
01283 {
01284 for (i = 0; i < caps->inks->n_items; i++)
01285 if (strcmp(ink_type, caps->inks->item[i].name) == 0)
01286 {
01287 stp_set_string_parameter(v, "STPIOutputType",
01288 caps->inks->item[i].output_type);
01289 ink_channels = caps->inks->item[i].output_channels;
01290 break;
01291 }
01292 }
01293
01294 stp_channel_reset(v);
01295 for (i = 0; i < ink_channels; i++)
01296 stp_channel_add(v, i, 0, 1.0);
01297
01298 out_channels = stp_color_init(v, image, 65536);
01299
01300 #if 0
01301 if (out_channels != ink_channels && out_channels != 1 && ink_channels != 1)
01302 {
01303 stp_eprintf(v, "Internal error! Output channels or input channels must be 1\n");
01304 return 0;
01305 }
01306 #endif
01307
01308 err_out = stp_malloc(print_px_width * ink_channels * 2);
01309 if (out_channels != ink_channels)
01310 final_out = stp_malloc(print_px_width * ink_channels * 2);
01311
01312 stp_set_float_parameter(v, "Density", 1.0);
01313
01314 if (ink_type && strcmp(ink_type, "RGB") == 0)
01315 {
01316 zeros = stp_malloc(ink_channels * print_px_width + 1);
01317 (void) memset(zeros, '\xff', ink_channels * print_px_width + 1);
01318 }
01319 else
01320 zeros = stp_zalloc(ink_channels * print_px_width + 1);
01321
01322 out_bytes = (caps->interlacing == OLYMPUS_INTERLACE_PLANE ? 1 : ink_channels);
01323
01324
01325 if (caps->printer_init_func)
01326 {
01327 stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->printer_init\n");
01328 (*(caps->printer_init_func))(v);
01329 }
01330
01331 if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_HEIGHT))
01332 {
01333 min_y = 0;
01334 max_y = print_px_height - 1;
01335 }
01336 else if (olympus_feature(caps, OLYMPUS_FEATURE_BLOCK_ALIGN))
01337 {
01338 min_y = out_px_top - (out_px_top % caps->block_size);
01339
01340 max_y = (out_px_bottom - 1) + (caps->block_size - 1)
01341 - ((out_px_bottom - 1) % caps->block_size);
01342
01343 }
01344 else
01345 {
01346 min_y = out_px_top;
01347 max_y = out_px_bottom - 1;
01348 }
01349
01350 if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH))
01351 {
01352 min_x = 0;
01353 max_x = print_px_width - 1;
01354 }
01355 else
01356 {
01357 min_x = out_px_left;
01358 max_x = out_px_right;
01359 }
01360
01361 r_errdiv = image_px_height / out_px_height;
01362 r_errmod = image_px_height % out_px_height;
01363 c_errdiv = image_px_width / out_px_width;
01364 c_errmod = image_px_width % out_px_width;
01365
01366 l = caps->planes;
01367 while (*l)
01368 {
01369 r_errval = 0;
01370 r_errlast = -1;
01371 r_errline = 0;
01372
01373 privdata.plane = *l;
01374
01375
01376 if (caps->plane_init_func)
01377 {
01378 stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->plane_init\n");
01379 (*(caps->plane_init_func))(v);
01380 }
01381
01382 for (y = min_y; y <= max_y; y++)
01383 {
01384 unsigned short *out;
01385 int duplicate_line = 1;
01386 unsigned zero_mask;
01387
01388 if (((y - min_y) % caps->block_size) == 0)
01389 {
01390
01391 privdata.block_min_y = y;
01392 privdata.block_min_x = min_x;
01393 privdata.block_max_y = MIN(y + caps->block_size - 1, max_y);
01394 privdata.block_max_x = max_x;
01395
01396 if (caps->block_init_func)
01397 {
01398 stp_deprintf(STP_DBG_OLYMPUS,
01399 "olympus: caps->block_init\n");
01400 (*(caps->block_init_func))(v);
01401 }
01402 }
01403
01404 if (y < out_px_top || y >= out_px_bottom)
01405 stp_zfwrite((char *) zeros, out_bytes, print_px_width, v);
01406 else
01407 {
01408 if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH)
01409 && out_px_left > 0)
01410 {
01411 stp_zfwrite((char *) zeros, out_bytes, out_px_left, v);
01412
01413 }
01414
01415 if (r_errline != r_errlast)
01416 {
01417 r_errlast = r_errline;
01418 duplicate_line = 0;
01419
01420
01421 if (stp_color_get_row(v, image, r_errline, &zero_mask))
01422 {
01423 status = 2;
01424 break;
01425 }
01426 }
01427
01428 out = stp_channel_get_output(v);
01429
01430 c_errval = 0;
01431 c_errlast = -1;
01432 c_errcol = 0;
01433 for (i = 0; i < out_px_width; i++)
01434 {
01435 if (c_errcol != c_errlast)
01436 c_errlast = c_errcol;
01437 for (j = 0; j < ink_channels; j++)
01438 err_out[i * ink_channels + j] =
01439 out[c_errcol * ink_channels + j];
01440
01441 c_errval += c_errmod;
01442 c_errcol += c_errdiv;
01443 if (c_errval >= out_px_width)
01444 {
01445 c_errval -= out_px_width;
01446 c_errcol ++;
01447 }
01448 }
01449
01450 real_out = err_out;
01451 if (out_channels != ink_channels)
01452 {
01453 real_out = final_out;
01454 if (out_channels < ink_channels)
01455 {
01456 for (i = 0; i < out_px_width; i++)
01457 {
01458 for (j = 0; j < ink_channels; j++)
01459 final_out[i * ink_channels + j] = err_out[i];
01460 }
01461 }
01462 else
01463 {
01464 for (i = 0; i < out_px_width; i++)
01465 {
01466 int avg = 0;
01467 for (j = 0; j < out_channels; j++)
01468 avg += err_out[i * out_channels + j];
01469 final_out[i] = avg / out_channels;
01470 }
01471 }
01472 }
01473 char_out = (unsigned char *) real_out;
01474 char_out_width = (caps->interlacing == OLYMPUS_INTERLACE_PLANE ?
01475 out_px_width : out_px_width * out_channels);
01476 for (i = 0; i < char_out_width; i++)
01477 {
01478 if (caps->interlacing == OLYMPUS_INTERLACE_PLANE)
01479 j = i * ink_channels + (caps->planes - l + 2);
01480 else if (caps->interlacing == OLYMPUS_INTERLACE_LINE)
01481 j = (i % out_px_width) + (i / out_px_width);
01482 else
01483 j = i;
01484
01485 char_out[i] = real_out[j] / 257;
01486 }
01487
01488 stp_zfwrite((char *) real_out, 1, char_out_width, v);
01489
01490 if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH)
01491 && out_px_right < print_px_width)
01492 {
01493 stp_zfwrite((char *) zeros, out_bytes,
01494 print_px_width - out_px_right, v);
01495
01496 }
01497
01498
01499 r_errval += r_errmod;
01500 r_errline += r_errdiv;
01501 if (r_errval >= out_px_height)
01502 {
01503 r_errval -= out_px_height;
01504 r_errline ++;
01505 }
01506 }
01507
01508 if (y == privdata.block_max_y)
01509 {
01510
01511 if (caps->block_end_func)
01512 {
01513 stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->block_end\n");
01514 (*(caps->block_end_func))(v);
01515 }
01516 }
01517 }
01518
01519
01520 if (caps->plane_end_func) {
01521 stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->plane_end\n");
01522 (*(caps->plane_end_func))(v);
01523 }
01524
01525 if (caps->interlacing != OLYMPUS_INTERLACE_PLANE)
01526 break;
01527
01528 l++;
01529 }
01530
01531
01532 if (caps->printer_end_func)
01533 {
01534 stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->printer_end\n");
01535 (*(caps->printer_end_func))(v);
01536 }
01537 stp_image_conclude(image);
01538 if (final_out)
01539 stp_free(final_out);
01540 if (err_out)
01541 stp_free(err_out);
01542 if (zeros)
01543 stp_free(zeros);
01544 return status;
01545 }
01546
01547 static int
01548 olympus_print(const stp_vars_t *v, stp_image_t *image)
01549 {
01550 int status;
01551 stp_vars_t *nv = stp_vars_create_copy(v);
01552 stp_prune_inactive_options(nv);
01553 status = olympus_do_print(nv, image);
01554 stp_vars_destroy(nv);
01555 return status;
01556 }
01557
01558 static const stp_printfuncs_t print_olympus_printfuncs =
01559 {
01560 olympus_list_parameters,
01561 olympus_parameters,
01562 stp_default_media_size,
01563 olympus_imageable_area,
01564 olympus_limit,
01565 olympus_print,
01566 olympus_describe_resolution,
01567 olympus_describe_output,
01568 stp_verify_printer_params,
01569 NULL,
01570 NULL
01571 };
01572
01573
01574
01575
01576 static stp_family_t print_olympus_module_data =
01577 {
01578 &print_olympus_printfuncs,
01579 NULL
01580 };
01581
01582
01583 static int
01584 print_olympus_module_init(void)
01585 {
01586 return stp_family_register(print_olympus_module_data.printer_list);
01587 }
01588
01589
01590 static int
01591 print_olympus_module_exit(void)
01592 {
01593 return stp_family_unregister(print_olympus_module_data.printer_list);
01594 }
01595
01596
01597
01598 #define stp_module_version print_olympus_LTX_stp_module_version
01599 #define stp_module_data print_olympus_LTX_stp_module_data
01600
01601 stp_module_version_t stp_module_version = {0, 0};
01602
01603 stp_module_t stp_module_data =
01604 {
01605 "olympus",
01606 VERSION,
01607 "Olympus family driver",
01608 STP_MODULE_CLASS_FAMILY,
01609 NULL,
01610 print_olympus_module_init,
01611 print_olympus_module_exit,
01612 (void *) &print_olympus_module_data
01613 };
01614