Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/print-olympus.c

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

Generated on Sat Jun 26 10:11:53 2004 for libgimpprint API Reference by doxygen1.2.17