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
6ace799f
Commit
6ace799f
authored
Feb 23, 2009
by
Jeremy White
Committed by
Alexandre Julliard
Feb 24, 2009
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sane.ds: Implement support for ICAP_XRESOLUTION and ICAP_YRESOLUTION.
parent
f728c19a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
336 additions
and
7 deletions
+336
-7
capability.c
dlls/sane.ds/capability.c
+140
-1
ds_ctrl.c
dlls/sane.ds/ds_ctrl.c
+7
-1
options.c
dlls/sane.ds/options.c
+54
-3
sane_i.h
dlls/sane.ds/sane_i.h
+8
-0
dsm.c
dlls/twain_32/tests/dsm.c
+127
-2
No files found.
dlls/sane.ds/capability.c
View file @
6ace799f
...
...
@@ -122,11 +122,40 @@ static TW_UINT16 msg_get_enum(pTW_CAPABILITY pCapability, const TW_UINT32 *value
return
TWCC_SUCCESS
;
}
#ifdef SONAME_LIBSANE
static
TW_UINT16
msg_get_range
(
pTW_CAPABILITY
pCapability
,
TW_UINT16
type
,
TW_UINT32
minval
,
TW_UINT32
maxval
,
TW_UINT32
step
,
TW_UINT32
def
,
TW_UINT32
current
)
{
TW_RANGE
*
range
=
NULL
;
pCapability
->
ConType
=
TWON_RANGE
;
pCapability
->
hContainer
=
0
;
pCapability
->
hContainer
=
GlobalAlloc
(
0
,
sizeof
(
*
range
));
if
(
pCapability
->
hContainer
)
range
=
GlobalLock
(
pCapability
->
hContainer
);
if
(
!
range
)
return
TWCC_LOWMEMORY
;
range
->
ItemType
=
type
;
range
->
MinValue
=
minval
;
range
->
MaxValue
=
maxval
;
range
->
StepSize
=
step
;
range
->
DefaultValue
=
def
;
range
->
CurrentValue
=
current
;
GlobalUnlock
(
pCapability
->
hContainer
);
return
TWCC_SUCCESS
;
}
#endif
static
TW_UINT16
TWAIN_GetSupportedCaps
(
pTW_CAPABILITY
pCapability
)
{
TW_ARRAY
*
a
;
static
const
UINT16
supported_caps
[]
=
{
CAP_SUPPORTEDCAPS
,
CAP_XFERCOUNT
,
CAP_UICONTROLLABLE
,
ICAP_XFERMECH
,
ICAP_PIXELTYPE
,
ICAP_COMPRESSION
,
ICAP_PIXELFLAVOR
};
ICAP_XFERMECH
,
ICAP_PIXELTYPE
,
ICAP_COMPRESSION
,
ICAP_PIXELFLAVOR
,
ICAP_XRESOLUTION
,
ICAP_YRESOLUTION
};
pCapability
->
hContainer
=
GlobalAlloc
(
0
,
FIELD_OFFSET
(
TW_ARRAY
,
ItemList
[
sizeof
(
supported_caps
)]
));
pCapability
->
ConType
=
TWON_ARRAY
;
...
...
@@ -345,6 +374,108 @@ static TW_UINT16 SANE_ICAPCompression (pTW_CAPABILITY pCapability, TW_UINT16 act
return
twCC
;
}
/* ICAP_XRESOLUTION, ICAP_YRESOLUTION */
static
TW_UINT16
SANE_ICAPResolution
(
pTW_CAPABILITY
pCapability
,
TW_UINT16
action
,
TW_UINT16
cap
)
{
TW_UINT16
twCC
=
TWCC_BADCAP
;
#ifdef SONAME_LIBSANE
TW_UINT32
val
;
SANE_Int
current_resolution
;
TW_FIX32
*
default_res
;
const
char
*
best_option_name
;
SANE_Int
minval
,
maxval
,
quantval
;
SANE_Status
sane_rc
;
SANE_Int
set_status
;
TRACE
(
"ICAP_%cRESOLUTION
\n
"
,
cap
==
ICAP_XRESOLUTION
?
'X'
:
'Y'
);
/* Some scanners support 'x-resolution', most seem to just support 'resolution' */
if
(
cap
==
ICAP_XRESOLUTION
)
{
best_option_name
=
"x-resolution"
;
default_res
=
&
activeDS
.
defaultXResolution
;
}
else
{
best_option_name
=
"y-resolution"
;
default_res
=
&
activeDS
.
defaultYResolution
;
}
if
(
sane_option_get_int
(
activeDS
.
deviceHandle
,
best_option_name
,
&
current_resolution
)
!=
SANE_STATUS_GOOD
)
{
best_option_name
=
"resolution"
;
if
(
sane_option_get_int
(
activeDS
.
deviceHandle
,
best_option_name
,
&
current_resolution
)
!=
SANE_STATUS_GOOD
)
return
TWCC_BADCAP
;
}
/* Sane does not support a concept of 'default' resolution, so we have to
* cache the resolution the very first time we load the scanner, and use that
* as the default */
if
(
cap
==
ICAP_XRESOLUTION
&&
!
activeDS
.
XResolutionSet
)
{
default_res
->
Whole
=
current_resolution
;
default_res
->
Frac
=
0
;
activeDS
.
XResolutionSet
=
TRUE
;
}
if
(
cap
==
ICAP_YRESOLUTION
&&
!
activeDS
.
YResolutionSet
)
{
default_res
->
Whole
=
current_resolution
;
default_res
->
Frac
=
0
;
activeDS
.
YResolutionSet
=
TRUE
;
}
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
:
sane_rc
=
sane_option_probe_resolution
(
activeDS
.
deviceHandle
,
best_option_name
,
&
minval
,
&
maxval
,
&
quantval
);
if
(
sane_rc
!=
SANE_STATUS_GOOD
)
twCC
=
TWCC_BADCAP
;
else
twCC
=
msg_get_range
(
pCapability
,
TWTY_FIX32
,
minval
,
maxval
,
quantval
==
0
?
1
:
quantval
,
default_res
->
Whole
,
current_resolution
);
break
;
case
MSG_SET
:
twCC
=
msg_set
(
pCapability
,
&
val
);
if
(
twCC
==
TWCC_SUCCESS
)
{
TW_FIX32
f32
;
memcpy
(
&
f32
,
&
val
,
sizeof
(
f32
));
sane_rc
=
sane_option_set_int
(
activeDS
.
deviceHandle
,
best_option_name
,
f32
.
Whole
,
&
set_status
);
if
(
sane_rc
!=
SANE_STATUS_GOOD
)
{
FIXME
(
"Status of %d not expected or handled
\n
"
,
sane_rc
);
twCC
=
TWCC_BADCAP
;
}
else
if
(
set_status
==
SANE_INFO_INEXACT
)
twCC
=
TWCC_CHECKSTATUS
;
}
break
;
case
MSG_GETDEFAULT
:
twCC
=
set_onevalue
(
pCapability
,
TWTY_FIX32
,
default_res
->
Whole
);
break
;
case
MSG_RESET
:
sane_rc
=
sane_option_set_int
(
activeDS
.
deviceHandle
,
best_option_name
,
default_res
->
Whole
,
NULL
);
if
(
sane_rc
!=
SANE_STATUS_GOOD
)
return
TWCC_BADCAP
;
/* .. fall through intentional .. */
case
MSG_GETCURRENT
:
twCC
=
set_onevalue
(
pCapability
,
TWTY_FIX32
,
current_resolution
);
break
;
}
#endif
return
twCC
;
}
/* ICAP_PIXELFLAVOR */
static
TW_UINT16
SANE_ICAPPixelFlavor
(
pTW_CAPABILITY
pCapability
,
TW_UINT16
action
)
{
...
...
@@ -427,6 +558,14 @@ TW_UINT16 SANE_SaneCapability (pTW_CAPABILITY pCapability, TW_UINT16 action)
case
ICAP_COMPRESSION
:
twCC
=
SANE_ICAPCompression
(
pCapability
,
action
);
break
;
case
ICAP_XRESOLUTION
:
twCC
=
SANE_ICAPResolution
(
pCapability
,
action
,
pCapability
->
Cap
);
break
;
case
ICAP_YRESOLUTION
:
twCC
=
SANE_ICAPResolution
(
pCapability
,
action
,
pCapability
->
Cap
);
break
;
}
/* Twain specifies that you should return a 0 in response to QUERYSUPPORT,
...
...
dlls/sane.ds/ds_ctrl.c
View file @
6ace799f
...
...
@@ -162,7 +162,13 @@ TW_UINT16 SANE_CapabilitySet (pTW_IDENTITY pOrigin,
else
{
twCC
=
SANE_SaneCapability
(
pCapability
,
MSG_SET
);
twRC
=
(
twCC
==
TWCC_SUCCESS
)
?
TWRC_SUCCESS
:
TWRC_FAILURE
;
if
(
twCC
==
TWCC_CHECKSTATUS
)
{
twCC
=
TWCC_SUCCESS
;
twRC
=
TWRC_CHECKSTATUS
;
}
else
twRC
=
(
twCC
==
TWCC_SUCCESS
)
?
TWRC_SUCCESS
:
TWRC_FAILURE
;
activeDS
.
twCC
=
twCC
;
}
return
twRC
;
...
...
dlls/sane.ds/options.c
View file @
6ace799f
...
...
@@ -26,7 +26,8 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
twain
);
#ifdef SONAME_LIBSANE
SANE_Status
sane_option_get_int
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
*
val
)
static
SANE_Status
sane_find_option
(
SANE_Handle
h
,
const
char
*
option_name
,
const
SANE_Option_Descriptor
**
opt_p
,
int
*
optno
,
SANE_Value_Type
type
)
{
SANE_Status
rc
;
SANE_Int
optcount
;
...
...
@@ -41,9 +42,59 @@ SANE_Status sane_option_get_int(SANE_Handle h, const char *option_name, SANE_Int
{
opt
=
psane_get_option_descriptor
(
h
,
i
);
if
(
opt
&&
(
opt
->
name
&&
strcmp
(
opt
->
name
,
option_name
)
==
0
)
&&
opt
->
type
==
SANE_TYPE_INT
)
return
psane_control_option
(
h
,
i
,
SANE_ACTION_GET_VALUE
,
val
,
NULL
);
opt
->
type
==
type
)
{
*
opt_p
=
opt
;
*
optno
=
i
;
return
SANE_STATUS_GOOD
;
}
}
return
SANE_STATUS_EOF
;
}
SANE_Status
sane_option_get_int
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
*
val
)
{
SANE_Status
rc
;
int
optno
;
const
SANE_Option_Descriptor
*
opt
;
rc
=
sane_find_option
(
h
,
option_name
,
&
opt
,
&
optno
,
SANE_TYPE_INT
);
if
(
rc
!=
SANE_STATUS_GOOD
)
return
rc
;
return
psane_control_option
(
h
,
optno
,
SANE_ACTION_GET_VALUE
,
val
,
NULL
);
}
SANE_Status
sane_option_set_int
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
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_INT
);
if
(
rc
!=
SANE_STATUS_GOOD
)
return
rc
;
return
psane_control_option
(
h
,
optno
,
SANE_ACTION_SET_VALUE
,
(
void
*
)
&
val
,
status
);
}
SANE_Status
sane_option_probe_resolution
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
*
minval
,
SANE_Int
*
maxval
,
SANE_Int
*
quant
)
{
SANE_Status
rc
;
int
optno
;
const
SANE_Option_Descriptor
*
opt
;
rc
=
sane_find_option
(
h
,
option_name
,
&
opt
,
&
optno
,
SANE_TYPE_INT
);
if
(
rc
!=
SANE_STATUS_GOOD
)
return
rc
;
if
(
opt
->
constraint_type
!=
SANE_CONSTRAINT_RANGE
)
return
SANE_STATUS_UNSUPPORTED
;
*
minval
=
opt
->
constraint
.
range
->
min
;
*
maxval
=
opt
->
constraint
.
range
->
max
;
*
quant
=
opt
->
constraint
.
range
->
quant
;
return
rc
;
}
#endif
dlls/sane.ds/sane_i.h
View file @
6ace799f
...
...
@@ -53,6 +53,8 @@ MAKE_FUNCPTR(sane_strstatus)
extern
HINSTANCE
SANE_instance
;
#define TWCC_CHECKSTATUS (TWCC_CUSTOMBASE + 1)
/* internal information about an active data source */
struct
tagActiveDS
{
...
...
@@ -73,6 +75,10 @@ struct tagActiveDS
/* Capabilities */
TW_UINT16
capXferMech
;
/* ICAP_XFERMECH */
TW_UINT16
capPixelType
;
/* ICAP_PIXELTYPE */
BOOL
XResolutionSet
;
TW_FIX32
defaultXResolution
;
BOOL
YResolutionSet
;
TW_FIX32
defaultYResolution
;
}
activeDS
;
/* Helper functions */
...
...
@@ -214,6 +220,8 @@ HWND ScanningDialogBox(HWND dialog, LONG progress);
/* Option functions */
#ifdef SONAME_LIBSANE
SANE_Status
sane_option_get_int
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
*
val
);
SANE_Status
sane_option_set_int
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
val
,
SANE_Int
*
status
);
SANE_Status
sane_option_probe_resolution
(
SANE_Handle
h
,
const
char
*
option_name
,
SANE_Int
*
minval
,
SANE_Int
*
maxval
,
SANE_Int
*
quant
);
#endif
...
...
dlls/twain_32/tests/dsm.c
View file @
6ace799f
...
...
@@ -267,6 +267,127 @@ static void test_onevalue_cap(TW_IDENTITY *appid, TW_IDENTITY *source, TW_UINT16
}
}
static
void
test_resolution
(
TW_IDENTITY
*
appid
,
TW_IDENTITY
*
source
,
TW_UINT16
captype
,
TW_INT32
minimum_support
)
{
TW_UINT16
rc
;
TW_STATUS
status
;
TW_CAPABILITY
cap
;
TW_UINT32
val
;
TW_UINT16
type
;
TW_INT32
actual_support
;
TW_FIX32
orig_value
=
{
0
,
0
};
TW_UINT32
new_value
=
0
;
TW_FIX32
default_value
=
{
0
,
0
};
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
if
(
rc
!=
TWRC_SUCCESS
)
return
;
ok
(
get_onevalue
(
cap
.
hContainer
,
(
TW_UINT32
*
)
&
actual_support
,
NULL
),
"Returned cap.hContainer invalid for QuerySupport on type 0x%x
\n
"
,
captype
);
ok
((
actual_support
&
minimum_support
)
==
minimum_support
,
"Error: minimum support 0x%x for type 0x%x, got 0x%x
\n
"
,
minimum_support
,
captype
,
actual_support
);
if
(
actual_support
&
TWQC_GETCURRENT
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
if
(
rc
==
TWRC_SUCCESS
)
{
get_onevalue
(
cap
.
hContainer
,
&
val
,
&
type
);
ok
(
type
==
TWTY_FIX32
,
"GETCURRENT for RESOLUTION is not type FIX32, is type %d
\n
"
,
type
);
memcpy
(
&
orig_value
,
&
val
,
sizeof
(
orig_value
));
GlobalFree
(
cap
.
hContainer
);
}
}
if
(
actual_support
&
TWQC_GETDEFAULT
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
if
(
rc
==
TWRC_SUCCESS
)
{
ok
(
type
==
TWTY_FIX32
,
"GETDEFAULT for RESOLUTION is not type FIX32, is type %d
\n
"
,
type
);
memcpy
(
&
default_value
,
&
val
,
sizeof
(
default_value
));
GlobalFree
(
cap
.
hContainer
);
}
}
if
(
actual_support
&
TWQC_GET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
if
(
rc
==
TWRC_SUCCESS
)
{
TW_RANGE
*
range
;
ok
(
cap
.
ConType
==
TWON_RANGE
,
"MSG_GET for ICAP_[XY]RESOLUTION did not return TWON_RANGE, but %d
\n
"
,
cap
.
ConType
);
range
=
GlobalLock
(
cap
.
hContainer
);
trace
(
"MSG_GET of 0x%x returned [ItemType %d|MinValue %d|MaxValue %d|StepSize %d|DefaultValue %d|CurrentValue %d]:
\n
"
,
cap
.
Cap
,
range
->
ItemType
,
range
->
MinValue
,
range
->
MaxValue
,
range
->
StepSize
,
range
->
DefaultValue
,
range
->
CurrentValue
);
for
(
new_value
=
range
->
MinValue
;
new_value
<
range
->
MaxValue
;
new_value
+=
range
->
StepSize
)
if
(
new_value
!=
range
->
CurrentValue
)
break
;
GlobalUnlock
(
cap
.
hContainer
);
GlobalFree
(
cap
.
hContainer
);
}
}
if
(
actual_support
&
TWQC_SET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
cap
.
ConType
=
TWON_ONEVALUE
;
cap
.
hContainer
=
alloc_and_set_onevalue
(
new_value
,
TWTY_FIX32
);
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
GlobalFree
(
cap
.
hContainer
);
}
if
(
actual_support
&
TWQC_RESET
)
{
memset
(
&
cap
,
0
,
sizeof
(
cap
));
cap
.
Cap
=
captype
;
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 type 0x%x
\n
"
,
rc
,
status
.
ConditionCode
,
captype
);
if
(
rc
==
TWRC_SUCCESS
)
GlobalFree
(
cap
.
hContainer
);
}
}
static
void
test_single_source
(
TW_IDENTITY
*
appid
,
TW_IDENTITY
*
source
)
{
...
...
@@ -356,10 +477,14 @@ static void test_single_source(TW_IDENTITY *appid, TW_IDENTITY *source)
if
(
capabilities
[
ICAP_XFERMECH
])
test_onevalue_cap
(
appid
,
source
,
ICAP_XFERMECH
,
TWTY_UINT16
,
TWQC_GET
|
TWQC_SET
|
TWQC_GETDEFAULT
|
TWQC_GETCURRENT
|
TWQC_RESET
);
todo_wine
ok
(
capabilities
[
ICAP_XRESOLUTION
],
"ICAP_XRESOLUTION not supported
\n
"
);
todo_wine
if
(
capabilities
[
ICAP_XRESOLUTION
])
test_resolution
(
appid
,
source
,
ICAP_XRESOLUTION
,
TWQC_GET
|
TWQC_SET
|
TWQC_GETDEFAULT
|
TWQC_GETCURRENT
|
TWQC_RESET
);
ok
(
capabilities
[
ICAP_YRESOLUTION
],
"ICAP_YRESOLUTION not supported
\n
"
);
if
(
capabilities
[
ICAP_YRESOLUTION
])
test_resolution
(
appid
,
source
,
ICAP_YRESOLUTION
,
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