1
0
mirror of https://github.com/wine-mirror/wine synced 2024-06-29 06:14:34 +00:00

sane.ds: Improve color mode and paper source detection.

This commit is contained in:
Ilia Docin 2024-06-21 21:23:45 +03:00 committed by Alexandre Julliard
parent 49457ccf21
commit 9cf95e76ef
3 changed files with 127 additions and 70 deletions

View File

@ -277,47 +277,32 @@ static TW_UINT16 SANE_CAPXferCount (pTW_CAPABILITY pCapability, TW_UINT16 action
return twCC;
}
static TW_UINT16 set_color_mode(TW_UINT32 pixeltype)
static TW_UINT16 set_option_value(const char* option_name, char* option_value)
{
TW_UINT16 twCC = TWCC_BADCAP;
TW_UINT16 twCC = TWCC_BADVALUE;
BOOL reload = FALSE;
int i;
const char * const * modes;
/* most of the values are taken from https://gitlab.gnome.org/GNOME/simple-scan/-/blob/master/src/scanner.vala */
static const char * const gray[] = {"Gray", "Grayscale", "True Gray", "8-bit Grayscale", "Grayscale - 256 Levels", "gray",
0};
static const char * const rgb[] = {"Color", "24bit Color[Fast]", "24bit Color",
"24 bit Color", "Color - 16 Million Colors", 0};
static const char * const bw[] = {"Lineart", "LineArt", "Black & White", "Binary", "Thresholded", "1-bit Black & White",
"Black and White - Line Art", "Black and White - Halftone", "Monochrome", 0};
switch (pixeltype)
if (*option_value)
{
case TWPT_GRAY:
modes = gray;
break;
case TWPT_RGB:
modes = rgb;
break;
case TWPT_BW:
modes = bw;
break;
default:
ERR("Unsupported pixeltype %lu\n", pixeltype);
return TWCC_BADVALUE;
break;
}
TRACE("Setting pixeltype to %lu\n", pixeltype);
for(i=0; modes[i]; ++i)
{
twCC = sane_option_set_str("mode", (char*)modes[i], &reload);
twCC = sane_option_set_str(option_name, option_value, &reload);
if (twCC == TWCC_SUCCESS) {
if (reload) get_sane_params(&activeDS.frame_params);
break;
}
}
return twCC;
}
static TW_UINT16 find_value_pos(const char* value, const char* values, TW_UINT16 buf_len, TW_UINT16 buf_count)
{
TW_UINT16 index;
for (index=0; index<buf_count; ++index)
{
if (!strncmp(value, values, buf_len))
return index;
values += buf_len;
}
return buf_count;
}
/* ICAP_PIXELTYPE */
static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 action)
{
@ -326,16 +311,39 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
int possible_value_count;
TW_UINT32 val;
TW_UINT16 current_pixeltype = TWPT_BW;
enum { buf_len = 64, buf_count = 3 };
char color_modes[buf_len * buf_count] = {'\0'}, current_mode[buf_len] = {'\0'}, *output = 0;
/* most of the values are taken from https://gitlab.gnome.org/GNOME/simple-scan/-/blob/master/src/scanner.vala */
static const WCHAR* bw[] = {L"Lineart", L"LineArt", L"Black & White", L"Binary", L"Thresholded",
L"1-bit Black & White", L"Black and White - Line Art", L"Black and White - Halftone", L"Monochrome", L"bw", 0};
static const WCHAR* gray[] = {L"Gray", L"Grayscale", L"True Gray", L"8-bit Grayscale", L"Grayscale - 256 Levels",
L"gray", 0};
static const WCHAR* rgb[] = {L"Color", L"24bit Color[Fast]", L"24bit Color", L"24 bit Color",
L"Color - 16 Million Colors", L"color", 0};
static const WCHAR* const* filter[] = {bw, gray, rgb, 0};
TRACE("ICAP_PIXELTYPE\n");
twCC = sane_option_probe_mode(&current_pixeltype, possible_values, &possible_value_count);
twCC = sane_option_probe_str("mode", filter, color_modes, buf_len);
if (twCC != TWCC_SUCCESS)
{
ERR("Unable to retrieve mode from sane, ICAP_PIXELTYPE unsupported\n");
ERR("Unable to retrieve modes from sane, ICAP_PIXELTYPE unsupported\n");
return twCC;
}
twCC = sane_option_get_str("mode", current_mode, buf_len);
if (twCC != TWCC_SUCCESS)
{
ERR("Unable to retrieve current mode from sane, ICAP_PIXELTYPE unsupported\n");
return twCC;
}
current_pixeltype = find_value_pos(current_mode, color_modes, buf_len, buf_count);
if (current_pixeltype == buf_count)
{
ERR("Wrong current mode value, ICAP_PIXELTYPE unsupported\n");
twCC = TWCC_BADVALUE;
return twCC;
}
/* Sane does not support a concept of a default mode, so we simply cache
* the first mode we find */
if (! activeDS.PixelTypeSet)
@ -352,17 +360,28 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
break;
case MSG_GET:
possible_value_count = 0;
for (val=TWPT_BW; val<=TWPT_RGB; ++val)
{
if (*(color_modes + val * buf_len))
possible_values[possible_value_count++] = val;
}
twCC = msg_get_enum(pCapability, possible_values, possible_value_count,
TWTY_UINT16, current_pixeltype, activeDS.defaultPixelType);
break;
case MSG_SET:
twCC = msg_set(pCapability, &val);
if (twCC == TWCC_SUCCESS)
if ((twCC == TWCC_SUCCESS) && (val < buf_count))
{
TRACE("Setting pixeltype to %ld\n", val);
twCC = set_color_mode(val);
output = color_modes + val * buf_len;
TRACE("Setting pixeltype to %lu: %s\n", val, output);
twCC = set_option_value("mode", output);
if (twCC != TWCC_SUCCESS)
ERR("Unable to set pixeltype to %lu: %s\n", val, output);
}
else
twCC = TWCC_BADVALUE;
break;
case MSG_GETDEFAULT:
@ -370,7 +389,7 @@ static TW_UINT16 SANE_ICAPPixelType (pTW_CAPABILITY pCapability, TW_UINT16 actio
break;
case MSG_RESET:
twCC = set_color_mode(activeDS.defaultPixelType);
twCC = set_option_value("mode", color_modes + activeDS.defaultPixelType * buf_len);
if (twCC == TWCC_SUCCESS)
current_pixeltype = activeDS.defaultPixelType;
else
@ -933,17 +952,39 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac
TW_UINT16 twCC = TWCC_BADCAP;
TW_UINT32 val;
TW_BOOL enabled;
char source[64];
enum { buf_len = 64, buf_count = 2 };
char paper_sources[buf_len * buf_count] = {'\0'}, current_source[buf_len] = {'\0'}, *output = 0;
/* most of the values are taken from https://gitlab.gnome.org/GNOME/simple-scan/-/blob/master/src/scanner.vala */
static const WCHAR* flatbed[] = {L"Flatbed", L"FlatBed", L"Platen", L"Normal", L"Document Table", 0};
static const WCHAR* autofeeder[] = {L"Auto", L"ADF", L"ADF Front", L"ADF Back", L"adf",
L"Automatic Document Feeder", L"Automatic Document Feeder(centrally aligned)",
L"Automatic Document Feeder(center aligned)", L"Automatic Document Feeder(left aligned)",
L"ADF Simplex" L"DP", 0};
static const WCHAR* const* filter[] = {flatbed, autofeeder, 0};
TRACE("CAP_FEEDERENABLED\n");
twCC = sane_option_probe_str("source", filter, paper_sources, buf_len);
if (twCC != TWCC_SUCCESS)
{
ERR("Unable to retrieve paper sources from sane, CAP_FEEDERENABLED unsupported\n");
return twCC;
}
if (sane_option_get_str("source", source, sizeof(source)) != TWCC_SUCCESS)
return TWCC_BADCAP;
twCC = sane_option_get_str("source", current_source, buf_len);
if (twCC != TWCC_SUCCESS)
{
ERR("Unable to retrieve current paper source from sane, CAP_FEEDERENABLED unsupported\n");
return twCC;
}
if (strcmp(source, "Auto") == 0 || strcmp(source, "ADF") == 0)
enabled = TRUE;
else
enabled = FALSE;
val = find_value_pos(current_source, paper_sources, buf_len, buf_count);
if (val == buf_count)
{
ERR("Wrong current paper source value, CAP_FEEDERENABLED unsupported\n");
twCC = TWCC_BADVALUE;
return twCC;
}
enabled = val > 0;
switch (action)
{
@ -958,16 +999,16 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac
case MSG_SET:
twCC = msg_set(pCapability, &val);
if (twCC == TWCC_SUCCESS)
if ((twCC == TWCC_SUCCESS) && (val < buf_count))
{
strcpy(source, "ADF");
twCC = sane_option_set_str("source", source, NULL);
output = paper_sources + val * buf_len;
TRACE("Setting paper source to %lu: %s\n", val, output);
twCC = set_option_value("source", output);
if (twCC != TWCC_SUCCESS)
{
strcpy(source, "Auto");
twCC = sane_option_set_str("source", source, NULL);
}
ERR("Unable to set paper source to %lu: %s\n", val, output);
}
else
twCC = TWCC_BADVALUE;
break;
case MSG_GETDEFAULT:
@ -975,9 +1016,14 @@ static TW_UINT16 SANE_CAPFeederEnabled (pTW_CAPABILITY pCapability, TW_UINT16 ac
break;
case MSG_RESET:
strcpy(source, "Auto");
if (sane_option_set_str("source", source, NULL) == TWCC_SUCCESS)
enabled = TRUE;
val = *(paper_sources + buf_len) ? 1 : 0; // set to Auto/ADF if it's supported
output = paper_sources + val * buf_len;
TRACE("Resetting paper source to %lu: %s\n", val, output);
twCC = set_option_value("source", output);
if (twCC != TWCC_SUCCESS)
ERR("Unable to reset paper source to %lu: %s\n", val, output);
else
enabled = val > 0;
/* .. fall through intentional .. */
case MSG_GETCURRENT:

View File

@ -115,30 +115,41 @@ TW_UINT16 sane_option_probe_resolution(const char *option_name, struct option_de
return sane_find_option(option_name, TYPE_INT, opt);
}
TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count)
static TW_UINT32 sane_categorize_value(const WCHAR* value, const WCHAR* const* filter[], char* categories, int buf_len)
{
TW_UINT32 i, j;
for(i=0; filter[i]; ++i)
{
if (!*categories)
{
for(j=0; filter[i][j]; ++j)
{
if (!wcscmp(value, filter[i][j]))
{
wcstombs(categories, value, buf_len);
return i;
}
}
}
categories += buf_len;
}
return 0;
}
TW_UINT16 sane_option_probe_str(const char* option_name, const WCHAR* const* filter[], char* opt_values, int buf_len)
{
WCHAR *p;
char buffer[256];
struct option_descriptor opt;
TW_UINT16 rc = sane_find_option("mode", TYPE_STRING, &opt);
TW_UINT16 rc = sane_find_option(option_name, TYPE_STRING, &opt);
if (rc != TWCC_SUCCESS) return rc;
if (opt.size > sizeof(buffer)) return TWCC_BADVALUE;
rc = sane_option_get_value( opt.optno, buffer );
if (rc != TWCC_SUCCESS) return rc;
if (opt.size > buf_len) return TWCC_BADVALUE;
if (!strcmp( buffer, "Lineart" )) *current = TWPT_BW;
else if (!strcmp( buffer, "Color" )) *current = TWPT_RGB;
else if (!strncmp( buffer, "Gray", 4 )) *current = TWPT_GRAY;
*count = 0;
if (opt.constraint_type == CONSTRAINT_STRING_LIST)
{
for (p = opt.constraint.strings; *p; p += lstrlenW(p) + 1)
{
if (!wcscmp( p, L"Lineart" )) choices[(*count)++] = TWPT_BW;
else if (!wcscmp( p, L"Color" )) choices[(*count)++] = TWPT_RGB;
else if (!wcsncmp( p, L"Gray", 4 )) choices[(*count)++] = TWPT_GRAY;
sane_categorize_value(p, filter, opt_values, buf_len);
}
}
return rc;

View File

@ -201,7 +201,7 @@ TW_UINT16 sane_option_set_int( const char *option_name, int val, BOOL *reload );
TW_UINT16 sane_option_get_str( const char *option_name, char *val, int len );
TW_UINT16 sane_option_set_str( const char *option_name, char *val, BOOL *reload );
TW_UINT16 sane_option_probe_resolution( const char *option_name, struct option_descriptor *opt );
TW_UINT16 sane_option_probe_mode(TW_UINT16 *current, TW_UINT32 *choices, int *count);
TW_UINT16 sane_option_probe_str( const char* option_name, const WCHAR* const* filter[], char* opt_vals, int buf_len );
TW_UINT16 sane_option_get_bool( const char *option_name, BOOL *val );
TW_UINT16 sane_option_set_bool( const char *option_name, BOOL val );
TW_UINT16 sane_option_get_scan_area( int *tlx, int *tly, int *brx, int *bry );