1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 1997 Geoffrey T. Dairiki
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci   This file is part of a SANE backend for HP Scanners supporting
40141cc406Sopenharmony_ci   HP Scanner Control Language (SCL).
41141cc406Sopenharmony_ci*/
42141cc406Sopenharmony_ci
43141cc406Sopenharmony_ci/* #define STUBS
44141cc406Sopenharmony_ciextern int sanei_debug_hp; */
45141cc406Sopenharmony_ci#define DEBUG_DECLARE_ONLY
46141cc406Sopenharmony_ci
47141cc406Sopenharmony_ci#include "../include/sane/config.h"
48141cc406Sopenharmony_ci#include "../include/sane/sanei_backend.h"
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci#include "../include/lassert.h"
51141cc406Sopenharmony_ci#include <string.h>
52141cc406Sopenharmony_ci
53141cc406Sopenharmony_ci#include <sys/types.h>
54141cc406Sopenharmony_ci
55141cc406Sopenharmony_ci#include "hp.h"
56141cc406Sopenharmony_ci#include "hp-option.h"
57141cc406Sopenharmony_ci#include "hp-accessor.h"
58141cc406Sopenharmony_ci#include "hp-device.h"
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#define DATA_SIZE_INCREMENT	(1024)
61141cc406Sopenharmony_ci
62141cc406Sopenharmony_ci/*
63141cc406Sopenharmony_ci * class HpData
64141cc406Sopenharmony_ci */
65141cc406Sopenharmony_cistruct hp_data_s
66141cc406Sopenharmony_ci{
67141cc406Sopenharmony_ci    hp_byte_t *	buf;
68141cc406Sopenharmony_ci    size_t	bufsiz;
69141cc406Sopenharmony_ci    size_t	length;
70141cc406Sopenharmony_ci    hp_bool_t	frozen;
71141cc406Sopenharmony_ci};
72141cc406Sopenharmony_ci
73141cc406Sopenharmony_ci
74141cc406Sopenharmony_cistatic void
75141cc406Sopenharmony_cihp_data_resize (HpData this, size_t newsize)
76141cc406Sopenharmony_ci{
77141cc406Sopenharmony_ci
78141cc406Sopenharmony_ci  if (this->bufsiz != newsize)
79141cc406Sopenharmony_ci    {
80141cc406Sopenharmony_ci      assert(!this->frozen);
81141cc406Sopenharmony_ci      this->buf = sanei_hp_realloc(this->buf, newsize);
82141cc406Sopenharmony_ci      assert(this->buf);
83141cc406Sopenharmony_ci      this->bufsiz = newsize;
84141cc406Sopenharmony_ci    }
85141cc406Sopenharmony_ci}
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_cistatic void
88141cc406Sopenharmony_cihp_data_freeze (HpData this)
89141cc406Sopenharmony_ci{
90141cc406Sopenharmony_ci  hp_data_resize(this, this->length);
91141cc406Sopenharmony_ci  this->frozen = 1;
92141cc406Sopenharmony_ci}
93141cc406Sopenharmony_ci
94141cc406Sopenharmony_cistatic size_t
95141cc406Sopenharmony_cihp_data_alloc (HpData this, size_t sz)
96141cc406Sopenharmony_ci{
97141cc406Sopenharmony_ci  size_t	newsize	= this->bufsiz;
98141cc406Sopenharmony_ci  size_t	offset	= this->length;
99141cc406Sopenharmony_ci
100141cc406Sopenharmony_ci /*
101141cc406Sopenharmony_ci  * mike@easysw.com:
102141cc406Sopenharmony_ci  *
103141cc406Sopenharmony_ci  * The following code is REQUIRED so that pointers, etc. aren't
104141cc406Sopenharmony_ci  * misaligned.  This causes MAJOR problems on all SPARC, ALPHA,
105141cc406Sopenharmony_ci  * and MIPS processors, and possibly others.
106141cc406Sopenharmony_ci  *
107141cc406Sopenharmony_ci  * The workaround is to ensure that all allocations are in multiples
108141cc406Sopenharmony_ci  * of 8 bytes.
109141cc406Sopenharmony_ci  */
110141cc406Sopenharmony_ci  sz = (sz + sizeof (long) - 1) & ~(sizeof (long) - 1);
111141cc406Sopenharmony_ci
112141cc406Sopenharmony_ci  while (newsize < this->length + sz)
113141cc406Sopenharmony_ci      newsize += DATA_SIZE_INCREMENT;
114141cc406Sopenharmony_ci  hp_data_resize(this, newsize);
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_ci  this->length += sz;
117141cc406Sopenharmony_ci  return offset;
118141cc406Sopenharmony_ci}
119141cc406Sopenharmony_ci
120141cc406Sopenharmony_cistatic void *
121141cc406Sopenharmony_cihp_data_data (HpData this, size_t offset)
122141cc406Sopenharmony_ci{
123141cc406Sopenharmony_ci  assert(offset < this->length);
124141cc406Sopenharmony_ci  return (char *)this->buf + offset;
125141cc406Sopenharmony_ci}
126141cc406Sopenharmony_ci
127141cc406Sopenharmony_ciHpData
128141cc406Sopenharmony_cisanei_hp_data_new (void)
129141cc406Sopenharmony_ci{
130141cc406Sopenharmony_ci  return sanei_hp_allocz(sizeof(struct hp_data_s));
131141cc406Sopenharmony_ci}
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_ciHpData
134141cc406Sopenharmony_cisanei_hp_data_dup (HpData orig)
135141cc406Sopenharmony_ci{
136141cc406Sopenharmony_ci  HpData new;
137141cc406Sopenharmony_ci
138141cc406Sopenharmony_ci  hp_data_freeze(orig);
139141cc406Sopenharmony_ci  if (!( new = sanei_hp_memdup(orig, sizeof(*orig)) ))
140141cc406Sopenharmony_ci      return 0;
141141cc406Sopenharmony_ci  if (!(new->buf = sanei_hp_memdup(orig->buf, orig->bufsiz)))
142141cc406Sopenharmony_ci      {
143141cc406Sopenharmony_ci	sanei_hp_free(new);
144141cc406Sopenharmony_ci	return 0;
145141cc406Sopenharmony_ci      }
146141cc406Sopenharmony_ci  return new;
147141cc406Sopenharmony_ci}
148141cc406Sopenharmony_ci
149141cc406Sopenharmony_civoid
150141cc406Sopenharmony_cisanei_hp_data_destroy (HpData this)
151141cc406Sopenharmony_ci{
152141cc406Sopenharmony_ci  sanei_hp_free(this->buf);
153141cc406Sopenharmony_ci  sanei_hp_free(this);
154141cc406Sopenharmony_ci}
155141cc406Sopenharmony_ci
156141cc406Sopenharmony_ci
157141cc406Sopenharmony_ci/*
158141cc406Sopenharmony_ci * class HpAccessor
159141cc406Sopenharmony_ci */
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_citypedef const struct hp_accessor_type_s *	HpAccessorType;
162141cc406Sopenharmony_citypedef struct hp_accessor_s *			_HpAccessor;
163141cc406Sopenharmony_ci
164141cc406Sopenharmony_cistruct hp_accessor_s
165141cc406Sopenharmony_ci{
166141cc406Sopenharmony_ci    HpAccessorType	type;
167141cc406Sopenharmony_ci    size_t		data_offset;
168141cc406Sopenharmony_ci    size_t		data_size;
169141cc406Sopenharmony_ci};
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_cistruct hp_accessor_type_s
172141cc406Sopenharmony_ci{
173141cc406Sopenharmony_ci    SANE_Status (*get)(HpAccessor this, HpData data, void * valp);
174141cc406Sopenharmony_ci    SANE_Status (*set)(HpAccessor this,  HpData data, void * valp);
175141cc406Sopenharmony_ci    int	 (*getint)(HpAccessor this, HpData data);
176141cc406Sopenharmony_ci    void (*setint)(HpAccessor this, HpData data, int val);
177141cc406Sopenharmony_ci};
178141cc406Sopenharmony_ci
179141cc406Sopenharmony_ciSANE_Status
180141cc406Sopenharmony_cisanei_hp_accessor_get (HpAccessor this, HpData data, void * valp)
181141cc406Sopenharmony_ci{
182141cc406Sopenharmony_ci  if (!this->type->get)
183141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
184141cc406Sopenharmony_ci  return (*this->type->get)(this, data, valp);
185141cc406Sopenharmony_ci}
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_ciSANE_Status
188141cc406Sopenharmony_cisanei_hp_accessor_set (HpAccessor this,  HpData data, void * valp)
189141cc406Sopenharmony_ci{
190141cc406Sopenharmony_ci  if (!this->type->set)
191141cc406Sopenharmony_ci      return SANE_STATUS_INVAL;
192141cc406Sopenharmony_ci  return (*this->type->set)(this, data, valp);
193141cc406Sopenharmony_ci}
194141cc406Sopenharmony_ci
195141cc406Sopenharmony_ciint
196141cc406Sopenharmony_cisanei_hp_accessor_getint (HpAccessor this, HpData data)
197141cc406Sopenharmony_ci{
198141cc406Sopenharmony_ci  assert (this->type->getint);
199141cc406Sopenharmony_ci  return (*this->type->getint)(this, data);
200141cc406Sopenharmony_ci}
201141cc406Sopenharmony_ci
202141cc406Sopenharmony_civoid
203141cc406Sopenharmony_cisanei_hp_accessor_setint (HpAccessor this, HpData data, int val)
204141cc406Sopenharmony_ci{
205141cc406Sopenharmony_ci  assert (this->type->setint);
206141cc406Sopenharmony_ci  (*this->type->setint)(this, data, val);
207141cc406Sopenharmony_ci}
208141cc406Sopenharmony_ci
209141cc406Sopenharmony_ciconst void *
210141cc406Sopenharmony_cisanei_hp_accessor_data (HpAccessor this, HpData data)
211141cc406Sopenharmony_ci{
212141cc406Sopenharmony_ci  return hp_data_data(data, this->data_offset);
213141cc406Sopenharmony_ci}
214141cc406Sopenharmony_ci
215141cc406Sopenharmony_civoid *
216141cc406Sopenharmony_cisanei__hp_accessor_data (HpAccessor this, HpData data)
217141cc406Sopenharmony_ci{
218141cc406Sopenharmony_ci  return hp_data_data(data, this->data_offset);
219141cc406Sopenharmony_ci}
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_cisize_t
222141cc406Sopenharmony_cisanei_hp_accessor_size (HpAccessor this)
223141cc406Sopenharmony_ci{
224141cc406Sopenharmony_ci  return  this->data_size;
225141cc406Sopenharmony_ci}
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ciHpAccessor
228141cc406Sopenharmony_cisanei_hp_accessor_new (HpData data, size_t sz)
229141cc406Sopenharmony_ci{
230141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
231141cc406Sopenharmony_ci      0, 0, 0, 0
232141cc406Sopenharmony_ci  };
233141cc406Sopenharmony_ci  _HpAccessor	 new = sanei_hp_alloc(sizeof(*new));
234141cc406Sopenharmony_ci  new->type = &type;
235141cc406Sopenharmony_ci  new->data_offset = hp_data_alloc(data, new->data_size = sz);
236141cc406Sopenharmony_ci  return new;
237141cc406Sopenharmony_ci}
238141cc406Sopenharmony_ci
239141cc406Sopenharmony_ci
240141cc406Sopenharmony_ci/*
241141cc406Sopenharmony_ci * class HpAccessorInt
242141cc406Sopenharmony_ci */
243141cc406Sopenharmony_ci
244141cc406Sopenharmony_ci#define hp_accessor_int_s	hp_accessor_s
245141cc406Sopenharmony_ci
246141cc406Sopenharmony_citypedef const struct hp_accessor_int_s *	HpAccessorInt;
247141cc406Sopenharmony_citypedef struct hp_accessor_int_s *		_HpAccessorInt;
248141cc406Sopenharmony_ci
249141cc406Sopenharmony_cistatic SANE_Status
250141cc406Sopenharmony_cihp_accessor_int_get (HpAccessor this, HpData data, void * valp)
251141cc406Sopenharmony_ci{
252141cc406Sopenharmony_ci  *(SANE_Int*)valp = *(int *)hp_data_data(data, this->data_offset);
253141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
254141cc406Sopenharmony_ci}
255141cc406Sopenharmony_ci
256141cc406Sopenharmony_cistatic SANE_Status
257141cc406Sopenharmony_cihp_accessor_int_set (HpAccessor this, HpData data, void * valp)
258141cc406Sopenharmony_ci{
259141cc406Sopenharmony_ci  *(int *)hp_data_data(data, this->data_offset) = *(SANE_Int*)valp;
260141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
261141cc406Sopenharmony_ci}
262141cc406Sopenharmony_ci
263141cc406Sopenharmony_cistatic int
264141cc406Sopenharmony_cihp_accessor_int_getint (HpAccessor this, HpData data)
265141cc406Sopenharmony_ci{
266141cc406Sopenharmony_ci  return *(int *)hp_data_data(data, this->data_offset);
267141cc406Sopenharmony_ci}
268141cc406Sopenharmony_ci
269141cc406Sopenharmony_cistatic void
270141cc406Sopenharmony_cihp_accessor_int_setint (HpAccessor this, HpData data, int val)
271141cc406Sopenharmony_ci{
272141cc406Sopenharmony_ci  *(int *)hp_data_data(data, this->data_offset) = val;
273141cc406Sopenharmony_ci}
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ciHpAccessor
276141cc406Sopenharmony_cisanei_hp_accessor_int_new (HpData data)
277141cc406Sopenharmony_ci{
278141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
279141cc406Sopenharmony_ci      hp_accessor_int_get, hp_accessor_int_set,
280141cc406Sopenharmony_ci      hp_accessor_int_getint, hp_accessor_int_setint
281141cc406Sopenharmony_ci  };
282141cc406Sopenharmony_ci  _HpAccessorInt	 new = sanei_hp_alloc(sizeof(*new));
283141cc406Sopenharmony_ci  new->type = &type;
284141cc406Sopenharmony_ci  new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int));
285141cc406Sopenharmony_ci  return (HpAccessor)new;
286141cc406Sopenharmony_ci}
287141cc406Sopenharmony_ci
288141cc406Sopenharmony_ci
289141cc406Sopenharmony_ci/*
290141cc406Sopenharmony_ci * class HpAccessorBool
291141cc406Sopenharmony_ci */
292141cc406Sopenharmony_ci
293141cc406Sopenharmony_ci#define hp_accessor_bool_s	hp_accessor_s
294141cc406Sopenharmony_ci
295141cc406Sopenharmony_citypedef const struct hp_accessor_bool_s *	HpAccessorBool;
296141cc406Sopenharmony_citypedef struct hp_accessor_bool_s *		_HpAccessorBool;
297141cc406Sopenharmony_ci
298141cc406Sopenharmony_cistatic SANE_Status
299141cc406Sopenharmony_cihp_accessor_bool_get (HpAccessor this, HpData data, void * valp)
300141cc406Sopenharmony_ci{
301141cc406Sopenharmony_ci  int val = *(int *)hp_data_data(data, this->data_offset);
302141cc406Sopenharmony_ci  *(SANE_Bool*)valp = val ? SANE_TRUE : SANE_FALSE;
303141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
304141cc406Sopenharmony_ci}
305141cc406Sopenharmony_ci
306141cc406Sopenharmony_cistatic SANE_Status
307141cc406Sopenharmony_cihp_accessor_bool_set (HpAccessor this, HpData data, void * valp)
308141cc406Sopenharmony_ci{
309141cc406Sopenharmony_ci  int * datap = hp_data_data(data, this->data_offset);
310141cc406Sopenharmony_ci  *datap = *(SANE_Bool*)valp == SANE_FALSE ? 0 : 1;
311141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
312141cc406Sopenharmony_ci}
313141cc406Sopenharmony_ci
314141cc406Sopenharmony_ciHpAccessor
315141cc406Sopenharmony_cisanei_hp_accessor_bool_new (HpData data)
316141cc406Sopenharmony_ci{
317141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
318141cc406Sopenharmony_ci      hp_accessor_bool_get, hp_accessor_bool_set,
319141cc406Sopenharmony_ci      hp_accessor_int_getint, hp_accessor_int_setint
320141cc406Sopenharmony_ci  };
321141cc406Sopenharmony_ci  _HpAccessorBool	 new = sanei_hp_alloc(sizeof(*new));
322141cc406Sopenharmony_ci  new->type = &type;
323141cc406Sopenharmony_ci  new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int));
324141cc406Sopenharmony_ci  return (HpAccessor)new;
325141cc406Sopenharmony_ci}
326141cc406Sopenharmony_ci
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci/*
329141cc406Sopenharmony_ci * class HpAccessorFixed
330141cc406Sopenharmony_ci */
331141cc406Sopenharmony_ci
332141cc406Sopenharmony_ci#define hp_accessor_fixed_s	hp_accessor_s
333141cc406Sopenharmony_ci
334141cc406Sopenharmony_citypedef const struct hp_accessor_fixed_s *	HpAccessorFixed;
335141cc406Sopenharmony_citypedef struct hp_accessor_fixed_s *		_HpAccessorFixed;
336141cc406Sopenharmony_ci
337141cc406Sopenharmony_cistatic SANE_Status
338141cc406Sopenharmony_cihp_accessor_fixed_get (HpAccessor this, HpData data, void * valp)
339141cc406Sopenharmony_ci{
340141cc406Sopenharmony_ci  *(SANE_Fixed*)valp = *(SANE_Fixed *)hp_data_data(data, this->data_offset);
341141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
342141cc406Sopenharmony_ci}
343141cc406Sopenharmony_ci
344141cc406Sopenharmony_cistatic SANE_Status
345141cc406Sopenharmony_cihp_accessor_fixed_set (HpAccessor this, HpData data, void * valp)
346141cc406Sopenharmony_ci{
347141cc406Sopenharmony_ci  *(SANE_Fixed *)hp_data_data(data, this->data_offset) = *(SANE_Fixed*)valp;
348141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
349141cc406Sopenharmony_ci}
350141cc406Sopenharmony_ci
351141cc406Sopenharmony_ciHpAccessor
352141cc406Sopenharmony_cisanei_hp_accessor_fixed_new (HpData data)
353141cc406Sopenharmony_ci{
354141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
355141cc406Sopenharmony_ci      hp_accessor_fixed_get, hp_accessor_fixed_set, 0, 0
356141cc406Sopenharmony_ci  };
357141cc406Sopenharmony_ci  _HpAccessorFixed	 new = sanei_hp_alloc(sizeof(*new));
358141cc406Sopenharmony_ci  new->type = &type;
359141cc406Sopenharmony_ci  new->data_offset = hp_data_alloc(data, new->data_size = sizeof(SANE_Fixed));
360141cc406Sopenharmony_ci  return (HpAccessor)new;
361141cc406Sopenharmony_ci}
362141cc406Sopenharmony_ci
363141cc406Sopenharmony_ci
364141cc406Sopenharmony_ci/*
365141cc406Sopenharmony_ci * class HpAccessorChoice
366141cc406Sopenharmony_ci */
367141cc406Sopenharmony_ci
368141cc406Sopenharmony_citypedef struct hp_accessor_choice_s *		_HpAccessorChoice;
369141cc406Sopenharmony_ci
370141cc406Sopenharmony_cistruct hp_accessor_choice_s
371141cc406Sopenharmony_ci{
372141cc406Sopenharmony_ci    HpAccessorType	type;
373141cc406Sopenharmony_ci    size_t		data_offset;
374141cc406Sopenharmony_ci    size_t		data_size;
375141cc406Sopenharmony_ci
376141cc406Sopenharmony_ci    HpChoice		choices;
377141cc406Sopenharmony_ci    SANE_String_Const * strlist;
378141cc406Sopenharmony_ci};
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_cistatic SANE_Status
381141cc406Sopenharmony_cihp_accessor_choice_get (HpAccessor this, HpData data, void * valp)
382141cc406Sopenharmony_ci{
383141cc406Sopenharmony_ci  HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset);
384141cc406Sopenharmony_ci  strcpy(valp, choice->name);
385141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
386141cc406Sopenharmony_ci}
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_cistatic SANE_Status
389141cc406Sopenharmony_cihp_accessor_choice_set (HpAccessor _this, HpData data, void * valp)
390141cc406Sopenharmony_ci{
391141cc406Sopenharmony_ci  HpAccessorChoice	this	= (HpAccessorChoice)_this;
392141cc406Sopenharmony_ci  HpChoice 		choice;
393141cc406Sopenharmony_ci  SANE_String_Const *	strlist = this->strlist;
394141cc406Sopenharmony_ci
395141cc406Sopenharmony_ci  for (choice = this->choices; choice; choice = choice->next)
396141cc406Sopenharmony_ci    {
397141cc406Sopenharmony_ci      /* Skip choices which aren't in strlist. */
398141cc406Sopenharmony_ci      if (!*strlist || strcmp(*strlist, choice->name) != 0)
399141cc406Sopenharmony_ci	  continue;
400141cc406Sopenharmony_ci      strlist++;
401141cc406Sopenharmony_ci
402141cc406Sopenharmony_ci      if (strcmp((const char *)valp, choice->name) == 0)
403141cc406Sopenharmony_ci	{
404141cc406Sopenharmony_ci	  *(HpChoice *)hp_data_data(data, this->data_offset) = choice;
405141cc406Sopenharmony_ci	  return SANE_STATUS_GOOD;
406141cc406Sopenharmony_ci	}
407141cc406Sopenharmony_ci    }
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ci  return SANE_STATUS_INVAL;
410141cc406Sopenharmony_ci}
411141cc406Sopenharmony_ci
412141cc406Sopenharmony_cistatic int
413141cc406Sopenharmony_cihp_accessor_choice_getint (HpAccessor this, HpData data)
414141cc406Sopenharmony_ci{
415141cc406Sopenharmony_ci  HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset);
416141cc406Sopenharmony_ci  return choice->val;
417141cc406Sopenharmony_ci}
418141cc406Sopenharmony_ci
419141cc406Sopenharmony_cistatic void
420141cc406Sopenharmony_cihp_accessor_choice_setint (HpAccessor _this,  HpData data, int val)
421141cc406Sopenharmony_ci{
422141cc406Sopenharmony_ci  HpAccessorChoice	this	= (HpAccessorChoice)_this;
423141cc406Sopenharmony_ci  HpChoice 		choice;
424141cc406Sopenharmony_ci  HpChoice 		first_choice = 0;
425141cc406Sopenharmony_ci  SANE_String_Const *	strlist = this->strlist;
426141cc406Sopenharmony_ci
427141cc406Sopenharmony_ci  for (choice = this->choices; choice; choice = choice->next)
428141cc406Sopenharmony_ci    {
429141cc406Sopenharmony_ci      /* Skip choices which aren't in strlist. */
430141cc406Sopenharmony_ci      if (!*strlist || strcmp(*strlist, choice->name) != 0)
431141cc406Sopenharmony_ci	  continue;
432141cc406Sopenharmony_ci      strlist++;
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_ci      if (!first_choice)
435141cc406Sopenharmony_ci	  first_choice = choice; /* First enabled choice */
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci      if (choice->val == val)
438141cc406Sopenharmony_ci	{
439141cc406Sopenharmony_ci	  *(HpChoice *)hp_data_data(data, this->data_offset) = choice;
440141cc406Sopenharmony_ci	  return;
441141cc406Sopenharmony_ci	}
442141cc406Sopenharmony_ci    }
443141cc406Sopenharmony_ci
444141cc406Sopenharmony_ci  if (first_choice)
445141cc406Sopenharmony_ci      *(HpChoice *)hp_data_data(data, this->data_offset) = first_choice;
446141cc406Sopenharmony_ci  else
447141cc406Sopenharmony_ci      assert(!"No choices to choose from?");
448141cc406Sopenharmony_ci}
449141cc406Sopenharmony_ci
450141cc406Sopenharmony_ciSANE_Int
451141cc406Sopenharmony_cisanei_hp_accessor_choice_maxsize (HpAccessorChoice this)
452141cc406Sopenharmony_ci{
453141cc406Sopenharmony_ci  HpChoice	choice;
454141cc406Sopenharmony_ci  SANE_Int	size	= 0;
455141cc406Sopenharmony_ci
456141cc406Sopenharmony_ci  for (choice = this->choices; choice; choice = choice->next)
457141cc406Sopenharmony_ci      if ((SANE_Int)strlen(choice->name) >= size)
458141cc406Sopenharmony_ci	  size = strlen(choice->name) + 1;
459141cc406Sopenharmony_ci  return size;
460141cc406Sopenharmony_ci}
461141cc406Sopenharmony_ci
462141cc406Sopenharmony_ciSANE_String_Const *
463141cc406Sopenharmony_cisanei_hp_accessor_choice_strlist (HpAccessorChoice this,
464141cc406Sopenharmony_ci			    HpOptSet optset, HpData data,
465141cc406Sopenharmony_ci                            const HpDeviceInfo *info)
466141cc406Sopenharmony_ci{
467141cc406Sopenharmony_ci  if (optset)
468141cc406Sopenharmony_ci    {
469141cc406Sopenharmony_ci      int	old_val = hp_accessor_choice_getint((HpAccessor)this, data);
470141cc406Sopenharmony_ci      HpChoice	choice;
471141cc406Sopenharmony_ci      size_t	count	= 0;
472141cc406Sopenharmony_ci
473141cc406Sopenharmony_ci      for (choice = this->choices; choice; choice = choice->next)
474141cc406Sopenharmony_ci	  if (sanei_hp_choice_isEnabled(choice, optset, data, info))
475141cc406Sopenharmony_ci	      this->strlist[count++] = choice->name;
476141cc406Sopenharmony_ci      this->strlist[count] = 0;
477141cc406Sopenharmony_ci
478141cc406Sopenharmony_ci      hp_accessor_choice_setint((HpAccessor)this, data, old_val);
479141cc406Sopenharmony_ci    }
480141cc406Sopenharmony_ci
481141cc406Sopenharmony_ci  return this->strlist;
482141cc406Sopenharmony_ci}
483141cc406Sopenharmony_ci
484141cc406Sopenharmony_ciHpAccessor
485141cc406Sopenharmony_cisanei_hp_accessor_choice_new (HpData data, HpChoice choices,
486141cc406Sopenharmony_ci                              hp_bool_t may_change)
487141cc406Sopenharmony_ci{
488141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
489141cc406Sopenharmony_ci      hp_accessor_choice_get, hp_accessor_choice_set,
490141cc406Sopenharmony_ci      hp_accessor_choice_getint, hp_accessor_choice_setint
491141cc406Sopenharmony_ci  };
492141cc406Sopenharmony_ci  HpChoice	choice;
493141cc406Sopenharmony_ci  size_t	count	= 0;
494141cc406Sopenharmony_ci  _HpAccessorChoice this;
495141cc406Sopenharmony_ci
496141cc406Sopenharmony_ci  if ( may_change ) data->frozen = 0;
497141cc406Sopenharmony_ci
498141cc406Sopenharmony_ci  for (choice = choices; choice; choice = choice->next)
499141cc406Sopenharmony_ci      count++;
500141cc406Sopenharmony_ci  this = sanei_hp_alloc(sizeof(*this) + (count+1) * sizeof(*this->strlist));
501141cc406Sopenharmony_ci  if (!this)
502141cc406Sopenharmony_ci      return 0;
503141cc406Sopenharmony_ci
504141cc406Sopenharmony_ci  this->type = &type;
505141cc406Sopenharmony_ci  this->data_offset = hp_data_alloc(data, this->data_size = sizeof(HpChoice));
506141cc406Sopenharmony_ci  this->choices = choices;
507141cc406Sopenharmony_ci  this->strlist = (SANE_String_Const *)(this + 1);
508141cc406Sopenharmony_ci
509141cc406Sopenharmony_ci  count = 0;
510141cc406Sopenharmony_ci  for (choice = this->choices; choice; choice = choice->next)
511141cc406Sopenharmony_ci      this->strlist[count++] = choice->name;
512141cc406Sopenharmony_ci  this->strlist[count] = 0;
513141cc406Sopenharmony_ci
514141cc406Sopenharmony_ci  return (HpAccessor)this;
515141cc406Sopenharmony_ci}
516141cc406Sopenharmony_ci
517141cc406Sopenharmony_ci/*
518141cc406Sopenharmony_ci * class HpAccessorVector
519141cc406Sopenharmony_ci */
520141cc406Sopenharmony_ci
521141cc406Sopenharmony_citypedef struct hp_accessor_vector_s *		_HpAccessorVector;
522141cc406Sopenharmony_ci
523141cc406Sopenharmony_cistruct hp_accessor_vector_s
524141cc406Sopenharmony_ci{
525141cc406Sopenharmony_ci    HpAccessorType	type;
526141cc406Sopenharmony_ci    size_t		data_offset;
527141cc406Sopenharmony_ci    size_t		data_size;
528141cc406Sopenharmony_ci
529141cc406Sopenharmony_ci    unsigned short	mask;
530141cc406Sopenharmony_ci    unsigned short	length;
531141cc406Sopenharmony_ci    unsigned short	offset;
532141cc406Sopenharmony_ci    short		stride;
533141cc406Sopenharmony_ci
534141cc406Sopenharmony_ci    unsigned short	(*unscale)(HpAccessorVector this, SANE_Fixed fval);
535141cc406Sopenharmony_ci    SANE_Fixed		(*scale)(HpAccessorVector this, unsigned short val);
536141cc406Sopenharmony_ci
537141cc406Sopenharmony_ci    SANE_Fixed		fmin;
538141cc406Sopenharmony_ci    SANE_Fixed		fmax;
539141cc406Sopenharmony_ci
540141cc406Sopenharmony_ci};
541141cc406Sopenharmony_ci
542141cc406Sopenharmony_ciunsigned
543141cc406Sopenharmony_cisanei_hp_accessor_vector_length (HpAccessorVector this)
544141cc406Sopenharmony_ci{
545141cc406Sopenharmony_ci  return this->length;
546141cc406Sopenharmony_ci}
547141cc406Sopenharmony_ci
548141cc406Sopenharmony_ciSANE_Fixed
549141cc406Sopenharmony_cisanei_hp_accessor_vector_minval (HpAccessorVector this)
550141cc406Sopenharmony_ci{
551141cc406Sopenharmony_ci  return this->fmin;
552141cc406Sopenharmony_ci}
553141cc406Sopenharmony_ci
554141cc406Sopenharmony_ciSANE_Fixed
555141cc406Sopenharmony_cisanei_hp_accessor_vector_maxval (HpAccessorVector this)
556141cc406Sopenharmony_ci{
557141cc406Sopenharmony_ci  return this->fmax;
558141cc406Sopenharmony_ci}
559141cc406Sopenharmony_ci
560141cc406Sopenharmony_cistatic unsigned short
561141cc406Sopenharmony_ci_v_get (HpAccessorVector this, const unsigned char * data)
562141cc406Sopenharmony_ci{
563141cc406Sopenharmony_ci  unsigned short val;
564141cc406Sopenharmony_ci
565141cc406Sopenharmony_ci  if (this->mask <= 255)
566141cc406Sopenharmony_ci      val = data[0];
567141cc406Sopenharmony_ci  else
568141cc406Sopenharmony_ci#ifndef NotOrig
569141cc406Sopenharmony_ci      val = (data[0] << 8) + data[1];
570141cc406Sopenharmony_ci#else
571141cc406Sopenharmony_ci      val = (data[1] << 8) + data[0];
572141cc406Sopenharmony_ci#endif
573141cc406Sopenharmony_ci
574141cc406Sopenharmony_ci  return val & this->mask;
575141cc406Sopenharmony_ci}
576141cc406Sopenharmony_ci
577141cc406Sopenharmony_cistatic void
578141cc406Sopenharmony_ci_v_set (HpAccessorVector this, unsigned char * data, unsigned short val)
579141cc406Sopenharmony_ci{
580141cc406Sopenharmony_ci  val &= this->mask;
581141cc406Sopenharmony_ci
582141cc406Sopenharmony_ci  if (this->mask <= 255)
583141cc406Sopenharmony_ci    {
584141cc406Sopenharmony_ci      data[0] = (unsigned char)val;
585141cc406Sopenharmony_ci    }
586141cc406Sopenharmony_ci  else
587141cc406Sopenharmony_ci    {
588141cc406Sopenharmony_ci#ifndef NotOrig
589141cc406Sopenharmony_ci      data[1] = (unsigned char)val;
590141cc406Sopenharmony_ci      data[0] = (unsigned char)(val >> 8);
591141cc406Sopenharmony_ci#else
592141cc406Sopenharmony_ci      data[0] = (unsigned char)val;
593141cc406Sopenharmony_ci      data[1] = (unsigned char)(val >> 8);
594141cc406Sopenharmony_ci#endif
595141cc406Sopenharmony_ci    }
596141cc406Sopenharmony_ci}
597141cc406Sopenharmony_ci
598141cc406Sopenharmony_cistatic SANE_Status
599141cc406Sopenharmony_cihp_accessor_vector_get (HpAccessor _this, HpData d, void * valp)
600141cc406Sopenharmony_ci{
601141cc406Sopenharmony_ci  HpAccessorVector	this	= (HpAccessorVector)_this;
602141cc406Sopenharmony_ci  SANE_Fixed *		ptr	= valp;
603141cc406Sopenharmony_ci  const SANE_Fixed *	end	= ptr + this->length;
604141cc406Sopenharmony_ci  const unsigned char *	data	= hp_data_data(d, this->data_offset);
605141cc406Sopenharmony_ci
606141cc406Sopenharmony_ci  data += this->offset;
607141cc406Sopenharmony_ci
608141cc406Sopenharmony_ci  while (ptr < end)
609141cc406Sopenharmony_ci    {
610141cc406Sopenharmony_ci      *ptr++ = (*this->scale)(this, _v_get(this, data));
611141cc406Sopenharmony_ci      data += this->stride;
612141cc406Sopenharmony_ci    }
613141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
614141cc406Sopenharmony_ci}
615141cc406Sopenharmony_ci
616141cc406Sopenharmony_cistatic SANE_Status
617141cc406Sopenharmony_cihp_accessor_vector_set (HpAccessor _this, HpData d, void * valp)
618141cc406Sopenharmony_ci{
619141cc406Sopenharmony_ci  HpAccessorVector	this	= (HpAccessorVector)_this;
620141cc406Sopenharmony_ci  SANE_Fixed *		ptr	= valp;
621141cc406Sopenharmony_ci  const SANE_Fixed *	end	= ptr + this->length;
622141cc406Sopenharmony_ci  unsigned char *	data	= hp_data_data(d, this->data_offset);
623141cc406Sopenharmony_ci
624141cc406Sopenharmony_ci  data += this->offset;
625141cc406Sopenharmony_ci
626141cc406Sopenharmony_ci  while (ptr < end)
627141cc406Sopenharmony_ci    {
628141cc406Sopenharmony_ci      if (*ptr < this->fmin)
629141cc406Sopenharmony_ci	  *ptr = this->fmin;
630141cc406Sopenharmony_ci      if (*ptr > this->fmax)
631141cc406Sopenharmony_ci	  *ptr = this->fmax;
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_ci      _v_set(this, data, (*this->unscale)(this, *ptr++));
634141cc406Sopenharmony_ci
635141cc406Sopenharmony_ci      data += this->stride;
636141cc406Sopenharmony_ci    }
637141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
638141cc406Sopenharmony_ci}
639141cc406Sopenharmony_ci
640141cc406Sopenharmony_cistatic unsigned short
641141cc406Sopenharmony_ci_vector_unscale (HpAccessorVector this, SANE_Fixed fval)
642141cc406Sopenharmony_ci{
643141cc406Sopenharmony_ci  unsigned short max_val = this->mask;
644141cc406Sopenharmony_ci  return (fval * max_val + SANE_FIX(0.5)) / SANE_FIX(1.0);
645141cc406Sopenharmony_ci}
646141cc406Sopenharmony_ci
647141cc406Sopenharmony_cistatic SANE_Fixed
648141cc406Sopenharmony_ci_vector_scale (HpAccessorVector this, unsigned short val)
649141cc406Sopenharmony_ci{
650141cc406Sopenharmony_ci  unsigned short max_val = this->mask;
651141cc406Sopenharmony_ci  return (SANE_FIX(1.0) * val + max_val / 2) / max_val;
652141cc406Sopenharmony_ci}
653141cc406Sopenharmony_ci
654141cc406Sopenharmony_ciHpAccessor
655141cc406Sopenharmony_cisanei_hp_accessor_vector_new (HpData data, unsigned length, unsigned depth)
656141cc406Sopenharmony_ci{
657141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
658141cc406Sopenharmony_ci      hp_accessor_vector_get, hp_accessor_vector_set, 0, 0
659141cc406Sopenharmony_ci  };
660141cc406Sopenharmony_ci  unsigned		width	= depth > 8 ? 2 : 1;
661141cc406Sopenharmony_ci  _HpAccessorVector	new	= sanei_hp_alloc(sizeof(*new));
662141cc406Sopenharmony_ci
663141cc406Sopenharmony_ci  if (!new)
664141cc406Sopenharmony_ci      return 0;
665141cc406Sopenharmony_ci
666141cc406Sopenharmony_ci  assert(depth > 0 && depth <= 16);
667141cc406Sopenharmony_ci  assert(length > 0);
668141cc406Sopenharmony_ci
669141cc406Sopenharmony_ci  new->type = &type;
670141cc406Sopenharmony_ci  new->data_size   = length * width;
671141cc406Sopenharmony_ci  new->data_offset = hp_data_alloc(data, new->data_size);
672141cc406Sopenharmony_ci
673141cc406Sopenharmony_ci  new->mask  = ((unsigned)1 << depth) - 1;
674141cc406Sopenharmony_ci  new->length = length;
675141cc406Sopenharmony_ci  new->offset = 0;
676141cc406Sopenharmony_ci  new->stride = width;
677141cc406Sopenharmony_ci
678141cc406Sopenharmony_ci  new->scale   = _vector_scale;
679141cc406Sopenharmony_ci  new->unscale = _vector_unscale;
680141cc406Sopenharmony_ci
681141cc406Sopenharmony_ci  new->fmin = SANE_FIX(0.0);
682141cc406Sopenharmony_ci  new->fmax = SANE_FIX(1.0);
683141cc406Sopenharmony_ci
684141cc406Sopenharmony_ci  return (HpAccessor)new;
685141cc406Sopenharmony_ci}
686141cc406Sopenharmony_ci
687141cc406Sopenharmony_cistatic unsigned short
688141cc406Sopenharmony_ci_gamma_vector_unscale (HpAccessorVector __sane_unused__ this, SANE_Fixed fval)
689141cc406Sopenharmony_ci{
690141cc406Sopenharmony_ci  unsigned short unscaled = fval / SANE_FIX(1.0);
691141cc406Sopenharmony_ci  if (unscaled > 255) unscaled = 255;
692141cc406Sopenharmony_ci  unscaled = 255 - unscaled;  /* Don't know why. But this is how it works. */
693141cc406Sopenharmony_ci
694141cc406Sopenharmony_ci  return unscaled;
695141cc406Sopenharmony_ci}
696141cc406Sopenharmony_ci
697141cc406Sopenharmony_cistatic SANE_Fixed
698141cc406Sopenharmony_ci_gamma_vector_scale (HpAccessorVector __sane_unused__ this, unsigned short val)
699141cc406Sopenharmony_ci{
700141cc406Sopenharmony_ci  SANE_Fixed scaled;
701141cc406Sopenharmony_ci  val = 255-val;     /* Don't know why. But this is how it works. */
702141cc406Sopenharmony_ci  scaled = val * SANE_FIX(1.0);
703141cc406Sopenharmony_ci
704141cc406Sopenharmony_ci  return scaled;
705141cc406Sopenharmony_ci}
706141cc406Sopenharmony_ci
707141cc406Sopenharmony_ciHpAccessor
708141cc406Sopenharmony_cisanei_hp_accessor_gamma_vector_new (HpData data, unsigned length,
709141cc406Sopenharmony_ci                                    unsigned depth)
710141cc406Sopenharmony_ci{
711141cc406Sopenharmony_ci  _HpAccessorVector	this	=
712141cc406Sopenharmony_ci      ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) );
713141cc406Sopenharmony_ci
714141cc406Sopenharmony_ci
715141cc406Sopenharmony_ci  if (!this)
716141cc406Sopenharmony_ci      return 0;
717141cc406Sopenharmony_ci
718141cc406Sopenharmony_ci  this->offset += this->stride * (this->length - 1);
719141cc406Sopenharmony_ci  this->stride = -this->stride;
720141cc406Sopenharmony_ci
721141cc406Sopenharmony_ci  this->scale   = _gamma_vector_scale;
722141cc406Sopenharmony_ci  this->unscale = _gamma_vector_unscale;
723141cc406Sopenharmony_ci
724141cc406Sopenharmony_ci  this->fmin = SANE_FIX(0.0);
725141cc406Sopenharmony_ci  this->fmax = SANE_FIX(255.0);
726141cc406Sopenharmony_ci
727141cc406Sopenharmony_ci  return (HpAccessor)this;
728141cc406Sopenharmony_ci}
729141cc406Sopenharmony_ci
730141cc406Sopenharmony_cistatic unsigned short
731141cc406Sopenharmony_ci_matrix_vector_unscale (HpAccessorVector this, SANE_Fixed fval)
732141cc406Sopenharmony_ci{
733141cc406Sopenharmony_ci  unsigned short max_val  = this->mask >> 1;
734141cc406Sopenharmony_ci  unsigned short sign_bit = this->mask & ~max_val;
735141cc406Sopenharmony_ci  unsigned short sign	  = 0;
736141cc406Sopenharmony_ci
737141cc406Sopenharmony_ci  if (fval == SANE_FIX(1.0))
738141cc406Sopenharmony_ci      return sign_bit;
739141cc406Sopenharmony_ci
740141cc406Sopenharmony_ci  if (fval < 0)
741141cc406Sopenharmony_ci    {
742141cc406Sopenharmony_ci      sign = sign_bit;
743141cc406Sopenharmony_ci      fval = -fval;
744141cc406Sopenharmony_ci    }
745141cc406Sopenharmony_ci  return sign | ((fval * max_val + this->fmax / 2) / this->fmax);
746141cc406Sopenharmony_ci}
747141cc406Sopenharmony_ci
748141cc406Sopenharmony_cistatic SANE_Fixed
749141cc406Sopenharmony_ci_matrix_vector_scale (HpAccessorVector this, unsigned short val)
750141cc406Sopenharmony_ci{
751141cc406Sopenharmony_ci  unsigned short max_val  = this->mask >> 1;
752141cc406Sopenharmony_ci  unsigned short sign_bit = this->mask & ~max_val;
753141cc406Sopenharmony_ci  SANE_Fixed	 fval;
754141cc406Sopenharmony_ci
755141cc406Sopenharmony_ci  if (val == sign_bit)
756141cc406Sopenharmony_ci      return SANE_FIX(1.0);
757141cc406Sopenharmony_ci
758141cc406Sopenharmony_ci  fval = (this->fmax * (val & max_val) + max_val / 2) / max_val;
759141cc406Sopenharmony_ci
760141cc406Sopenharmony_ci  if ((val & sign_bit) != 0)
761141cc406Sopenharmony_ci      fval = -fval;
762141cc406Sopenharmony_ci
763141cc406Sopenharmony_ci  return fval;
764141cc406Sopenharmony_ci}
765141cc406Sopenharmony_ci
766141cc406Sopenharmony_ciHpAccessor
767141cc406Sopenharmony_cisanei_hp_accessor_matrix_vector_new (HpData data, unsigned length,
768141cc406Sopenharmony_ci                                     unsigned depth)
769141cc406Sopenharmony_ci{
770141cc406Sopenharmony_ci  _HpAccessorVector	this	=
771141cc406Sopenharmony_ci      ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) );
772141cc406Sopenharmony_ci
773141cc406Sopenharmony_ci  if (!this)
774141cc406Sopenharmony_ci      return 0;
775141cc406Sopenharmony_ci
776141cc406Sopenharmony_ci  this->scale   = _matrix_vector_scale;
777141cc406Sopenharmony_ci  this->unscale = _matrix_vector_unscale;
778141cc406Sopenharmony_ci
779141cc406Sopenharmony_ci  this->fmax = depth == 10 ? SANE_FIX(4.0) : SANE_FIX(2.0);
780141cc406Sopenharmony_ci  this->fmax *= (this->mask >> 1);
781141cc406Sopenharmony_ci  this->fmax >>= (depth - 1);
782141cc406Sopenharmony_ci  this->fmin = - this->fmax;
783141cc406Sopenharmony_ci
784141cc406Sopenharmony_ci  return (HpAccessor)this;
785141cc406Sopenharmony_ci}
786141cc406Sopenharmony_ci
787141cc406Sopenharmony_ciHpAccessor
788141cc406Sopenharmony_cisanei_hp_accessor_subvector_new (HpAccessorVector super,
789141cc406Sopenharmony_ci			   unsigned nchan, unsigned chan)
790141cc406Sopenharmony_ci{
791141cc406Sopenharmony_ci  _HpAccessorVector	this	= sanei_hp_memdup(super, sizeof(*this));
792141cc406Sopenharmony_ci
793141cc406Sopenharmony_ci  if (!this)
794141cc406Sopenharmony_ci      return 0;
795141cc406Sopenharmony_ci
796141cc406Sopenharmony_ci  assert(chan < nchan);
797141cc406Sopenharmony_ci  assert(this->length % nchan == 0);
798141cc406Sopenharmony_ci
799141cc406Sopenharmony_ci  this->length /= nchan;
800141cc406Sopenharmony_ci
801141cc406Sopenharmony_ci  if (this->stride < 0)
802141cc406Sopenharmony_ci      this->offset += (nchan - chan - 1) * this->stride;
803141cc406Sopenharmony_ci  else
804141cc406Sopenharmony_ci      this->offset += chan * this->stride;
805141cc406Sopenharmony_ci
806141cc406Sopenharmony_ci  this->stride *= nchan;
807141cc406Sopenharmony_ci
808141cc406Sopenharmony_ci  return (HpAccessor)this;
809141cc406Sopenharmony_ci}
810141cc406Sopenharmony_ci
811141cc406Sopenharmony_ci/*
812141cc406Sopenharmony_ci * class HpAccessorGeometry
813141cc406Sopenharmony_ci */
814141cc406Sopenharmony_ci
815141cc406Sopenharmony_citypedef const struct hp_accessor_geometry_s *	HpAccessorGeometry;
816141cc406Sopenharmony_citypedef struct hp_accessor_geometry_s *		_HpAccessorGeometry;
817141cc406Sopenharmony_ci
818141cc406Sopenharmony_cistruct hp_accessor_geometry_s
819141cc406Sopenharmony_ci{
820141cc406Sopenharmony_ci    HpAccessorType	type;
821141cc406Sopenharmony_ci    size_t		data_offset;
822141cc406Sopenharmony_ci    size_t		data_size;
823141cc406Sopenharmony_ci
824141cc406Sopenharmony_ci    HpAccessor		this;
825141cc406Sopenharmony_ci    HpAccessor		other;
826141cc406Sopenharmony_ci    hp_bool_t		is_br;
827141cc406Sopenharmony_ci    HpAccessor		resolution;
828141cc406Sopenharmony_ci};
829141cc406Sopenharmony_ci
830141cc406Sopenharmony_ci
831141cc406Sopenharmony_cistatic SANE_Status
832141cc406Sopenharmony_cihp_accessor_geometry_set (HpAccessor _this, HpData data, void * _valp)
833141cc406Sopenharmony_ci{
834141cc406Sopenharmony_ci  HpAccessorGeometry	this	= (HpAccessorGeometry)_this;
835141cc406Sopenharmony_ci  SANE_Fixed *		valp	= _valp;
836141cc406Sopenharmony_ci  SANE_Fixed		limit;
837141cc406Sopenharmony_ci
838141cc406Sopenharmony_ci  sanei_hp_accessor_get(this->other, data, &limit);
839141cc406Sopenharmony_ci  if (this->is_br ? *valp < limit : *valp > limit)
840141cc406Sopenharmony_ci      *valp = limit;
841141cc406Sopenharmony_ci  return sanei_hp_accessor_set(this->this, data, valp);
842141cc406Sopenharmony_ci}
843141cc406Sopenharmony_ci
844141cc406Sopenharmony_cistatic int
845141cc406Sopenharmony_ci_to_devpixels (SANE_Fixed val_mm, SANE_Fixed mm_per_pix)
846141cc406Sopenharmony_ci{
847141cc406Sopenharmony_ci  assert(val_mm >= 0);
848141cc406Sopenharmony_ci  return (val_mm + mm_per_pix / 2) / mm_per_pix;
849141cc406Sopenharmony_ci}
850141cc406Sopenharmony_ci
851141cc406Sopenharmony_cistatic int
852141cc406Sopenharmony_cihp_accessor_geometry_getint (HpAccessor _this, HpData data)
853141cc406Sopenharmony_ci{
854141cc406Sopenharmony_ci  HpAccessorGeometry	this	= (HpAccessorGeometry)_this;
855141cc406Sopenharmony_ci  SANE_Fixed		this_val, other_val;
856141cc406Sopenharmony_ci  int			res	= sanei_hp_accessor_getint(this->resolution,
857141cc406Sopenharmony_ci                                                           data);
858141cc406Sopenharmony_ci  SANE_Fixed		mm_per_pix = (SANE_FIX(MM_PER_INCH) + res / 2) / res;
859141cc406Sopenharmony_ci
860141cc406Sopenharmony_ci  assert(res > 0);
861141cc406Sopenharmony_ci  sanei_hp_accessor_get(this->this, data, &this_val);
862141cc406Sopenharmony_ci
863141cc406Sopenharmony_ci  if (this->is_br)
864141cc406Sopenharmony_ci    {
865141cc406Sopenharmony_ci      /* Convert to extent. */
866141cc406Sopenharmony_ci      sanei_hp_accessor_get(this->other, data, &other_val);
867141cc406Sopenharmony_ci      assert(this_val >= other_val && other_val >= 0);
868141cc406Sopenharmony_ci      return (_to_devpixels(this_val, mm_per_pix)
869141cc406Sopenharmony_ci	      - _to_devpixels(other_val, mm_per_pix) + 1);
870141cc406Sopenharmony_ci    }
871141cc406Sopenharmony_ci  return _to_devpixels(this_val, mm_per_pix);
872141cc406Sopenharmony_ci}
873141cc406Sopenharmony_ci
874141cc406Sopenharmony_ci/*
875141cc406Sopenharmony_ci * we should implement hp_accessor_geometry_setint, but we don't
876141cc406Sopenharmony_ci * need it yet...
877141cc406Sopenharmony_ci */
878141cc406Sopenharmony_ci
879141cc406Sopenharmony_ci
880141cc406Sopenharmony_ciHpAccessor
881141cc406Sopenharmony_cisanei_hp_accessor_geometry_new (HpAccessor val, HpAccessor lim, hp_bool_t is_br,
882141cc406Sopenharmony_ci			  HpAccessor resolution)
883141cc406Sopenharmony_ci{
884141cc406Sopenharmony_ci  static const struct hp_accessor_type_s type = {
885141cc406Sopenharmony_ci      hp_accessor_fixed_get, hp_accessor_geometry_set,
886141cc406Sopenharmony_ci      hp_accessor_geometry_getint, 0
887141cc406Sopenharmony_ci  };
888141cc406Sopenharmony_ci  _HpAccessorGeometry new = sanei_hp_alloc(sizeof(*new));
889141cc406Sopenharmony_ci
890141cc406Sopenharmony_ci  new->type = &type;
891141cc406Sopenharmony_ci  new->data_offset = val->data_offset;
892141cc406Sopenharmony_ci  new->data_size   = val->data_size;
893141cc406Sopenharmony_ci
894141cc406Sopenharmony_ci  new->this  = val;
895141cc406Sopenharmony_ci  new->other = lim;
896141cc406Sopenharmony_ci  new->is_br = is_br;
897141cc406Sopenharmony_ci  new->resolution = resolution;
898141cc406Sopenharmony_ci
899141cc406Sopenharmony_ci  return (HpAccessor)new;
900141cc406Sopenharmony_ci}
901