sane-project-backends/backend/snapscan-options.c

1413 wiersze
52 KiB
C

/* sane - Scanner Access Now Easy.
Copyright (C) 1997, 1998, 2001 Franck Schnefra, Michel Roelofs,
Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Mikael Magnusson,
Oliver Schwartz and Kevin Charter
This file is part of the SANE package.
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA.
As a special exception, the authors of SANE give permission for
additional uses of the libraries contained in this release of SANE.
The exception is that, if you link a SANE library with other files
to produce an executable, this does not by itself cause the
resulting executable to be covered by the GNU General Public
License. Your use of that executable is in no way restricted on
account of linking the SANE library code into it.
This exception does not, however, invalidate any other reasons why
the executable file might be covered by the GNU General Public
License.
If you submit changes to SANE to the maintainers to be included in
a subsequent release, you agree by submitting the changes that
those changes may be distributed with this exception intact.
If you write modifications of your own for SANE, it is your choice
whether to permit this exception to apply to your modifications.
If you do not wish that, delete this exception notice.
This file is a component of the implementation of a backend for many
of the the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners. */
/* $Id$
SANE SnapScan backend */
/* ranges */
static const SANE_Range x_range_fb =
{
SANE_FIX (0.0), SANE_FIX (216.0), 0
}; /* mm */
static const SANE_Range y_range_fb =
{
SANE_FIX (0.0), SANE_FIX (297.0), 0
}; /* mm */
/* default TPO range (shortest y_range
to avoid tray collision.
*/
static const SANE_Range x_range_tpo_default =
{
SANE_FIX (0.0), SANE_FIX (129.0), 0
}; /* mm */
static const SANE_Range y_range_tpo_default =
{
SANE_FIX (0.0), SANE_FIX (180.0), 0
}; /* mm */
/* TPO range for the Agfa 1236 */
static const SANE_Range x_range_tpo_1236 =
{
SANE_FIX (0.0), SANE_FIX (203.0), 0
}; /* mm */
static const SANE_Range y_range_tpo_1236 =
{
SANE_FIX (0.0), SANE_FIX (254.0), 0
}; /* mm */
/* TPO range for the Agfa e50 */
static const SANE_Range x_range_tpo_e50 =
{
SANE_FIX (0.0), SANE_FIX (40.0), 0
}; /* mm */
static const SANE_Range y_range_tpo_e50 =
{
SANE_FIX (0.0), SANE_FIX (240.0), 0
}; /* mm */
static SANE_Range x_range_tpo;
static SANE_Range y_range_tpo;
static const SANE_Range gamma_range =
{
SANE_FIX (0.0), SANE_FIX (4.0), 0
};
static const SANE_Range gamma_vrange =
{
0, 255, 1
};
static const SANE_Range lpr_range =
{
1, 50, 1
};
static const SANE_Range brightness_range =
{
-400 << SANE_FIXED_SCALE_SHIFT,
400 << SANE_FIXED_SCALE_SHIFT,
1 << SANE_FIXED_SCALE_SHIFT
};
static const SANE_Range contrast_range =
{
-100 << SANE_FIXED_SCALE_SHIFT,
400 << SANE_FIXED_SCALE_SHIFT,
1 << SANE_FIXED_SCALE_SHIFT
};
static const SANE_Range positive_percent_range =
{
0 << SANE_FIXED_SCALE_SHIFT,
100 << SANE_FIXED_SCALE_SHIFT,
1 << SANE_FIXED_SCALE_SHIFT
};
/* init_options -- initialize the option set for a scanner; expects the
scanner structure's hardware configuration byte (hconfig) to be valid.
ARGS: a pointer to an existing scanner structure
RET: nothing
SIDE: the option set of *ps is initialized; this includes both
the option descriptors and the option values themselves */
static void init_options (SnapScan_Scanner * ps)
{
static SANE_Word resolutions_300[] =
{6, 50, 75, 100, 150, 200, 300};
static SANE_Word resolutions_600[] =
{8, 50, 75, 100, 150, 200, 300, 450, 600};
static SANE_Word resolutions_1200[] =
{10, 50, 75, 100, 150, 200, 300, 450, 600, 900, 1200};
static SANE_String_Const names_all[] =
{md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
static SANE_String_Const names_basic[] =
{md_colour, md_greyscale, md_lineart, NULL};
static SANE_String_Const preview_names_all[] =
{md_auto, md_colour, md_bilevelcolour, md_greyscale, md_lineart, NULL};
static SANE_String_Const preview_names_basic[] =
{md_auto, md_colour, md_greyscale, md_lineart, NULL};
SANE_Option_Descriptor *po = ps->options;
/* Initialize TPO range */
switch (ps->pdev->model)
{
case SNAPSCAN1236:
x_range_tpo = x_range_tpo_1236;
y_range_tpo = y_range_tpo_1236;
break;
case SNAPSCANE20:
case SNAPSCANE50:
case SNAPSCANE52:
x_range_tpo = x_range_tpo_e50;
y_range_tpo = y_range_tpo_e50;
break;
default:
x_range_tpo = x_range_tpo_default;
y_range_tpo = y_range_tpo_default;
break;
}
/* Initialize option descriptors */
po[OPT_COUNT].name = SANE_NAME_NUM_OPTIONS;
po[OPT_COUNT].title = SANE_TITLE_NUM_OPTIONS;
po[OPT_COUNT].desc = SANE_DESC_NUM_OPTIONS;
po[OPT_COUNT].type = SANE_TYPE_INT;
po[OPT_COUNT].unit = SANE_UNIT_NONE;
po[OPT_COUNT].size = sizeof (SANE_Word);
po[OPT_COUNT].cap = SANE_CAP_SOFT_DETECT;
{
static SANE_Range count_range =
{NUM_OPTS, NUM_OPTS, 0};
po[OPT_COUNT].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_COUNT].constraint.range = &count_range;
}
po[OPT_MODE_GROUP].title = SANE_I18N("Scan Mode");
po[OPT_MODE_GROUP].desc = "";
po[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
po[OPT_MODE_GROUP].cap = 0;
po[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_SCANRES].name = SANE_NAME_SCAN_RESOLUTION;
po[OPT_SCANRES].title = SANE_TITLE_SCAN_RESOLUTION;
po[OPT_SCANRES].desc = SANE_DESC_SCAN_RESOLUTION;
po[OPT_SCANRES].type = SANE_TYPE_INT;
po[OPT_SCANRES].unit = SANE_UNIT_DPI;
po[OPT_SCANRES].size = sizeof (SANE_Word);
po[OPT_SCANRES].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_SCANRES].constraint_type = SANE_CONSTRAINT_WORD_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S: /* WG changed */
po[OPT_SCANRES].constraint.word_list = resolutions_300;
break;
case SNAPSCANE50:
case SNAPSCANE52:
case PRISA5300:
case PRISA1240:
po[OPT_SCANRES].constraint.word_list = resolutions_1200;
break;
default:
po[OPT_SCANRES].constraint.word_list = resolutions_600;
break;
}
ps->res = DEFAULT_RES;
po[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
po[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
po[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
po[OPT_PREVIEW].type = SANE_TYPE_BOOL;
po[OPT_PREVIEW].unit = SANE_UNIT_NONE;
po[OPT_PREVIEW].size = sizeof (SANE_Word);
po[OPT_PREVIEW].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_PREVIEW].constraint_type = SANE_CONSTRAINT_NONE;
ps->preview = DEFAULT_PREVIEW;
po[OPT_BRIGHTNESS].name = SANE_NAME_BRIGHTNESS;
po[OPT_BRIGHTNESS].title = SANE_TITLE_BRIGHTNESS;
po[OPT_BRIGHTNESS].desc = SANE_DESC_BRIGHTNESS;
po[OPT_BRIGHTNESS].type = SANE_TYPE_FIXED;
po[OPT_BRIGHTNESS].unit = SANE_UNIT_PERCENT;
po[OPT_BRIGHTNESS].size = sizeof (int);
po[OPT_BRIGHTNESS].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_BRIGHTNESS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRIGHTNESS].constraint.range = &brightness_range;
ps->bright = DEFAULT_BRIGHTNESS;
po[OPT_CONTRAST].name = SANE_NAME_CONTRAST;
po[OPT_CONTRAST].title = SANE_TITLE_CONTRAST;
po[OPT_CONTRAST].desc = SANE_DESC_CONTRAST;
po[OPT_CONTRAST].type = SANE_TYPE_FIXED;
po[OPT_CONTRAST].unit = SANE_UNIT_PERCENT;
po[OPT_CONTRAST].size = sizeof (int);
po[OPT_CONTRAST].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_CONTRAST].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_CONTRAST].constraint.range = &contrast_range;
ps->contrast = DEFAULT_CONTRAST;
po[OPT_MODE].name = SANE_NAME_SCAN_MODE;
po[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
po[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
po[OPT_MODE].type = SANE_TYPE_STRING;
po[OPT_MODE].unit = SANE_UNIT_NONE;
po[OPT_MODE].size = 32;
po[OPT_MODE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S:
po[OPT_MODE].constraint.string_list = names_basic;
break;
default:
po[OPT_MODE].constraint.string_list = names_all;
break;
}
ps->mode_s = md_colour;
ps->mode = MD_COLOUR;
po[OPT_PREVIEW_MODE].name = "preview-mode";
po[OPT_PREVIEW_MODE].title = SANE_I18N("Preview mode");
po[OPT_PREVIEW_MODE].desc = SANE_I18N(
"Select the mode for previews. Greyscale previews usually give "
"the best combination of speed and detail.");
po[OPT_PREVIEW_MODE].type = SANE_TYPE_STRING;
po[OPT_PREVIEW_MODE].unit = SANE_UNIT_NONE;
po[OPT_PREVIEW_MODE].size = 32;
po[OPT_PREVIEW_MODE].cap = SANE_CAP_SOFT_SELECT
| SANE_CAP_SOFT_DETECT
| SANE_CAP_ADVANCED
| SANE_CAP_AUTOMATIC;
po[OPT_PREVIEW_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->pdev->model)
{
case SNAPSCAN310:
case VUEGO310S:
po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_basic;
break;
default:
po[OPT_PREVIEW_MODE].constraint.string_list = preview_names_all;
break;
}
ps->preview_mode_s = md_auto;
ps->preview_mode = ps->mode;
/* source */
po[OPT_SOURCE].name = SANE_NAME_SCAN_SOURCE;
po[OPT_SOURCE].title = SANE_TITLE_SCAN_SOURCE;
po[OPT_SOURCE].desc = SANE_DESC_SCAN_SOURCE;
po[OPT_SOURCE].type = SANE_TYPE_STRING;
po[OPT_SOURCE].cap = SANE_CAP_SOFT_SELECT
| SANE_CAP_SOFT_DETECT
| SANE_CAP_INACTIVE
| SANE_CAP_AUTOMATIC;
po[OPT_SOURCE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
{
static SANE_String_Const source_list[3];
int i = 0;
source_list[i++]= src_flatbed;
if (ps->hconfig & HCFG_TPO)
{
source_list[i++] = src_tpo;
po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
}
if (ps->hconfig & HCFG_ADF)
{
source_list[i++] = src_adf;
po[OPT_SOURCE].cap &= ~SANE_CAP_INACTIVE;
}
source_list[i] = 0;
po[OPT_SOURCE].size = max_string_size(source_list);
po[OPT_SOURCE].constraint.string_list = source_list;
ps->source = SRC_FLATBED;
ps->source_s = (SANE_Char *) strdup(src_flatbed);
}
po[OPT_GEOMETRY_GROUP].title = SANE_I18N("Geometry");
po[OPT_GEOMETRY_GROUP].desc = "";
po[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
po[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
po[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_TLX].name = SANE_NAME_SCAN_TL_X;
po[OPT_TLX].title = SANE_TITLE_SCAN_TL_X;
po[OPT_TLX].desc = SANE_DESC_SCAN_TL_X;
po[OPT_TLX].type = SANE_TYPE_FIXED;
po[OPT_TLX].unit = SANE_UNIT_MM;
po[OPT_TLX].size = sizeof (SANE_Word);
po[OPT_TLX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_TLX].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_TLX].constraint.range = &(ps->pdev->x_range);
ps->tlx = ps->pdev->x_range.min;
po[OPT_TLY].name = SANE_NAME_SCAN_TL_Y;
po[OPT_TLY].title = SANE_TITLE_SCAN_TL_Y;
po[OPT_TLY].desc = SANE_DESC_SCAN_TL_Y;
po[OPT_TLY].type = SANE_TYPE_FIXED;
po[OPT_TLY].unit = SANE_UNIT_MM;
po[OPT_TLY].size = sizeof (SANE_Word);
po[OPT_TLY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_TLY].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_TLY].constraint.range = &(ps->pdev->y_range);
ps->tly = ps->pdev->y_range.min;
po[OPT_BRX].name = SANE_NAME_SCAN_BR_X;
po[OPT_BRX].title = SANE_TITLE_SCAN_BR_X;
po[OPT_BRX].desc = SANE_DESC_SCAN_BR_X;
po[OPT_BRX].type = SANE_TYPE_FIXED;
po[OPT_BRX].unit = SANE_UNIT_MM;
po[OPT_BRX].size = sizeof (SANE_Word);
po[OPT_BRX].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_BRX].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRX].constraint.range = &(ps->pdev->x_range);
ps->brx = ps->pdev->x_range.max;
po[OPT_BRY].name = SANE_NAME_SCAN_BR_Y;
po[OPT_BRY].title = SANE_TITLE_SCAN_BR_Y;
po[OPT_BRY].desc = SANE_DESC_SCAN_BR_Y;
po[OPT_BRY].type = SANE_TYPE_FIXED;
po[OPT_BRY].unit = SANE_UNIT_MM;
po[OPT_BRY].size = sizeof (SANE_Word);
po[OPT_BRY].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_AUTOMATIC;
po[OPT_BRY].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_BRY].constraint.range = &(ps->pdev->y_range);
ps->bry = ps->pdev->y_range.max;
po[OPT_PREDEF_WINDOW].name = "predef-window";
po[OPT_PREDEF_WINDOW].title = SANE_I18N("Predefined settings");
po[OPT_PREDEF_WINDOW].desc = SANE_I18N(
"Provides standard scanning areas for photographs, printed pages "
"and the like.");
po[OPT_PREDEF_WINDOW].type = SANE_TYPE_STRING;
po[OPT_PREDEF_WINDOW].unit = SANE_UNIT_NONE;
po[OPT_PREDEF_WINDOW].size = 32;
po[OPT_PREDEF_WINDOW].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
{
static SANE_String_Const names[] =
{pdw_none, pdw_6X4, pdw_8X10, pdw_85X11, NULL};
po[OPT_PREDEF_WINDOW].constraint_type = SANE_CONSTRAINT_STRING_LIST;
po[OPT_PREDEF_WINDOW].constraint.string_list = names;
}
ps->predef_window = pdw_none;
po[OPT_ENHANCEMENT_GROUP].title = SANE_I18N("Enhancement");
po[OPT_ENHANCEMENT_GROUP].desc = "";
po[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
po[OPT_ENHANCEMENT_GROUP].cap = 0;
po[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_QUALITY_CAL].name = SANE_NAME_QUALITY_CAL;
po[OPT_QUALITY_CAL].title = SANE_TITLE_QUALITY_CAL;
po[OPT_QUALITY_CAL].desc = SANE_DESC_QUALITY_CAL;
po[OPT_QUALITY_CAL].type = SANE_TYPE_BOOL;
po[OPT_QUALITY_CAL].unit = SANE_UNIT_NONE;
po[OPT_QUALITY_CAL].size = sizeof (SANE_Bool);
po[OPT_QUALITY_CAL].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_QUALITY_CAL].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
ps->val[OPT_QUALITY_CAL].b = DEFAULT_QUALITY;
/* Disable quality calibration option if not supported
Note: Snapscan e52 and Prisa5300 do not support quality calibration,
although HCFG_CAL_ALLOWED is set. */
if ((!(ps->hconfig & HCFG_CAL_ALLOWED))
|| (ps->pdev->model == SNAPSCANE52)
|| (ps->pdev->model == PRISA5300)) {
po[OPT_QUALITY_CAL].cap |= SANE_CAP_INACTIVE;
ps->val[OPT_QUALITY_CAL].b = SANE_FALSE;
}
po[OPT_GAMMA_BIND].name = SANE_NAME_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].title = SANE_TITLE_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].desc = SANE_DESC_ANALOG_GAMMA_BIND;
po[OPT_GAMMA_BIND].type = SANE_TYPE_BOOL;
po[OPT_GAMMA_BIND].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_BIND].size = sizeof (SANE_Bool);
po[OPT_GAMMA_BIND].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_GAMMA_BIND].constraint_type = SANE_CONSTRAINT_NONE;
ps->val[OPT_GAMMA_BIND].b = DEFAULT_GAMMA_BIND;
po[OPT_GAMMA_GS].name = SANE_NAME_ANALOG_GAMMA;
po[OPT_GAMMA_GS].title = SANE_TITLE_ANALOG_GAMMA;
po[OPT_GAMMA_GS].desc = SANE_DESC_ANALOG_GAMMA;
po[OPT_GAMMA_GS].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_GS].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_GS].size = sizeof (SANE_Word);
po[OPT_GAMMA_GS].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
po[OPT_GAMMA_GS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_GS].constraint.range = &gamma_range;
ps->gamma_gs = DEFAULT_GAMMA;
po[OPT_GAMMA_R].name = SANE_NAME_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].title = SANE_TITLE_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].desc = SANE_DESC_ANALOG_GAMMA_R;
po[OPT_GAMMA_R].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_R].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_R].size = sizeof (SANE_Word);
po[OPT_GAMMA_R].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_R].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_R].constraint.range = &gamma_range;
ps->gamma_r = DEFAULT_GAMMA;
po[OPT_GAMMA_G].name = SANE_NAME_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].title = SANE_TITLE_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].desc = SANE_DESC_ANALOG_GAMMA_G;
po[OPT_GAMMA_G].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_G].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_G].size = sizeof (SANE_Word);
po[OPT_GAMMA_G].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_G].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_G].constraint.range = &gamma_range;
ps->gamma_g = DEFAULT_GAMMA;
po[OPT_GAMMA_B].name = SANE_NAME_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].title = SANE_TITLE_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].desc = SANE_DESC_ANALOG_GAMMA_B;
po[OPT_GAMMA_B].type = SANE_TYPE_FIXED;
po[OPT_GAMMA_B].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_B].size = sizeof (SANE_Word);
po[OPT_GAMMA_B].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_B].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_B].constraint.range = &gamma_range;
ps->gamma_b = DEFAULT_GAMMA;
po[OPT_CUSTOM_GAMMA].name = SANE_NAME_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].title = SANE_TITLE_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].desc = SANE_DESC_CUSTOM_GAMMA;
po[OPT_CUSTOM_GAMMA].type = SANE_TYPE_BOOL;
po[OPT_CUSTOM_GAMMA].unit = SANE_UNIT_NONE;
po[OPT_CUSTOM_GAMMA].size = sizeof (SANE_Bool);
po[OPT_CUSTOM_GAMMA].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
ps->val[OPT_CUSTOM_GAMMA].b = DEFAULT_CUSTOM_GAMMA;
po[OPT_GAMMA_VECTOR_GS].name = SANE_NAME_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].title = SANE_TITLE_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].desc = SANE_DESC_GAMMA_VECTOR;
po[OPT_GAMMA_VECTOR_GS].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_GS].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_GS].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_GS].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_GS].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_GS].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_GS].wa = ps->gamma_table_gs;
po[OPT_GAMMA_VECTOR_R].name = SANE_NAME_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].title = SANE_TITLE_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].desc = SANE_DESC_GAMMA_VECTOR_R;
po[OPT_GAMMA_VECTOR_R].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_R].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_R].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_R].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_R].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_R].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_R].wa = ps->gamma_table_r;
po[OPT_GAMMA_VECTOR_G].name = SANE_NAME_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].title = SANE_TITLE_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].desc = SANE_DESC_GAMMA_VECTOR_G;
po[OPT_GAMMA_VECTOR_G].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_G].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_G].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_G].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_G].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_G].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_G].wa = ps->gamma_table_g;
po[OPT_GAMMA_VECTOR_B].name = SANE_NAME_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].title = SANE_TITLE_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].desc = SANE_DESC_GAMMA_VECTOR_B;
po[OPT_GAMMA_VECTOR_B].type = SANE_TYPE_INT;
po[OPT_GAMMA_VECTOR_B].unit = SANE_UNIT_NONE;
po[OPT_GAMMA_VECTOR_B].size = ps->gamma_length * sizeof (SANE_Word);
po[OPT_GAMMA_VECTOR_B].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_GAMMA_VECTOR_B].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GAMMA_VECTOR_B].constraint.range = &gamma_vrange;
ps->val[OPT_GAMMA_VECTOR_B].wa = ps->gamma_table_b;
po[OPT_HALFTONE].name = SANE_NAME_HALFTONE;
po[OPT_HALFTONE].title = SANE_TITLE_HALFTONE;
po[OPT_HALFTONE].desc = SANE_DESC_HALFTONE;
po[OPT_HALFTONE].type = SANE_TYPE_BOOL;
po[OPT_HALFTONE].unit = SANE_UNIT_NONE;
po[OPT_HALFTONE].size = sizeof (SANE_Bool);
po[OPT_HALFTONE].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_HALFTONE].constraint_type = SANE_CONSTRAINT_NONE;
ps->halftone = DEFAULT_HALFTONE;
po[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
po[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
po[OPT_HALFTONE_PATTERN].unit = SANE_UNIT_NONE;
po[OPT_HALFTONE_PATTERN].size = 32;
po[OPT_HALFTONE_PATTERN].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
switch (ps->hconfig & HCFG_HT)
{
case HCFG_HT:
/* both 16x16, 8x8 matrices */
{
static SANE_String_Const names[] = {dm_dd8x8, dm_dd16x16, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd8x8;
}
break;
case HCFG_HT16:
/* 16x16 matrices only */
{
static SANE_String_Const names[] = {dm_dd16x16, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd16x16;
}
break;
case HCFG_HT8:
/* 8x8 matrices only */
{
static SANE_String_Const names[] = {dm_dd8x8, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_dd8x8;
}
break;
default:
/* no halftone matrices */
{
static SANE_String_Const names[] = {dm_none, NULL};
po[OPT_HALFTONE_PATTERN].constraint.string_list = names;
ps->dither_matrix = dm_none;
}
}
po[OPT_NEGATIVE].name = SANE_NAME_NEGATIVE;
po[OPT_NEGATIVE].title = SANE_TITLE_NEGATIVE;
po[OPT_NEGATIVE].desc = SANE_DESC_NEGATIVE;
po[OPT_NEGATIVE].type = SANE_TYPE_BOOL;
po[OPT_NEGATIVE].unit = SANE_UNIT_NONE;
po[OPT_NEGATIVE].size = sizeof (SANE_Bool);
po[OPT_NEGATIVE].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE | SANE_CAP_AUTOMATIC;
po[OPT_NEGATIVE].constraint_type = SANE_CONSTRAINT_NONE;
ps->negative = DEFAULT_NEGATIVE;
po[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
po[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
po[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
po[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
po[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
po[OPT_THRESHOLD].size = sizeof (SANE_Int);
po[OPT_THRESHOLD].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE;
po[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_THRESHOLD].constraint.range = &positive_percent_range;
ps->threshold = DEFAULT_THRESHOLD;
po[OPT_ADVANCED_GROUP].title = SANE_I18N("Advanced");
po[OPT_ADVANCED_GROUP].desc = "";
po[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
po[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
po[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
po[OPT_RGB_LPR].name = "rgb-lpr";
po[OPT_RGB_LPR].title = SANE_I18N("Colour lines per read");
po[OPT_RGB_LPR].desc = lpr_desc;
po[OPT_RGB_LPR].type = SANE_TYPE_INT;
po[OPT_RGB_LPR].unit = SANE_UNIT_NONE;
po[OPT_RGB_LPR].size = sizeof (SANE_Word);
po[OPT_RGB_LPR].cap =
SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC;
po[OPT_RGB_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_RGB_LPR].constraint.range = &lpr_range;
ps->rgb_lpr = def_rgb_lpr;
po[OPT_GS_LPR].name = "gs-lpr";
po[OPT_GS_LPR].title = SANE_I18N("Greyscale lines per read");
po[OPT_GS_LPR].desc = lpr_desc;
po[OPT_GS_LPR].type = SANE_TYPE_INT;
po[OPT_GS_LPR].unit = SANE_UNIT_NONE;
po[OPT_GS_LPR].size = sizeof (SANE_Word);
po[OPT_GS_LPR].cap = SANE_CAP_SOFT_SELECT
| SANE_CAP_SOFT_DETECT
| SANE_CAP_ADVANCED
| SANE_CAP_INACTIVE
| SANE_CAP_AUTOMATIC;
po[OPT_GS_LPR].constraint_type = SANE_CONSTRAINT_RANGE;
po[OPT_GS_LPR].constraint.range = &lpr_range;
ps->gs_lpr = def_gs_lpr;
}
const SANE_Option_Descriptor *sane_get_option_descriptor (SANE_Handle h,
SANE_Int n)
{
DBG (DL_CALL_TRACE,
"sane_snapscan_get_option_descriptor (%p, %ld)\n",
(void *) h,
(long) n);
if ((n >= 0) && (n < NUM_OPTS))
return ((SnapScan_Scanner *) h)->options + n;
return NULL;
}
/* Activates or deactivates options depending on mode */
static void control_options(SnapScan_Scanner *pss)
{
/* first deactivate all options */
pss->options[OPT_CUSTOM_GAMMA].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_BRIGHTNESS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_BIND].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_GS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_R].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_G].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_B].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_GS].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_R].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_G].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_B].cap |= SANE_CAP_INACTIVE;
if ((pss->mode == MD_COLOUR) ||
((pss->mode == MD_BILEVELCOLOUR) && (pss->hconfig & HCFG_HT) &&
pss->halftone))
{
pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_BIND].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_CUSTOM_GAMMA].b)
{
if (pss->val[OPT_GAMMA_BIND].b)
{
pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_GAMMA_VECTOR_R].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_G].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_VECTOR_B].cap &= ~SANE_CAP_INACTIVE;
}
}
else
{
pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_GAMMA_BIND].b)
{
pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_GAMMA_R].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_G].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_B].cap &= ~SANE_CAP_INACTIVE;
}
}
}
else if ((pss->mode == MD_GREYSCALE) ||
((pss->mode == MD_LINEART) && (pss->hconfig & HCFG_HT) &&
pss->halftone))
{
pss->options[OPT_CUSTOM_GAMMA].cap &= ~SANE_CAP_INACTIVE;
if (pss->val[OPT_CUSTOM_GAMMA].b)
{
pss->options[OPT_GAMMA_VECTOR_GS].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_BRIGHTNESS].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_CONTRAST].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GAMMA_GS].cap &= ~SANE_CAP_INACTIVE;
}
}
}
SANE_Status sane_control_option (SANE_Handle h,
SANE_Int n,
SANE_Action a,
void *v,
SANE_Int *i)
{
static const char *me = "sane_snapscan_control_option";
SnapScan_Scanner *pss = h;
SnapScan_Device *pdev = pss->pdev;
static SANE_Status status;
DBG (DL_CALL_TRACE,
"%s (%p, %ld, %ld, %p, %p)\n",
me,
(void *) h,
(long) n,
(long) a,
v,
(void *) i);
switch (a)
{
case SANE_ACTION_GET_VALUE:
/* prevent getting of inactive options */
if (!SANE_OPTION_IS_ACTIVE(pss->options[n].cap)) {
return SANE_STATUS_INVAL;
}
switch (n)
{
case OPT_COUNT:
*(SANE_Int *) v = NUM_OPTS;
break;
case OPT_SCANRES:
*(SANE_Int *) v = pss->res;
break;
case OPT_PREVIEW:
*(SANE_Bool *) v = pss->preview;
break;
case OPT_MODE:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->mode_s,
(SANE_String) v);
strcpy ((SANE_String) v, pss->mode_s);
break;
case OPT_PREVIEW_MODE:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->preview_mode_s,
(SANE_String) v);
strcpy ((SANE_String) v, pss->preview_mode_s);
break;
case OPT_SOURCE:
strcpy (v, pss->source_s);
break;
case OPT_TLX:
*(SANE_Fixed *) v = pss->tlx;
break;
case OPT_TLY:
*(SANE_Fixed *) v = pss->tly;
break;
case OPT_BRX:
*(SANE_Fixed *) v = pss->brx;
break;
case OPT_BRY:
*(SANE_Fixed *) v = pss->bry;
break;
case OPT_BRIGHTNESS:
*(SANE_Int *) v = pss->bright << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_CONTRAST:
*(SANE_Int *) v = pss->contrast << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_PREDEF_WINDOW:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->predef_window,
(SANE_String) v);
strcpy ((SANE_String) v, pss->predef_window);
break;
case OPT_GAMMA_GS:
*(SANE_Fixed *) v = pss->gamma_gs;
break;
case OPT_GAMMA_R:
*(SANE_Fixed *) v = pss->gamma_r;
break;
case OPT_GAMMA_G:
*(SANE_Fixed *) v = pss->gamma_g;
break;
case OPT_GAMMA_B:
*(SANE_Fixed *) v = pss->gamma_b;
break;
case OPT_CUSTOM_GAMMA:
case OPT_GAMMA_BIND:
case OPT_QUALITY_CAL:
*(SANE_Bool *) v = pss->val[n].b;
break;
case OPT_GAMMA_VECTOR_GS:
case OPT_GAMMA_VECTOR_R:
case OPT_GAMMA_VECTOR_G:
case OPT_GAMMA_VECTOR_B:
memcpy (v, pss->val[n].wa, pss->options[n].size);
break;
case OPT_HALFTONE:
*(SANE_Bool *) v = pss->halftone;
break;
case OPT_HALFTONE_PATTERN:
DBG (DL_VERBOSE,
"%s: writing \"%s\" to location %p\n",
me,
pss->dither_matrix,
(SANE_String) v);
strcpy ((SANE_String) v, pss->dither_matrix);
break;
case OPT_NEGATIVE:
*(SANE_Bool *) v = pss->negative;
break;
case OPT_THRESHOLD:
*(SANE_Int *) v = pss->threshold << SANE_FIXED_SCALE_SHIFT;
break;
case OPT_RGB_LPR:
*(SANE_Int *) v = pss->rgb_lpr;
break;
case OPT_GS_LPR:
*(SANE_Int *) v = pss->gs_lpr;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
break;
case SANE_ACTION_SET_VALUE:
if (i)
*i = 0;
/* prevent setting of inactive options */
if ((!SANE_OPTION_IS_SETTABLE(pss->options[n].cap)) ||
(!SANE_OPTION_IS_ACTIVE(pss->options[n].cap))) {
return SANE_STATUS_INVAL;
}
/* prevent setting of options during a scan */
if ((pss->state==ST_SCAN_INIT) || (pss->state==ST_SCANNING)) {
DBG(DL_INFO,
"set value for option %s ignored: scanner is still scanning (status %d)\n",
pss->options[n].name,
pss->state
);
return SANE_STATUS_DEVICE_BUSY;
}
status = sanei_constrain_value(&pss->options[n], v, i);
if (status != SANE_STATUS_GOOD) {
return status;
}
switch (n)
{
case OPT_COUNT:
return SANE_STATUS_UNSUPPORTED;
case OPT_SCANRES:
pss->res = *(SANE_Int *) v;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_PREVIEW:
pss->preview = *(SANE_Bool *) v;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_MODE:
{
char *s = (SANE_String) v;
if (strcmp (s, md_colour) == 0)
{
pss->mode_s = md_colour;
pss->mode = MD_COLOUR;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_COLOUR;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_bilevelcolour) == 0)
{
int ht_cap = pss->hconfig & HCFG_HT;
pss->mode_s = md_bilevelcolour;
pss->mode = MD_BILEVELCOLOUR;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_BILEVELCOLOUR;
if (ht_cap)
pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
if (ht_cap && pss->halftone)
{
pss->options[OPT_HALFTONE_PATTERN].cap &=
~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |=
SANE_CAP_INACTIVE;
}
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_greyscale) == 0)
{
pss->mode_s = md_greyscale;
pss->mode = MD_GREYSCALE;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_GREYSCALE;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
}
else if (strcmp (s, md_lineart) == 0)
{
int ht_cap = pss->hconfig & HCFG_HT;
pss->mode_s = md_lineart;
pss->mode = MD_LINEART;
if (pss->preview_mode_s == md_auto)
pss->preview_mode = MD_LINEART;
if (ht_cap)
pss->options[OPT_HALFTONE].cap &= ~SANE_CAP_INACTIVE;
if (ht_cap && pss->halftone)
{
pss->options[OPT_HALFTONE_PATTERN].cap &=
~SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |=
SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
}
pss->options[OPT_NEGATIVE].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap &= ~SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap |= SANE_CAP_INACTIVE;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal mode "
"string \"%s\"\n",
me,
s);
}
}
control_options (pss);
if (i)
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_PREVIEW_MODE:
{
char *s = (SANE_String) v;
if (strcmp (s, md_auto) == 0)
{
pss->preview_mode_s = md_auto;
pss->preview_mode = pss->mode;
}
else if (strcmp (s, md_colour) == 0)
{
pss->preview_mode_s = md_colour;
pss->preview_mode = MD_COLOUR;
}
else if (strcmp (s, md_bilevelcolour) == 0)
{
pss->preview_mode_s = md_bilevelcolour;
pss->preview_mode = MD_BILEVELCOLOUR;
}
else if (strcmp (s, md_greyscale) == 0)
{
pss->preview_mode_s = md_greyscale;
pss->preview_mode = MD_GREYSCALE;
}
else if (strcmp (s, md_lineart) == 0)
{
pss->preview_mode_s = md_lineart;
pss->preview_mode = MD_LINEART;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal mode string "
"\"%s\"\n",
me,
s);
}
break;
}
case OPT_SOURCE:
if (strcmp(v, src_flatbed) == 0)
{
pss->source = SRC_FLATBED;
pss->pdev->x_range.max = x_range_fb.max;
pss->pdev->y_range.max = y_range_fb.max;
}
else if (strcmp(v, src_tpo) == 0)
{
pss->source = SRC_TPO;
pss->pdev->x_range.max = x_range_tpo.max;
pss->pdev->y_range.max = y_range_tpo.max;
}
else if (strcmp(v, src_adf) == 0)
{
pss->source = SRC_ADF;
pss->pdev->x_range.max = x_range_fb.max;
pss->pdev->y_range.max = y_range_fb.max;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal source string "
"\"%s\"\n",
me,
(char *) v);
}
/* Adjust actual range values to new max values */
if (pss->brx > pss->pdev->x_range.max)
pss->brx = pss->pdev->x_range.max;
if (pss->bry > pss->pdev->y_range.max)
pss->bry = pss->pdev->y_range.max;
pss->predef_window = pdw_none;
if (pss->source_s)
free (pss->source_s);
pss->source_s = (SANE_Char *) strdup(v);
if (i)
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_TLX:
pss->tlx = *(SANE_Fixed *) v;
pss->predef_window = pdw_none;
if (pss->tlx > pdev->x_range.max) {
pss->tlx = pdev->x_range.max;
}
if (pss->brx < pss->tlx) {
pss->brx = pss->tlx;
}
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_TLY:
pss->tly = *(SANE_Fixed *) v;
pss->predef_window = pdw_none;
if (pss->tly > pdev->y_range.max){
pss->tly = pdev->y_range.max;
}
if (pss->bry < pss->tly) {
pss->bry = pss->tly;
}
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRX:
pss->brx = *(SANE_Fixed *) v;
pss->predef_window = pdw_none;
if (pss->brx < pdev->x_range.min) {
pss->brx = pdev->x_range.min;
}
if (pss->brx < pss->tlx) {
pss->tlx = pss->brx;
}
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRY:
pss->bry = *(SANE_Fixed *) v;
pss->predef_window = pdw_none;
if (pss->bry < pdev->y_range.min) {
pss->bry = pdev->y_range.min;
}
if (pss->bry < pss->tly) {
pss->tly = pss->bry;
}
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRIGHTNESS:
pss->bright = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
break;
case OPT_CONTRAST:
pss->contrast = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
break;
case OPT_PREDEF_WINDOW:
{
char *s = (SANE_String) v;
if (strcmp (s, pdw_none) != 0)
{
pss->tlx = 0;
pss->tly = 0;
if (strcmp (s, pdw_6X4) == 0)
{
pss->predef_window = pdw_6X4;
pss->brx = SANE_FIX (6.0*MM_PER_IN);
pss->bry = SANE_FIX (4.0*MM_PER_IN);
}
else if (strcmp (s, pdw_8X10) == 0)
{
pss->predef_window = pdw_8X10;
pss->brx = SANE_FIX (8.0*MM_PER_IN);
pss->bry = SANE_FIX (10.0*MM_PER_IN);
}
else if (strcmp (s, pdw_85X11) == 0)
{
pss->predef_window = pdw_85X11;
pss->brx = SANE_FIX (8.5*MM_PER_IN);
pss->bry = SANE_FIX (11.0*MM_PER_IN);
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: trying to set predef window with "
"garbage value.", me);
pss->predef_window = pdw_none;
pss->brx = SANE_FIX (6.0*MM_PER_IN);
pss->bry = SANE_FIX (4.0*MM_PER_IN);
}
}
else
{
pss->predef_window = pdw_none;
}
}
if (i)
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_GAMMA_GS:
pss->gamma_gs = *(SANE_Fixed *) v;
break;
case OPT_GAMMA_R:
pss->gamma_r = *(SANE_Fixed *) v;
break;
case OPT_GAMMA_G:
pss->gamma_g = *(SANE_Fixed *) v;
break;
case OPT_GAMMA_B:
pss->gamma_b = *(SANE_Fixed *) v;
break;
case OPT_QUALITY_CAL:
pss->val[n].b = *(SANE_Bool *)v;
break;
case OPT_CUSTOM_GAMMA:
case OPT_GAMMA_BIND:
{
SANE_Bool b = *(SANE_Bool *) v;
if (b == pss->val[n].b) { break; }
pss->val[n].b = b;
control_options (pss);
if (i)
{
*i |= SANE_INFO_RELOAD_OPTIONS;
}
break;
}
case OPT_GAMMA_VECTOR_GS:
case OPT_GAMMA_VECTOR_R:
case OPT_GAMMA_VECTOR_G:
case OPT_GAMMA_VECTOR_B:
memcpy(pss->val[n].wa, v, pss->options[n].size);
break;
case OPT_HALFTONE:
pss->halftone = *(SANE_Bool *) v;
if (pss->halftone)
{
switch (pss->mode)
{
case MD_BILEVELCOLOUR:
break;
case MD_LINEART:
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
break;
default:
break;
}
pss->options[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE;
}
else
{
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
if (pss->mode == MD_LINEART)
pss->options[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
}
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_HALFTONE_PATTERN:
{
char *s = (SANE_String) v;
if (strcmp (s, dm_dd8x8) == 0)
{
pss->dither_matrix = dm_dd8x8;
}
else if (strcmp (s, dm_dd16x16) == 0)
{
pss->dither_matrix = dm_dd16x16;
}
else
{
DBG (DL_MAJOR_ERROR,
"%s: internal error: given illegal halftone pattern "
"string \"%s\"\n",
me,
s);
}
}
break;
case OPT_NEGATIVE:
pss->negative = *(SANE_Bool *) v;
break;
case OPT_THRESHOLD:
pss->threshold = *(SANE_Int *) v >> SANE_FIXED_SCALE_SHIFT;
break;
case OPT_RGB_LPR:
pss->rgb_lpr = *(SANE_Int *) v;
break;
case OPT_GS_LPR:
pss->gs_lpr = *(SANE_Int *) v;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
DBG (DL_DATA_TRACE, "%s: option %s set to value ",
me, pss->options[n].name);
switch (pss->options[n].type)
{
case SANE_TYPE_INT:
DBG (DL_VERBOSE, "%ld\n", (long) (*(SANE_Int *) v));
break;
case SANE_TYPE_BOOL:
{
char *valstr = (*(SANE_Bool *) v == SANE_TRUE) ? "TRUE" : "FALSE";
DBG (DL_DATA_TRACE, "%s\n", valstr);
}
break;
default:
DBG (DL_DATA_TRACE, "other than an integer or boolean.\n");
break;
}
break;
case SANE_ACTION_SET_AUTO:
if (i)
*i = 0;
switch (n)
{
case OPT_SCANRES:
pss->res = 300;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_PREVIEW:
pss->preview = SANE_FALSE;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_MODE:
pss->mode_s = md_colour;
pss->mode = MD_COLOUR;
pss->options[OPT_HALFTONE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_NEGATIVE].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_GS_LPR].cap |= SANE_CAP_INACTIVE;
pss->options[OPT_RGB_LPR].cap &= ~SANE_CAP_INACTIVE;
control_options (pss);
if (i)
*i = SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_PREVIEW_MODE:
pss->preview_mode_s = md_greyscale;
pss->preview_mode = MD_GREYSCALE;
break;
case OPT_SOURCE:
pss->source = SRC_FLATBED;
pss->pdev->x_range.max = x_range_fb.max;
pss->pdev->y_range.max = y_range_fb.max;
pss->predef_window = pdw_none;
if (pss->source_s)
free (pss->source_s);
pss->source_s = (SANE_Char *) strdup(src_flatbed);
if (i)
*i |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break;
case OPT_TLX:
pss->tlx = pss->pdev->x_range.min;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_TLY:
pss->tly = pss->pdev->y_range.min;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRX:
pss->brx = pss->pdev->x_range.max;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_BRY:
pss->bry = pss->pdev->y_range.max;
if (i)
*i |= SANE_INFO_RELOAD_PARAMS;
break;
case OPT_NEGATIVE:
pss->negative = DEFAULT_NEGATIVE;
break;
case OPT_RGB_LPR:
pss->rgb_lpr = def_rgb_lpr;
break;
case OPT_GS_LPR:
pss->gs_lpr = def_gs_lpr;
break;
default:
DBG (DL_MAJOR_ERROR,
"%s: invalid option number %ld\n",
me,
(long) n);
return SANE_STATUS_UNSUPPORTED;
}
break;
default:
DBG (DL_MAJOR_ERROR, "%s: invalid action code %ld\n", me, (long) a);
return SANE_STATUS_UNSUPPORTED;
}
return SANE_STATUS_GOOD;
}
/*
* $Log$
* Revision 1.5 2002/07/12 23:29:05 oliverschwartz
* SnapScan backend 1.4.15
*
* Revision 1.6 2002/07/12 23:23:06 oliverschwartz
* Disable quality calibration for 5300
*
* Revision 1.5 2002/06/06 20:40:00 oliverschwartz
* Changed default scan area for transparancy unit of SnapScan e50
*
* Revision 1.4 2002/05/02 18:28:44 oliverschwartz
* Added ADF support
*
* Revision 1.3 2002/04/27 14:43:59 oliverschwartz
* - Remove SCSI debug options
* - Fix option handling (errors detected by tstbackend)
*
* Revision 1.2 2002/04/23 22:50:24 oliverschwartz
* Improve handling of scan area options
*
* Revision 1.1 2002/03/24 12:07:15 oliverschwartz
* Moved option functions from snapscan.c to snapscan-options.c
*
*
* */