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

Generated on Wed May 12 20:21:32 2004 for libgimpprint API Reference by doxygen1.2.17