1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2    All Rights Reserved.
3 
4    This software is provided AS-IS with no warranty, either express or
5    implied.
6 
7    This software is distributed under license and may not be copied,
8    modified or distributed except as expressly authorized under the terms
9    of the license contained in the file LICENSE in this distribution.
10 
11    Refer to licensing information at http://www.artifex.com or contact
12    Artifex Software, Inc.,  1305 Grant Avenue - Suite 200, Novato,
13    CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15 
16 
17 /* Templates for sample lookup and expansion */
18 
19 /* This module is allowed to include several times into a single .c file.
20    The following macros to be defined in advance :
21         MULTIPLE_MAPS - 1 if num_components_per_plane > 0 and
22                         components use different maps, 0 otherwise.
23         TEMPLATE_sample_unpack_1 - a name for the function
24         TEMPLATE_sample_unpack_2 - a name for the function
25         TEMPLATE_sample_unpack_4 - a name for the function
26         TEMPLATE_sample_unpack_8 - a name for the function
27  */
28 
29 #if defined(TEMPLATE_sample_unpack_1) && defined(TEMPLATE_sample_unpack_2) && defined(TEMPLATE_sample_unpack_4) && defined(TEMPLATE_sample_unpack_8)
30 
31 #include "valgrind.h"
32 
33 #if MULTIPLE_MAPS
34 #   define NEXT_MAP map = smap[++smap_index % num_components_per_plane].table.lookup4x1to32
35 #   define NEXT_MAP8 map = smap[++smap_index % num_components_per_plane].table.lookup8
36 #   define DEFINE_SMAP_INDEX int smap_index = 0;
37 #else
38 #   define NEXT_MAP
39 #   define NEXT_MAP8
40 #   define DEFINE_SMAP_INDEX
41 #endif
42 
43 const byte *
TEMPLATE_sample_unpack_1(byte * bptr,int * pdata_x,const byte * data,int data_x,uint dsize,const sample_map * smap,int spread,int num_components_per_plane)44 TEMPLATE_sample_unpack_1(byte * bptr, int *pdata_x, const byte * data, int data_x,
45                 uint dsize, const sample_map *smap, int spread,
46                 int num_components_per_plane)
47 {
48     const sample_lookup_t * ptab = &smap->table;
49     const byte *psrc = data + (data_x >> 3);
50     int left = dsize - (data_x >> 3);
51     DEFINE_SMAP_INDEX
52 
53 #ifdef PACIFY_VALGRIND
54     byte *bend = bptr + left*spread;
55     byte vbits = 0;
56 
57     /* Allow for undefined bits at the end */
58     VALGRIND_GET_VBITS(&psrc[left-1], &vbits, 1);
59     /* At least the top bit must be defined. If not,
60      * don't change anything, and let valgrind complain. */
61     if ((vbits & 0x80) == 0) {
62         byte zero = 0;
63         VALGRIND_SET_VBITS(&psrc[left-1], &zero, 1);
64     }
65 #endif
66 
67     if (spread == 1) {
68         bits32 *bufp = (bits32 *) bptr;
69         const bits32 *map = &ptab->lookup4x1to32[0];
70         uint b;
71 
72         if (left & 1) {
73             b = psrc[0];
74             bufp[0] = map[b >> 4];
75             NEXT_MAP;
76             bufp[1] = map[b & 0xf];
77             NEXT_MAP;
78             psrc++, bufp += 2;
79         }
80         left >>= 1;
81         while (left--) {
82             b = psrc[0];
83             bufp[0] = map[b >> 4];
84             NEXT_MAP;
85             bufp[1] = map[b & 0xf];
86             NEXT_MAP;
87             b = psrc[1];
88             bufp[2] = map[b >> 4];
89             NEXT_MAP;
90             bufp[3] = map[b & 0xf];
91             NEXT_MAP;
92             psrc += 2, bufp += 4;
93         }
94     } else {
95         byte *bufp = bptr;
96         const byte *map = &ptab->lookup8[0];
97 
98         while (left--) {
99             uint b = *psrc++;
100 
101             *bufp = map[b >> 7];
102             NEXT_MAP8;
103             bufp += spread;
104             *bufp = map[(b >> 6) & 1];
105             NEXT_MAP8;
106             bufp += spread;
107             *bufp = map[(b >> 5) & 1];
108             NEXT_MAP8;
109             bufp += spread;
110             *bufp = map[(b >> 4) & 1];
111             NEXT_MAP8;
112             bufp += spread;
113             *bufp = map[(b >> 3) & 1];
114             NEXT_MAP8;
115             bufp += spread;
116             *bufp = map[(b >> 2) & 1];
117             NEXT_MAP8;
118             bufp += spread;
119             *bufp = map[(b >> 1) & 1];
120             NEXT_MAP8;
121             bufp += spread;
122             *bufp = map[b & 1];
123             NEXT_MAP8;
124             bufp += spread;
125         }
126     }
127 #ifdef PACIFY_VALGRIND
128     /* Put any undefinedness back, and carry it over to the output. */
129     VALGRIND_SET_VBITS(psrc-1, &vbits, 1);
130     {
131         byte ones = 0xff;
132         if (vbits & 0x40)
133             VALGRIND_SET_VBITS(bend - spread*7, &ones, 1);
134         if (vbits & 0x20)
135             VALGRIND_SET_VBITS(bend - spread*6, &ones, 1);
136         if (vbits & 0x10)
137             VALGRIND_SET_VBITS(bend - spread*5, &ones, 1);
138         if (vbits & 0x08)
139             VALGRIND_SET_VBITS(bend - spread*4, &ones, 1);
140         if (vbits & 0x04)
141             VALGRIND_SET_VBITS(bend - spread*3, &ones, 1);
142         if (vbits & 0x02)
143             VALGRIND_SET_VBITS(bend - spread*2, &ones, 1);
144         if (vbits & 0x01)
145             VALGRIND_SET_VBITS(bend - spread*1, &ones, 1);
146     }
147 #endif
148     *pdata_x = data_x & 7;
149     return bptr;
150 }
151 
152 #undef NEXT_MAP
153 
154 #if MULTIPLE_MAPS
155 #   define NEXT_MAP  map = smap[++smap_index % num_components_per_plane].table.lookup2x2to16
156 #else
157 #   define NEXT_MAP
158 #endif
159 
160 const byte *
TEMPLATE_sample_unpack_2(byte * bptr,int * pdata_x,const byte * data,int data_x,uint dsize,const sample_map * smap,int spread,int num_components_per_plane)161 TEMPLATE_sample_unpack_2(byte * bptr, int *pdata_x, const byte * data, int data_x,
162                 uint dsize, const sample_map *smap, int spread,
163                 int num_components_per_plane)
164 {
165     const sample_lookup_t * ptab = &smap->table;
166     const byte *psrc = data + (data_x >> 2);
167     int left = dsize - (data_x >> 2);
168     DEFINE_SMAP_INDEX
169 
170 #ifdef PACIFY_VALGRIND
171     byte *bend = bptr + left*spread;
172     byte vbits = 0;
173 
174     /* Allow for undefined bits at the end */
175     VALGRIND_GET_VBITS(&psrc[left-1], &vbits, 1);
176     /* At least the top 2 bits must be defined. If not,
177      * don't change anything, and let valgrind complain. */
178     if ((vbits & 0xC0) == 0) {
179         byte zero = 0;
180         VALGRIND_SET_VBITS(&psrc[left-1], &zero, 1);
181     }
182 #endif
183 
184     if (spread == 1) {
185         bits16 *bufp = (bits16 *) bptr;
186         const bits16 *map = &ptab->lookup2x2to16[0];
187 
188         while (left--) {
189             uint b = *psrc++;
190 
191             *bufp++ = map[b >> 4];
192             NEXT_MAP;
193             *bufp++ = map[b & 0xf];
194             NEXT_MAP;
195         }
196     } else {
197         byte *bufp = bptr;
198         const byte *map = &ptab->lookup8[0];
199 
200         while (left--) {
201             unsigned b = *psrc++;
202 
203             *bufp = map[b >> 6];
204             NEXT_MAP8;
205             bufp += spread;
206             *bufp = map[(b >> 4) & 3];
207             NEXT_MAP8;
208             bufp += spread;
209             *bufp = map[(b >> 2) & 3];
210             NEXT_MAP8;
211             bufp += spread;
212             *bufp = map[b & 3];
213             NEXT_MAP8;
214             bufp += spread;
215         }
216     }
217     *pdata_x = data_x & 3;
218 #ifdef PACIFY_VALGRIND
219     /* Put any undefinedness back, and carry it over to the output. */
220     VALGRIND_SET_VBITS(psrc-1, &vbits, 1);
221     {
222         byte ones = 0xff;
223         if (vbits & 0x30)
224             VALGRIND_SET_VBITS(bend - spread*3, &ones, 1);
225         if (vbits & 0x0C)
226             VALGRIND_SET_VBITS(bend - spread*2, &ones, 1);
227         if (vbits & 0x03)
228             VALGRIND_SET_VBITS(bend - spread*1, &ones, 1);
229     }
230 #endif
231     return bptr;
232 }
233 
234 #undef NEXT_MAP
235 
236 const byte *
TEMPLATE_sample_unpack_4(byte * bptr,int * pdata_x,const byte * data,int data_x,uint dsize,const sample_map * smap,int spread,int num_components_per_plane)237 TEMPLATE_sample_unpack_4(byte * bptr, int *pdata_x, const byte * data, int data_x,
238                 uint dsize, const sample_map *smap, int spread,
239                 int num_components_per_plane)
240 {
241     const sample_lookup_t * ptab = &smap->table;
242     byte *bufp = bptr;
243     const byte *psrc = data + (data_x >> 1);
244     int left = dsize - (data_x >> 1);
245     const byte *map = &ptab->lookup8[0];
246     DEFINE_SMAP_INDEX
247 
248 #ifdef PACIFY_VALGRIND
249     byte vbits = 0;
250 
251     /* Allow for undefined bits at the end */
252     VALGRIND_GET_VBITS(&psrc[left-1], &vbits, 1);
253     /* At least the top 4 bits must be defined. If not,
254      * don't change anything, and let valgrind complain. */
255     if ((vbits & 0xf0) == 0) {
256         byte zero = 0;
257         VALGRIND_SET_VBITS(&psrc[left-1], &zero, 1);
258     }
259 #endif
260 
261     while (left--) {
262         uint b = *psrc++;
263 
264         *bufp = map[b >> 4];
265         NEXT_MAP8;
266         bufp += spread;
267         *bufp = map[b & 0xf];
268         NEXT_MAP8;
269         bufp += spread;
270     }
271 #ifdef PACIFY_VALGRIND
272     /* Put any undefinedness back, and carry it over to the output. */
273     VALGRIND_SET_VBITS(psrc-1, &vbits, 1);
274     if ((vbits & 0x0f) != 0) {
275         byte ones = 0xFF;
276         VALGRIND_SET_VBITS(bufp-spread, &ones, 1);
277     }
278 #endif
279     *pdata_x = data_x & 1;
280     return bptr;
281 }
282 
283 const byte *
TEMPLATE_sample_unpack_8(byte * bptr,int * pdata_x,const byte * data,int data_x,uint dsize,const sample_map * smap,int spread,int num_components_per_plane)284 TEMPLATE_sample_unpack_8(byte * bptr, int *pdata_x, const byte * data, int data_x,
285                 uint dsize, const sample_map *smap, int spread,
286                 int num_components_per_plane)
287 {
288     const sample_lookup_t * ptab = &smap->table;
289     byte *bufp = bptr;
290     const byte *psrc = data + data_x;
291     DEFINE_SMAP_INDEX
292 
293     *pdata_x = 0;
294     if (spread == 1) {
295         if (MULTIPLE_MAPS ||
296             ptab->lookup8[0] != 0 ||
297             ptab->lookup8[255] != 255
298             ) {
299             uint left = dsize - data_x;
300             const byte *map = &ptab->lookup8[0];
301 
302             while (left--) {
303                 *bufp++ = map[*psrc++];
304                 NEXT_MAP8;
305             }
306         } else {		/* No copying needed, and we'll use the data right away. */
307             return psrc;
308         }
309     } else {
310         int left = dsize - data_x;
311         const byte *map = &ptab->lookup8[0];
312 
313         for (; left--; psrc++, bufp += spread) {
314             *bufp = map[*psrc];
315             NEXT_MAP8;
316         }
317     }
318     return bptr;
319 }
320 
321 #undef NEXT_MAP
322 #undef NEXT_MAP8
323 #undef DEFINE_SMAP_INDEX
324 
325 #else
326 int dummy;
327 #endif
328 
329