libgimpprint API Reference: src/main/escp2-driver.c Source File

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

# src/main/escp2-driver.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: escp2-driver_8c-source.html,v 1.1.1.2 2004/12/22 23:49:00 jlovell Exp $"
    00003  *
    00004  *   Print plug-in EPSON ESC/P2 driver for the GIMP.
    00005  *
    00006  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
    00007  *      Robert Krawitz (rlk@alum.mit.edu)
    00008  *
    00009  *   This program is free software; you can redistribute it and/or modify it
    00010  *   under the terms of the GNU General Public License as published by the Free
    00011  *   Software Foundation; either version 2 of the License, or (at your option)
    00012  *   any later version.
    00013  *
    00014  *   This program is distributed in the hope that it will be useful, but
    00015  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00016  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00017  *   for more details.
    00018  *
    00019  *   You should have received a copy of the GNU General Public License
    00020  *   along with this program; if not, write to the Free Software
    00021  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00022  */
    00023
    00024 /*
    00025  * This file must include only standard C header files.  The core code must
    00026  * compile on generic platforms that don't support glib, gimp, gtk, etc.
    00027  */
    00028
    00029 #ifdef HAVE_CONFIG_H
    00030 #include <config.h>
    00031 #endif
    00032 #include <gimp-print/gimp-print.h>
    00033 #include <gimp-print/gimp-print-intl-internal.h>
    00034 #include "gimp-print-internal.h"
    00035 #include <string.h>
    00036 #include "print-escp2.h"
    00037
    00038 #ifdef __GNUC__
    00039 #define inline __inline__
    00040 #endif
    00041
    00042 static escp2_privdata_t *
    00043 get_privdata(stp_vars_t *v)
    00044 {
    00045   return (escp2_privdata_t *) stp_get_component_data(v, "Driver");
    00046 }
    00047
    00048 static void
    00049 escp2_reset_printer(stp_vars_t *v)
    00050 {
    00051   escp2_privdata_t *pd = get_privdata(v);
    00052   /*
    00053    * Magic initialization string that's needed to take printer out of
    00054    * packet mode.
    00055    */
    00056   if (pd->init_sequence)
    00057     stp_zfwrite(pd->init_sequence->data, pd->init_sequence->bytes, 1, v);
    00058
    00059   stp_send_command(v, "\033@", "");
    00060 }
    00061
    00062 static void
    00063 print_remote_param(stp_vars_t *v, const char *param, const char *value)
    00064 {
    00065   stp_send_command(v, "\033(R", "bcscs", '\0', param, ':',
    00066                     value ? value : "NULL");
    00067   stp_send_command(v, "\033", "ccc", 0, 0, 0);
    00068 }
    00069
    00070 static void
    00071 print_remote_int_param(stp_vars_t *v, const char *param, int value)
    00072 {
    00073   char buf[64];
    00074   (void) snprintf(buf, 64, "%d", value);
    00075   print_remote_param(v, param, buf);
    00076 }
    00077
    00078 static void
    00079 print_remote_float_param(stp_vars_t *v, const char *param, double value)
    00080 {
    00081   char buf[64];
    00082   (void) snprintf(buf, 64, "%f", value);
    00083   print_remote_param(v, param, buf);
    00084 }
    00085
    00086 static void
    00087 print_debug_params(stp_vars_t *v)
    00088 {
    00089   escp2_privdata_t *pd = get_privdata(v);
    00090   stp_parameter_list_t params = stp_get_parameter_list(v);
    00091   int count = stp_parameter_list_count(params);
    00092   int i;
    00093   print_remote_param(v, "Package", PACKAGE);
    00094   print_remote_param(v, "Version", VERSION);
    00095   print_remote_param(v, "Release Date", RELEASE_DATE);
    00096   print_remote_param(v, "Driver", stp_get_driver(v));
    00097   print_remote_int_param(v, "Left", stp_get_left(v));
    00098   print_remote_int_param(v, "Top", stp_get_top(v));
    00099   print_remote_int_param(v, "Page Width", stp_get_page_width(v));
    00100   print_remote_int_param(v, "Page Height", stp_get_page_height(v));
    00101   print_remote_int_param(v, "Model", stp_get_model_id(v));
    00102   print_remote_int_param(v, "Ydpi", pd->res->vres);
    00103   print_remote_int_param(v, "Xdpi", pd->res->hres);
    00104   print_remote_int_param(v, "Use_softweave", pd->res->softweave);
    00105   print_remote_int_param(v, "Use_printer_weave", pd->res->printer_weave);
    00106   print_remote_int_param(v, "Use_printer_weave", pd->use_printer_weave);
    00107   print_remote_int_param(v, "Page_left", pd->page_left);
    00108   print_remote_int_param(v, "Page_right", pd->page_right);
    00109   print_remote_int_param(v, "Page_top", pd->page_top);
    00110   print_remote_int_param(v, "Page_bottom", pd->page_bottom);
    00111   print_remote_int_param(v, "Page_width", pd->page_width);
    00112   print_remote_int_param(v, "Page_height", pd->page_height);
    00113   print_remote_int_param(v, "Page_true_height", pd->page_true_height);
    00114   print_remote_int_param(v, "Image_left", pd->image_left);
    00115   print_remote_int_param(v, "Image_top", pd->image_top);
    00116   print_remote_int_param(v, "Image_width", pd->image_width);
    00117   print_remote_int_param(v, "Image_height", pd->image_height);
    00118   print_remote_int_param(v, "Image_scaled_width", pd->image_scaled_width);
    00119   print_remote_int_param(v, "Image_scaled_height", pd->image_scaled_height);
    00120   print_remote_int_param(v, "Image_printed_width", pd->image_printed_width);
    00121   print_remote_int_param(v, "Image_printed_height", pd->image_printed_height);
    00122   print_remote_int_param(v, "Image_left_position", pd->image_left_position);
    00123   print_remote_int_param(v, "Nozzles", pd->nozzles);
    00124   print_remote_int_param(v, "Nozzle_separation", pd->nozzle_separation);
    00125   print_remote_int_param(v, "Horizontal_passes", pd->horizontal_passes);
    00126   print_remote_int_param(v, "Vertical_passes", pd->res->vertical_passes);
    00127   print_remote_int_param(v, "Physical_xdpi", pd->physical_xdpi);
    00128   print_remote_int_param(v, "Page_management_units", pd->page_management_units);
    00129   print_remote_int_param(v, "Vertical_units", pd->vertical_units);
    00130   print_remote_int_param(v, "Horizontal_units", pd->horizontal_units);
    00131   print_remote_int_param(v, "Micro_units", pd->micro_units);
    00132   print_remote_int_param(v, "Unit_scale", pd->unit_scale);
    00133   print_remote_int_param(v, "Zero_advance", pd->send_zero_pass_advance);
    00134   print_remote_int_param(v, "Bits", pd->bitwidth);
    00135   print_remote_int_param(v, "Resid", pd->ink_resid);
    00136   print_remote_int_param(v, "Drop Size", pd->drop_size);
    00137   print_remote_int_param(v, "Initial_vertical_offset", pd->initial_vertical_offset);
    00138   print_remote_int_param(v, "Channels_in_use", pd->channels_in_use);
    00139   print_remote_int_param(v, "Logical_channels", pd->logical_channels);
    00140   print_remote_int_param(v, "Physical_channels", pd->physical_channels);
    00141   print_remote_int_param(v, "Use_black_parameters", pd->use_black_parameters);
    00142   print_remote_int_param(v, "Use_fast_360", pd->use_fast_360);
    00143   print_remote_int_param(v, "Command_set", pd->command_set);
    00144   print_remote_int_param(v, "Variable_dots", pd->variable_dots);
    00145   print_remote_int_param(v, "Has_vacuum", pd->has_vacuum);
    00146   print_remote_int_param(v, "Has_graymode", pd->has_graymode);
    00147   print_remote_int_param(v, "Base_separation", pd->base_separation);
    00148   print_remote_int_param(v, "Resolution_scale", pd->resolution_scale);
    00149   print_remote_int_param(v, "Printing_resolution", pd->printing_resolution);
    00150   print_remote_int_param(v, "Separation_rows", pd->separation_rows);
    00151   print_remote_int_param(v, "Pseudo_separation_rows", pd->pseudo_separation_rows);
    00152   print_remote_int_param(v, "Extra_720dpi_separation", pd->extra_720dpi_separation);
    00153   print_remote_param(v, "Ink name", pd->inkname->name);
    00154   print_remote_int_param(v, "  channels", pd->inkname->channel_set->channel_count);
    00155   print_remote_int_param(v, "  inkset", pd->inkname->inkset);
    00156   for (i = 0; i < count; i++)
    00157     {
    00158       const stp_parameter_t *p = stp_parameter_list_param(params, i);
    00159       switch (p->p_type)
    00160         {
    00161         case STP_PARAMETER_TYPE_DOUBLE:
    00162           if (stp_check_float_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00163             print_remote_float_param(v, p->name,
    00164                                      stp_get_float_parameter(v, p->name));
    00165           break;
    00166         case STP_PARAMETER_TYPE_INT:
    00167           if (stp_check_int_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00168             print_remote_int_param(v, p->name,
    00169                                    stp_get_int_parameter(v, p->name));
    00170           break;
    00171         case STP_PARAMETER_TYPE_DIMENSION:
    00172           if (stp_check_dimension_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00173             print_remote_int_param(v, p->name,
    00174                                    stp_get_dimension_parameter(v, p->name));
    00175           break;
    00176         case STP_PARAMETER_TYPE_BOOLEAN:
    00177           if (stp_check_boolean_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00178             print_remote_int_param(v, p->name,
    00179                                    stp_get_boolean_parameter(v, p->name));
    00180           break;
    00181         case STP_PARAMETER_TYPE_STRING_LIST:
    00182           if (stp_check_string_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00183             print_remote_param(v, p->name,
    00184                                stp_get_string_parameter(v, p->name));
    00185           break;
    00186         case STP_PARAMETER_TYPE_CURVE:
    00187           if (stp_check_curve_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
    00188             {
    00189               char *curve =
    00190                 stp_curve_write_string(stp_get_curve_parameter(v, p->name));
    00191               print_remote_param(v, p->name, curve);
    00192               stp_free(curve);
    00193             }
    00194           break;
    00195         default:
    00196           break;
    00197         }
    00198     }
    00199   stp_parameter_list_destroy(params);
    00200   stp_send_command(v, "\033", "ccc", 0, 0, 0);
    00201 }
    00202
    00203 static void
    00204 escp2_set_remote_sequence(stp_vars_t *v)
    00205 {
    00206   /* Magic remote mode commands, whatever they do */
    00207   escp2_privdata_t *pd = get_privdata(v);
    00208
    00209   if (stp_get_debug_level() & STP_DBG_MARK_FILE)
    00210     print_debug_params(v);
    00211   if (pd->advanced_command_set || pd->input_slot)
    00212     {
    00213       int feed_sequence = 0;
    00214       /* Enter remote mode */
    00215       stp_send_command(v, "\033(R", "bcs", 0, "REMOTE1");
    00216       if (pd->command_set == MODEL_COMMAND_PRO)
    00217         {
    00218           if (pd->paper_type)
    00219             {
    00220               stp_send_command(v, "PH", "bcc", 0,
    00221                                pd->paper_type->paper_thickness);
    00222               if (pd->has_vacuum)
    00223                 stp_send_command(v, "SN", "bccc", 0, 5,
    00224                                  pd->paper_type->vacuum_intensity);
    00225               stp_send_command(v, "SN", "bccc", 0, 4,
    00226                                pd->paper_type->feed_adjustment);
    00227             }
    00228         }
    00229       else if (pd->advanced_command_set)
    00230         {
    00231           if (pd->paper_type)
    00232             feed_sequence = pd->paper_type->paper_feed_sequence;
    00233           /* Function unknown */
    00234           stp_send_command(v, "PM", "bh", 0);
    00235           /* Set mechanism sequence */
    00236           stp_send_command(v, "SN", "bccc", 0, 0, feed_sequence);
    00237           if (stp_get_boolean_parameter(v, "FullBleed"))
    00238             stp_send_command(v, "FP", "bch", 0, 0xffb0);
    00239         }
    00240       if (pd->input_slot)
    00241         {
    00242           int divisor = pd->base_separation / 360;
    00243           int height = pd->page_true_height * 5 / divisor;
    00244           if (pd->input_slot->init_sequence.bytes)
    00245             stp_zfwrite(pd->input_slot->init_sequence.data,
    00246                         pd->input_slot->init_sequence.bytes, 1, v);
    00247           switch (pd->input_slot->roll_feed_cut_flags)
    00248             {
    00249             case ROLL_FEED_CUT_ALL:
    00250               stp_send_command(v, "JS", "bh", 0);
    00251               stp_send_command(v, "CO", "bccccl", 0, 0, 1, 0, 0);
    00252               stp_send_command(v, "CO", "bccccl", 0, 0, 0, 0, height);
    00253               break;
    00254             case ROLL_FEED_CUT_LAST:
    00255               stp_send_command(v, "CO", "bccccl", 0, 0, 1, 0, 0);
    00256               stp_send_command(v, "CO", "bccccl", 0, 0, 2, 0, height);
    00257               break;
    00258             default:
    00259               break;
    00260             }
    00261         }
    00262
    00263       /* Exit remote mode */
    00264
    00265       stp_send_command(v, "\033", "ccc", 0, 0, 0);
    00266     }
    00267 }
    00268
    00269 static void
    00270 escp2_set_graphics_mode(stp_vars_t *v)
    00271 {
    00272   stp_send_command(v, "\033(G", "bc", 1);
    00273 }
    00274
    00275 static void
    00276 escp2_set_resolution(stp_vars_t *v)
    00277 {
    00278   escp2_privdata_t *pd = get_privdata(v);
    00279   if (pd->use_extended_commands)
    00280     stp_send_command(v, "\033(U", "bccch",
    00281                      pd->unit_scale / pd->page_management_units,
    00282                      pd->unit_scale / pd->vertical_units,
    00283                      pd->unit_scale / pd->horizontal_units,
    00284                      pd->unit_scale);
    00285   else
    00286     stp_send_command(v, "\033(U", "bc",
    00287                      pd->unit_scale / pd->page_management_units);
    00288 }
    00289
    00290 static void
    00291 escp2_set_color(stp_vars_t *v)
    00292 {
    00293   escp2_privdata_t *pd = get_privdata(v);
    00294   if (pd->use_fast_360)
    00295     stp_send_command(v, "\033(K", "bcc", 0, 3);
    00296   else if (pd->has_graymode)
    00297     stp_send_command(v, "\033(K", "bcc", 0,
    00298                      (pd->use_black_parameters ? 1 : 2));
    00299 }
    00300
    00301 static void
    00302 escp2_set_printer_weave(stp_vars_t *v)
    00303 {
    00304   escp2_privdata_t *pd = get_privdata(v);
    00305   int printer_weave_parm = 0;
    00306   if (pd->printer_weave)
    00307     printer_weave_parm = pd->printer_weave->value;
    00308   else if (pd->res->printer_weave)
    00309     printer_weave_parm = pd->res->printer_weave;
    00310   stp_send_command(v, "\033(i", "bc", printer_weave_parm);
    00311 }
    00312
    00313 static void
    00314 escp2_set_printhead_speed(stp_vars_t *v)
    00315 {
    00316   escp2_privdata_t *pd = get_privdata(v);
    00317   const char *direction = stp_get_string_parameter(v, "PrintingDirection");
    00318   int unidirectional;
    00319   if (direction && strcmp(direction, "Unidirectional") == 0)
    00320     unidirectional = 1;
    00321   else if (direction && strcmp(direction, "Bidirectional") == 0)
    00322     unidirectional = 0;
    00323   else if (pd->res->hres >= 720 && pd->res->vres >= 720)
    00324     unidirectional = 1;
    00325   else
    00326     unidirectional = 0;
    00327   if (unidirectional)
    00328     {
    00329       stp_send_command(v, "\033U", "c", 1);
    00330       if (pd->res->hres > pd->printing_resolution)
    00331         stp_send_command(v, "\033(s", "bc", 2);
    00332     }
    00333   else
    00334     stp_send_command(v, "\033U", "c", 0);
    00335 }
    00336
    00337 static void
    00338 escp2_set_dot_size(stp_vars_t *v)
    00339 {
    00340   escp2_privdata_t *pd = get_privdata(v);
    00341   /* Dot size */
    00342   if (pd->drop_size >= 0)
    00343     stp_send_command(v, "\033(e", "bcc", 0, pd->drop_size);
    00344 }
    00345
    00346 static void
    00347 escp2_set_page_height(stp_vars_t *v)
    00348 {
    00349   escp2_privdata_t *pd = get_privdata(v);
    00350   int l = pd->page_management_units * pd->page_true_height / 72;
    00351   if (pd->use_extended_commands)
    00352     stp_send_command(v, "\033(C", "bl", l);
    00353   else
    00354     stp_send_command(v, "\033(C", "bh", l);
    00355 }
    00356
    00357 static void
    00358 escp2_set_margins(stp_vars_t *v)
    00359 {
    00360   escp2_privdata_t *pd = get_privdata(v);
    00361   int bot = pd->page_management_units * pd->page_bottom / 72;
    00362   int top = pd->page_management_units * pd->page_top / 72;
    00363
    00364   top += pd->initial_vertical_offset;
    00365   if (pd->use_extended_commands &&
    00366       (pd->command_set == MODEL_COMMAND_2000 ||
    00367        pd->command_set == MODEL_COMMAND_PRO))
    00368     stp_send_command(v, "\033(c", "bll", top, bot);
    00369   else
    00370     stp_send_command(v, "\033(c", "bhh", top, bot);
    00371 }
    00372
    00373 static void
    00374 escp2_set_form_factor(stp_vars_t *v)
    00375 {
    00376   escp2_privdata_t *pd = get_privdata(v);
    00377   if (pd->advanced_command_set)
    00378     {
    00379       int w = pd->page_width * pd->page_management_units / 72;
    00380       int h = pd->page_true_height * pd->page_management_units / 72;
    00381
    00382       if (stp_get_boolean_parameter(v, "FullBleed"))
    00383         /* Make the page 160/360" wider for full bleed printing. */
    00384         /* Per the Epson manual, the margin should be expanded by 80/360" */
    00385         /* so we need to do this on the left and the right */
    00386         w += 320 * pd->page_management_units / 720;
    00387
    00388       stp_send_command(v, "\033(S", "bll", w, h);
    00389     }
    00390 }
    00391
    00392 static void
    00393 escp2_set_printhead_resolution(stp_vars_t *v)
    00394 {
    00395   escp2_privdata_t *pd = get_privdata(v);
    00396   if (pd->use_extended_commands)
    00397     {
    00398       int xres;
    00399       int yres = pd->resolution_scale;
    00400
    00401       xres = pd->resolution_scale / pd->physical_xdpi;
    00402
    00403       if (pd->command_set == MODEL_COMMAND_PRO && !pd->res->softweave)
    00404         yres = yres /  pd->res->vres;
    00405       else
    00406         yres = yres * pd->nozzle_separation / pd->base_separation;
    00407
    00408       /* Magic resolution cookie */
    00409       stp_send_command(v, "\033(D", "bhcc", pd->resolution_scale, yres, xres);
    00410     }
    00411 }
    00412
    00413 static void
    00414 set_vertical_position(stp_vars_t *v, stp_pass_t *pass)
    00415 {
    00416   escp2_privdata_t *pd = get_privdata(v);
    00417   int advance = pass->logicalpassstart - pd->last_pass_offset -
    00418     (pd->separation_rows - 1);
    00419   advance = advance * pd->vertical_units / pd->res->vres;
    00420   if (pass->logicalpassstart > pd->last_pass_offset ||
    00421       (pd->send_zero_pass_advance && pass->pass > pd->last_pass) ||
    00422       pd->printing_initial_vertical_offset != 0)
    00423     {
    00424       advance += pd->printing_initial_vertical_offset;
    00425       pd->printing_initial_vertical_offset = 0;
    00426       if (pd->use_extended_commands)
    00427         stp_send_command(v, "\033(v", "bl", advance);
    00428       else
    00429         stp_send_command(v, "\033(v", "bh", advance);
    00430       pd->last_pass_offset = pass->logicalpassstart;
    00431       pd->last_pass = pass->pass;
    00432     }
    00433 }
    00434
    00435 static void
    00436 set_color(stp_vars_t *v, stp_pass_t *pass, int color)
    00437 {
    00438   escp2_privdata_t *pd = get_privdata(v);
    00439   if (pd->last_color != color && ! pd->use_extended_commands)
    00440     {
    00441       int ncolor = pd->channels[color]->color;
    00442       int subchannel = pd->channels[color]->subchannel;
    00443       if (subchannel >= 0)
    00444         stp_send_command(v, "\033(r", "bcc", subchannel, ncolor);
    00445       else
    00446         stp_send_command(v, "\033r", "c", ncolor);
    00447       pd->last_color = color;
    00448     }
    00449 }
    00450
    00451 static void
    00452 set_horizontal_position(stp_vars_t *v, stp_pass_t *pass, int vertical_subpass)
    00453 {
    00454   escp2_privdata_t *pd = get_privdata(v);
    00455   int microoffset = (vertical_subpass & (pd->horizontal_passes - 1)) *
    00456     pd->image_scaled_width / pd->image_printed_width;
    00457   int pos = pd->image_left_position + microoffset;
    00458
    00459   if (pos != 0)
    00460     {
    00461       /* Note hard-coded 1440 -- from Epson manuals */
    00462       if (pd->command_set == MODEL_COMMAND_PRO || pd->variable_dots)
    00463         stp_send_command(v, "\033($", "bl", pos);
    00464       else if (pd->advanced_command_set || pd->res->hres > 720)
    00465         stp_send_command(v, "\033(\\", "bhh", pd->micro_units, pos);
    00466       else
    00467         stp_send_command(v, "\033\\", "h", pos);
    00468     }
    00469 }
    00470
    00471 static void
    00472 send_print_command(stp_vars_t *v, stp_pass_t *pass, int color, int nlines)
    00473 {
    00474   escp2_privdata_t *pd = get_privdata(v);
    00475   int lwidth = (pd->image_printed_width + (pd->horizontal_passes - 1)) /
    00476     pd->horizontal_passes;
    00477   if (pd->command_set == MODEL_COMMAND_PRO || pd->variable_dots)
    00478     {
    00479       int ncolor = pd->channels[color]->color;
    00480       int subchannel = pd->channels[color]->subchannel;
    00481       int nwidth = pd->bitwidth * ((lwidth + 7) / 8);
    00482       if (subchannel >= 0)
    00483         ncolor |= (subchannel << 4);
    00484       stp_send_command(v, "\033i", "ccchh", ncolor, COMPRESSION,
    00485                        pd->bitwidth, nwidth, nlines);
    00486     }
    00487   else
    00488     {
    00489       int ygap = 3600 / pd->vertical_units;
    00490       int xgap = 3600 / pd->physical_xdpi;
    00491       if (pd->nozzles == 1)
    00492         {
    00493           if (pd->vertical_units == 720 && pd->extra_720dpi_separation)
    00494             ygap *= pd->extra_720dpi_separation;
    00495         }
    00496       else if (pd->extra_720dpi_separation)
    00497         ygap *= pd->extra_720dpi_separation;
    00498       else if (pd->pseudo_separation_rows > 0)
    00499         ygap *= pd->pseudo_separation_rows;
    00500       else
    00501         ygap *= pd->separation_rows;
    00502       stp_send_command(v, "\033.", "cccch", COMPRESSION, ygap, xgap, nlines,
    00503                        lwidth);
    00504     }
    00505 }
    00506
    00507 static void
    00508 send_extra_data(stp_vars_t *v, int extralines)
    00509 {
    00510   escp2_privdata_t *pd = get_privdata(v);
    00511   int lwidth = (pd->image_printed_width + (pd->horizontal_passes - 1)) /
    00512     pd->horizontal_passes;
    00513 #if TEST_UNCOMPRESSED
    00514   int i;
    00515   for (i = 0; i < pd->bitwidth * (lwidth + 7) / 8; i++)
    00516     stp_putc(0, v);
    00517 #else  /* !TEST_UNCOMPRESSED */
    00518   int k, l;
    00519   int bytes_to_fill = pd->bitwidth * ((lwidth + 7) / 8);
    00520   int full_blocks = bytes_to_fill / 128;
    00521   int leftover = bytes_to_fill % 128;
    00522   int total_bytes = extralines * (full_blocks + 1) * 2;
    00523   unsigned char *buf = stp_malloc(total_bytes);
    00524   total_bytes = 0;
    00525   for (k = 0; k < extralines; k++)
    00526     {
    00527       for (l = 0; l < full_blocks; l++)
    00528         {
    00529           buf[total_bytes++] = 129;
    00530           buf[total_bytes++] = 0;
    00531         }
    00532       if (leftover == 1)
    00533         {
    00534           buf[total_bytes++] = 1;
    00535           buf[total_bytes++] = 0;
    00536         }
    00537       else if (leftover > 0)
    00538         {
    00539           buf[total_bytes++] = 257 - leftover;
    00540           buf[total_bytes++] = 0;
    00541         }
    00542     }
    00543   stp_zfwrite((const char *) buf, total_bytes, 1, v);
    00544   stp_free(buf);
    00545 #endif /* TEST_UNCOMPRESSED */
    00546 }
    00547
    00548 void
    00549 stpi_escp2_init_printer(stp_vars_t *v)
    00550 {
    00551   escp2_reset_printer(v);
    00552   escp2_set_remote_sequence(v);
    00553   escp2_set_graphics_mode(v);
    00554   escp2_set_resolution(v);
    00555   escp2_set_color(v);
    00556   escp2_set_printer_weave(v);
    00557   escp2_set_printhead_speed(v);
    00558   escp2_set_dot_size(v);
    00559   escp2_set_printhead_resolution(v);
    00560   escp2_set_page_height(v);
    00561   escp2_set_margins(v);
    00562   escp2_set_form_factor(v);
    00563 }
    00564
    00565 void
    00566 stpi_escp2_deinit_printer(stp_vars_t *v)
    00567 {
    00568   escp2_privdata_t *pd = get_privdata(v);
    00569   stp_puts("\033@", v); /* ESC/P2 reset */
    00570   if (pd->advanced_command_set || pd->input_slot)
    00571     {
    00572       stp_send_command(v, "\033(R", "bcs", 0, "REMOTE1");
    00573       if (pd->input_slot && pd->input_slot->deinit_sequence.bytes)
    00574         stp_zfwrite(pd->input_slot->deinit_sequence.data,
    00575                     pd->input_slot->deinit_sequence.bytes, 1, v);
    00576       /* Load settings from NVRAM */
    00577       stp_send_command(v, "LD", "b");
    00578
    00579       /* Magic deinit sequence reported by Simone Falsini */
    00580       if (pd->deinit_sequence)
    00581         stp_zfwrite(pd->deinit_sequence->data, pd->deinit_sequence->bytes,
    00582                     1, v);
    00583       /* Exit remote mode */
    00584       stp_send_command(v, "\033", "ccc", 0, 0, 0);
    00585     }
    00586 }
    00587
    00588 void
    00589 stpi_escp2_flush_pass(stp_vars_t *v, int passno, int vertical_subpass)
    00590 {
    00591   int j;
    00592   escp2_privdata_t *pd = get_privdata(v);
    00593   stp_lineoff_t *lineoffs = stp_get_lineoffsets_by_pass(v, passno);
    00594   stp_lineactive_t *lineactive = stp_get_lineactive_by_pass(v, passno);
    00595   const stp_linebufs_t *bufs = stp_get_linebases_by_pass(v, passno);
    00596   stp_pass_t *pass = stp_get_pass_by_pass(v, passno);
    00597   stp_linecount_t *linecount = stp_get_linecount_by_pass(v, passno);
    00598   int minlines = pd->min_nozzles;
    00599
    00600   for (j = 0; j < pd->channels_in_use; j++)
    00601     {
    00602       if (lineactive[0].v[j] > 0)
    00603         {
    00604           int nlines = linecount[0].v[j];
    00605           int extralines = 0;
    00606           if (nlines < minlines)
    00607             {
    00608               extralines = minlines - nlines;
    00609               nlines = minlines;
    00610             }
    00611           set_vertical_position(v, pass);
    00612           set_color(v, pass, j);
    00613           set_horizontal_position(v, pass, vertical_subpass);
    00614           send_print_command(v, pass, j, nlines);
    00615
    00616           /*
    00617            * Send the data
    00618            */
    00619           stp_zfwrite((const char *)bufs[0].v[j], lineoffs[0].v[j], 1, v);
    00620           if (extralines)
    00621             send_extra_data(v, extralines);
    00622           stp_send_command(v, "\r", "");
    00623           pd->printed_something = 1;
    00624         }
    00625       lineoffs[0].v[j] = 0;
    00626       linecount[0].v[j] = 0;
    00627     }
    00628 }
    00629
    00630 void
    00631 stpi_escp2_terminate_page(stp_vars_t *v)
    00632 {
    00633   escp2_privdata_t *pd = get_privdata(v);
    00634   if (!pd->input_slot ||
    00635       pd->input_slot->roll_feed_cut_flags != ROLL_FEED_DONT_EJECT)
    00636     {
    00637       if (!pd->printed_something)
    00638         stp_send_command(v, "\n", "");
    00639       stp_send_command(v, "\f", "");    /* Eject page */
    00640     }
    00641 }