1 /* sane - Scanner Access Now Easy.
2    Copyright (C) 1997 Geoffrey T. Dairiki
3    This file is part of the SANE package.
4 
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 
18    As a special exception, the authors of SANE give permission for
19    additional uses of the libraries contained in this release of SANE.
20 
21    The exception is that, if you link a SANE library with other files
22    to produce an executable, this does not by itself cause the
23    resulting executable to be covered by the GNU General Public
24    License.  Your use of that executable is in no way restricted on
25    account of linking the SANE library code into it.
26 
27    This exception does not, however, invalidate any other reasons why
28    the executable file might be covered by the GNU General Public
29    License.
30 
31    If you submit changes to SANE to the maintainers to be included in
32    a subsequent release, you agree by submitting the changes that
33    those changes may be distributed with this exception intact.
34 
35    If you write modifications of your own for SANE, it is your choice
36    whether to permit this exception to apply to your modifications.
37    If you do not wish that, delete this exception notice.
38 
39    This file is part of a SANE backend for HP Scanners supporting
40    HP Scanner Control Language (SCL).
41 */
42 
43 /* #define STUBS
44 extern int sanei_debug_hp; */
45 #define DEBUG_DECLARE_ONLY
46 
47 #include "../include/sane/config.h"
48 #include "../include/sane/sanei_backend.h"
49 
50 #include "../include/lassert.h"
51 #include <string.h>
52 
53 #include <sys/types.h>
54 
55 #include "hp.h"
56 #include "hp-option.h"
57 #include "hp-accessor.h"
58 #include "hp-device.h"
59 
60 #define DATA_SIZE_INCREMENT	(1024)
61 
62 /*
63  * class HpData
64  */
65 struct hp_data_s
66 {
67     hp_byte_t *	buf;
68     size_t	bufsiz;
69     size_t	length;
70     hp_bool_t	frozen;
71 };
72 
73 
74 static void
hp_data_resize(HpData this, size_t newsize)75 hp_data_resize (HpData this, size_t newsize)
76 {
77 
78   if (this->bufsiz != newsize)
79     {
80       assert(!this->frozen);
81       this->buf = sanei_hp_realloc(this->buf, newsize);
82       assert(this->buf);
83       this->bufsiz = newsize;
84     }
85 }
86 
87 static void
hp_data_freeze(HpData this)88 hp_data_freeze (HpData this)
89 {
90   hp_data_resize(this, this->length);
91   this->frozen = 1;
92 }
93 
94 static size_t
hp_data_alloc(HpData this, size_t sz)95 hp_data_alloc (HpData this, size_t sz)
96 {
97   size_t	newsize	= this->bufsiz;
98   size_t	offset	= this->length;
99 
100  /*
101   * mike@easysw.com:
102   *
103   * The following code is REQUIRED so that pointers, etc. aren't
104   * misaligned.  This causes MAJOR problems on all SPARC, ALPHA,
105   * and MIPS processors, and possibly others.
106   *
107   * The workaround is to ensure that all allocations are in multiples
108   * of 8 bytes.
109   */
110   sz = (sz + sizeof (long) - 1) & ~(sizeof (long) - 1);
111 
112   while (newsize < this->length + sz)
113       newsize += DATA_SIZE_INCREMENT;
114   hp_data_resize(this, newsize);
115 
116   this->length += sz;
117   return offset;
118 }
119 
120 static void *
hp_data_data(HpData this, size_t offset)121 hp_data_data (HpData this, size_t offset)
122 {
123   assert(offset < this->length);
124   return (char *)this->buf + offset;
125 }
126 
127 HpData
sanei_hp_data_new(void)128 sanei_hp_data_new (void)
129 {
130   return sanei_hp_allocz(sizeof(struct hp_data_s));
131 }
132 
133 HpData
sanei_hp_data_dup(HpData orig)134 sanei_hp_data_dup (HpData orig)
135 {
136   HpData new;
137 
138   hp_data_freeze(orig);
139   if (!( new = sanei_hp_memdup(orig, sizeof(*orig)) ))
140       return 0;
141   if (!(new->buf = sanei_hp_memdup(orig->buf, orig->bufsiz)))
142       {
143 	sanei_hp_free(new);
144 	return 0;
145       }
146   return new;
147 }
148 
149 void
sanei_hp_data_destroy(HpData this)150 sanei_hp_data_destroy (HpData this)
151 {
152   sanei_hp_free(this->buf);
153   sanei_hp_free(this);
154 }
155 
156 
157 /*
158  * class HpAccessor
159  */
160 
161 typedef const struct hp_accessor_type_s *	HpAccessorType;
162 typedef struct hp_accessor_s *			_HpAccessor;
163 
164 struct hp_accessor_s
165 {
166     HpAccessorType	type;
167     size_t		data_offset;
168     size_t		data_size;
169 };
170 
171 struct hp_accessor_type_s
172 {
173     SANE_Status (*get)(HpAccessor this, HpData data, void * valp);
174     SANE_Status (*set)(HpAccessor this,  HpData data, void * valp);
175     int	 (*getint)(HpAccessor this, HpData data);
176     void (*setint)(HpAccessor this, HpData data, int val);
177 };
178 
179 SANE_Status
sanei_hp_accessor_get(HpAccessor this, HpData data, void * valp)180 sanei_hp_accessor_get (HpAccessor this, HpData data, void * valp)
181 {
182   if (!this->type->get)
183       return SANE_STATUS_INVAL;
184   return (*this->type->get)(this, data, valp);
185 }
186 
187 SANE_Status
sanei_hp_accessor_set(HpAccessor this, HpData data, void * valp)188 sanei_hp_accessor_set (HpAccessor this,  HpData data, void * valp)
189 {
190   if (!this->type->set)
191       return SANE_STATUS_INVAL;
192   return (*this->type->set)(this, data, valp);
193 }
194 
195 int
sanei_hp_accessor_getint(HpAccessor this, HpData data)196 sanei_hp_accessor_getint (HpAccessor this, HpData data)
197 {
198   assert (this->type->getint);
199   return (*this->type->getint)(this, data);
200 }
201 
202 void
sanei_hp_accessor_setint(HpAccessor this, HpData data, int val)203 sanei_hp_accessor_setint (HpAccessor this, HpData data, int val)
204 {
205   assert (this->type->setint);
206   (*this->type->setint)(this, data, val);
207 }
208 
209 const void *
sanei_hp_accessor_data(HpAccessor this, HpData data)210 sanei_hp_accessor_data (HpAccessor this, HpData data)
211 {
212   return hp_data_data(data, this->data_offset);
213 }
214 
215 void *
sanei__hp_accessor_data(HpAccessor this, HpData data)216 sanei__hp_accessor_data (HpAccessor this, HpData data)
217 {
218   return hp_data_data(data, this->data_offset);
219 }
220 
221 size_t
sanei_hp_accessor_size(HpAccessor this)222 sanei_hp_accessor_size (HpAccessor this)
223 {
224   return  this->data_size;
225 }
226 
227 HpAccessor
sanei_hp_accessor_new(HpData data, size_t sz)228 sanei_hp_accessor_new (HpData data, size_t sz)
229 {
230   static const struct hp_accessor_type_s type = {
231       0, 0, 0, 0
232   };
233   _HpAccessor	 new = sanei_hp_alloc(sizeof(*new));
234   new->type = &type;
235   new->data_offset = hp_data_alloc(data, new->data_size = sz);
236   return new;
237 }
238 
239 
240 /*
241  * class HpAccessorInt
242  */
243 
244 #define hp_accessor_int_s	hp_accessor_s
245 
246 typedef const struct hp_accessor_int_s *	HpAccessorInt;
247 typedef struct hp_accessor_int_s *		_HpAccessorInt;
248 
249 static SANE_Status
hp_accessor_int_get(HpAccessor this, HpData data, void * valp)250 hp_accessor_int_get (HpAccessor this, HpData data, void * valp)
251 {
252   *(SANE_Int*)valp = *(int *)hp_data_data(data, this->data_offset);
253   return SANE_STATUS_GOOD;
254 }
255 
256 static SANE_Status
hp_accessor_int_set(HpAccessor this, HpData data, void * valp)257 hp_accessor_int_set (HpAccessor this, HpData data, void * valp)
258 {
259   *(int *)hp_data_data(data, this->data_offset) = *(SANE_Int*)valp;
260   return SANE_STATUS_GOOD;
261 }
262 
263 static int
hp_accessor_int_getint(HpAccessor this, HpData data)264 hp_accessor_int_getint (HpAccessor this, HpData data)
265 {
266   return *(int *)hp_data_data(data, this->data_offset);
267 }
268 
269 static void
hp_accessor_int_setint(HpAccessor this, HpData data, int val)270 hp_accessor_int_setint (HpAccessor this, HpData data, int val)
271 {
272   *(int *)hp_data_data(data, this->data_offset) = val;
273 }
274 
275 HpAccessor
sanei_hp_accessor_int_new(HpData data)276 sanei_hp_accessor_int_new (HpData data)
277 {
278   static const struct hp_accessor_type_s type = {
279       hp_accessor_int_get, hp_accessor_int_set,
280       hp_accessor_int_getint, hp_accessor_int_setint
281   };
282   _HpAccessorInt	 new = sanei_hp_alloc(sizeof(*new));
283   new->type = &type;
284   new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int));
285   return (HpAccessor)new;
286 }
287 
288 
289 /*
290  * class HpAccessorBool
291  */
292 
293 #define hp_accessor_bool_s	hp_accessor_s
294 
295 typedef const struct hp_accessor_bool_s *	HpAccessorBool;
296 typedef struct hp_accessor_bool_s *		_HpAccessorBool;
297 
298 static SANE_Status
hp_accessor_bool_get(HpAccessor this, HpData data, void * valp)299 hp_accessor_bool_get (HpAccessor this, HpData data, void * valp)
300 {
301   int val = *(int *)hp_data_data(data, this->data_offset);
302   *(SANE_Bool*)valp = val ? SANE_TRUE : SANE_FALSE;
303   return SANE_STATUS_GOOD;
304 }
305 
306 static SANE_Status
hp_accessor_bool_set(HpAccessor this, HpData data, void * valp)307 hp_accessor_bool_set (HpAccessor this, HpData data, void * valp)
308 {
309   int * datap = hp_data_data(data, this->data_offset);
310   *datap = *(SANE_Bool*)valp == SANE_FALSE ? 0 : 1;
311   return SANE_STATUS_GOOD;
312 }
313 
314 HpAccessor
sanei_hp_accessor_bool_new(HpData data)315 sanei_hp_accessor_bool_new (HpData data)
316 {
317   static const struct hp_accessor_type_s type = {
318       hp_accessor_bool_get, hp_accessor_bool_set,
319       hp_accessor_int_getint, hp_accessor_int_setint
320   };
321   _HpAccessorBool	 new = sanei_hp_alloc(sizeof(*new));
322   new->type = &type;
323   new->data_offset = hp_data_alloc(data, new->data_size = sizeof(int));
324   return (HpAccessor)new;
325 }
326 
327 
328 /*
329  * class HpAccessorFixed
330  */
331 
332 #define hp_accessor_fixed_s	hp_accessor_s
333 
334 typedef const struct hp_accessor_fixed_s *	HpAccessorFixed;
335 typedef struct hp_accessor_fixed_s *		_HpAccessorFixed;
336 
337 static SANE_Status
hp_accessor_fixed_get(HpAccessor this, HpData data, void * valp)338 hp_accessor_fixed_get (HpAccessor this, HpData data, void * valp)
339 {
340   *(SANE_Fixed*)valp = *(SANE_Fixed *)hp_data_data(data, this->data_offset);
341   return SANE_STATUS_GOOD;
342 }
343 
344 static SANE_Status
hp_accessor_fixed_set(HpAccessor this, HpData data, void * valp)345 hp_accessor_fixed_set (HpAccessor this, HpData data, void * valp)
346 {
347   *(SANE_Fixed *)hp_data_data(data, this->data_offset) = *(SANE_Fixed*)valp;
348   return SANE_STATUS_GOOD;
349 }
350 
351 HpAccessor
sanei_hp_accessor_fixed_new(HpData data)352 sanei_hp_accessor_fixed_new (HpData data)
353 {
354   static const struct hp_accessor_type_s type = {
355       hp_accessor_fixed_get, hp_accessor_fixed_set, 0, 0
356   };
357   _HpAccessorFixed	 new = sanei_hp_alloc(sizeof(*new));
358   new->type = &type;
359   new->data_offset = hp_data_alloc(data, new->data_size = sizeof(SANE_Fixed));
360   return (HpAccessor)new;
361 }
362 
363 
364 /*
365  * class HpAccessorChoice
366  */
367 
368 typedef struct hp_accessor_choice_s *		_HpAccessorChoice;
369 
370 struct hp_accessor_choice_s
371 {
372     HpAccessorType	type;
373     size_t		data_offset;
374     size_t		data_size;
375 
376     HpChoice		choices;
377     SANE_String_Const * strlist;
378 };
379 
380 static SANE_Status
hp_accessor_choice_get(HpAccessor this, HpData data, void * valp)381 hp_accessor_choice_get (HpAccessor this, HpData data, void * valp)
382 {
383   HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset);
384   strcpy(valp, choice->name);
385   return SANE_STATUS_GOOD;
386 }
387 
388 static SANE_Status
hp_accessor_choice_set(HpAccessor _this, HpData data, void * valp)389 hp_accessor_choice_set (HpAccessor _this, HpData data, void * valp)
390 {
391   HpAccessorChoice	this	= (HpAccessorChoice)_this;
392   HpChoice 		choice;
393   SANE_String_Const *	strlist = this->strlist;
394 
395   for (choice = this->choices; choice; choice = choice->next)
396     {
397       /* Skip choices which aren't in strlist. */
398       if (!*strlist || strcmp(*strlist, choice->name) != 0)
399 	  continue;
400       strlist++;
401 
402       if (strcmp((const char *)valp, choice->name) == 0)
403 	{
404 	  *(HpChoice *)hp_data_data(data, this->data_offset) = choice;
405 	  return SANE_STATUS_GOOD;
406 	}
407     }
408 
409   return SANE_STATUS_INVAL;
410 }
411 
412 static int
hp_accessor_choice_getint(HpAccessor this, HpData data)413 hp_accessor_choice_getint (HpAccessor this, HpData data)
414 {
415   HpChoice choice = *(HpChoice *)hp_data_data(data, this->data_offset);
416   return choice->val;
417 }
418 
419 static void
hp_accessor_choice_setint(HpAccessor _this, HpData data, int val)420 hp_accessor_choice_setint (HpAccessor _this,  HpData data, int val)
421 {
422   HpAccessorChoice	this	= (HpAccessorChoice)_this;
423   HpChoice 		choice;
424   HpChoice 		first_choice = 0;
425   SANE_String_Const *	strlist = this->strlist;
426 
427   for (choice = this->choices; choice; choice = choice->next)
428     {
429       /* Skip choices which aren't in strlist. */
430       if (!*strlist || strcmp(*strlist, choice->name) != 0)
431 	  continue;
432       strlist++;
433 
434       if (!first_choice)
435 	  first_choice = choice; /* First enabled choice */
436 
437       if (choice->val == val)
438 	{
439 	  *(HpChoice *)hp_data_data(data, this->data_offset) = choice;
440 	  return;
441 	}
442     }
443 
444   if (first_choice)
445       *(HpChoice *)hp_data_data(data, this->data_offset) = first_choice;
446   else
447       assert(!"No choices to choose from?");
448 }
449 
450 SANE_Int
sanei_hp_accessor_choice_maxsize(HpAccessorChoice this)451 sanei_hp_accessor_choice_maxsize (HpAccessorChoice this)
452 {
453   HpChoice	choice;
454   SANE_Int	size	= 0;
455 
456   for (choice = this->choices; choice; choice = choice->next)
457       if ((SANE_Int)strlen(choice->name) >= size)
458 	  size = strlen(choice->name) + 1;
459   return size;
460 }
461 
462 SANE_String_Const *
sanei_hp_accessor_choice_strlist(HpAccessorChoice this, HpOptSet optset, HpData data, const HpDeviceInfo *info)463 sanei_hp_accessor_choice_strlist (HpAccessorChoice this,
464 			    HpOptSet optset, HpData data,
465                             const HpDeviceInfo *info)
466 {
467   if (optset)
468     {
469       int	old_val = hp_accessor_choice_getint((HpAccessor)this, data);
470       HpChoice	choice;
471       size_t	count	= 0;
472 
473       for (choice = this->choices; choice; choice = choice->next)
474 	  if (sanei_hp_choice_isEnabled(choice, optset, data, info))
475 	      this->strlist[count++] = choice->name;
476       this->strlist[count] = 0;
477 
478       hp_accessor_choice_setint((HpAccessor)this, data, old_val);
479     }
480 
481   return this->strlist;
482 }
483 
484 HpAccessor
sanei_hp_accessor_choice_new(HpData data, HpChoice choices, hp_bool_t may_change)485 sanei_hp_accessor_choice_new (HpData data, HpChoice choices,
486                               hp_bool_t may_change)
487 {
488   static const struct hp_accessor_type_s type = {
489       hp_accessor_choice_get, hp_accessor_choice_set,
490       hp_accessor_choice_getint, hp_accessor_choice_setint
491   };
492   HpChoice	choice;
493   size_t	count	= 0;
494   _HpAccessorChoice this;
495 
496   if ( may_change ) data->frozen = 0;
497 
498   for (choice = choices; choice; choice = choice->next)
499       count++;
500   this = sanei_hp_alloc(sizeof(*this) + (count+1) * sizeof(*this->strlist));
501   if (!this)
502       return 0;
503 
504   this->type = &type;
505   this->data_offset = hp_data_alloc(data, this->data_size = sizeof(HpChoice));
506   this->choices = choices;
507   this->strlist = (SANE_String_Const *)(this + 1);
508 
509   count = 0;
510   for (choice = this->choices; choice; choice = choice->next)
511       this->strlist[count++] = choice->name;
512   this->strlist[count] = 0;
513 
514   return (HpAccessor)this;
515 }
516 
517 /*
518  * class HpAccessorVector
519  */
520 
521 typedef struct hp_accessor_vector_s *		_HpAccessorVector;
522 
523 struct hp_accessor_vector_s
524 {
525     HpAccessorType	type;
526     size_t		data_offset;
527     size_t		data_size;
528 
529     unsigned short	mask;
530     unsigned short	length;
531     unsigned short	offset;
532     short		stride;
533 
534     unsigned short	(*unscale)(HpAccessorVector this, SANE_Fixed fval);
535     SANE_Fixed		(*scale)(HpAccessorVector this, unsigned short val);
536 
537     SANE_Fixed		fmin;
538     SANE_Fixed		fmax;
539 
540 };
541 
542 unsigned
sanei_hp_accessor_vector_length(HpAccessorVector this)543 sanei_hp_accessor_vector_length (HpAccessorVector this)
544 {
545   return this->length;
546 }
547 
548 SANE_Fixed
sanei_hp_accessor_vector_minval(HpAccessorVector this)549 sanei_hp_accessor_vector_minval (HpAccessorVector this)
550 {
551   return this->fmin;
552 }
553 
554 SANE_Fixed
sanei_hp_accessor_vector_maxval(HpAccessorVector this)555 sanei_hp_accessor_vector_maxval (HpAccessorVector this)
556 {
557   return this->fmax;
558 }
559 
560 static unsigned short
_v_get(HpAccessorVector this, const unsigned char * data)561 _v_get (HpAccessorVector this, const unsigned char * data)
562 {
563   unsigned short val;
564 
565   if (this->mask <= 255)
566       val = data[0];
567   else
568 #ifndef NotOrig
569       val = (data[0] << 8) + data[1];
570 #else
571       val = (data[1] << 8) + data[0];
572 #endif
573 
574   return val & this->mask;
575 }
576 
577 static void
_v_set(HpAccessorVector this, unsigned char * data, unsigned short val)578 _v_set (HpAccessorVector this, unsigned char * data, unsigned short val)
579 {
580   val &= this->mask;
581 
582   if (this->mask <= 255)
583     {
584       data[0] = (unsigned char)val;
585     }
586   else
587     {
588 #ifndef NotOrig
589       data[1] = (unsigned char)val;
590       data[0] = (unsigned char)(val >> 8);
591 #else
592       data[0] = (unsigned char)val;
593       data[1] = (unsigned char)(val >> 8);
594 #endif
595     }
596 }
597 
598 static SANE_Status
hp_accessor_vector_get(HpAccessor _this, HpData d, void * valp)599 hp_accessor_vector_get (HpAccessor _this, HpData d, void * valp)
600 {
601   HpAccessorVector	this	= (HpAccessorVector)_this;
602   SANE_Fixed *		ptr	= valp;
603   const SANE_Fixed *	end	= ptr + this->length;
604   const unsigned char *	data	= hp_data_data(d, this->data_offset);
605 
606   data += this->offset;
607 
608   while (ptr < end)
609     {
610       *ptr++ = (*this->scale)(this, _v_get(this, data));
611       data += this->stride;
612     }
613   return SANE_STATUS_GOOD;
614 }
615 
616 static SANE_Status
hp_accessor_vector_set(HpAccessor _this, HpData d, void * valp)617 hp_accessor_vector_set (HpAccessor _this, HpData d, void * valp)
618 {
619   HpAccessorVector	this	= (HpAccessorVector)_this;
620   SANE_Fixed *		ptr	= valp;
621   const SANE_Fixed *	end	= ptr + this->length;
622   unsigned char *	data	= hp_data_data(d, this->data_offset);
623 
624   data += this->offset;
625 
626   while (ptr < end)
627     {
628       if (*ptr < this->fmin)
629 	  *ptr = this->fmin;
630       if (*ptr > this->fmax)
631 	  *ptr = this->fmax;
632 
633       _v_set(this, data, (*this->unscale)(this, *ptr++));
634 
635       data += this->stride;
636     }
637   return SANE_STATUS_GOOD;
638 }
639 
640 static unsigned short
_vector_unscale(HpAccessorVector this, SANE_Fixed fval)641 _vector_unscale (HpAccessorVector this, SANE_Fixed fval)
642 {
643   unsigned short max_val = this->mask;
644   return (fval * max_val + SANE_FIX(0.5)) / SANE_FIX(1.0);
645 }
646 
647 static SANE_Fixed
_vector_scale(HpAccessorVector this, unsigned short val)648 _vector_scale (HpAccessorVector this, unsigned short val)
649 {
650   unsigned short max_val = this->mask;
651   return (SANE_FIX(1.0) * val + max_val / 2) / max_val;
652 }
653 
654 HpAccessor
sanei_hp_accessor_vector_new(HpData data, unsigned length, unsigned depth)655 sanei_hp_accessor_vector_new (HpData data, unsigned length, unsigned depth)
656 {
657   static const struct hp_accessor_type_s type = {
658       hp_accessor_vector_get, hp_accessor_vector_set, 0, 0
659   };
660   unsigned		width	= depth > 8 ? 2 : 1;
661   _HpAccessorVector	new	= sanei_hp_alloc(sizeof(*new));
662 
663   if (!new)
664       return 0;
665 
666   assert(depth > 0 && depth <= 16);
667   assert(length > 0);
668 
669   new->type = &type;
670   new->data_size   = length * width;
671   new->data_offset = hp_data_alloc(data, new->data_size);
672 
673   new->mask  = ((unsigned)1 << depth) - 1;
674   new->length = length;
675   new->offset = 0;
676   new->stride = width;
677 
678   new->scale   = _vector_scale;
679   new->unscale = _vector_unscale;
680 
681   new->fmin = SANE_FIX(0.0);
682   new->fmax = SANE_FIX(1.0);
683 
684   return (HpAccessor)new;
685 }
686 
687 static unsigned short
_gamma_vector_unscale(HpAccessorVector __sane_unused__ this, SANE_Fixed fval)688 _gamma_vector_unscale (HpAccessorVector __sane_unused__ this, SANE_Fixed fval)
689 {
690   unsigned short unscaled = fval / SANE_FIX(1.0);
691   if (unscaled > 255) unscaled = 255;
692   unscaled = 255 - unscaled;  /* Don't know why. But this is how it works. */
693 
694   return unscaled;
695 }
696 
697 static SANE_Fixed
_gamma_vector_scale(HpAccessorVector __sane_unused__ this, unsigned short val)698 _gamma_vector_scale (HpAccessorVector __sane_unused__ this, unsigned short val)
699 {
700   SANE_Fixed scaled;
701   val = 255-val;     /* Don't know why. But this is how it works. */
702   scaled = val * SANE_FIX(1.0);
703 
704   return scaled;
705 }
706 
707 HpAccessor
sanei_hp_accessor_gamma_vector_new(HpData data, unsigned length, unsigned depth)708 sanei_hp_accessor_gamma_vector_new (HpData data, unsigned length,
709                                     unsigned depth)
710 {
711   _HpAccessorVector	this	=
712       ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) );
713 
714 
715   if (!this)
716       return 0;
717 
718   this->offset += this->stride * (this->length - 1);
719   this->stride = -this->stride;
720 
721   this->scale   = _gamma_vector_scale;
722   this->unscale = _gamma_vector_unscale;
723 
724   this->fmin = SANE_FIX(0.0);
725   this->fmax = SANE_FIX(255.0);
726 
727   return (HpAccessor)this;
728 }
729 
730 static unsigned short
_matrix_vector_unscale(HpAccessorVector this, SANE_Fixed fval)731 _matrix_vector_unscale (HpAccessorVector this, SANE_Fixed fval)
732 {
733   unsigned short max_val  = this->mask >> 1;
734   unsigned short sign_bit = this->mask & ~max_val;
735   unsigned short sign	  = 0;
736 
737   if (fval == SANE_FIX(1.0))
738       return sign_bit;
739 
740   if (fval < 0)
741     {
742       sign = sign_bit;
743       fval = -fval;
744     }
745   return sign | ((fval * max_val + this->fmax / 2) / this->fmax);
746 }
747 
748 static SANE_Fixed
_matrix_vector_scale(HpAccessorVector this, unsigned short val)749 _matrix_vector_scale (HpAccessorVector this, unsigned short val)
750 {
751   unsigned short max_val  = this->mask >> 1;
752   unsigned short sign_bit = this->mask & ~max_val;
753   SANE_Fixed	 fval;
754 
755   if (val == sign_bit)
756       return SANE_FIX(1.0);
757 
758   fval = (this->fmax * (val & max_val) + max_val / 2) / max_val;
759 
760   if ((val & sign_bit) != 0)
761       fval = -fval;
762 
763   return fval;
764 }
765 
766 HpAccessor
sanei_hp_accessor_matrix_vector_new(HpData data, unsigned length, unsigned depth)767 sanei_hp_accessor_matrix_vector_new (HpData data, unsigned length,
768                                      unsigned depth)
769 {
770   _HpAccessorVector	this	=
771       ( (_HpAccessorVector) sanei_hp_accessor_vector_new(data, length, depth) );
772 
773   if (!this)
774       return 0;
775 
776   this->scale   = _matrix_vector_scale;
777   this->unscale = _matrix_vector_unscale;
778 
779   this->fmax = depth == 10 ? SANE_FIX(4.0) : SANE_FIX(2.0);
780   this->fmax *= (this->mask >> 1);
781   this->fmax >>= (depth - 1);
782   this->fmin = - this->fmax;
783 
784   return (HpAccessor)this;
785 }
786 
787 HpAccessor
sanei_hp_accessor_subvector_new(HpAccessorVector super, unsigned nchan, unsigned chan)788 sanei_hp_accessor_subvector_new (HpAccessorVector super,
789 			   unsigned nchan, unsigned chan)
790 {
791   _HpAccessorVector	this	= sanei_hp_memdup(super, sizeof(*this));
792 
793   if (!this)
794       return 0;
795 
796   assert(chan < nchan);
797   assert(this->length % nchan == 0);
798 
799   this->length /= nchan;
800 
801   if (this->stride < 0)
802       this->offset += (nchan - chan - 1) * this->stride;
803   else
804       this->offset += chan * this->stride;
805 
806   this->stride *= nchan;
807 
808   return (HpAccessor)this;
809 }
810 
811 /*
812  * class HpAccessorGeometry
813  */
814 
815 typedef const struct hp_accessor_geometry_s *	HpAccessorGeometry;
816 typedef struct hp_accessor_geometry_s *		_HpAccessorGeometry;
817 
818 struct hp_accessor_geometry_s
819 {
820     HpAccessorType	type;
821     size_t		data_offset;
822     size_t		data_size;
823 
824     HpAccessor		this;
825     HpAccessor		other;
826     hp_bool_t		is_br;
827     HpAccessor		resolution;
828 };
829 
830 
831 static SANE_Status
hp_accessor_geometry_set(HpAccessor _this, HpData data, void * _valp)832 hp_accessor_geometry_set (HpAccessor _this, HpData data, void * _valp)
833 {
834   HpAccessorGeometry	this	= (HpAccessorGeometry)_this;
835   SANE_Fixed *		valp	= _valp;
836   SANE_Fixed		limit;
837 
838   sanei_hp_accessor_get(this->other, data, &limit);
839   if (this->is_br ? *valp < limit : *valp > limit)
840       *valp = limit;
841   return sanei_hp_accessor_set(this->this, data, valp);
842 }
843 
844 static int
_to_devpixels(SANE_Fixed val_mm, SANE_Fixed mm_per_pix)845 _to_devpixels (SANE_Fixed val_mm, SANE_Fixed mm_per_pix)
846 {
847   assert(val_mm >= 0);
848   return (val_mm + mm_per_pix / 2) / mm_per_pix;
849 }
850 
851 static int
hp_accessor_geometry_getint(HpAccessor _this, HpData data)852 hp_accessor_geometry_getint (HpAccessor _this, HpData data)
853 {
854   HpAccessorGeometry	this	= (HpAccessorGeometry)_this;
855   SANE_Fixed		this_val, other_val;
856   int			res	= sanei_hp_accessor_getint(this->resolution,
857                                                            data);
858   SANE_Fixed		mm_per_pix = (SANE_FIX(MM_PER_INCH) + res / 2) / res;
859 
860   assert(res > 0);
861   sanei_hp_accessor_get(this->this, data, &this_val);
862 
863   if (this->is_br)
864     {
865       /* Convert to extent. */
866       sanei_hp_accessor_get(this->other, data, &other_val);
867       assert(this_val >= other_val && other_val >= 0);
868       return (_to_devpixels(this_val, mm_per_pix)
869 	      - _to_devpixels(other_val, mm_per_pix) + 1);
870     }
871   return _to_devpixels(this_val, mm_per_pix);
872 }
873 
874 /*
875  * we should implement hp_accessor_geometry_setint, but we don't
876  * need it yet...
877  */
878 
879 
880 HpAccessor
sanei_hp_accessor_geometry_new(HpAccessor val, HpAccessor lim, hp_bool_t is_br, HpAccessor resolution)881 sanei_hp_accessor_geometry_new (HpAccessor val, HpAccessor lim, hp_bool_t is_br,
882 			  HpAccessor resolution)
883 {
884   static const struct hp_accessor_type_s type = {
885       hp_accessor_fixed_get, hp_accessor_geometry_set,
886       hp_accessor_geometry_getint, 0
887   };
888   _HpAccessorGeometry new = sanei_hp_alloc(sizeof(*new));
889 
890   new->type = &type;
891   new->data_offset = val->data_offset;
892   new->data_size   = val->data_size;
893 
894   new->this  = val;
895   new->other = lim;
896   new->is_br = is_br;
897   new->resolution = resolution;
898 
899   return (HpAccessor)new;
900 }
901