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