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.c,v 1.52 2004/08/18 09:59:16 m0m 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 

Generated on Wed Aug 25 07:56:14 2004 for libgimpprint API Reference by doxygen 1.3.6