libgimpprint API Reference: src/main/print-olympus.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/print-olympus.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: print-olympus_8c-source.html,v 1.1.1.2 2004/12/22 23:49:08 jlovell Exp $"
    00003  *
    00004  *   Print plug-in Olympus driver for the GIMP.
    00005  *
    00006  *   Copyright 2003 Michael Mraka (Michael.Mraka@linux.cz)
    00007  *
    00008  *   The plug-in is based on the code of the RAW plugin for the GIMP of
    00009  *   Michael Sweet (mike@easysw.com) and Robert Krawitz (rlk@alum.mit.edu)
    00010  *
    00011  *   This program is free software; you can redistribute it and/or modify it
    00012  *   under the terms of the GNU General Public License as published by the Free
    00013  *   Software Foundation; either version 2 of the License, or (at your option)
    00014  *   any later version.
    00015  *
    00016  *   This program is distributed in the hope that it will be useful, but
    00017  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00018  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00019  *   for more details.
    00020  *
    00021  *   You should have received a copy of the GNU General Public License
    00022  *   along with this program; if not, write to the Free Software
    00023  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00024  */
    00025
    00026 /*
    00027  * This file must include only standard C header files.  The core code must
    00028  * compile on generic platforms that don't support glib, gimp, gtk, etc.
    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_NONE            0x00000000
    00049 #define OLYMPUS_FEATURE_FULL_WIDTH      0x00000001
    00050 #define OLYMPUS_FEATURE_FULL_HEIGHT     0x00000002
    00051 #define OLYMPUS_FEATURE_BLOCK_ALIGN     0x00000004
    00052 #define OLYMPUS_FEATURE_BORDERLESS      0x00000008
    00053 #define OLYMPUS_FEATURE_WHITE_BORDER    0x00000010
    00054
    00055 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
    00056 #define MAX(a,b)        (((a) > (b)) ? (a) : (b))
    00057
    00058 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";
    00059
    00060 typedef struct
    00061 {
    00062   const char *output_type;
    00063   int output_channels;
    00064   const char *name;
    00065   const char *channel_order;
    00066 } ink_t;
    00067
    00068 typedef struct {
    00069   const ink_t *item;
    00070   size_t n_items;
    00071 } ink_list_t;
    00072
    00073 typedef struct {
    00074   const char* name;
    00075   int xdpi;
    00076   int ydpi;
    00077 } olymp_resolution_t;
    00078
    00079 typedef struct {
    00080   const olymp_resolution_t *item;
    00081   size_t n_items;
    00082 } olymp_resolution_list_t;
    00083
    00084 typedef struct {
    00085   const char* name;
    00086   const char* text;
    00087   int width_pt;
    00088   int height_pt;
    00089   int border_pt_left;
    00090   int border_pt_right;
    00091   int border_pt_top;
    00092   int border_pt_bottom;
    00093 } olymp_pagesize_t;
    00094
    00095 typedef struct {
    00096   const olymp_pagesize_t *item;
    00097   size_t n_items;
    00098 } olymp_pagesize_list_t;
    00099
    00100 typedef struct {
    00101   const char* res_name;
    00102   const char* pagesize_name;
    00103   int width_px;
    00104   int height_px;
    00105 } olymp_printsize_t;
    00106
    00107 typedef struct {
    00108   const olymp_printsize_t *item;
    00109   size_t n_items;
    00110 } olymp_printsize_list_t;
    00111
    00112
    00113 typedef struct {
    00114   const char *name;
    00115   const char *text;
    00116   const stp_raw_t seq;
    00117 } laminate_t;
    00118
    00119 typedef struct {
    00120   const laminate_t *item;
    00121   size_t n_items;
    00122 } laminate_list_t;
    00123
    00124 typedef struct
    00125 {
    00126   int xdpi, ydpi;
    00127   int xsize, ysize;
    00128   char plane;
    00129   int block_min_x, block_min_y;
    00130   int block_max_x, block_max_y;
    00131   const char* pagesize;
    00132   const laminate_t* laminate;
    00133 } olympus_privdata_t;
    00134
    00135 static olympus_privdata_t privdata;
    00136
    00137 typedef struct /* printer specific parameters */
    00138 {
    00139   int model;            /* printer model number from printers.xml*/
    00140   const ink_list_t *inks;
    00141   const olymp_resolution_list_t *resolution;
    00142   const olymp_pagesize_list_t *pages;
    00143   const olymp_printsize_list_t *printsize;
    00144   int interlacing;      /* color interlacing scheme */
    00145   int block_size;
    00146   int features;
    00147   void (*printer_init_func)(stp_vars_t *);
    00148   void (*printer_end_func)(stp_vars_t *);
    00149   void (*plane_init_func)(stp_vars_t *);
    00150   void (*plane_end_func)(stp_vars_t *);
    00151   void (*block_init_func)(stp_vars_t *);
    00152   void (*block_end_func)(stp_vars_t *);
    00153   const char *adj_cyan;         /* default color adjustment */
    00154   const char *adj_magenta;
    00155   const char *adj_yellow;
    00156   const laminate_list_t *laminate;
    00157 } olympus_cap_t;
    00158
    00159
    00160 static const olympus_cap_t* olympus_get_model_capabilities(int model);
    00161 static const laminate_t* olympus_get_laminate_pattern(stp_vars_t *v);
    00162
    00163
    00164 static const ink_t cmy_inks[] =
    00165 {
    00166   { "CMY", 3, "CMY", "\1\2\3" },
    00167 };
    00168
    00169 static const ink_list_t cmy_ink_list =
    00170 {
    00171   cmy_inks, sizeof(cmy_inks) / sizeof(ink_t)
    00172 };
    00173
    00174 static const ink_t ymc_inks[] =
    00175 {
    00176   { "CMY", 3, "CMY", "\3\2\1" },
    00177 };
    00178
    00179 static const ink_list_t ymc_ink_list =
    00180 {
    00181   ymc_inks, sizeof(ymc_inks) / sizeof(ink_t)
    00182 };
    00183
    00184 static const ink_t rgb_inks[] =
    00185 {
    00186   { "RGB", 3, "RGB", "\1\2\3" },
    00187 };
    00188
    00189 static const ink_list_t rgb_ink_list =
    00190 {
    00191   rgb_inks, sizeof(rgb_inks) / sizeof(ink_t)
    00192 };
    00193
    00194 static const ink_t bgr_inks[] =
    00195 {
    00196   { "RGB", 3, "RGB", "\3\2\1" },
    00197 };
    00198
    00199 static const ink_list_t bgr_ink_list =
    00200 {
    00201   bgr_inks, sizeof(bgr_inks) / sizeof(ink_t)
    00202 };
    00203
    00204
    00205 /* Olympus P-10 */
    00206 static const olymp_resolution_t res_320dpi[] =
    00207 {
    00208   { "320x320", 320, 320},
    00209 };
    00210
    00211 static const olymp_resolution_list_t res_320dpi_list =
    00212 {
    00213   res_320dpi, sizeof(res_320dpi) / sizeof(olymp_resolution_t)
    00214 };
    00215
    00216 static const olymp_pagesize_t p10_page[] =
    00217 {
    00218   { "w288h432", "4 x 6", -1, -1, 0, 0, 16, 0},  /* 4x6" */
    00219   { "B7", "3.5 x 5", -1, -1, 0, 0, 4, 0},       /* 3.5x5" */
    00220   { "Custom", NULL, -1, -1, 28, 28, 48, 48},
    00221 };
    00222
    00223 static const olymp_pagesize_list_t p10_page_list =
    00224 {
    00225   p10_page, sizeof(p10_page) / sizeof(olymp_pagesize_t)
    00226 };
    00227
    00228 static const olymp_printsize_t p10_printsize[] =
    00229 {
    00230   { "320x320", "w288h432", 1280, 1848},
    00231   { "320x320", "B7",  1144,  1591},
    00232   { "320x320", "Custom", 1280, 1848},
    00233 };
    00234
    00235 static const olymp_printsize_list_t p10_printsize_list =
    00236 {
    00237   p10_printsize, sizeof(p10_printsize) / sizeof(olymp_printsize_t)
    00238 };
    00239
    00240 static void p10_printer_init_func(stp_vars_t *v)
    00241 {
    00242   stp_zfwrite("\033R\033M\033S\2\033N\1\033D\1\033Y", 1, 15, v);
    00243   stp_zfwrite((privdata.laminate->seq).data, 1,
    00244                   (privdata.laminate->seq).bytes, v); /* laminate */
    00245   stp_zfwrite("\033Z\0", 1, 3, v);
    00246 }
    00247
    00248 static void p10_printer_end_func(stp_vars_t *v)
    00249 {
    00250   stp_zfwrite("\033P", 1, 2, v);
    00251 }
    00252
    00253 static void p10_block_init_func(stp_vars_t *v)
    00254 {
    00255   stp_zprintf(v, "\033T%c", privdata.plane);
    00256   stp_put16_le(privdata.block_min_x, v);
    00257   stp_put16_le(privdata.block_min_y, v);
    00258   stp_put16_le(privdata.block_max_x + 1, v);
    00259   stp_put16_le(privdata.block_max_y + 1, v);
    00260 }
    00261
    00262 static const laminate_t p10_laminate[] =
    00263 {
    00264   {"Coated",  N_("Coated"),  {1, "\x00"}},
    00265   {"None",    N_("None"),    {1, "\x02"}},
    00266 };
    00267
    00268 static const laminate_list_t p10_laminate_list =
    00269 {
    00270   p10_laminate, sizeof(p10_laminate) / sizeof(laminate_t)
    00271 };
    00272
    00273
    00274 /* Olympus P-200 series */
    00275 static const olymp_pagesize_t p200_page[] =
    00276 {
    00277   { "ISOB7", "80x125mm", -1, -1, 16, 17, 33, 33},
    00278   { "Custom", NULL, -1, -1, 16, 17, 33, 33},
    00279 };
    00280
    00281 static const olymp_pagesize_list_t p200_page_list =
    00282 {
    00283   p200_page, sizeof(p200_page) / sizeof(olymp_pagesize_t)
    00284 };
    00285
    00286 static const olymp_printsize_t p200_printsize[] =
    00287 {
    00288   { "320x320", "ISOB7", 960, 1280},
    00289   { "320x320", "Custom", 960, 1280},
    00290 };
    00291
    00292 static const olymp_printsize_list_t p200_printsize_list =
    00293 {
    00294   p200_printsize, sizeof(p200_printsize) / sizeof(olymp_printsize_t)
    00295 };
    00296
    00297 static void p200_printer_init_func(stp_vars_t *v)
    00298 {
    00299   stp_zfwrite("S000001\0S010001\1", 1, 16, v);
    00300 }
    00301
    00302 static void p200_plane_init_func(stp_vars_t *v)
    00303 {
    00304   stp_zprintf(v, "P0%d9999", 3 - privdata.plane+1 );
    00305   stp_put32_be(privdata.xsize * privdata.ysize, v);
    00306 }
    00307
    00308 static void p200_printer_end_func(stp_vars_t *v)
    00309 {
    00310   stp_zprintf(v, "P000001\1");
    00311 }
    00312
    00313 static const char p200_adj_any[] =
    00314   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00315   "<gimp-print>\n"
    00316   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00317   "<sequence count=\"33\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00318   "0.000000 0.039216 0.078431 0.117647 0.152941 0.192157 0.231373 0.266667\n"
    00319   "0.301961 0.341176 0.376471 0.411765 0.447059 0.482353 0.513725 0.549020\n"
    00320   "0.580392 0.615686 0.647059 0.678431 0.709804 0.741176 0.768627 0.796078\n"
    00321   "0.827451 0.854902 0.878431 0.905882 0.929412 0.949020 0.972549 0.988235\n"
    00322   "1.000000\n"
    00323   "</sequence>\n"
    00324   "</curve>\n"
    00325   "</gimp-print>\n";
    00326
    00327
    00328 /* Olympus P-300 series */
    00329 static const olymp_resolution_t p300_res[] =
    00330 {
    00331   { "306x306", 306, 306},
    00332   { "153x153", 153, 153},
    00333 };
    00334
    00335 static const olymp_resolution_list_t p300_res_list =
    00336 {
    00337   p300_res, sizeof(p300_res) / sizeof(olymp_resolution_t)
    00338 };
    00339
    00340 static const olymp_pagesize_t p300_page[] =
    00341 {
    00342   { "A6", NULL, -1, -1, 28, 28, 48, 48},
    00343   { "Custom", NULL, -1, -1, 28, 28, 48, 48},
    00344 };
    00345
    00346 static const olymp_pagesize_list_t p300_page_list =
    00347 {
    00348   p300_page, sizeof(p300_page) / sizeof(olymp_pagesize_t)
    00349 };
    00350
    00351 static const olymp_printsize_t p300_printsize[] =
    00352 {
    00353   { "306x306", "A6", 1024, 1376},
    00354   { "153x153", "A6",  512,  688},
    00355   { "306x306", "Custom", 1024, 1376},
    00356   { "153x153", "Custom", 1024, 1376},
    00357 };
    00358
    00359 static const olymp_printsize_list_t p300_printsize_list =
    00360 {
    00361   p300_printsize, sizeof(p300_printsize) / sizeof(olymp_printsize_t)
    00362 };
    00363
    00364 static void p300_printer_init_func(stp_vars_t *v)
    00365 {
    00366   stp_zfwrite("\033\033\033C\033N\1\033F\0\1\033MS\xff\xff\xff"
    00367               "\033Z", 1, 19, v);
    00368   stp_put16_be(privdata.xdpi, v);
    00369   stp_put16_be(privdata.ydpi, v);
    00370 }
    00371
    00372 static void p300_plane_end_func(stp_vars_t *v)
    00373 {
    00374   const char *c = "CMY";
    00375   stp_zprintf(v, "\033\033\033P%cS", c[privdata.plane-1]);
    00376   stp_deprintf(STP_DBG_OLYMPUS, "olympus: p300_plane_end_func: %c\n",
    00377         c[privdata.plane-1]);
    00378 }
    00379
    00380 static void p300_block_init_func(stp_vars_t *v)
    00381 {
    00382   const char *c = "CMY";
    00383   stp_zprintf(v, "\033\033\033W%c", c[privdata.plane-1]);
    00384   stp_put16_be(privdata.block_min_y, v);
    00385   stp_put16_be(privdata.block_min_x, v);
    00386   stp_put16_be(privdata.block_max_y, v);
    00387   stp_put16_be(privdata.block_max_x, v);
    00388
    00389   stp_deprintf(STP_DBG_OLYMPUS, "olympus: p300_block_init_func: %d-%dx%d-%d\n",
    00390         privdata.block_min_x, privdata.block_max_x,
    00391         privdata.block_min_y, privdata.block_max_y);
    00392 }
    00393
    00394 static const char p300_adj_cyan[] =
    00395   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00396   "<gimp-print>\n"
    00397   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00398   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00399   "0.078431 0.211765 0.250980 0.282353 0.309804 0.333333 0.352941 0.368627\n"
    00400   "0.388235 0.403922 0.427451 0.443137 0.458824 0.478431 0.498039 0.513725\n"
    00401   "0.529412 0.545098 0.556863 0.576471 0.592157 0.611765 0.627451 0.647059\n"
    00402   "0.666667 0.682353 0.701961 0.713725 0.725490 0.729412 0.733333 0.737255\n"
    00403   "</sequence>\n"
    00404   "</curve>\n"
    00405   "</gimp-print>\n";
    00406
    00407 static const char p300_adj_magenta[] =
    00408   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00409   "<gimp-print>\n"
    00410   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00411   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00412   "0.047059 0.211765 0.250980 0.278431 0.305882 0.333333 0.349020 0.364706\n"
    00413   "0.380392 0.396078 0.415686 0.435294 0.450980 0.466667 0.482353 0.498039\n"
    00414   "0.513725 0.525490 0.541176 0.556863 0.572549 0.592157 0.611765 0.631373\n"
    00415   "0.650980 0.670588 0.694118 0.705882 0.721569 0.741176 0.745098 0.756863\n"
    00416   "</sequence>\n"
    00417   "</curve>\n"
    00418   "</gimp-print>\n";
    00419
    00420 static const char p300_adj_yellow[] =
    00421   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00422   "<gimp-print>\n"
    00423   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00424   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00425   "0.047059 0.117647 0.203922 0.250980 0.274510 0.301961 0.321569 0.337255\n"
    00426   "0.352941 0.364706 0.380392 0.396078 0.407843 0.423529 0.439216 0.450980\n"
    00427   "0.466667 0.482353 0.498039 0.513725 0.533333 0.552941 0.572549 0.596078\n"
    00428   "0.615686 0.635294 0.650980 0.666667 0.682353 0.690196 0.701961 0.713725\n"
    00429   "</sequence>\n"
    00430   "</curve>\n"
    00431   "</gimp-print>\n";
    00432
    00433
    00434 /* Olympus P-400 series */
    00435 static const olymp_resolution_t res_314dpi[] =
    00436 {
    00437   { "314x314", 314, 314},
    00438 };
    00439
    00440 static const olymp_resolution_list_t res_314dpi_list =
    00441 {
    00442   res_314dpi, sizeof(res_314dpi) / sizeof(olymp_resolution_t)
    00443 };
    00444
    00445 static const olymp_pagesize_t p400_page[] =
    00446 {
    00447   { "A4", NULL, -1, -1, 22, 22, 54, 54},
    00448   { "c8x10", "A5 wide", -1, -1, 58, 59, 84, 85},
    00449   { "C6", "2 Postcards (A4)", -1, -1, 9, 9, 9, 9},
    00450   { "Custom", NULL, -1, -1, 22, 22, 54, 54},
    00451 };
    00452
    00453 static const olymp_pagesize_list_t p400_page_list =
    00454 {
    00455   p400_page, sizeof(p400_page) / sizeof(olymp_pagesize_t)
    00456 };
    00457
    00458 static const olymp_printsize_t p400_printsize[] =
    00459 {
    00460   { "314x314", "A4", 2400, 3200},
    00461   { "314x314", "c8x10", 2000, 2400},
    00462   { "314x314", "C6", 1328, 1920},
    00463   { "314x314", "Custom", 2400, 3200},
    00464 };
    00465
    00466 static const olymp_printsize_list_t p400_printsize_list =
    00467 {
    00468   p400_printsize, sizeof(p400_printsize) / sizeof(olymp_printsize_t)
    00469 };
    00470
    00471 static void p400_printer_init_func(stp_vars_t *v)
    00472 {
    00473   int wide = (strcmp(privdata.pagesize, "c8x10") == 0
    00474                   || strcmp(privdata.pagesize, "C6") == 0);
    00475
    00476   stp_zprintf(v, "\033ZQ"); stp_zfwrite(zero, 1, 61, v);
    00477   stp_zprintf(v, "\033FP"); stp_zfwrite(zero, 1, 61, v);
    00478   stp_zprintf(v, "\033ZF");
    00479   stp_putc((wide ? '\x40' : '\x00'), v); stp_zfwrite(zero, 1, 60, v);
    00480   stp_zprintf(v, "\033ZS");
    00481   if (wide)
    00482     {
    00483       stp_put16_be(privdata.ysize, v);
    00484       stp_put16_be(privdata.xsize, v);
    00485     }
    00486   else
    00487     {
    00488       stp_put16_be(privdata.xsize, v);
    00489       stp_put16_be(privdata.ysize, v);
    00490     }
    00491   stp_zfwrite(zero, 1, 57, v);
    00492   stp_zprintf(v, "\033ZP"); stp_zfwrite(zero, 1, 61, v);
    00493 }
    00494
    00495 static void p400_plane_init_func(stp_vars_t *v)
    00496 {
    00497   stp_zprintf(v, "\033ZC"); stp_zfwrite(zero, 1, 61, v);
    00498 }
    00499
    00500 static void p400_plane_end_func(stp_vars_t *v)
    00501 {
    00502   stp_zprintf(v, "\033P"); stp_zfwrite(zero, 1, 62, v);
    00503 }
    00504
    00505 static void p400_block_init_func(stp_vars_t *v)
    00506 {
    00507   int wide = (strcmp(privdata.pagesize, "c8x10") == 0
    00508                   || strcmp(privdata.pagesize, "C6") == 0);
    00509
    00510   stp_zprintf(v, "\033Z%c", '3' - privdata.plane + 1);
    00511   if (wide)
    00512     {
    00513       stp_put16_be(privdata.ysize - privdata.block_max_y - 1, v);
    00514       stp_put16_be(privdata.xsize - privdata.block_max_x - 1, v);
    00515       stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
    00516       stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
    00517     }
    00518   else
    00519     {
    00520       stp_put16_be(privdata.block_min_x, v);
    00521       stp_put16_be(privdata.block_min_y, v);
    00522       stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
    00523       stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
    00524     }
    00525   stp_zfwrite(zero, 1, 53, v);
    00526 }
    00527
    00528 static const char p400_adj_cyan[] =
    00529   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00530   "<gimp-print>\n"
    00531   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00532   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00533   "0.003922 0.031373 0.058824 0.090196 0.125490 0.156863 0.184314 0.219608\n"
    00534   "0.250980 0.278431 0.309804 0.341176 0.376471 0.403922 0.439216 0.470588\n"
    00535   "0.498039 0.517647 0.533333 0.545098 0.564706 0.576471 0.596078 0.615686\n"
    00536   "0.627451 0.647059 0.658824 0.678431 0.690196 0.705882 0.721569 0.737255\n"
    00537   "</sequence>\n"
    00538   "</curve>\n"
    00539   "</gimp-print>\n";
    00540
    00541 static const char p400_adj_magenta[] =
    00542   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00543   "<gimp-print>\n"
    00544   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00545   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00546   "0.003922 0.031373 0.062745 0.098039 0.125490 0.156863 0.188235 0.215686\n"
    00547   "0.250980 0.282353 0.309804 0.345098 0.376471 0.407843 0.439216 0.470588\n"
    00548   "0.501961 0.521569 0.549020 0.572549 0.592157 0.619608 0.643137 0.662745\n"
    00549   "0.682353 0.713725 0.737255 0.756863 0.784314 0.807843 0.827451 0.850980\n"
    00550   "</sequence>\n"
    00551   "</curve>\n"
    00552   "</gimp-print>\n";
    00553
    00554 static const char p400_adj_yellow[] =
    00555   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00556   "<gimp-print>\n"
    00557   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00558   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00559   "0.003922 0.027451 0.054902 0.090196 0.121569 0.156863 0.184314 0.215686\n"
    00560   "0.250980 0.282353 0.309804 0.345098 0.372549 0.400000 0.435294 0.466667\n"
    00561   "0.498039 0.525490 0.552941 0.580392 0.607843 0.631373 0.658824 0.678431\n"
    00562   "0.698039 0.725490 0.760784 0.784314 0.811765 0.839216 0.866667 0.890196\n"
    00563   "</sequence>\n"
    00564   "</curve>\n"
    00565   "</gimp-print>\n";
    00566
    00567
    00568 /* Olympus P-440 series */
    00569 static const olymp_pagesize_t p440_page[] =
    00570 {
    00571   { "A4", NULL, -1, -1, 10, 9, 54, 54},
    00572   { "c8x10", "A5 wide", -1, -1, 58, 59, 72, 72},
    00573   { "C6", "2 Postcards (A4)", -1, -1, 9, 9, 9, 9},
    00574   { "w255h581", "A6 wide", -1, -1, 25, 25, 25, 24},
    00575   { "Custom", NULL, -1, -1, 22, 22, 54, 54},
    00576 };
    00577
    00578 static const olymp_pagesize_list_t p440_page_list =
    00579 {
    00580   p440_page, sizeof(p440_page) / sizeof(olymp_pagesize_t)
    00581 };
    00582
    00583 static const olymp_printsize_t p440_printsize[] =
    00584 {
    00585   { "314x314", "A4", 2508, 3200},
    00586   { "314x314", "c8x10", 2000, 2508},
    00587   { "314x314", "C6", 1328, 1920},
    00588   { "314x314", "w255h581", 892, 2320},
    00589   { "314x314", "Custom", 2508, 3200},
    00590 };
    00591
    00592 static const olymp_printsize_list_t p440_printsize_list =
    00593 {
    00594   p440_printsize, sizeof(p440_printsize) / sizeof(olymp_printsize_t)
    00595 };
    00596
    00597 static void p440_printer_init_func(stp_vars_t *v)
    00598 {
    00599   int wide = ! (strcmp(privdata.pagesize, "A4") == 0
    00600                   || strcmp(privdata.pagesize, "Custom") == 0);
    00601
    00602   stp_zprintf(v, "\033FP"); stp_zfwrite(zero, 1, 61, v);
    00603   stp_zprintf(v, "\033Y");
    00604   stp_zfwrite((privdata.laminate->seq).data, 1,
    00605                   (privdata.laminate->seq).bytes, v); /* laminate */
    00606   stp_zfwrite(zero, 1, 61, v);
    00607   stp_zprintf(v, "\033FC"); stp_zfwrite(zero, 1, 61, v);
    00608   stp_zprintf(v, "\033ZF");
    00609   stp_putc((wide ? '\x40' : '\x00'), v); stp_zfwrite(zero, 1, 60, v);
    00610   stp_zprintf(v, "\033N\1"); stp_zfwrite(zero, 1, 61, v);
    00611   stp_zprintf(v, "\033ZS");
    00612   if (wide)
    00613     {
    00614       stp_put16_be(privdata.ysize, v);
    00615       stp_put16_be(privdata.xsize, v);
    00616     }
    00617   else
    00618     {
    00619       stp_put16_be(privdata.xsize, v);
    00620       stp_put16_be(privdata.ysize, v);
    00621     }
    00622   stp_zfwrite(zero, 1, 57, v);
    00623   if (strcmp(privdata.pagesize, "C6") == 0)
    00624     {
    00625       stp_zprintf(v, "\033ZC"); stp_zfwrite(zero, 1, 61, v);
    00626     }
    00627 }
    00628
    00629 static void p440_printer_end_func(stp_vars_t *v)
    00630 {
    00631   stp_zprintf(v, "\033P"); stp_zfwrite(zero, 1, 62, v);
    00632 }
    00633
    00634 static void p440_block_init_func(stp_vars_t *v)
    00635 {
    00636   int wide = ! (strcmp(privdata.pagesize, "A4") == 0
    00637                   || strcmp(privdata.pagesize, "Custom") == 0);
    00638
    00639   stp_zprintf(v, "\033ZT");
    00640   if (wide)
    00641     {
    00642       stp_put16_be(privdata.ysize - privdata.block_max_y - 1, v);
    00643       stp_put16_be(privdata.xsize - privdata.block_max_x - 1, v);
    00644       stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
    00645       stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
    00646     }
    00647   else
    00648     {
    00649       stp_put16_be(privdata.block_min_x, v);
    00650       stp_put16_be(privdata.block_min_y, v);
    00651       stp_put16_be(privdata.block_max_x - privdata.block_min_x + 1, v);
    00652       stp_put16_be(privdata.block_max_y - privdata.block_min_y + 1, v);
    00653     }
    00654   stp_zfwrite(zero, 1, 53, v);
    00655 }
    00656
    00657 static void p440_block_end_func(stp_vars_t *v)
    00658 {
    00659   int pad = (64 - (((privdata.block_max_x - privdata.block_min_x + 1)
    00660           * (privdata.block_max_y - privdata.block_min_y + 1) * 3) % 64)) % 64;
    00661   stp_deprintf(STP_DBG_OLYMPUS,
    00662                   "olympus: max_x %d min_x %d max_y %d min_y %d\n",
    00663                   privdata.block_max_x, privdata.block_min_x,
    00664                   privdata.block_max_y, privdata.block_min_y);
    00665   stp_deprintf(STP_DBG_OLYMPUS, "olympus: olympus-p440 padding=%d\n", pad);
    00666   stp_zfwrite(zero, 1, pad, v);
    00667 }
    00668
    00669
    00670 /* Canon CP-100 series */
    00671 static const olymp_pagesize_t cpx00_page[] =
    00672 {
    00673   { "Postcard", "Postcard 148x100mm", -1, -1, 13, 13, 16, 18},
    00674   { "w253h337", "CP_L 89x119mm", -1, -1, 13, 13, 15, 15},
    00675   { "w244h155", "Card 54x86mm", -1, -1, 15, 15, 13, 13},
    00676   { "Custom", NULL, -1, -1, 13, 13, 16, 18},
    00677 };
    00678
    00679 static const olymp_pagesize_list_t cpx00_page_list =
    00680 {
    00681   cpx00_page, sizeof(cpx00_page) / sizeof(olymp_pagesize_t)
    00682 };
    00683
    00684 static const olymp_printsize_t cpx00_printsize[] =
    00685 {
    00686   { "314x314", "Postcard", 1232, 1808},
    00687   { "314x314", "w253h337", 1100, 1456},
    00688   { "314x314", "w244h155", 1040, 672},
    00689   { "314x314", "Custom", 1232, 1808},
    00690 };
    00691
    00692 static const olymp_printsize_list_t cpx00_printsize_list =
    00693 {
    00694   cpx00_printsize, sizeof(cpx00_printsize) / sizeof(olymp_printsize_t)
    00695 };
    00696
    00697 static void cpx00_printer_init_func(stp_vars_t *v)
    00698 {
    00699   char pg = (strcmp(privdata.pagesize, "Postcard") == 0 ? '\1' :
    00700                 (strcmp(privdata.pagesize, "w253h337") == 0 ? '\2' :
    00701                 (strcmp(privdata.pagesize, "w244h155") == 0 ? '\3' :
    00702                 (strcmp(privdata.pagesize, "w283h566") == 0 ? '\4' :
    00703                  '\1' ))));
    00704
    00705   stp_put16_be(0x4000, v);
    00706   stp_putc('\0', v);
    00707   stp_putc(pg, v);
    00708   stp_zfwrite(zero, 1, 8, v);
    00709 }
    00710
    00711 static void cpx00_plane_init_func(stp_vars_t *v)
    00712 {
    00713   stp_put16_be(0x4001, v);
    00714   stp_put16_le(3 - privdata.plane, v);
    00715   stp_put32_le(privdata.xsize * privdata.ysize, v);
    00716   stp_zfwrite(zero, 1, 4, v);
    00717 }
    00718
    00719 static const char cpx00_adj_cyan[] =
    00720   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00721   "<gimp-print>\n"
    00722   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00723   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00724   "0.000000 0.035294 0.070588 0.101961 0.117647 0.168627 0.180392 0.227451\n"
    00725   "0.258824 0.286275 0.317647 0.341176 0.376471 0.411765 0.427451 0.478431\n"
    00726   "0.505882 0.541176 0.576471 0.611765 0.654902 0.678431 0.705882 0.737255\n"
    00727   "0.764706 0.792157 0.811765 0.839216 0.862745 0.894118 0.909804 0.925490\n"
    00728   "</sequence>\n"
    00729   "</curve>\n"
    00730   "</gimp-print>\n";
    00731
    00732 static const char cpx00_adj_magenta[] =
    00733   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00734   "<gimp-print>\n"
    00735   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00736   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00737   "0.011765 0.019608 0.035294 0.047059 0.054902 0.101961 0.133333 0.156863\n"
    00738   "0.192157 0.235294 0.274510 0.321569 0.360784 0.403922 0.443137 0.482353\n"
    00739   "0.521569 0.549020 0.584314 0.619608 0.658824 0.705882 0.749020 0.792157\n"
    00740   "0.831373 0.890196 0.933333 0.964706 0.988235 0.992157 0.992157 0.996078\n"
    00741   "</sequence>\n"
    00742   "</curve>\n"
    00743   "</gimp-print>\n";
    00744
    00745 static const char cpx00_adj_yellow[] =
    00746   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00747   "<gimp-print>\n"
    00748   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00749   "<sequence count=\"32\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00750   "0.003922 0.015686 0.015686 0.023529 0.027451 0.054902 0.094118 0.129412\n"
    00751   "0.180392 0.219608 0.250980 0.286275 0.317647 0.341176 0.388235 0.427451\n"
    00752   "0.470588 0.509804 0.552941 0.596078 0.627451 0.682353 0.768627 0.796078\n"
    00753   "0.890196 0.921569 0.949020 0.968627 0.984314 0.992157 0.992157 1.000000\n"
    00754   "</sequence>\n"
    00755   "</curve>\n"
    00756   "</gimp-print>\n";
    00757
    00758
    00759 /* Canon CP-220 series */
    00760 static const olymp_pagesize_t cp220_page[] =
    00761 {
    00762   { "Postcard", "Postcard 148x100mm", -1, -1, 13, 13, 16, 18},
    00763   { "w253h337", "CP_L 89x119mm", -1, -1, 13, 13, 15, 15},
    00764   { "w244h155", "Card 54x86mm", -1, -1, 15, 15, 13, 13},
    00765   { "w283h566", "Wide 200x100mm", -1, -1, 13, 13, 20, 20},
    00766   { "Custom", NULL, -1, -1, 13, 13, 16, 18},
    00767 };
    00768
    00769 static const olymp_pagesize_list_t cp220_page_list =
    00770 {
    00771   cp220_page, sizeof(cp220_page) / sizeof(olymp_pagesize_t)
    00772 };
    00773
    00774 static const olymp_printsize_t cp220_printsize[] =
    00775 {
    00776   { "314x314", "Postcard", 1232, 1808},
    00777   { "314x314", "w253h337", 1100, 1456},
    00778   { "314x314", "w244h155", 1040, 672},
    00779   { "314x314", "w283h566", 1232, 2416},
    00780   { "314x314", "Custom", 1232, 1808},
    00781 };
    00782
    00783 static const olymp_printsize_list_t cp220_printsize_list =
    00784 {
    00785   cp220_printsize, sizeof(cp220_printsize) / sizeof(olymp_printsize_t)
    00786 };
    00787
    00788
    00789 /* Sony UP-DP10 */
    00790 static const olymp_resolution_t updp10_res[] =
    00791 {
    00792   { "300x300", 300, 300},
    00793 };
    00794
    00795 static const olymp_resolution_list_t updp10_res_list =
    00796 {
    00797   updp10_res, sizeof(updp10_res) / sizeof(olymp_resolution_t)
    00798 };
    00799
    00800 static const olymp_pagesize_t updp10_page[] =
    00801 {
    00802   { "w288h432", "UPC-10P23 (2:3)", -1, -1, 12, 12, 18, 18},
    00803   { "w288h387", "UPC-10P34 (3:4)", -1, -1, 12, 12, 16, 16},
    00804   { "w288h432", "UPC-10S01 (Sticker)", -1, -1, 12, 12, 18, 18},
    00805   { "Custom", NULL, -1, -1, 12, 12, 0, 0},
    00806 };
    00807
    00808 static const olymp_pagesize_list_t updp10_page_list =
    00809 {
    00810   updp10_page, sizeof(updp10_page) / sizeof(olymp_pagesize_t)
    00811 };
    00812
    00813 static const olymp_printsize_t updp10_printsize[] =
    00814 {
    00815   { "300x300", "w288h432", 1200, 1800},
    00816   { "300x300", "w288h387", 1200, 1600},
    00817   { "300x300", "Custom", 1200, 1800},
    00818 };
    00819
    00820 static const olymp_printsize_list_t updp10_printsize_list =
    00821 {
    00822   updp10_printsize, sizeof(updp10_printsize) / sizeof(olymp_printsize_t)
    00823 };
    00824
    00825 static void updp10_printer_init_func(stp_vars_t *v)
    00826 {
    00827   stp_zfwrite("\x98\xff\xff\xff\xff\xff\xff\xff"
    00828               "\x14\x00\x00\x00\x1b\x15\x00\x00"
    00829               "\x00\x0d\x00\x00\x00\x00\x00\xc7"
    00830               "\x00\x00\x00\x00", 1, 28, v);
    00831   stp_put16_be(privdata.xsize, v);
    00832   stp_put16_be(privdata.ysize, v);
    00833   stp_put32_le(privdata.xsize*privdata.ysize*3+11, v);
    00834   stp_zfwrite("\x1b\xea\x00\x00\x00\x00", 1, 6, v);
    00835   stp_put32_be(privdata.xsize*privdata.ysize*3, v);
    00836   stp_zfwrite("\x00", 1, 1, v);
    00837 }
    00838
    00839 static void updp10_printer_end_func(stp_vars_t *v)
    00840 {
    00841         stp_zfwrite("\x12\x00\x00\x00\x1b\xe1\x00\x00"
    00842                     "\x00\xb0\x00\x00\04", 1, 13, v);
    00843         stp_zfwrite((privdata.laminate->seq).data, 1,
    00844                         (privdata.laminate->seq).bytes, v); /*laminate pattern*/
    00845         stp_zfwrite("\x00\x00\x00\x00" , 1, 4, v);
    00846         stp_put16_be(privdata.ysize, v);
    00847         stp_put16_be(privdata.xsize, v);
    00848         stp_zfwrite("\xff\xff\xff\xff\x09\x00\x00\x00"
    00849                     "\x1b\xee\x00\x00\x00\x02\x00\x00"
    00850                     "\x01\x07\x00\x00\x00\x1b\x0a\x00"
    00851                     "\x00\x00\x00\x00\xfd\xff\xff\xff"
    00852                     "\xff\xff\xff\xff\xf8\xff\xff\xff"
    00853                     , 1, 40, v);
    00854 }
    00855
    00856 static const laminate_t updp10_laminate[] =
    00857 {
    00858   {"Glossy",  N_("Glossy"),  {1, "\x00"}},
    00859   {"Texture", N_("Texture"), {1, "\x08"}},
    00860   {"Matte",   N_("Matte"),   {1, "\x0c"}},
    00861 };
    00862
    00863 static const laminate_list_t updp10_laminate_list =
    00864 {
    00865   updp10_laminate, sizeof(updp10_laminate) / sizeof(laminate_t)
    00866 };
    00867
    00868 static const char updp10_adj_cyan[] =
    00869   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00870   "<gimp-print>\n"
    00871   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00872   "<sequence count=\"33\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00873   "0.113725 0.188235 0.247059 0.286275 0.317647 0.345098 0.368627 0.384314\n"
    00874   "0.400000 0.407843 0.423529 0.439216 0.450980 0.466667 0.482353 0.498039\n"
    00875   "0.509804 0.525490 0.545098 0.560784 0.580392 0.596078 0.619608 0.643137\n"
    00876   "0.662745 0.686275 0.709804 0.729412 0.756863 0.780392 0.811765 0.843137\n"
    00877   "1.000000\n"
    00878   "</sequence>\n"
    00879   "</curve>\n"
    00880   "</gimp-print>\n";
    00881
    00882 static const char updp10_adj_magenta[] =
    00883   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00884   "<gimp-print>\n"
    00885   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00886   "<sequence count=\"33\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00887   "0.105882 0.211765 0.286275 0.333333 0.364706 0.388235 0.403922 0.415686\n"
    00888   "0.427451 0.439216 0.450980 0.462745 0.478431 0.494118 0.505882 0.521569\n"
    00889   "0.537255 0.552941 0.568627 0.584314 0.600000 0.619608 0.643137 0.662745\n"
    00890   "0.682353 0.709804 0.733333 0.760784 0.792157 0.823529 0.858824 0.890196\n"
    00891   "1.000000\n"
    00892   "</sequence>\n"
    00893   "</curve>\n"
    00894   "</gimp-print>\n";
    00895
    00896 static const char updp10_adj_yellow[] =
    00897   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
    00898   "<gimp-print>\n"
    00899   "<curve wrap=\"nowrap\" type=\"spline\" gamma=\"0\">\n"
    00900   "<sequence count=\"33\" lower-bound=\"0\" upper-bound=\"1\">\n"
    00901   "0.101961 0.160784 0.196078 0.227451 0.243137 0.254902 0.266667 0.286275\n"
    00902   "0.309804 0.337255 0.368627 0.396078 0.423529 0.443137 0.462745 0.478431\n"
    00903   "0.501961 0.517647 0.537255 0.556863 0.576471 0.596078 0.619608 0.643137\n"
    00904   "0.666667 0.690196 0.709804 0.737255 0.760784 0.780392 0.796078 0.803922\n"
    00905   "1.000000\n"
    00906   "</sequence>\n"
    00907   "</curve>\n"
    00908   "</gimp-print>\n";
    00909
    00910
    00911 /* Fujifilm CX-400 */
    00912 static const olymp_resolution_t cx400_res[] =
    00913 {
    00914   { "317x316", 317, 316},
    00915 };
    00916
    00917 static const olymp_resolution_list_t cx400_res_list =
    00918 {
    00919   cx400_res, sizeof(cx400_res) / sizeof(olymp_resolution_t)
    00920 };
    00921
    00922 static const olymp_pagesize_t cx400_page[] =
    00923 {
    00924   { "w288h432", NULL, -1, -1, 23, 23, 28, 28},
    00925   { "w288h387", "4x5 3/8 (Digital Camera 3:4)", -1, -1, 23, 23, 27, 26},
    00926   { "w288h504", NULL, -1, -1, 23, 23, 23, 22},
    00927   { "Custom", NULL, -1, -1, 0, 0, 0, 0},
    00928 };
    00929
    00930 static const olymp_pagesize_list_t cx400_page_list =
    00931 {
    00932   cx400_page, sizeof(cx400_page) / sizeof(olymp_pagesize_t)
    00933 };
    00934
    00935 static const olymp_printsize_t cx400_printsize[] =
    00936 {
    00937   { "317x316", "w288h387", 1268, 1658},
    00938   { "317x316", "w288h432", 1268, 1842},
    00939   { "317x316", "w288h504", 1268, 2208},
    00940   { "317x316", "Custom", 1268, 1842},
    00941 };
    00942
    00943 static const olymp_printsize_list_t cx400_printsize_list =
    00944 {
    00945   cx400_printsize, sizeof(cx400_printsize) / sizeof(olymp_printsize_t)
    00946 };
    00947
    00948 static void cx400_printer_init_func(stp_vars_t *v)
    00949 {
    00950   char pg = '\0';
    00951   const char *pname = "XXXXXX";
    00952
    00953   stp_deprintf(STP_DBG_OLYMPUS,
    00954         "olympus: fuji driver %s\n", stp_get_driver(v));
    00955   if (strcmp(stp_get_driver(v),"fujifilm-cx400") == 0)
    00956     pname = "NX1000";
    00957   else if (strcmp(stp_get_driver(v),"fujifilm-cx550") == 0)
    00958     pname = "QX200\0";
    00959
    00960   stp_zfwrite("FUJIFILM", 1, 8, v);
    00961   stp_zfwrite(pname, 1, 6, v);
    00962   stp_putc('\0', v);
    00963   stp_put16_le(privdata.xsize, v);
    00964   stp_put16_le(privdata.ysize, v);
    00965   if (strcmp(privdata.pagesize,"w288h504") == 0)
    00966     pg = '\x0d';
    00967   else if (strcmp(privdata.pagesize,"w288h432") == 0)
    00968     pg = '\x0c';
    00969   else if (strcmp(privdata.pagesize,"w288h387") == 0)
    00970     pg = '\x0b';
    00971   stp_putc(pg, v);
    00972   stp_zfwrite("\x00\x00\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00"
    00973                   "\x00\x00\x2d\x00\x00\x00\x00", 1, 19, v);
    00974   stp_zfwrite("FUJIFILM", 1, 8, v);
    00975   stp_zfwrite(pname, 1, 6, v);
    00976   stp_putc('\1', v);
    00977 }
    00978
    00979 static const olymp_resolution_t all_resolutions[] =
    00980 {
    00981   { "306x306", 306, 306},
    00982   { "153x153", 153, 153},
    00983   { "314x314", 314, 314},
    00984   { "300x300", 300, 300},
    00985   { "317x316", 317, 316},
    00986   { "320x320", 320, 320},
    00987 };
    00988
    00989 static const olymp_resolution_list_t all_res_list =
    00990 {
    00991   all_resolutions, sizeof(all_resolutions) / sizeof(olymp_resolution_t)
    00992 };
    00993
    00994 static const olympus_cap_t olympus_model_capabilities[] =
    00995 {
    00996   { /* Olympus P-10 */
    00997     2,
    00998     &rgb_ink_list,
    00999     &res_320dpi_list,
    01000     &p10_page_list,
    01001     &p10_printsize_list,
    01002     OLYMPUS_INTERLACE_PLANE,
    01003     1848,
    01004     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT,
    01005     &p10_printer_init_func, &p10_printer_end_func,
    01006     NULL, NULL,
    01007     &p10_block_init_func, NULL,
    01008     NULL, NULL, NULL,   /* color profile/adjustment is built into printer */
    01009     &p10_laminate_list,
    01010   },
    01011   { /* Olympus P-200 */
    01012     4,
    01013     &ymc_ink_list,
    01014     &res_320dpi_list,
    01015     &p200_page_list,
    01016     &p200_printsize_list,
    01017     OLYMPUS_INTERLACE_PLANE,
    01018     1280,
    01019     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_BLOCK_ALIGN,
    01020     &p200_printer_init_func, &p200_printer_end_func,
    01021     &p200_plane_init_func, NULL,
    01022     NULL, NULL,
    01023     p200_adj_any, p200_adj_any, p200_adj_any,
    01024     NULL,
    01025   },
    01026   { /* Olympus P-300 */
    01027     0,
    01028     &ymc_ink_list,
    01029     &p300_res_list,
    01030     &p300_page_list,
    01031     &p300_printsize_list,
    01032     OLYMPUS_INTERLACE_PLANE,
    01033     16,
    01034     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_BLOCK_ALIGN,
    01035     &p300_printer_init_func, NULL,
    01036     NULL, &p300_plane_end_func,
    01037     &p300_block_init_func, NULL,
    01038     p300_adj_cyan, p300_adj_magenta, p300_adj_yellow,
    01039     NULL,
    01040   },
    01041   { /* Olympus P-400 */
    01042     1,
    01043     &ymc_ink_list,
    01044     &res_314dpi_list,
    01045     &p400_page_list,
    01046     &p400_printsize_list,
    01047     OLYMPUS_INTERLACE_PLANE,
    01048     180,
    01049     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT,
    01050     &p400_printer_init_func, NULL,
    01051     &p400_plane_init_func, &p400_plane_end_func,
    01052     &p400_block_init_func, NULL,
    01053     p400_adj_cyan, p400_adj_magenta, p400_adj_yellow,
    01054     NULL,
    01055   },
    01056   { /* Olympus P-440 */
    01057     3,
    01058     &bgr_ink_list,
    01059     &res_314dpi_list,
    01060     &p440_page_list,
    01061     &p440_printsize_list,
    01062     OLYMPUS_INTERLACE_NONE,
    01063     128,
    01064     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT,
    01065     &p440_printer_init_func, &p440_printer_end_func,
    01066     NULL, NULL,
    01067     &p440_block_init_func, &p440_block_end_func,
    01068     NULL, NULL, NULL,   /* color profile/adjustment is built into printer */
    01069     &p10_laminate_list,
    01070   },
    01071   { /* Canon CP-100, CP-200, CP-300 */
    01072     1000,
    01073     &ymc_ink_list,
    01074     &res_314dpi_list,
    01075     &cpx00_page_list,
    01076     &cpx00_printsize_list,
    01077     OLYMPUS_INTERLACE_PLANE,
    01078     1808,
    01079     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
    01080       | OLYMPUS_FEATURE_BORDERLESS | OLYMPUS_FEATURE_WHITE_BORDER,
    01081     &cpx00_printer_init_func, NULL,
    01082     &cpx00_plane_init_func, NULL,
    01083     NULL, NULL,
    01084     cpx00_adj_cyan, cpx00_adj_magenta, cpx00_adj_yellow,
    01085     NULL,
    01086   },
    01087   { /* Canon CP-220, CP-330 */
    01088     1001,
    01089     &ymc_ink_list,
    01090     &res_314dpi_list,
    01091     &cp220_page_list,
    01092     &cp220_printsize_list,
    01093     OLYMPUS_INTERLACE_PLANE,
    01094     1808,
    01095     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
    01096       | OLYMPUS_FEATURE_BORDERLESS | OLYMPUS_FEATURE_WHITE_BORDER,
    01097     &cpx00_printer_init_func, NULL,
    01098     &cpx00_plane_init_func, NULL,
    01099     NULL, NULL,
    01100     cpx00_adj_cyan, cpx00_adj_magenta, cpx00_adj_yellow,
    01101     NULL,
    01102   },
    01103   { /* Sony UP-DP10  */
    01104     2000,
    01105     &cmy_ink_list,
    01106     &updp10_res_list,
    01107     &updp10_page_list,
    01108     &updp10_printsize_list,
    01109     OLYMPUS_INTERLACE_NONE,
    01110     1800,
    01111     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
    01112       | OLYMPUS_FEATURE_BORDERLESS,
    01113     &updp10_printer_init_func, &updp10_printer_end_func,
    01114     NULL, NULL,
    01115     NULL, NULL,
    01116     updp10_adj_cyan, updp10_adj_magenta, updp10_adj_yellow,
    01117     &updp10_laminate_list,
    01118   },
    01119   { /* Fujifilm Printpix CX-400  */
    01120     3000,
    01121     &rgb_ink_list,
    01122     &cx400_res_list,
    01123     &cx400_page_list,
    01124     &cx400_printsize_list,
    01125     OLYMPUS_INTERLACE_NONE,
    01126     2208,
    01127     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
    01128       | OLYMPUS_FEATURE_BORDERLESS,
    01129     &cx400_printer_init_func, NULL,
    01130     NULL, NULL,
    01131     NULL, NULL,
    01132     NULL, NULL, NULL,   /* color profile/adjustment is built into printer */
    01133     NULL,
    01134   },
    01135   { /* Fujifilm Printpix CX-550  */
    01136     3001,
    01137     &rgb_ink_list,
    01138     &cx400_res_list,
    01139     &cx400_page_list,
    01140     &cx400_printsize_list,
    01141     OLYMPUS_INTERLACE_NONE,
    01142     2208,
    01143     OLYMPUS_FEATURE_FULL_WIDTH | OLYMPUS_FEATURE_FULL_HEIGHT
    01144       | OLYMPUS_FEATURE_BORDERLESS,
    01145     &cx400_printer_init_func, NULL,
    01146     NULL, NULL,
    01147     NULL, NULL,
    01148     NULL, NULL, NULL,   /* color profile/adjustment is built into printer */
    01149     NULL,
    01150   },
    01151 };
    01152
    01153 static const stp_parameter_t the_parameters[] =
    01154 {
    01155   {
    01156     "PageSize", N_("Page Size"), N_("Basic Printer Setup"),
    01157     N_("Size of the paper being printed to"),
    01158     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
    01159     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01160   },
    01161   {
    01162     "MediaType", N_("Media Type"), N_("Basic Printer Setup"),
    01163     N_("Type of media (plain paper, photo paper, etc.)"),
    01164     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01165     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01166   },
    01167   {
    01168     "InputSlot", N_("Media Source"), N_("Basic Printer Setup"),
    01169     N_("Source (input slot) of the media"),
    01170     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01171     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01172   },
    01173   {
    01174     "Resolution", N_("Resolution"), N_("Basic Printer Setup"),
    01175     N_("Resolution and quality of the print"),
    01176     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01177     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01178   },
    01179   {
    01180     "InkType", N_("Ink Type"), N_("Advanced Printer Setup"),
    01181     N_("Type of ink in the printer"),
    01182     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01183     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01184   },
    01185   {
    01186     "Laminate", N_("Laminate Pattern"), N_("Advanced Printer Setup"),
    01187     N_("Laminate Pattern"),
    01188     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_FEATURE,
    01189     STP_PARAMETER_LEVEL_BASIC, 1, 0, -1, 1, 0
    01190   },
    01191   {
    01192     "Borderless", N_("Borderless"), N_("Advanced Printer Setup"),
    01193     N_("Print without borders"),
    01194     STP_PARAMETER_TYPE_BOOLEAN, STP_PARAMETER_CLASS_FEATURE,
    01195     STP_PARAMETER_LEVEL_BASIC, 1, 0, -1, 1, 0
    01196   },
    01197   {
    01198     "PrintingMode", N_("Printing Mode"), N_("Core Parameter"),
    01199     N_("Printing Output Mode"),
    01200     STP_PARAMETER_TYPE_STRING_LIST, STP_PARAMETER_CLASS_CORE,
    01201     STP_PARAMETER_LEVEL_BASIC, 1, 1, -1, 1, 0
    01202   },
    01203 };
    01204
    01205 static int the_parameter_count =
    01206 sizeof(the_parameters) / sizeof(const stp_parameter_t);
    01207
    01208 typedef struct
    01209 {
    01210   const stp_parameter_t param;
    01211   double min;
    01212   double max;
    01213   double defval;
    01214   int color_only;
    01215 } float_param_t;
    01216
    01217 static const float_param_t float_parameters[] =
    01218 {
    01219   {
    01220     {
    01221       "CyanDensity", N_("Cyan Balance"), N_("Output Level Adjustment"),
    01222       N_("Adjust the cyan balance"),
    01223       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01224       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 1, 1, 0
    01225     }, 0.0, 2.0, 1.0, 1
    01226   },
    01227   {
    01228     {
    01229       "MagentaDensity", N_("Magenta Balance"), N_("Output Level Adjustment"),
    01230       N_("Adjust the magenta balance"),
    01231       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01232       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 2, 1, 0
    01233     }, 0.0, 2.0, 1.0, 1
    01234   },
    01235   {
    01236     {
    01237       "YellowDensity", N_("Yellow Balance"), N_("Output Level Adjustment"),
    01238       N_("Adjust the yellow balance"),
    01239       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01240       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 3, 1, 0
    01241     }, 0.0, 2.0, 1.0, 1
    01242   },
    01243   {
    01244     {
    01245       "BlackDensity", N_("Black Balance"), N_("Output Level Adjustment"),
    01246       N_("Adjust the black balance"),
    01247       STP_PARAMETER_TYPE_DOUBLE, STP_PARAMETER_CLASS_OUTPUT,
    01248       STP_PARAMETER_LEVEL_ADVANCED, 0, 1, 0, 1, 0
    01249     }, 0.0, 2.0, 1.0, 1
    01250   },
    01251 };
    01252
    01253 static const int float_parameter_count =
    01254 sizeof(float_parameters) / sizeof(const float_param_t);
    01255
    01256 static const olympus_cap_t* olympus_get_model_capabilities(int model)
    01257 {
    01258   int i;
    01259   int models = sizeof(olympus_model_capabilities) / sizeof(olympus_cap_t);
    01260
    01261   for (i=0; i<models; i++)
    01262     {
    01263       if (olympus_model_capabilities[i].model == model)
    01264         return &(olympus_model_capabilities[i]);
    01265     }
    01266   stp_deprintf(STP_DBG_OLYMPUS,
    01267         "olympus: model %d not found in capabilities list.\n", model);
    01268   return &(olympus_model_capabilities[0]);
    01269 }
    01270
    01271 static const laminate_t* olympus_get_laminate_pattern(stp_vars_t *v)
    01272 {
    01273   const char *lpar = stp_get_string_parameter(v, "Laminate");
    01274   const olympus_cap_t *caps = olympus_get_model_capabilities(
    01275                                                 stp_get_model_id(v));
    01276   const laminate_list_t *llist = caps->laminate;
    01277   const laminate_t *l = NULL;
    01278   int i;
    01279
    01280   for (i = 0; i < llist->n_items; i++)
    01281     {
    01282       l = &(llist->item[i]);
    01283       if (strcmp(l->name, lpar) == 0)
    01284          break;
    01285     }
    01286   return l;
    01287 }
    01288
    01289 static void
    01290 olympus_printsize(const stp_vars_t *v,
    01291                    int  *width,
    01292                    int  *height)
    01293 {
    01294   int i;
    01295   const char *page = stp_get_string_parameter(v, "PageSize");
    01296   const char *resolution = stp_get_string_parameter(v, "Resolution");
    01297   const olympus_cap_t *caps = olympus_get_model_capabilities(
    01298                                                 stp_get_model_id(v));
    01299   const olymp_printsize_list_t *p = caps->printsize;
    01300
    01301   for (i = 0; i < p->n_items; i++)
    01302     {
    01303       if (strcmp(p->item[i].res_name,resolution) == 0 &&
    01304           strcmp(p->item[i].pagesize_name,page) == 0)
    01305         {
    01306           *width  = p->item[i].width_px;
    01307           *height = p->item[i].height_px;
    01308           return;
    01309         }
    01310     }
    01311   stp_erprintf("olympus_printsize: printsize not found (%s, %s)\n",
    01312                page, resolution);
    01313 }
    01314
    01315 static int
    01316 olympus_feature(const olympus_cap_t *caps, int feature)
    01317 {
    01318   return ((caps->features & feature) == feature);
    01319 }
    01320
    01321 static stp_parameter_list_t
    01322 olympus_list_parameters(const stp_vars_t *v)
    01323 {
    01324   stp_parameter_list_t *ret = stp_parameter_list_create();
    01325   int i;
    01326
    01327   for (i = 0; i < the_parameter_count; i++)
    01328     stp_parameter_list_add_param(ret, &(the_parameters[i]));
    01329   for (i = 0; i < float_parameter_count; i++)
    01330     stp_parameter_list_add_param(ret, &(float_parameters[i].param));
    01331   return ret;
    01332 }
    01333
    01334 static void
    01335 olympus_parameters(const stp_vars_t *v, const char *name,
    01336                stp_parameter_t *description)
    01337 {
    01338   int   i;
    01339   const olympus_cap_t *caps = olympus_get_model_capabilities(
    01340                                                 stp_get_model_id(v));
    01341
    01342   description->p_type = STP_PARAMETER_TYPE_INVALID;
    01343   if (name == NULL)
    01344     return;
    01345
    01346   description->deflt.str = NULL;
    01347   for (i = 0; i < float_parameter_count; i++)
    01348     if (strcmp(name, float_parameters[i].param.name) == 0)
    01349       {
    01350         stp_fill_parameter_settings(description,
    01351                                      &(float_parameters[i].param));
    01352         description->deflt.dbl = float_parameters[i].defval;
    01353         description->bounds.dbl.upper = float_parameters[i].max;
    01354         description->bounds.dbl.lower = float_parameters[i].min;
    01355       }
    01356
    01357   for (i = 0; i < the_parameter_count; i++)
    01358     if (strcmp(name, the_parameters[i].name) == 0)
    01359       {
    01360         stp_fill_parameter_settings(description, &(the_parameters[i]));
    01361         break;
    01362       }
    01363   if (strcmp(name, "PageSize") == 0)
    01364     {
    01365       int default_specified = 0;
    01366       const olymp_pagesize_list_t *p = caps->pages;
    01367       const char* text;
    01368
    01369       description->bounds.str = stp_string_list_create();
    01370       for (i = 0; i < p->n_items; i++)
    01371         {
    01372           const stp_papersize_t *pt = stp_get_papersize_by_name(
    01373                           p->item[i].name);
    01374
    01375           text = (p->item[i].text ? p->item[i].text : pt->text);
    01376           stp_string_list_add_string(description->bounds.str,
    01377                           p->item[i].name, text);
    01378           if (! default_specified && pt && pt->width > 0 && pt->height > 0)
    01379             {
    01380               description->deflt.str = p->item[i].name;
    01381               default_specified = 1;
    01382             }
    01383         }
    01384       if (!default_specified)
    01385         description->deflt.str =
    01386           stp_string_list_param(description->bounds.str, 0)->name;
    01387     }
    01388   else if (strcmp(name, "MediaType") == 0)
    01389     {
    01390       description->bounds.str = stp_string_list_create();
    01391       description->is_active = 0;
    01392     }
    01393   else if (strcmp(name, "InputSlot") == 0)
    01394     {
    01395       description->bounds.str = stp_string_list_create();
    01396       description->is_active = 0;
    01397     }
    01398   else if (strcmp(name, "Resolution") == 0)
    01399     {
    01400       char res_text[24];
    01401       const olymp_resolution_list_t *r = caps->resolution;
    01402
    01403       description->bounds.str = stp_string_list_create();
    01404       for (i = 0; i < r->n_items; i++)
    01405         {
    01406           sprintf(res_text, "%s DPI", r->item[i].name);
    01407           stp_string_list_add_string(description->bounds.str,
    01408                 r->item[i].name, _(res_text));
    01409         }
    01410       if (r->n_items < 1)
    01411         description->is_active = 0;
    01412       description->deflt.str =
    01413         stp_string_list_param(description->bounds.str, 0)->name;
    01414     }
    01415   else if (strcmp(name, "InkType") == 0)
    01416     {
    01417       description->bounds.str = stp_string_list_create();
    01418       for (i = 0; i < caps->inks->n_items; i++)
    01419         stp_string_list_add_string(description->bounds.str,
    01420                           caps->inks->item[i].name, caps->inks->item[i].name);
    01421       description->deflt.str =
    01422         stp_string_list_param(description->bounds.str, 0)->name;
    01423       if (caps->inks->n_items < 2)
    01424         description->is_active = 0;
    01425     }
    01426   else if (strcmp(name, "Laminate") == 0)
    01427     {
    01428       description->bounds.str = stp_string_list_create();
    01429       if (caps->laminate)
    01430         {
    01431           const laminate_list_t *llist = caps->laminate;
    01432
    01433           for (i = 0; i < llist->n_items; i++)
    01434             {
    01435               const laminate_t *l = &(llist->item[i]);
    01436               stp_string_list_add_string(description->bounds.str,
    01437                                 l->name, l->text);
    01438             }
    01439           description->deflt.str =
    01440           stp_string_list_param(description->bounds.str, 0)->name;
    01441           description->is_active = 1;
    01442         }
    01443     }
    01444   else if (strcmp(name, "Borderless") == 0)
    01445     {
    01446       if (olympus_feature(caps, OLYMPUS_FEATURE_BORDERLESS))
    01447         description->is_active = 1;
    01448     }
    01449   else if (strcmp(name, "PrintingMode") == 0)
    01450     {
    01451       description->bounds.str = stp_string_list_create();
    01452       stp_string_list_add_string
    01453         (description->bounds.str, "Color", _("Color"));
    01454       description->deflt.str =
    01455         stp_string_list_param(description->bounds.str, 0)->name;
    01456     }
    01457   else
    01458     description->is_active = 0;
    01459 }
    01460
    01461
    01462 static void
    01463 olympus_imageable_area(const stp_vars_t *v,
    01464                    int  *left,
    01465                    int  *right,
    01466                    int  *bottom,
    01467                    int  *top)
    01468 {
    01469   int width, height;
    01470   int i;
    01471   const char *page = stp_get_string_parameter(v, "PageSize");
    01472   const stp_papersize_t *pt = stp_get_papersize_by_name(page);
    01473   const olympus_cap_t *caps = olympus_get_model_capabilities(
    01474                                                 stp_get_model_id(v));
    01475   const olymp_pagesize_list_t *p = caps->pages;
    01476
    01477   for (i = 0; i < p->n_items; i++)
    01478     {
    01479       if (strcmp(p->item[i].name,pt->name) == 0)
    01480         {
    01481 /*
    01482           if (p->item[i].width_pt >= 0)
    01483                   stp_set_page_width(v, p->item[i].width_pt);
    01484           if (p->item[i].height_pt >= 0)
    01485                   stp_set_page_height(v, p->item[i].height_pt);
    01486 */
    01487
    01488           stp_default_media_size(v, &width, &height);
    01489
    01490
    01491           if (olympus_feature(caps, OLYMPUS_FEATURE_BORDERLESS)
    01492             && stp_get_boolean_parameter(v, "Borderless"))
    01493             {
    01494               *left = 0;
    01495               *top  = 0;
    01496               *right  = width;
    01497               *bottom = height;
    01498             }
    01499           else
    01500             {
    01501               *left = p->item[i].border_pt_left;
    01502               *top  = p->item[i].border_pt_top;
    01503               *right  = width  - p->item[i].border_pt_right;
    01504               *bottom = height - p->item[i].border_pt_bottom;
    01505             }
    01506           break;
    01507         }
    01508     }
    01509 }
    01510
    01511 static void
    01512 olympus_limit(const stp_vars_t *v,                      /* I */
    01513             int *width, int *height,
    01514             int *min_width, int *min_height)
    01515 {
    01516   *width = 65535;
    01517   *height = 65535;
    01518   *min_width = 1;
    01519   *min_height = 1;
    01520 }
    01521
    01522 static void
    01523 olympus_describe_resolution(const stp_vars_t *v, int *x, int *y)
    01524 {
    01525   const char *resolution = stp_get_string_parameter(v, "Resolution");
    01526   int i;
    01527
    01528   *x = -1;
    01529   *y = -1;
    01530   if (resolution)
    01531     {
    01532       for (i = 0; i < all_res_list.n_items; i++)
    01533         {
    01534           if (strcmp(resolution, all_res_list.item[i].name) == 0)
    01535             {
    01536               *x = all_res_list.item[i].xdpi;
    01537               *y = all_res_list.item[i].ydpi;
    01538             }
    01539         }
    01540     }
    01541   return;
    01542 }
    01543
    01544 static const char *
    01545 olympus_describe_output(const stp_vars_t *v)
    01546 {
    01547   return "CMY";
    01548 }
    01549
    01550 static unsigned short *
    01551 olympus_get_cached_output(stp_vars_t *v,
    01552              stp_image_t *image,
    01553              unsigned short **cache,
    01554              int line, int size)
    01555 {
    01556   unsigned zero_mask;
    01557
    01558   stp_deprintf(STP_DBG_OLYMPUS, "olympus: get row %d", line);
    01559   if (cache[line] == NULL)
    01560     {
    01561       stp_deprintf(STP_DBG_OLYMPUS, " (calling stp_color_get_row())\n");
    01562       if (!stp_color_get_row(v, image, line, &zero_mask))
    01563         {
    01564           cache[line] = stp_malloc(size);
    01565           memcpy(cache[line], stp_channel_get_output(v), size);
    01566         }
    01567     }
    01568   else
    01569     {
    01570       stp_deprintf(STP_DBG_OLYMPUS, " (cached)\n");
    01571     }
    01572   return cache[line];
    01573 }
    01574
    01575 /*
    01576  * olympus_print()
    01577  */
    01578 static int
    01579 olympus_do_print(stp_vars_t *v, stp_image_t *image)
    01580 {
    01581   int i, j;
    01582   int y, min_y, max_y;                  /* Looping vars */
    01583   int min_x, max_x;
    01584   int out_channels, out_bytes;
    01585   unsigned short *final_out = NULL;
    01586   unsigned char  *char_out = NULL;
    01587   unsigned short *real_out = NULL;
    01588   unsigned short *err_out = NULL;
    01589   unsigned short **rows = NULL;         /* "cache" of rows read from image */
    01590   int char_out_width;
    01591   int status = 1;
    01592   int ink_channels = 1;
    01593   const char *ink_order = NULL;
    01594   stp_curve_t   *adjustment = NULL;
    01595
    01596   int r_errdiv, r_errmod;
    01597   int r_errval  = 0;
    01598   int r_errlast = -1;
    01599   int r_errline = 0;
    01600   int c_errdiv, c_errmod;
    01601   int c_errval  = 0;
    01602   int c_errlast = -1;
    01603   int c_errcol = 0;
    01604
    01605   const int model           = stp_get_model_id(v);
    01606   const char *ink_type      = stp_get_string_parameter(v, "InkType");
    01607   const olympus_cap_t *caps = olympus_get_model_capabilities(model);
    01608   int max_print_px_width, max_print_px_height;
    01609   int xdpi, ydpi;       /* Resolution */
    01610
    01611   /* image in pixels */
    01612   int image_px_width;
    01613   int image_px_height;
    01614
    01615   /* output in 1/72" */
    01616   int out_pt_width  = stp_get_width(v);
    01617   int out_pt_height = stp_get_height(v);
    01618   int out_pt_left   = stp_get_left(v);
    01619   int out_pt_top    = stp_get_top(v);
    01620
    01621   /* output in pixels */
    01622   int out_px_width, out_px_height;
    01623   int out_px_left, out_px_right, out_px_top, out_px_bottom;
    01624
    01625   /* page in 1/72" */
    01626   int page_pt_width  = stp_get_page_width(v);
    01627   int page_pt_height = stp_get_page_height(v);
    01628   int page_pt_left = 0;
    01629   int page_pt_right = 0;
    01630   int page_pt_top = 0;
    01631   int page_pt_bottom = 0;
    01632
    01633   /* page w/out borders in pixels (according to selected dpi) */
    01634   int print_px_width;
    01635   int print_px_height;
    01636
    01637   int pl;
    01638   unsigned char *zeros = NULL;
    01639
    01640   if (!stp_verify(v))
    01641     {
    01642       stp_eprintf(v, _("Print options not verified; cannot print.\n"));
    01643       return 0;
    01644     }
    01645
    01646   stp_image_init(image);
    01647   image_px_width  = stp_image_width(image);
    01648   image_px_height = stp_image_height(image);
    01649
    01650   stp_describe_resolution(v, &xdpi, &ydpi);
    01651   olympus_printsize(v, &max_print_px_width, &max_print_px_height);
    01652
    01653   privdata.pagesize = stp_get_string_parameter(v, "PageSize");
    01654   if (caps->laminate)
    01655           privdata.laminate = olympus_get_laminate_pattern(v);
    01656
    01657   if (olympus_feature(caps, OLYMPUS_FEATURE_WHITE_BORDER))
    01658     stp_default_media_size(v, &page_pt_right, &page_pt_bottom);
    01659   else
    01660     olympus_imageable_area(v, &page_pt_left, &page_pt_right,
    01661         &page_pt_bottom, &page_pt_top);
    01662
    01663   print_px_width  = MIN(max_print_px_width,
    01664                         (page_pt_right - page_pt_left) * xdpi / 72);
    01665   print_px_height = MIN(max_print_px_height,
    01666                         (page_pt_bottom - page_pt_top) * ydpi / 72);
    01667   out_px_width  = out_pt_width  * xdpi / 72;
    01668   out_px_height = out_pt_height * ydpi / 72;
    01669
    01670
    01671   /* if image size is close enough to output size send out original size */
    01672   if (out_px_width - image_px_width > -5
    01673       && out_px_width - image_px_width < 5
    01674       && out_px_height - image_px_height > -5
    01675       && out_px_height - image_px_height < 5)
    01676     {
    01677       out_px_width  = image_px_width;
    01678       out_px_height = image_px_height;
    01679     }
    01680
    01681   out_px_width  = MIN(out_px_width, print_px_width);
    01682   out_px_height = MIN(out_px_height, print_px_height);
    01683   out_px_left   = MIN(((out_pt_left - page_pt_left) * xdpi / 72),
    01684                         print_px_width - out_px_width);
    01685   out_px_top    = MIN(((out_pt_top  - page_pt_top)  * ydpi / 72),
    01686                         print_px_height - out_px_height);
    01687   out_px_right  = out_px_left + out_px_width;
    01688   out_px_bottom = out_px_top  + out_px_height;
    01689
    01690
    01691   stp_deprintf(STP_DBG_OLYMPUS,
    01692               "paper (pt)   %d x %d\n"
    01693               "image (px)   %d x %d\n"
    01694               "image (pt)   %d x %d\n"
    01695               "* out (pt)   %d x %d\n"
    01696               "* out (px)   %d x %d\n"
    01697               "* left x top (pt) %d x %d\n"
    01698               "* left x top (px) %d x %d\n"
    01699               "border (pt) (%d - %d) = %d x (%d - %d) = %d\n"
    01700               "printable pixels (px)   %d x %d\n"
    01701               "res (dpi)               %d x %d\n",
    01702               page_pt_width, page_pt_height,
    01703               image_px_width, image_px_height,
    01704               image_px_width * 72 / xdpi, image_px_height * 72 / ydpi,
    01705               out_pt_width, out_pt_height,
    01706               out_px_width, out_px_height,
    01707               out_pt_left, out_pt_top,
    01708               out_px_left, out_px_top,
    01709               page_pt_right, page_pt_left, page_pt_right - page_pt_left,
    01710               page_pt_bottom, page_pt_top, page_pt_bottom - page_pt_top,
    01711               print_px_width, print_px_height,
    01712               xdpi, ydpi
    01713               );
    01714
    01715   privdata.xdpi = xdpi;
    01716   privdata.ydpi = ydpi;
    01717   privdata.xsize = print_px_width;
    01718   privdata.ysize = print_px_height;
    01719
    01720   stp_set_string_parameter(v, "STPIOutputType", "CMY");
    01721
    01722   if (caps->adj_cyan &&
    01723         !stp_check_curve_parameter(v, "CyanCurve", STP_PARAMETER_ACTIVE))
    01724     {
    01725       adjustment = stp_curve_create_from_string(caps->adj_cyan);
    01726       stp_set_curve_parameter(v, "CyanCurve", adjustment);
    01727       stp_set_curve_parameter_active(v, "CyanCurve", STP_PARAMETER_ACTIVE);
    01728       stp_curve_destroy(adjustment);
    01729     }
    01730   if (caps->adj_magenta &&
    01731         !stp_check_curve_parameter(v, "MagentaCurve", STP_PARAMETER_ACTIVE))
    01732     {
    01733       adjustment = stp_curve_create_from_string(caps->adj_magenta);
    01734       stp_set_curve_parameter(v, "MagentaCurve", adjustment);
    01735       stp_set_curve_parameter_active(v, "MagentaCurve", STP_PARAMETER_ACTIVE);
    01736       stp_curve_destroy(adjustment);
    01737     }
    01738   if (caps->adj_yellow &&
    01739         !stp_check_curve_parameter(v, "YellowCurve", STP_PARAMETER_ACTIVE))
    01740     {
    01741       adjustment = stp_curve_create_from_string(caps->adj_yellow);
    01742       stp_set_curve_parameter(v, "YellowCurve", adjustment);
    01743       stp_set_curve_parameter_active(v, "YellowCurve", STP_PARAMETER_ACTIVE);
    01744       stp_curve_destroy(adjustment);
    01745     }
    01746
    01747   if (ink_type)
    01748     {
    01749       for (i = 0; i < caps->inks->n_items; i++)
    01750         if (strcmp(ink_type, caps->inks->item[i].name) == 0)
    01751           {
    01752             stp_set_string_parameter(v, "STPIOutputType",
    01753                                      caps->inks->item[i].output_type);
    01754             ink_channels = caps->inks->item[i].output_channels;
    01755             ink_order = caps->inks->item[i].channel_order;
    01756             break;
    01757           }
    01758     }
    01759
    01760   stp_channel_reset(v);
    01761   for (i = 0; i < ink_channels; i++)
    01762     stp_channel_add(v, i, 0, 1.0);
    01763
    01764   out_channels = stp_color_init(v, image, 65536);
    01765
    01766 #if 0
    01767   if (out_channels != ink_channels && out_channels != 1 && ink_channels != 1)
    01768     {
    01769       stp_eprintf(v, "Internal error!  Output channels or input channels must be 1\n");
    01770       return 0;
    01771     }
    01772 #endif
    01773
    01774   rows = stp_zalloc(image_px_height * sizeof(unsigned short *));
    01775   err_out = stp_malloc(print_px_width * ink_channels * 2);
    01776   if (out_channels != ink_channels)
    01777     final_out = stp_malloc(print_px_width * ink_channels * 2);
    01778
    01779   stp_set_float_parameter(v, "Density", 1.0);
    01780
    01781   if (ink_type &&
    01782         (strcmp(ink_type, "RGB") == 0 || strcmp(ink_type, "BGR") == 0))
    01783     {
    01784       zeros = stp_malloc(ink_channels * print_px_width + 1);
    01785       (void) memset(zeros, '\xff', ink_channels * print_px_width + 1);
    01786     }
    01787   else
    01788     zeros = stp_zalloc(ink_channels * print_px_width + 1);
    01789
    01790   out_bytes = (caps->interlacing == OLYMPUS_INTERLACE_PLANE ? 1 : ink_channels);
    01791
    01792   /* printer init */
    01793   if (caps->printer_init_func)
    01794     {
    01795       stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->printer_init\n");
    01796       (*(caps->printer_init_func))(v);
    01797     }
    01798
    01799   if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_HEIGHT))
    01800     {
    01801       min_y = 0;
    01802       max_y = print_px_height - 1;
    01803     }
    01804   else if (olympus_feature(caps, OLYMPUS_FEATURE_BLOCK_ALIGN))
    01805     {
    01806       min_y = out_px_top - (out_px_top % caps->block_size);
    01807                                 /* floor to multiple of block_size */
    01808       max_y = (out_px_bottom - 1) + (caps->block_size - 1)
    01809                 - ((out_px_bottom - 1) % caps->block_size);
    01810                                 /* ceil to multiple of block_size */
    01811     }
    01812   else
    01813     {
    01814       min_y = out_px_top;
    01815       max_y = out_px_bottom - 1;
    01816     }
    01817
    01818   if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH))
    01819     {
    01820       min_x = 0;
    01821       max_x = print_px_width - 1;
    01822     }
    01823   else
    01824     {
    01825       min_x = out_px_left;
    01826       max_x = out_px_right;
    01827     }
    01828
    01829   r_errdiv  = image_px_height / out_px_height;
    01830   r_errmod  = image_px_height % out_px_height;
    01831   c_errdiv = image_px_width / out_px_width;
    01832   c_errmod = image_px_width % out_px_width;
    01833
    01834   for (pl = 0; pl < (caps->interlacing == OLYMPUS_INTERLACE_PLANE
    01835                         ? ink_channels : 1); pl++)
    01836     {
    01837       r_errval  = 0;
    01838       r_errlast = -1;
    01839       r_errline = 0;
    01840
    01841       privdata.plane = ink_order[pl];
    01842       stp_deprintf(STP_DBG_OLYMPUS, "olympus: plane %d\n", privdata.plane);
    01843
    01844       /* plane init */
    01845       if (caps->plane_init_func)
    01846         {
    01847           stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->plane_init\n");
    01848           (*(caps->plane_init_func))(v);
    01849         }
    01850
    01851       for (y = min_y; y <= max_y; y++)
    01852         {
    01853           unsigned short *out;
    01854           int duplicate_line = 1;
    01855 /*          unsigned zero_mask; */
    01856
    01857           if (((y - min_y) % caps->block_size) == 0)
    01858             {
    01859               /* block init */
    01860               privdata.block_min_y = y;
    01861               privdata.block_min_x = min_x;
    01862               privdata.block_max_y = MIN(y + caps->block_size - 1, max_y);
    01863               privdata.block_max_x = max_x;
    01864
    01865               if (caps->block_init_func)
    01866                 {
    01867                   stp_deprintf(STP_DBG_OLYMPUS,
    01868                                "olympus: caps->block_init\n");
    01869                   (*(caps->block_init_func))(v);
    01870                 }
    01871             }
    01872
    01873           if (y < out_px_top || y >= out_px_bottom)
    01874             stp_zfwrite((char *) zeros, out_bytes, print_px_width, v);
    01875           else
    01876             {
    01877               if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH)
    01878                 && out_px_left > 0)
    01879                 {
    01880                   stp_zfwrite((char *) zeros, out_bytes, out_px_left, v);
    01881                   /* stp_erprintf("left %d ", out_px_left); */
    01882                 }
    01883
    01884 #if 0
    01885               if (r_errline != r_errlast)
    01886                 {
    01887                   r_errlast = r_errline;
    01888                   duplicate_line = 0;
    01889
    01890                   /* stp_erprintf("r_errline %d, ", r_errline); */
    01891                   if (stp_color_get_row(v, image, r_errline, &zero_mask))
    01892                     {
    01893                       status = 2;
    01894                       break;
    01895                     }
    01896                 }
    01897
    01898               out = stp_channel_get_output(v);
    01899 #endif
    01900               if (r_errline != r_errlast)
    01901                 {
    01902                   r_errlast = r_errline;
    01903                   duplicate_line = 0;
    01904                 }
    01905
    01906               out = olympus_get_cached_output(v, image, rows, r_errline,
    01907                                           image_px_width * ink_channels * 2);
    01908               if (out == NULL)
    01909                 {
    01910                   status = 2;
    01911                   break;
    01912                 }
    01913
    01914               c_errval  = 0;
    01915               c_errlast = -1;
    01916               c_errcol  = 0;
    01917               for (i = 0; i < out_px_width; i++)
    01918                 {
    01919                   if (c_errcol != c_errlast)
    01920                     c_errlast = c_errcol;
    01921                   for (j = 0; j < ink_channels; j++)
    01922                     err_out[i * ink_channels + j] =
    01923                                 out[c_errcol * ink_channels + ink_order[j]-1];
    01924
    01925                   c_errval += c_errmod;
    01926                   c_errcol += c_errdiv;
    01927                   if (c_errval >= out_px_width)
    01928                     {
    01929                       c_errval -= out_px_width;
    01930                       c_errcol ++;
    01931                     }
    01932                 }
    01933
    01934               real_out = err_out;
    01935               if (out_channels != ink_channels)
    01936                 {
    01937                   real_out = final_out;
    01938                   if (out_channels < ink_channels)
    01939                     {
    01940                       for (i = 0; i < out_px_width; i++)
    01941                         {
    01942                           for (j = 0; j < ink_channels; j++)
    01943                             final_out[i * ink_channels + j] = err_out[i];
    01944                         }
    01945                     }
    01946                   else
    01947                     {
    01948                       for (i = 0; i < out_px_width; i++)
    01949                         {
    01950                           int avg = 0;
    01951                           for (j = 0; j < out_channels; j++)
    01952                             avg += err_out[i * out_channels + j];
    01953                           final_out[i] = avg / out_channels;
    01954                         }
    01955                     }
    01956                 }
    01957               char_out = (unsigned char *) real_out;
    01958               char_out_width = (caps->interlacing == OLYMPUS_INTERLACE_PLANE ?
    01959                                 out_px_width : out_px_width * out_channels);
    01960               for (i = 0; i < char_out_width; i++)
    01961                 {
    01962                   if (caps->interlacing == OLYMPUS_INTERLACE_PLANE)
    01963                     j = i * ink_channels + pl;
    01964                   else if (caps->interlacing == OLYMPUS_INTERLACE_LINE)
    01965                     j = (i % out_px_width) + (i / out_px_width);
    01966                   else  /* OLYMPUS_INTERLACE_NONE */
    01967                     j = i;
    01968
    01969                   char_out[i] = real_out[j] / 257;
    01970                 }
    01971
    01972               stp_zfwrite((char *) real_out, 1, char_out_width, v);
    01973               /* stp_erprintf("data %d ", out_px_width); */
    01974               if (olympus_feature(caps, OLYMPUS_FEATURE_FULL_WIDTH)
    01975                 && out_px_right < print_px_width)
    01976                 {
    01977                   stp_zfwrite((char *) zeros, out_bytes,
    01978                                   print_px_width - out_px_right, v);
    01979                   /* stp_erprintf("right %d ", print_px_width-out_px_right); */
    01980                 }
    01981               /* stp_erprintf("\n"); */
    01982
    01983               r_errval += r_errmod;
    01984               r_errline += r_errdiv;
    01985               if (r_errval >= out_px_height)
    01986                 {
    01987                   r_errval -= out_px_height;
    01988                   r_errline ++;
    01989                 }
    01990             }
    01991
    01992           if (y == privdata.block_max_y)
    01993             {
    01994               /* block end */
    01995               if (caps->block_end_func)
    01996                 {
    01997                   stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->block_end\n");
    01998                   (*(caps->block_end_func))(v);
    01999                 }
    02000             }
    02001         }
    02002
    02003       /* plane end */
    02004       if (caps->plane_end_func) {
    02005         stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->plane_end\n");
    02006         (*(caps->plane_end_func))(v);
    02007       }
    02008     }
    02009
    02010   /* printer end */
    02011   if (caps->printer_end_func)
    02012     {
    02013       stp_deprintf(STP_DBG_OLYMPUS, "olympus: caps->printer_end\n");
    02014       (*(caps->printer_end_func))(v);
    02015     }
    02016   stp_image_conclude(image);
    02017   if (final_out)
    02018     stp_free(final_out);
    02019   if (err_out)
    02020     stp_free(err_out);
    02021   if (zeros)
    02022     stp_free(zeros);
    02023   if (rows)
    02024     {
    02025       for (i = 0; i <image_px_height; i++)
    02026         stp_free(rows[i]);
    02027       stp_free(rows);
    02028     }
    02029   return status;
    02030 }
    02031
    02032 static int
    02033 olympus_print(const stp_vars_t *v, stp_image_t *image)
    02034 {
    02035   int status;
    02036   stp_vars_t *nv = stp_vars_create_copy(v);
    02037   stp_prune_inactive_options(nv);
    02038   status = olympus_do_print(nv, image);
    02039   stp_vars_destroy(nv);
    02040   return status;
    02041 }
    02042
    02043 static const stp_printfuncs_t print_olympus_printfuncs =
    02044 {
    02045   olympus_list_parameters,
    02046   olympus_parameters,
    02047   stp_default_media_size,
    02048   olympus_imageable_area,
    02049   olympus_limit,
    02050   olympus_print,
    02051   olympus_describe_resolution,
    02052   olympus_describe_output,
    02053   stp_verify_printer_params,
    02054   NULL,
    02055   NULL
    02056 };
    02057
    02058
    02059
    02060
    02061 static stp_family_t print_olympus_module_data =
    02062   {
    02063     &print_olympus_printfuncs,
    02064     NULL
    02065   };
    02066
    02067
    02068 static int
    02069 print_olympus_module_init(void)
    02070 {
    02071   return stp_family_register(print_olympus_module_data.printer_list);
    02072 }
    02073
    02074
    02075 static int
    02076 print_olympus_module_exit(void)
    02077 {
    02078   return stp_family_unregister(print_olympus_module_data.printer_list);
    02079 }
    02080
    02081
    02082 /* Module header */
    02083 #define stp_module_version print_olympus_LTX_stp_module_version
    02084 #define stp_module_data print_olympus_LTX_stp_module_data
    02085
    02086 stp_module_version_t stp_module_version = {0, 0};
    02087
    02088 stp_module_t stp_module_data =
    02089   {
    02090     "olympus",
    02091     VERSION,
    02092     "Olympus family driver",
    02093     STP_MODULE_CLASS_FAMILY,
    02094     NULL,
    02095     print_olympus_module_init,
    02096     print_olympus_module_exit,
    02097     (void *) &print_olympus_module_data
    02098   };
    02099