/*
*
* Print plug-in EPSON ESC/P2 driver for the GIMP.
*
* Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
* Robert Krawitz (rlk@alum.mit.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
/*
* This file must include only standard C header files. The core code must
* compile on generic platforms that don't support glib, gimp, gtk, etc.
*/
#ifdef HAVE_CONFIG_H
#include
#endif
#include
#include
#include "gutenprint-internal.h"
#include
#include "print-escp2.h"
#ifdef __GNUC__
#define inline __inline__
#endif
static escp2_privdata_t *
get_privdata(stp_vars_t *v)
{
return (escp2_privdata_t *) stp_get_component_data(v, "Driver");
}
static void
escp2_reset_printer(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
/*
* Magic initialization string that's needed to take printer out of
* packet mode.
*/
if (pd->preinit_sequence)
stp_write_raw(pd->preinit_sequence, v);
stp_send_command(v, "\033@", "");
}
static void
print_remote_param(stp_vars_t *v, const char *param, const char *value)
{
stp_send_command(v, "\033(R", "bcscs", '\0', param, ':',
value ? value : "NULL");
stp_send_command(v, "\033", "ccc", 0, 0, 0);
}
static void
print_remote_int_param(stp_vars_t *v, const char *param, int value)
{
char buf[64];
(void) snprintf(buf, 64, "%d", value);
print_remote_param(v, param, buf);
}
static void
print_remote_float_param(stp_vars_t *v, const char *param, double value)
{
char buf[64];
(void) snprintf(buf, 64, "%f", value);
print_remote_param(v, param, buf);
}
static void
print_remote_dim_param(stp_vars_t *v, const char *param, double value)
{
print_remote_float_param(v, param, value);
}
static void
print_debug_params(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
stp_parameter_list_t params = stp_get_parameter_list(v);
int count = stp_parameter_list_count(params);
int i;
print_remote_param(v, "Package", PACKAGE);
print_remote_param(v, "Version", VERSION);
print_remote_param(v, "Release Date", RELEASE_DATE);
print_remote_param(v, "Driver", stp_get_driver(v));
print_remote_dim_param(v, "Left", stp_get_left(v));
print_remote_dim_param(v, "Top", stp_get_top(v));
print_remote_dim_param(v, "Page Width", stp_get_page_width(v));
print_remote_dim_param(v, "Page Height", stp_get_page_height(v));
print_remote_int_param(v, "Model", stp_get_model_id(v));
print_remote_int_param(v, "Ydpi", pd->res->vres);
print_remote_int_param(v, "Xdpi", pd->res->hres);
print_remote_int_param(v, "Printed_ydpi", pd->res->printed_vres);
print_remote_int_param(v, "Printed_xdpi", pd->res->printed_hres);
/*
print_remote_int_param(v, "Use_softweave", pd->res->softweave);
print_remote_int_param(v, "Printer_weave", pd->res->printer_weave);
*/
print_remote_int_param(v, "Use_printer_weave", pd->use_printer_weave);
print_remote_int_param(v, "Duplex", pd->duplex);
print_remote_dim_param(v, "Page_left", pd->page_left);
print_remote_dim_param(v, "Page_right", pd->page_right);
print_remote_dim_param(v, "Page_top", pd->page_top);
print_remote_dim_param(v, "Page_bottom", pd->page_bottom);
print_remote_dim_param(v, "Page_width", pd->page_width);
print_remote_dim_param(v, "Page_height", pd->page_height);
print_remote_dim_param(v, "Page_true_height", pd->page_true_height);
print_remote_dim_param(v, "Page_extra_height", pd->page_extra_height);
print_remote_dim_param(v, "Paper_extra_bottom", pd->paper_extra_bottom);
print_remote_dim_param(v, "Image_left", pd->image_left);
print_remote_dim_param(v, "Image_top", pd->image_top);
print_remote_dim_param(v, "Image_width", pd->image_width);
print_remote_dim_param(v, "Image_height", pd->image_height);
print_remote_dim_param(v, "CD_X_offset", pd->cd_x_offset);
print_remote_dim_param(v, "CD_Y_offset", pd->cd_y_offset);
print_remote_dim_param(v, "CD_inner_radius", pd->cd_inner_radius);
print_remote_dim_param(v, "CD_outer_radius", pd->cd_outer_radius);
print_remote_int_param(v, "Image_scaled_width", pd->image_scaled_width);
print_remote_int_param(v, "Image_scaled_height", pd->image_scaled_height);
print_remote_int_param(v, "Image_printed_width", pd->image_printed_width);
print_remote_int_param(v, "Image_printed_height", pd->image_printed_height);
print_remote_int_param(v, "Image_left_position", pd->image_left_position);
print_remote_int_param(v, "Nozzles", pd->nozzles);
print_remote_int_param(v, "Nozzle_separation", pd->nozzle_separation);
print_remote_int_param(v, "Horizontal_passes", pd->horizontal_passes);
print_remote_int_param(v, "Vertical_passes", pd->res->vertical_passes);
print_remote_int_param(v, "Physical_xdpi", pd->physical_xdpi);
print_remote_int_param(v, "Page_management_units", pd->page_management_units);
print_remote_int_param(v, "Vertical_units", pd->vertical_units);
print_remote_int_param(v, "Horizontal_units", pd->horizontal_units);
print_remote_int_param(v, "Micro_units", pd->micro_units);
print_remote_int_param(v, "Unit_scale", pd->unit_scale);
print_remote_int_param(v, "Zero_advance", pd->send_zero_pass_advance);
print_remote_int_param(v, "Bits", pd->bitwidth);
print_remote_int_param(v, "Drop Size", pd->drop_size);
print_remote_int_param(v, "Initial_vertical_offset", pd->initial_vertical_offset);
print_remote_int_param(v, "Channels_in_use", pd->channels_in_use);
print_remote_int_param(v, "Logical_channels", pd->logical_channels);
print_remote_int_param(v, "Physical_channels", pd->physical_channels);
print_remote_int_param(v, "Use_black_parameters", pd->use_black_parameters);
print_remote_int_param(v, "Use_fast_360", pd->use_fast_360);
print_remote_int_param(v, "Command_set", pd->command_set);
print_remote_int_param(v, "Variable_dots", pd->variable_dots);
print_remote_int_param(v, "Has_graymode", pd->has_graymode);
print_remote_int_param(v, "Base_separation", pd->base_separation);
print_remote_int_param(v, "Resolution_scale", pd->resolution_scale);
#if 0
print_remote_int_param(v, "Printing_resolution", pd->printing_resolution);
#endif
print_remote_int_param(v, "Separation_rows", pd->separation_rows);
print_remote_int_param(v, "Pseudo_separation_rows", pd->pseudo_separation_rows);
print_remote_int_param(v, "Extra_720dpi_separation", pd->extra_720dpi_separation);
print_remote_int_param(v, "Use_aux_channels", pd->use_aux_channels);
print_remote_param(v, "Ink name", pd->inkname->name);
print_remote_int_param(v, " channels", pd->inkname->channel_count);
print_remote_int_param(v, " inkset", pd->inkname->inkset);
for (i = 0; i < count; i++)
{
const stp_parameter_t *p = stp_parameter_list_param(params, i);
switch (p->p_type)
{
case STP_PARAMETER_TYPE_DOUBLE:
if (stp_check_float_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
print_remote_float_param(v, p->name,
stp_get_float_parameter(v, p->name));
break;
case STP_PARAMETER_TYPE_INT:
if (stp_check_int_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
print_remote_int_param(v, p->name,
stp_get_int_parameter(v, p->name));
break;
case STP_PARAMETER_TYPE_DIMENSION:
if (stp_check_dimension_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
print_remote_int_param(v, p->name,
stp_get_dimension_parameter(v, p->name));
break;
case STP_PARAMETER_TYPE_BOOLEAN:
if (stp_check_boolean_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
print_remote_int_param(v, p->name,
stp_get_boolean_parameter(v, p->name));
break;
case STP_PARAMETER_TYPE_STRING_LIST:
if (stp_check_string_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
print_remote_param(v, p->name,
stp_get_string_parameter(v, p->name));
break;
case STP_PARAMETER_TYPE_CURVE:
if (stp_check_curve_parameter(v, p->name, STP_PARAMETER_DEFAULTED))
{
char *curve =
stp_curve_write_string(stp_get_curve_parameter(v, p->name));
print_remote_param(v, p->name, curve);
stp_free(curve);
}
break;
default:
break;
}
}
stp_parameter_list_destroy(params);
stp_send_command(v, "\033", "ccc", 0, 0, 0);
}
static void
escp2_set_remote_sequence(stp_vars_t *v)
{
/* Magic remote mode commands, whatever they do */
escp2_privdata_t *pd = get_privdata(v);
const stp_vars_t *pv = pd->media_settings;
if (stp_get_debug_level() & STP_DBG_MARK_FILE)
print_debug_params(v);
if (pd->advanced_command_set || pd->input_slot)
{
/* Enter remote mode */
stp_send_command(v, "\033(R", "bcs", 0, "REMOTE1");
/* Per the manual, job setup comes first, then SN command */
if (pd->input_slot &&
pd->input_slot->roll_feed_cut_flags == ROLL_FEED_CUT_ALL)
stp_send_command(v, "JS", "bh", 0);
if (pd->preinit_remote_sequence)
stp_write_raw(pd->preinit_remote_sequence, v);
if (stp_check_int_parameter(pv, "FeedAdjustment", STP_PARAMETER_ACTIVE))
stp_send_command(v, "SN", "bccc", 0, 4,
stp_get_int_parameter(pv, "FeedAdjustment"));
if (stp_check_int_parameter(pv, "VacuumIntensity", STP_PARAMETER_ACTIVE))
stp_send_command(v, "SN", "bccc", 0, 5,
stp_get_int_parameter(pv, "VacuumIntensity"));
if (stp_check_float_parameter(pv, "ScanDryTime", STP_PARAMETER_ACTIVE))
stp_send_command(v, "DR", "bcch", 0, 0,
(int) (stp_get_float_parameter(pv, "ScanDryTime") * 1000));
if (stp_check_float_parameter(pv, "ScanMinDryTime", STP_PARAMETER_ACTIVE))
stp_send_command(v, "DR", "bcch", 0, 0x40,
(int) (stp_get_float_parameter(pv, "ScanMinDryTime") * 1000));
if (stp_check_float_parameter(pv, "PageDryTime", STP_PARAMETER_ACTIVE))
stp_send_command(v, "DR", "bcch", 0, 1,
(int) stp_get_float_parameter(pv, "PageDryTime"));
/* Next comes paper path */
if (pd->input_slot)
{
int divisor = pd->base_separation / 360;
int height = pd->page_true_height * 5 / divisor;
if (pd->input_slot->init_sequence)
stp_write_raw(pd->input_slot->init_sequence, v);
switch (pd->input_slot->roll_feed_cut_flags)
{
case ROLL_FEED_CUT_ALL:
stp_send_command(v, "CO", "bccccl", 0, 0, 1, 0, 0);
stp_send_command(v, "CO", "bccccl", 0, 0, 0, 0, height);
break;
case ROLL_FEED_CUT_LAST:
stp_send_command(v, "CO", "bccccl", 0, 0, 1, 0, 0);
stp_send_command(v, "CO", "bccccl", 0, 0, 2, 0, height);
break;
default:
break;
}
}
if (stp_check_int_parameter(pv, "PaperMedia", STP_PARAMETER_ACTIVE))
stp_send_command(v, "MI", "bcccc", 0, 1,
stp_get_int_parameter(pv, "PaperMedia"),
(stp_check_int_parameter(pv, "PaperMediaSize", STP_PARAMETER_ACTIVE) ?
stp_get_int_parameter(pv, "PaperMediaSize") :
99)); /* User-defined size (for now!) */
if (pd->duplex)
{
/* If there's ever duplex no tumble, we'll need to special
case it, too */
if (pd->duplex == DUPLEX_TUMBLE && pd->input_slot && (pd->input_slot->duplex & DUPLEX_TUMBLE))
stp_send_command(v, "DP", "bcc", 0, 2); /* Auto duplex */
else
stp_send_command(v, "DP", "bcc", 0, 2); /* Auto duplex */
}
if (stp_check_int_parameter(pv, "PaperThickness", STP_PARAMETER_ACTIVE))
stp_send_command(v, "PH", "bcc", 0,
stp_get_int_parameter(pv, "PaperThickness"));
if (stp_check_int_parameter(pv, "FeedSequence", STP_PARAMETER_ACTIVE))
stp_send_command(v, "SN", "bccc", 0, 0,
stp_get_int_parameter(pv, "FeedSequence"));
if (stp_check_int_parameter(pv, "PlatenGap", STP_PARAMETER_ACTIVE))
stp_send_command(v, "US", "bccc", 0, 1,
stp_get_int_parameter(pv, "PlatenGap"));
if (stp_get_boolean_parameter(v, "FullBleed"))
{
stp_send_command(v, "FP", "bch", 0,
(unsigned short) -pd->zero_margin_offset);
if (pd->borderless_sequence)
stp_write_raw(pd->borderless_sequence, v);
}
if (pd->inkname->init_sequence)
stp_write_raw(pd->inkname->init_sequence, v);
/* Exit remote mode */
stp_send_command(v, "\033", "ccc", 0, 0, 0);
}
}
static void
escp2_set_graphics_mode(stp_vars_t *v)
{
stp_send_command(v, "\033(G", "bc", 1);
}
static void
escp2_set_resolution(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->use_extended_commands)
stp_send_command(v, "\033(U", "bccch",
pd->unit_scale / pd->page_management_units,
pd->unit_scale / pd->vertical_units,
pd->unit_scale / pd->horizontal_units,
pd->unit_scale);
else
stp_send_command(v, "\033(U", "bc",
pd->unit_scale / pd->page_management_units);
}
static void
escp2_set_color(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->use_fast_360)
stp_send_command(v, "\033(K", "bcc", 0, 3);
else if (pd->has_graymode)
stp_send_command(v, "\033(K", "bcc", 0,
(pd->use_black_parameters ? 1 : 2));
}
static void
escp2_set_printer_weave(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->printer_weave)
stp_write_raw(pd->printer_weave, v);
else
stp_send_command(v, "\033(i", "bc", 0);
}
static void
escp2_set_printhead_speed(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
const char *direction = stp_get_string_parameter(v, "PrintingDirection");
int unidirectional = -1;
if (direction && strcmp(direction, "Unidirectional") == 0)
unidirectional = 1;
else if (direction && strcmp(direction, "Bidirectional") == 0)
unidirectional = 0;
else if (pd->bidirectional_upper_limit >= 0 &&
pd->res->printed_hres * pd->res->printed_vres *
pd->res->vertical_passes >= pd->bidirectional_upper_limit)
{
stp_dprintf(STP_DBG_ESCP2, v,
"Setting unidirectional: hres %d vres %d passes %d total %d limit %d\n",
pd->res->printed_hres, pd->res->printed_vres,
pd->res->vertical_passes,
(pd->res->printed_hres * pd->res->printed_vres *
pd->res->vertical_passes),
pd->bidirectional_upper_limit);
unidirectional = 1;
}
else if (pd->bidirectional_upper_limit >= 0)
{
stp_dprintf(STP_DBG_ESCP2, v,
"Setting bidirectional: hres %d vres %d passes %d total %d limit %d\n",
pd->res->printed_hres, pd->res->printed_vres,
pd->res->vertical_passes,
(pd->res->printed_hres * pd->res->printed_vres *
pd->res->vertical_passes),
pd->bidirectional_upper_limit);
unidirectional = 0;
}
if (unidirectional == 1)
{
stp_send_command(v, "\033U", "c", 1);
if (pd->res->hres > pd->physical_xdpi)
stp_send_command(v, "\033(s", "bc", 2);
}
else if (unidirectional == 0)
stp_send_command(v, "\033U", "c", 0);
}
static void
escp2_set_dot_size(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
/* Dot size */
if (pd->drop_size >= 0)
stp_send_command(v, "\033(e", "bcc", 0, pd->drop_size);
}
static void
escp2_set_page_height(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
int l = (pd->page_true_height + pd->paper_extra_bottom) *
pd->page_management_units / 72;
if (pd->use_extended_commands)
stp_send_command(v, "\033(C", "bl", l);
else
stp_send_command(v, "\033(C", "bh", l);
}
static void
escp2_set_margins(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
int bot = pd->page_management_units * pd->page_bottom / 72;
int top = pd->page_management_units * pd->page_top / 72;
top += pd->initial_vertical_offset;
top -= pd->page_extra_height;
bot += pd->page_extra_height;
if (pd->use_extended_commands &&
(pd->command_set == MODEL_COMMAND_2000 ||
pd->command_set == MODEL_COMMAND_PRO))
stp_send_command(v, "\033(c", "bll", top, bot);
else
stp_send_command(v, "\033(c", "bhh", top, bot);
}
static void
escp2_set_paper_dimensions(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->advanced_command_set)
{
const stp_vars_t *pv = pd->media_settings;
int w = pd->page_true_width * pd->page_management_units / 72;
int h = (pd->page_true_height + pd->paper_extra_bottom) *
pd->page_management_units / 72;
stp_send_command(v, "\033(S", "bll", w, h);
if (stp_check_int_parameter(pv, "PrintMethod", STP_PARAMETER_ACTIVE))
stp_send_command(v, "\033(m", "bc",
stp_get_int_parameter(pv, "PrintMethod"));
}
}
static void
escp2_set_printhead_resolution(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->use_extended_commands)
{
int xres;
int yres = pd->resolution_scale;
xres = pd->resolution_scale / pd->physical_xdpi;
if (pd->command_set == MODEL_COMMAND_PRO && pd->printer_weave)
yres = yres / pd->res->vres;
else if (pd->split_channel_count > 1)
yres = yres * pd->nozzle_separation / pd->base_separation *
pd->split_channel_count;
else
yres = yres * pd->nozzle_separation / pd->base_separation;
/* Magic resolution cookie */
stp_send_command(v, "\033(D", "bhcc", pd->resolution_scale, yres, xres);
}
}
static void
set_vertical_position(stp_vars_t *v, stp_pass_t *pass)
{
escp2_privdata_t *pd = get_privdata(v);
int advance = pass->logicalpassstart - pd->last_pass_offset -
(pd->separation_rows - 1);
advance = advance * pd->vertical_units / pd->res->printed_vres;
if (pass->logicalpassstart > pd->last_pass_offset ||
(pd->send_zero_pass_advance && pass->pass > pd->last_pass) ||
pd->printing_initial_vertical_offset != 0)
{
advance += pd->printing_initial_vertical_offset;
pd->printing_initial_vertical_offset = 0;
if (pd->use_extended_commands)
stp_send_command(v, "\033(v", "bl", advance);
else
stp_send_command(v, "\033(v", "bh", advance);
pd->last_pass_offset = pass->logicalpassstart;
pd->last_pass = pass->pass;
}
}
static void
set_color(stp_vars_t *v, stp_pass_t *pass, int color)
{
escp2_privdata_t *pd = get_privdata(v);
if (pd->last_color != color && ! pd->use_extended_commands)
{
int ncolor = pd->channels[color]->color;
int subchannel = pd->channels[color]->subchannel;
if (subchannel >= 0)
stp_send_command(v, "\033(r", "bcc", subchannel, ncolor);
else
stp_send_command(v, "\033r", "c", ncolor);
pd->last_color = color;
}
}
static void
set_horizontal_position(stp_vars_t *v, stp_pass_t *pass, int vertical_subpass)
{
escp2_privdata_t *pd = get_privdata(v);
int microoffset = (vertical_subpass & (pd->horizontal_passes - 1)) *
pd->image_scaled_width / pd->image_printed_width;
int pos = pd->image_left_position + microoffset;
if (pos != 0)
{
if (pd->command_set == MODEL_COMMAND_PRO || pd->variable_dots)
stp_send_command(v, "\033($", "bl", pos);
else if (pd->advanced_command_set || pd->res->hres > 720)
stp_send_command(v, "\033(\\", "bhh", pd->micro_units, pos);
else
stp_send_command(v, "\033\\", "h", pos);
}
}
static void
send_print_command(stp_vars_t *v, stp_pass_t *pass, int ncolor, int nlines)
{
escp2_privdata_t *pd = get_privdata(v);
int lwidth = (pd->image_printed_width + (pd->horizontal_passes - 1)) /
pd->horizontal_passes;
if (pd->command_set == MODEL_COMMAND_PRO || pd->variable_dots)
{
int nwidth = pd->bitwidth * ((lwidth + 7) / 8);
stp_send_command(v, "\033i", "ccchh", ncolor,
(stp_get_debug_level() & STP_DBG_NO_COMPRESSION) ? 0 : 1,
pd->bitwidth, nwidth, nlines);
}
else
{
int ygap = 3600 / pd->vertical_units;
int xgap = 3600 / pd->physical_xdpi;
if (pd->nozzles == 1)
{
if (pd->vertical_units == 720 && pd->extra_720dpi_separation)
ygap *= pd->extra_720dpi_separation;
}
else if (pd->extra_720dpi_separation)
ygap *= pd->extra_720dpi_separation;
else if (pd->pseudo_separation_rows > 0)
ygap *= pd->pseudo_separation_rows;
else
ygap *= pd->separation_rows;
stp_send_command(v, "\033.", "cccch",
(stp_get_debug_level() & STP_DBG_NO_COMPRESSION) ? 0 : 1,
ygap, xgap, nlines, lwidth);
}
}
static void
send_extra_data(stp_vars_t *v, int extralines)
{
escp2_privdata_t *pd = get_privdata(v);
int lwidth = (pd->image_printed_width + (pd->horizontal_passes - 1)) /
pd->horizontal_passes;
if (stp_get_debug_level() & STP_DBG_NO_COMPRESSION)
{
int i, k;
for (k = 0; k < extralines; k++)
for (i = 0; i < pd->bitwidth * (lwidth + 7) / 8; i++)
stp_putc(0, v);
}
else
{
int k, l;
int bytes_to_fill = pd->bitwidth * ((lwidth + 7) / 8);
int full_blocks = bytes_to_fill / 128;
int leftover = bytes_to_fill % 128;
int total_bytes = extralines * (full_blocks + 1) * 2;
unsigned char *buf = stp_malloc(total_bytes);
total_bytes = 0;
for (k = 0; k < extralines; k++)
{
for (l = 0; l < full_blocks; l++)
{
buf[total_bytes++] = 129;
buf[total_bytes++] = 0;
}
if (leftover == 1)
{
buf[total_bytes++] = 1;
buf[total_bytes++] = 0;
}
else if (leftover > 0)
{
buf[total_bytes++] = 257 - leftover;
buf[total_bytes++] = 0;
}
}
stp_zfwrite((const char *) buf, total_bytes, 1, v);
stp_free(buf);
}
}
void
stpi_escp2_init_printer(stp_vars_t *v)
{
escp2_reset_printer(v);
escp2_set_remote_sequence(v);
escp2_set_graphics_mode(v);
escp2_set_resolution(v);
escp2_set_color(v);
escp2_set_printer_weave(v);
escp2_set_printhead_speed(v);
escp2_set_dot_size(v);
escp2_set_printhead_resolution(v);
escp2_set_page_height(v);
escp2_set_margins(v);
escp2_set_paper_dimensions(v);
}
void
stpi_escp2_deinit_printer(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
stp_puts("\033@", v); /* ESC/P2 reset */
if (pd->advanced_command_set || pd->input_slot)
{
stp_send_command(v, "\033(R", "bcs", 0, "REMOTE1");
if (pd->inkname->deinit_sequence)
stp_write_raw(pd->inkname->deinit_sequence, v);
if (pd->input_slot && pd->input_slot->deinit_sequence)
stp_write_raw(pd->input_slot->deinit_sequence, v);
/* Load settings from NVRAM */
stp_send_command(v, "LD", "b");
/* Magic deinit sequence reported by Simone Falsini */
if (pd->deinit_remote_sequence)
stp_write_raw(pd->deinit_remote_sequence, v);
/* Exit remote mode */
stp_send_command(v, "\033", "ccc", 0, 0, 0);
}
}
void
stpi_escp2_flush_pass(stp_vars_t *v, int passno, int vertical_subpass)
{
int j;
escp2_privdata_t *pd = get_privdata(v);
stp_lineoff_t *lineoffs = stp_get_lineoffsets_by_pass(v, passno);
stp_lineactive_t *lineactive = stp_get_lineactive_by_pass(v, passno);
const stp_linebufs_t *bufs = stp_get_linebases_by_pass(v, passno);
stp_pass_t *pass = stp_get_pass_by_pass(v, passno);
stp_linecount_t *linecount = stp_get_linecount_by_pass(v, passno);
int minlines = pd->min_nozzles;
int nozzle_start = pd->nozzle_start;
for (j = 0; j < pd->channels_in_use; j++)
{
if (lineactive->v[j] > 0)
{
int ncolor = pd->channels[j]->color;
int subchannel = pd->channels[j]->subchannel;
int nlines = linecount->v[j];
int extralines = 0;
set_vertical_position(v, pass);
set_color(v, pass, j);
if (subchannel >= 0)
ncolor |= (subchannel << 4);
if (pd->split_channels)
{
int sc = pd->split_channel_count;
int k, l;
int minlines_lo, nozzle_start_lo;
minlines /= sc;
nozzle_start /= sc;
minlines_lo = pd->min_nozzles - (minlines * sc);
nozzle_start_lo = pd->nozzle_start - (nozzle_start * sc);
for (k = 0; k < sc; k++)
{
int ml = minlines + (k < minlines_lo ? 1 : 0);
int ns = nozzle_start + (k < nozzle_start_lo ? 1 : 0);
int lc = ((nlines + (sc - k - 1)) / sc);
int base = (pd->nozzle_start + k) % sc;
if (lc < ml)
extralines = ml - lc;
else
extralines = 0;
extralines -= ns;
if (extralines < 0)
extralines = 0;
if (lc + extralines > 0)
{
int sc_off = k + j * sc;
set_horizontal_position(v, pass, vertical_subpass);
send_print_command(v, pass, pd->split_channels[sc_off],
lc + extralines + ns);
if (ns > 0)
send_extra_data(v, ns);
for (l = 0; l < lc; l++)
{
int sp = (l * sc) + base;
unsigned long offset = sp * pd->split_channel_width;
if (!(stp_get_debug_level() & STP_DBG_NO_COMPRESSION))
{
unsigned char *comp_ptr;
stp_pack_tiff(v, bufs->v[j] + offset,
pd->split_channel_width,
pd->comp_buf, &comp_ptr, NULL, NULL);
stp_zfwrite((const char *) pd->comp_buf,
comp_ptr - pd->comp_buf, 1, v);
}
else
stp_zfwrite((const char *) bufs->v[j] + offset,
pd->split_channel_width, 1, v);
}
if (extralines > 0)
send_extra_data(v, extralines);
stp_send_command(v, "\r", "");
}
}
}
else
{
set_horizontal_position(v, pass, vertical_subpass);
if (nlines < minlines)
{
extralines = minlines - nlines;
nlines = minlines;
}
send_print_command(v, pass, ncolor, nlines);
extralines -= nozzle_start;
/*
* Send the data
*/
if (nozzle_start)
send_extra_data(v, nozzle_start);
stp_zfwrite((const char *)bufs->v[j], lineoffs->v[j], 1, v);
if (extralines > 0)
send_extra_data(v, extralines);
stp_send_command(v, "\r", "");
}
pd->printed_something = 1;
}
lineoffs->v[j] = 0;
linecount->v[j] = 0;
}
}
void
stpi_escp2_terminate_page(stp_vars_t *v)
{
escp2_privdata_t *pd = get_privdata(v);
if (!pd->input_slot ||
!(pd->input_slot->roll_feed_cut_flags & ROLL_FEED_DONT_EJECT))
{
if (!pd->printed_something)
stp_send_command(v, "\n", "");
stp_send_command(v, "\f", ""); /* Eject page */
}
}