Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
81b28887
Commit
81b28887
authored
Mar 06, 2009
by
Jeremy White
Committed by
Alexandre Julliard
Mar 09, 2009
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sane.ds: Add support for ICAP_SUPPORTEDSIZES, enabling rational sizing for scans.
parent
fdb37491
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
363 additions
and
1 deletion
+363
-1
capability.c
dlls/sane.ds/capability.c
+236
-1
options.c
dlls/sane.ds/options.c
+13
-0
sane_i.h
dlls/sane.ds/sane_i.h
+1
-0
dsm.c
dlls/twain_32/tests/dsm.c
+113
-0
No files found.
dlls/sane.ds/capability.c
View file @
81b28887
...
...
@@ -29,6 +29,7 @@
#include "winbase.h"
#include "twain.h"
#include "sane_i.h"
#include "winnls.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
twain
);
...
...
@@ -168,7 +169,7 @@ static TW_UINT16 TWAIN_GetSupportedCaps(pTW_CAPABILITY pCapability)
static
const
UINT16
supported_caps
[]
=
{
CAP_SUPPORTEDCAPS
,
CAP_XFERCOUNT
,
CAP_UICONTROLLABLE
,
CAP_AUTOFEED
,
CAP_FEEDERENABLED
,
ICAP_XFERMECH
,
ICAP_PIXELTYPE
,
ICAP_UNITS
,
ICAP_BITDEPTH
,
ICAP_COMPRESSION
,
ICAP_PIXELFLAVOR
,
ICAP_XRESOLUTION
,
ICAP_YRESOLUTION
,
ICAP_PHYSICALHEIGHT
,
ICAP_PHYSICALWIDTH
};
ICAP_XRESOLUTION
,
ICAP_YRESOLUTION
,
ICAP_PHYSICALHEIGHT
,
ICAP_PHYSICALWIDTH
,
ICAP_SUPPORTEDSIZES
};
pCapability
->
hContainer
=
GlobalAlloc
(
0
,
FIELD_OFFSET
(
TW_ARRAY
,
ItemList
[
sizeof
(
supported_caps
)]
));
pCapability
->
ConType
=
TWON_ARRAY
;
...
...
@@ -815,6 +816,229 @@ static TW_UINT16 SANE_ICAPPixelFlavor (pTW_CAPABILITY pCapability, TW_UINT16 act
return
twCC
;
}
#ifdef SONAME_LIBSANE
static
TW_UINT16
get_width_height
(
double
*
width
,
double
*
height
,
BOOL
max
)
{
SANE_Status
status
;
SANE_Fixed
tlx_current
,
tlx_min
,
tlx_max
;
SANE_Fixed
tly_current
,
tly_min
,
tly_max
;
SANE_Fixed
brx_current
,
brx_min
,
brx_max
;
SANE_Fixed
bry_current
,
bry_min
,
bry_max
;
status
=
sane_option_probe_scan_area
(
activeDS
.
deviceHandle
,
"tl-x"
,
&
tlx_current
,
NULL
,
&
tlx_min
,
&
tlx_max
,
NULL
);
if
(
status
!=
SANE_STATUS_GOOD
)
return
sane_status_to_twcc
(
status
);
status
=
sane_option_probe_scan_area
(
activeDS
.
deviceHandle
,
"tl-y"
,
&
tly_current
,
NULL
,
&
tly_min
,
&
tly_max
,
NULL
);
if
(
status
!=
SANE_STATUS_GOOD
)
return
sane_status_to_twcc
(
status
);
status
=
sane_option_probe_scan_area
(
activeDS
.
deviceHandle
,
"br-x"
,
&
brx_current
,
NULL
,
&
brx_min
,
&
brx_max
,
NULL
);
if
(
status
!=
SANE_STATUS_GOOD
)
return
sane_status_to_twcc
(
status
);
status
=
sane_option_probe_scan_area
(
activeDS
.
deviceHandle
,
"br-y"
,
&
bry_current
,
NULL
,
&
bry_min
,
&
bry_max
,
NULL
);
if
(
status
!=
SANE_STATUS_GOOD
)
return
sane_status_to_twcc
(
status
);
if
(
max
)
*
width
=
SANE_UNFIX
(
brx_max
)
-
SANE_UNFIX
(
tlx_min
);
else
*
width
=
SANE_UNFIX
(
brx_current
)
-
SANE_UNFIX
(
tlx_current
);
if
(
max
)
*
height
=
SANE_UNFIX
(
bry_max
)
-
SANE_UNFIX
(
tly_min
);
else
*
height
=
SANE_UNFIX
(
bry_current
)
-
SANE_UNFIX
(
tly_current
);
return
(
TWCC_SUCCESS
);
}
static
TW_UINT16
set_one_coord
(
const
char
*
name
,
double
coord
)
{
SANE_Status
status
;
status
=
sane_option_set_fixed
(
activeDS
.
deviceHandle
,
name
,
SANE_FIX
(
coord
),
NULL
);
if
(
status
!=
SANE_STATUS_GOOD
)
return
sane_status_to_twcc
(
status
);
return
TWCC_SUCCESS
;
}
static
TW_UINT16
set_width_height
(
double
width
,
double
height
)
{
TW_UINT16
rc
=
TWCC_SUCCESS
;
rc
=
set_one_coord
(
"tl-x"
,
0
);
if
(
rc
!=
TWCC_SUCCESS
)
return
rc
;
rc
=
set_one_coord
(
"br-x"
,
width
);
if
(
rc
!=
TWCC_SUCCESS
)
return
rc
;
rc
=
set_one_coord
(
"tl-y"
,
0
);
if
(
rc
!=
TWCC_SUCCESS
)
return
rc
;
rc
=
set_one_coord
(
"br-y"
,
height
);
return
rc
;
}
typedef
struct
{
TW_UINT32
size
;
double
x
;
double
y
;
}
supported_size_t
;
static
const
supported_size_t
supported_sizes
[]
=
{
{
TWSS_NONE
,
0
,
0
},
{
TWSS_A4
,
210
,
297
},
{
TWSS_JISB5
,
182
,
257
},
{
TWSS_USLETTER
,
215
.
9
,
279
.
4
},
{
TWSS_USLEGAL
,
215
.
9
,
355
.
6
},
{
TWSS_A5
,
148
,
210
},
{
TWSS_B4
,
250
,
353
},
{
TWSS_B6
,
125
,
176
},
{
TWSS_USLEDGER
,
215
.
9
,
431
.
8
},
{
TWSS_USEXECUTIVE
,
184
.
15
,
266
.
7
},
{
TWSS_A3
,
297
,
420
},
};
#define SUPPORTED_SIZE_COUNT (sizeof(supported_sizes) / sizeof(supported_sizes[0]))
static
TW_UINT16
get_default_paper_size
(
const
supported_size_t
*
s
,
int
n
)
{
DWORD
paper
;
int
rc
;
int
defsize
=
-
1
;
double
width
,
height
;
int
i
;
rc
=
GetLocaleInfoA
(
LOCALE_USER_DEFAULT
,
LOCALE_IPAPERSIZE
|
LOCALE_RETURN_NUMBER
,
(
void
*
)
&
paper
,
sizeof
(
paper
));
if
(
rc
>
0
)
switch
(
paper
)
{
case
1
:
defsize
=
TWSS_USLETTER
;
break
;
case
5
:
defsize
=
TWSS_USLEGAL
;
break
;
case
8
:
defsize
=
TWSS_A3
;
break
;
case
9
:
defsize
=
TWSS_A4
;
break
;
}
if
(
defsize
==
-
1
)
return
TWSS_NONE
;
if
(
get_width_height
(
&
width
,
&
height
,
TRUE
)
!=
TWCC_SUCCESS
)
return
TWSS_NONE
;
for
(
i
=
0
;
i
<
n
;
i
++
)
if
(
s
[
i
].
size
==
defsize
)
{
/* Sane's use of integers to store floats is a hair lossy; deal with it */
if
(
s
[
i
].
x
>
(
width
+
.
01
)
||
s
[
i
].
y
>
(
height
+
0
.
01
))
return
TWSS_NONE
;
else
return
s
[
i
].
size
;
}
return
TWSS_NONE
;
}
static
TW_UINT16
get_current_paper_size
(
const
supported_size_t
*
s
,
int
n
)
{
int
i
;
double
width
,
height
;
double
xdelta
,
ydelta
;
if
(
get_width_height
(
&
width
,
&
height
,
FALSE
)
!=
TWCC_SUCCESS
)
return
TWSS_NONE
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
/* Sane's use of integers to store floats results
* in a very small error; cope with that */
xdelta
=
s
[
i
].
x
-
width
;
ydelta
=
s
[
i
].
y
-
height
;
if
(
xdelta
<
0
.
01
&&
xdelta
>
-
0
.
01
&&
ydelta
<
0
.
01
&&
ydelta
>
-
0
.
01
)
return
s
[
i
].
size
;
}
return
TWSS_NONE
;
}
#endif
/* ICAP_SUPPORTEDSIZES */
static
TW_UINT16
SANE_ICAPSupportedSizes
(
pTW_CAPABILITY
pCapability
,
TW_UINT16
action
)
{
TW_UINT16
twCC
=
TWCC_BADCAP
;
#ifdef SONAME_LIBSANE
static
TW_UINT32
possible_values
[
SUPPORTED_SIZE_COUNT
];
int
i
;
TW_UINT32
val
;
TW_UINT16
default_size
=
get_default_paper_size
(
supported_sizes
,
SUPPORTED_SIZE_COUNT
);
TW_UINT16
current_size
=
get_current_paper_size
(
supported_sizes
,
SUPPORTED_SIZE_COUNT
);
TRACE
(
"ICAP_SUPPORTEDSIZES
\n
"
);
switch
(
action
)
{
case
MSG_QUERYSUPPORT
:
twCC
=
set_onevalue
(
pCapability
,
TWTY_INT32
,
TWQC_GET
|
TWQC_SET
|
TWQC_GETDEFAULT
|
TWQC_GETCURRENT
|
TWQC_RESET
);
break
;
case
MSG_GET
:
for
(
i
=
0
;
i
<
sizeof
(
supported_sizes
)
/
sizeof
(
supported_sizes
[
0
]);
i
++
)
possible_values
[
i
]
=
supported_sizes
[
i
].
size
;
twCC
=
msg_get_enum
(
pCapability
,
possible_values
,
sizeof
(
possible_values
)
/
sizeof
(
possible_values
[
0
]),
TWTY_UINT16
,
current_size
,
default_size
);
WARN
(
"Partial Stub: our supported size selection is a bit thin.
\n
"
);
break
;
case
MSG_SET
:
twCC
=
msg_set
(
pCapability
,
&
val
);
if
(
twCC
==
TWCC_SUCCESS
)
for
(
i
=
1
;
i
<
SUPPORTED_SIZE_COUNT
;
i
++
)
if
(
supported_sizes
[
i
].
size
==
val
)
return
set_width_height
(
supported_sizes
[
i
].
x
,
supported_sizes
[
i
].
y
);
ERR
(
"Unsupported size %d
\n
"
,
val
);
twCC
=
TWCC_BADCAP
;
break
;
case
MSG_GETDEFAULT
:
twCC
=
set_onevalue
(
pCapability
,
TWTY_UINT16
,
default_size
);
break
;
case
MSG_RESET
:
twCC
=
TWCC_BADCAP
;
for
(
i
=
1
;
i
<
SUPPORTED_SIZE_COUNT
;
i
++
)
if
(
supported_sizes
[
i
].
size
==
default_size
)
{
twCC
=
set_width_height
(
supported_sizes
[
i
].
x
,
supported_sizes
[
i
].
y
);
break
;
}
if
(
twCC
!=
TWCC_SUCCESS
)
return
twCC
;
/* .. fall through intentional .. */
case
MSG_GETCURRENT
:
twCC
=
set_onevalue
(
pCapability
,
TWTY_UINT16
,
current_size
);
break
;
}
#undef SUPPORTED_SIZE_COUNT
#endif
return
twCC
;
}
/* CAP_AUTOFEED */
static
TW_UINT16
SANE_CAPAutofeed
(
pTW_CAPABILITY
pCapability
,
TW_UINT16
action
)
{
...
...
@@ -1027,6 +1251,10 @@ TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action)
twCC
=
SANE_ICAPPhysical
(
pCapability
,
action
,
pCapability
->
Cap
);
break
;
case
ICAP_SUPPORTEDSIZES
:
twCC
=
SANE_ICAPSupportedSizes
(
pCapability
,
action
);
break
;
}
/* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
...
...
@@ -1058,5 +1286,12 @@ TW_UINT16 SANE_SaneSetDefaults (void)
if
(
SANE_SaneCapability
(
&
cap
,
MSG_RESET
)
==
TWCC_SUCCESS
)
GlobalFree
(
cap
.
hContainer
);
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
if
(
SANE_SaneCapability
(
&
cap
,
MSG_RESET
)
==
TWCC_SUCCESS
)
GlobalFree
(
cap
.
hContainer
);
return
TWCC_SUCCESS
;
}
dlls/sane.ds/options.c
View file @
81b28887
...
...
@@ -111,6 +111,19 @@ SANE_Status sane_option_set_bool(SANE_Handle h, const char *option_name, SANE_Bo
return
psane_control_option
(
h
,
optno
,
SANE_ACTION_SET_VALUE
,
(
void
*
)
&
val
,
status
);
}
SANE_Status
sane_option_set_fixed
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Fixed
val
,
SANE_Int
*
status
)
{
SANE_Status
rc
;
int
optno
;
const
SANE_Option_Descriptor
*
opt
;
rc
=
sane_find_option
(
h
,
option_name
,
&
opt
,
&
optno
,
SANE_TYPE_FIXED
);
if
(
rc
!=
SANE_STATUS_GOOD
)
return
rc
;
return
psane_control_option
(
h
,
optno
,
SANE_ACTION_SET_VALUE
,
(
void
*
)
&
val
,
status
);
}
SANE_Status
sane_option_get_str
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_String
val
,
size_t
len
,
SANE_Int
*
status
)
{
SANE_Status
rc
;
...
...
dlls/sane.ds/sane_i.h
View file @
81b28887
...
...
@@ -233,6 +233,7 @@ SANE_Status sane_option_probe_scan_area(SANE_Handle h, const char *option_name,
SANE_Unit
*
unit
,
SANE_Fixed
*
min
,
SANE_Fixed
*
max
,
SANE_Fixed
*
quant
);
SANE_Status
sane_option_get_bool
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Bool
*
val
,
SANE_Int
*
status
);
SANE_Status
sane_option_set_bool
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Bool
val
,
SANE_Int
*
status
);
SANE_Status
sane_option_set_fixed
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Fixed
val
,
SANE_Int
*
status
);
#endif
...
...
dlls/twain_32/tests/dsm.c
View file @
81b28887
...
...
@@ -473,6 +473,116 @@ static void test_physical(TW_IDENTITY *appid, TW_IDENTITY *source, TW_UINT16 cap
}
static
void
test_supported_sizes
(
TW_IDENTITY
*
appid
,
TW_IDENTITY
*
source
,
TW_INT32
minimum_support
)
{
TW_UINT16
rc
;
TW_STATUS
status
;
TW_CAPABILITY
cap
;
TW_UINT32
val
;
TW_UINT16
type
;
TW_INT32
actual_support
;
TW_UINT32
orig_value
;
TW_UINT32
default_value
;
TW_UINT32
new_value
=
TWSS_NONE
;
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_QUERYSUPPORT
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_QUERYSUPPORT for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
if
(
rc
!=
TWRC_SUCCESS
)
return
;
ok
(
get_onevalue
(
cap
.
hContainer
,
(
TW_UINT32
*
)
&
actual_support
,
NULL
),
"Returned cap.hContainer invalid for QuerySupport on ICAP_SUPPORTEDSIZES
\n
"
);
ok
((
actual_support
&
minimum_support
)
==
minimum_support
,
"Error: minimum support 0x%x for ICAP_SUPPORTEDSIZES, got 0x%x
\n
"
,
minimum_support
,
actual_support
);
if
(
actual_support
&
TWQC_GETCURRENT
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_GETCURRENT
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_GETCURRENT for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
if
(
rc
==
TWRC_SUCCESS
)
{
get_onevalue
(
cap
.
hContainer
,
&
val
,
&
type
);
ok
(
type
==
TWTY_UINT16
,
"GETCURRENT for ICAP_SUPPORTEDSIZES is not type UINT16, is type %d
\n
"
,
type
);
trace
(
"Current size is %d
\n
"
,
val
);
GlobalFree
(
cap
.
hContainer
);
orig_value
=
val
;
}
}
if
(
actual_support
&
TWQC_GETDEFAULT
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_GETDEFAULT
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_GETDEFAULT for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
if
(
rc
==
TWRC_SUCCESS
)
{
get_onevalue
(
cap
.
hContainer
,
&
val
,
&
type
);
ok
(
type
==
TWTY_UINT16
,
"GETDEFAULT for PHYSICALXXX is not type TWTY_UINT16, is type %d
\n
"
,
type
);
trace
(
"Default size is %d
\n
"
,
val
);
GlobalFree
(
cap
.
hContainer
);
default_value
=
val
;
}
}
if
(
actual_support
&
TWQC_GET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_GET
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_GET for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
check_get
(
&
cap
,
actual_support
,
orig_value
,
default_value
,
&
new_value
);
}
if
(
actual_support
&
TWQC_SET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_ONEVALUE
;
cap
.
hContainer
=
alloc_and_set_onevalue
(
new_value
,
TWTY_UINT16
);
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_SET
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_SET for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
GlobalFree
(
cap
.
hContainer
);
}
if
(
actual_support
&
TWQC_RESET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
ICAP_SUPPORTEDSIZES
;
cap
.
ConType
=
TWON_DONTCARE16
;
rc
=
pDSM_Entry
(
appid
,
source
,
DG_CONTROL
,
DAT_CAPABILITY
,
MSG_RESET
,
&
cap
);
get_condition_code
(
appid
,
source
,
&
status
);
ok
(
rc
==
TWRC_SUCCESS
&&
status
.
ConditionCode
==
TWCC_SUCCESS
,
"Error [rc %d|cc %d] doing MSG_RESET for ICAP_SUPPORTEDSIZES
\n
"
,
rc
,
status
.
ConditionCode
);
if
(
rc
==
TWRC_SUCCESS
)
GlobalFree
(
cap
.
hContainer
);
}
}
static
void
test_single_source
(
TW_IDENTITY
*
appid
,
TW_IDENTITY
*
source
)
{
...
...
@@ -586,6 +696,9 @@ static void test_single_source(TW_IDENTITY *appid, TW_IDENTITY *source)
if
(
capabilities
[
CAP_FEEDERENABLED
])
test_onevalue_cap
(
appid
,
source
,
CAP_FEEDERENABLED
,
TWTY_BOOL
,
TWQC_GET
|
TWQC_SET
|
TWQC_GETDEFAULT
|
TWQC_GETCURRENT
|
TWQC_RESET
);
if
(
capabilities
[
ICAP_SUPPORTEDSIZES
])
test_supported_sizes
(
appid
,
source
,
TWQC_GET
|
TWQC_SET
|
TWQC_GETDEFAULT
|
TWQC_GETCURRENT
|
TWQC_RESET
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment