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