Tizen 2.1 base
[platform/upstream/hplip.git] / ip / xtable.c
1 /* libhpojip -- HP OfficeJet image-processing library. */
2
3 /* Copyright (C) 1995-2002 Hewlett-Packard Company
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  * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
12  * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
13  * NON-INFRINGEMENT.  See the GNU 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18  * MA 02111-1307, USA.
19  *
20  * In addition, as a special exception, Hewlett-Packard Company
21  * gives permission to link the code of this program with any
22  * version of the OpenSSL library which is distributed under a
23  * license identical to that listed in the included LICENSE.OpenSSL
24  * file, and distribute linked combinations including the two.
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL.  If you modify
27  * this file, you may extend this exception to your version of the
28  * file, but you are not obligated to do so.  If you do not wish to
29  * do so, delete this exception statement from your version.
30  */
31
32 /* Original author: Mark Overton and others.
33  *
34  * Ported to Linux by David Paschal.
35  */
36
37 /******************************************************************************\
38  *
39  * xtable.c - Performs a 256-entry table lookup on all bytes
40  *
41  ******************************************************************************
42  *
43  * Name of Global Jump-Table:
44  *
45  *    tableTbl
46  *
47  * Items in aXformInfo array passed into setXformSpec:
48  *
49  *    aXformInfo[IP_TABLE_WHICH] = contents of table to use:
50  *          IP_TABLE_USER            = user-supplied pointer to a 256-byte table,
51  *          IP_TABLE_USER_WORD       = user-supplied pointer to a 4096-word table,
52  *          IP_TABLE_PASS_THRU       = pass-thru table that does nothing,
53  *          IP_TABLE_GAMMA           = gamma function,
54  *          IP_TABLE_THRESHOLD       = threshold (snaps each incoming byte to 0 or 255),
55  *          IP_TABLE_MIRROR          = mirror-image each incoming byte,
56  *          IP_TABLE_USER_THREE      = three user-supplied table pointers,
57  *          IP_TABLE_USER_THREE_WORD = three user-supplied table pointers for 48-bit (see format below),
58  *          IP_TABLE_BW_CLIP         = white/black clipper (2 thresholds below)
59  *
60  *    aXformInfo[IP_TABLE_OPTION] =
61  *          parameter based on type of table to use.  values:
62  *                       - (type IP_TABLE_USER) pointer to user table,
63  *                         this table is copied into this xform's instance,
64  *                       - (type IP_TABLE_GAMMA) gamma value, in 16.16 fixed-point, a value
65  *                         less than 1.0 does an inverse gamma, (for
66  *                         type IP_TABLE_GAMMA above),
67  *                       - (type IP_TABLE_THRESHOLD) threshold value. if an incoming byte is >=
68  *                         this value, it changes to 255, else it changes
69  *                         to 0 (for type IP_TABLE_THRESHOLD above),
70  *                       - (type IP_TABLE_BW_CLIP) hi word = number of 0 entries at start,
71  *                                                 lo word = number of 255 entries at end,
72  *
73  *    For option IP_TABLE_USER_THREE above (three user-supplied table pointers),
74  *    these three 256-byte tables are for 3-component color data.  The pointers are in
75  *    aXformInfo[IP_TABLE_COLOR_1], aXformInfo[IP_TABLE_COLOR_2], and aXformInfo[IP_TABLE_COLOR_3].
76  *
77  *    For option IP_TABLE_USER_THREE_WORD (three user tables for 48-bit color data),
78  *    the pointers are in aXformInfo as with IP_TABLE_USER_THREE.
79  *    Each table consists of 4096 words (8192 bytes) which are indexed by the high 12 bits
80  *    of each color-channel.  The low four bits are interpolated herein.  Each table-entry
81  *    contains a 16-bit pixel-value, even though it's indexed by just 12 bits.
82  *
83  *    IP_TABLE_USER_WORD is like IP_TABLE_USER_THREE_WORD described above.
84  *
85  *    For option IP_TABLE_BW_CLIP, the white/black clipper, the table starts with the given
86  *    number of 0's, and ends with the given number of 255's, and linearly
87  *    progresses between 1 and 254 in between them.  This serves to snap
88  *    almost-black to black, and almost-white to white.  If these numbers
89  *    are large, this table also boosts contrast.
90  *
91  * Capabilities and Limitations:
92  *
93  *    The incoming data can be any kind of raw pixels of 1, 8, 16, 24 or 48
94  *    bits/pixel.  Bi-level (1 bit/pixel) data is treated as 8 pixels per byte.
95  *    All table-types support all these forms of input data. For 16 bits/channel
96  *    data, the tables are interpolated.
97  *
98  *    For improved precision, the following define larger (12-bit index) tables:
99  *           IP_TABLE_USER_WORD       - 16 bits per pixel (grayscale)
100  *           IP_TABLE_USER_THREE_WORD - 48 bits per pixel (color)
101  *
102  *    Also, IP_TABLE_GAMMA will create a 12-bit table when the input data
103  *    is 16 bits/channel.
104  *
105  *    12-bit tables work with 8-bit/channel data, and 8-bit tables work with
106  *    16-bit/channel data.  Truncation or interpolation is done as needed.
107  *
108  * Default Input Traits, and Output Traits:
109  *
110  *          trait             default input             output
111  *    -------------------  ---------------------  ------------------------
112  *    iPixelsPerRow         * passed into output   same as default input
113  *    iBitsPerPixel         * passed into output   same as default input
114  *    iComponentsPerPixel     passed into output   same as default input
115  *    lHorizDPI               passed into output   same as default input
116  *    lVertDPI                passed into output   same as default input
117  *    lNumRows                passed into output   same as default input
118  *    iNumPages               passed into output   same as default input
119  *    iPageNum                passed into output   same as default input
120  *
121  *    Above, a "*" by an item indicates it must be valid (not negative).
122  *
123  * Apr 1998 Mark Overton -- wrote original code
124  *
125 \******************************************************************************/
126
127 #include "hpip.h"
128 #include "ipdefs.h"
129 #include "string.h"    /* for memset and memcpy */
130 #include "math.h"      /* for pow for generating gamma table */
131
132
133 #if 0
134     #include "stdio.h"
135     #include <tchar.h>
136
137     #define PRINT(msg,arg1,arg2) \
138         _ftprintf(stderr, msg, (int)arg1, (int)arg2)
139 #else
140     #define PRINT(msg,arg1,arg2)
141 #endif
142
143 #define CHECK_VALUE 0x4ba1dace
144
145
146 typedef struct {
147     IP_IMAGE_TRAITS traits;   /* traits of the input and output image */
148     BYTE     bWhich;          /* which table to generate */
149     BYTE     bTables[3][256]; /* the 8-bit look-up tables */
150     WORD    *pwTables[3];     /* ptrs to 12-bit-index tables (for 16-bits/pixel) */
151     BOOL     bBigTable;       /* are we using the 12-bit tables? */
152     int      nTables;         /* # of tables defined (1 or 3) */
153     DWORD    dwBytesPerRow;   /* # of bytes in each row */
154     DWORD    dwRowsDone;      /* number of rows converted so far */
155     DWORD    dwInNextPos;     /* file pos for subsequent input */
156     DWORD    dwOutNextPos;    /* file pos for subsequent output */
157     DWORD    dwValidChk;      /* struct validity check value */
158 } TBL_INST, *PTBL_INST;
159
160
161 typedef enum {
162     TBL_USER,
163     TBL_PASS_THRU,
164     TBL_GAMMA,
165     TBL_THRESHOLD,
166     TBL_MIRROR,
167     TBL_USER_THREE,
168     TBL_BW_CLIP
169 } TABLE_TYPE;
170
171
172
173 static BOOL generateTable (
174     PTBL_INST g,
175     DWORD_OR_PVOID aXformInfo[])
176 {
177     IP_TABLE_TYPE which;
178     DWORD         dwparam;
179     PVOID         pvparam;
180     float         flparam;
181     PBYTE         pTable;
182     PWORD         pwTable;
183     int           nTable;
184
185     g->nTables = 1;
186     g->bBigTable = FALSE;
187     pTable = g->bTables[0];
188     dwparam =                aXformInfo[IP_TABLE_OPTION].dword;
189     pvparam =                aXformInfo[IP_TABLE_OPTION].pvoid;
190     flparam =                aXformInfo[IP_TABLE_OPTION].fl;
191     which = (IP_TABLE_TYPE)aXformInfo[IP_TABLE_WHICH].dword;
192     g->bWhich = (BYTE)which;
193
194     switch (which)
195     {
196         case IP_TABLE_USER:
197             if (pvparam == 0)
198                 return FALSE;
199             memcpy (pTable, (PBYTE)pvparam, 256);
200         break;
201
202         case IP_TABLE_USER_WORD:
203             if (pvparam == 0)
204                 return FALSE;
205             IP_MEM_ALLOC (4097*sizeof(WORD), pwTable);  /* 4097: extra entry at end */
206             g->pwTables[0] = pwTable;
207             memcpy (pwTable, (PWORD)pvparam, 4096*sizeof(WORD));
208             pwTable[4096] = pwTable[4095];  /* extra entry to help interpolation */
209             g->bBigTable = TRUE;
210         break;
211
212         case IP_TABLE_USER_THREE:
213             if (aXformInfo[IP_TABLE_COLOR_1].pvoid==0 ||
214                 aXformInfo[IP_TABLE_COLOR_2].pvoid==0 ||
215                 aXformInfo[IP_TABLE_COLOR_3].pvoid==0)
216                 return FALSE;
217             memcpy (g->bTables[0], (PBYTE)aXformInfo[IP_TABLE_COLOR_1].pvoid, 256);
218             memcpy (g->bTables[1], (PBYTE)aXformInfo[IP_TABLE_COLOR_2].pvoid, 256);
219             memcpy (g->bTables[2], (PBYTE)aXformInfo[IP_TABLE_COLOR_3].pvoid, 256);
220             g->nTables = 3;
221         break;
222
223         case IP_TABLE_USER_THREE_WORD:
224             if (aXformInfo[IP_TABLE_COLOR_1].pvoid==0 ||
225                 aXformInfo[IP_TABLE_COLOR_2].pvoid==0 ||
226                 aXformInfo[IP_TABLE_COLOR_3].pvoid==0)
227                 return FALSE;
228
229             for (nTable=0; nTable<3; nTable++) {
230                 IP_MEM_ALLOC (4097*sizeof(WORD), pwTable);  /* 4097: extra entry at end */
231                 g->pwTables[nTable] = pwTable;
232                 memcpy (pwTable, (PWORD)aXformInfo[IP_TABLE_COLOR_1+nTable].pvoid, 4096*sizeof(WORD));
233                 pwTable[4096] = pwTable[4095];  /* extra entry to help interpolation */
234             }
235             g->nTables = 3;
236             g->bBigTable = TRUE;
237         break;
238
239         case IP_TABLE_PASS_THRU:
240         {
241             int i;
242
243             for (i=0; i<=255; i++)
244                 pTable[i] = i;
245         }
246         break;
247
248         case IP_TABLE_GAMMA:
249         {
250             int   index;
251             float fval;
252             float gamma;
253             float gamval;
254
255             gamma = (float)flparam / (float)(1L<<16);
256             if (gamma<=0.0f || gamma>=10.0f)
257                 return FALSE;
258             gamma = 1.0f / gamma;
259
260             if (g->traits.iBitsPerPixel==16 || g->traits.iBitsPerPixel==48) {
261                 WORD *pwTable;
262                 IP_MEM_ALLOC (4097*sizeof(WORD), pwTable);  /* 4097: extra entry at end */
263                 g->pwTables[0] = pwTable;
264
265                 for (index=0; index<=4095u; index++) {
266                     fval = (float)index / 4095.0f;
267                     gamval = 65535.0f * (float)pow(fval, gamma);
268                     pwTable[index] = (WORD)(gamval + 0.5f);
269                 }
270
271                 pwTable[4096] = pwTable[4095];  /* extra entry to help interpolation */
272                 g->bBigTable = TRUE;
273             } else {
274                 for (index=0; index<=255u; index++) {
275                     fval = (float)index / 255.0f;
276                     gamval = 255.0f * (float)pow(fval, gamma);
277                     pTable[index] = (BYTE)(gamval + 0.5f);
278                 }
279             }
280         }
281         break;
282
283         case IP_TABLE_THRESHOLD:
284             if (dwparam<1 || dwparam>255)
285                 return FALSE;
286             memset (pTable, 0, dwparam);
287             memset (pTable+dwparam, 255, 256-dwparam);
288         break;
289
290         case IP_TABLE_MIRROR:
291         {
292             UINT index, mask;
293
294             for (index=0; index<=255; index++) {
295                 for (mask=0x01u; mask<=0x80u; mask<<=1) {
296                     pTable[index] <<= 1;
297                     if (index & mask)
298                         pTable[index] += 1;
299                 }
300             }
301         }
302         break;
303
304         case IP_TABLE_BW_CLIP:
305         {
306             DWORD nBlack, nWhite, nMid, slopeMid, posMid, index;
307
308             nBlack = dwparam >> 16;
309             nWhite = dwparam & 0xFFFFu;
310
311             if (nBlack+nWhite > 256)
312                 return FALSE;
313
314             for (index=0; index<nBlack; index++)
315                 pTable[index] = 0;
316
317             for (index=256-nWhite; index<=255; index++)
318                 pTable[index] = 255;
319
320             nMid = 256 - nBlack - nWhite;
321             slopeMid = (255ul<<16) / (nMid + 1);
322             posMid = 0x8000u;   /* offset for rounding */
323
324             for (index=nBlack; index<256-nWhite; index++) {
325                 posMid += slopeMid;
326                 pTable[index] = (BYTE)(posMid >> 16);
327             }
328         }
329         break;
330
331         default:
332             return FALSE;
333     }
334
335     return TRUE;
336
337 fatal_error:
338     return FALSE;
339 }
340
341
342
343 /*****************************************************************************\
344  *
345  * table_openXform - Creates a new instance of the transformer
346  *
347  *****************************************************************************
348  *
349  * This returns a handle for the new instance to be passed into
350  * all subsequent calls.
351  *
352  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
353  *
354 \*****************************************************************************/
355
356 static WORD table_openXform (
357     IP_XFORM_HANDLE *pXform)   /* out: returned handle */
358 {
359     PTBL_INST g;
360
361     INSURE (pXform != NULL);
362     IP_MEM_ALLOC (sizeof(TBL_INST), g);
363     *pXform = g;
364     memset (g, 0, sizeof(TBL_INST));
365     g->dwValidChk = CHECK_VALUE;
366     return IP_DONE;
367
368     fatal_error:
369     return IP_FATAL_ERROR;
370 }
371
372
373
374 /*****************************************************************************\
375  *
376  * table_setDefaultInputTraits - Specifies default input image traits
377  *
378  *****************************************************************************
379  *
380  * The header of the file-type handled by the transform probably does
381  * not include *all* the image traits we'd like to know.  Those not
382  * specified in the file-header are filled in from info provided by
383  * this routine.
384  *
385  * Return value: IP_DONE=success; IP_FATAL_ERROR=misc error.
386  *
387 \*****************************************************************************/
388
389 static WORD table_setDefaultInputTraits (
390     IP_XFORM_HANDLE  hXform,     /* in: handle for xform */
391     PIP_IMAGE_TRAITS pTraits)    /* in: default image traits */
392 {
393     PTBL_INST g;
394
395     HANDLE_TO_PTR (hXform, g);
396
397     /* insure that traits we care about are known */
398     INSURE (pTraits->iPixelsPerRow>0 && pTraits->iBitsPerPixel>0);
399     g->traits = *pTraits;   /* a structure copy */
400     g->dwBytesPerRow = (g->traits.iPixelsPerRow*g->traits.iBitsPerPixel + 7) / 8;
401     return IP_DONE;
402
403     fatal_error:
404     return IP_FATAL_ERROR;
405 }
406
407
408
409 /*****************************************************************************\
410  *
411  * table_setXformSpec - Provides xform-specific information
412  *
413 \*****************************************************************************/
414
415 static WORD table_setXformSpec (
416     IP_XFORM_HANDLE hXform,         /* in: handle for xform */
417     DWORD_OR_PVOID  aXformInfo[])   /* in: xform information */
418 {
419     PTBL_INST g;
420
421     HANDLE_TO_PTR (hXform, g);
422
423     if (! generateTable(g,aXformInfo))
424         goto fatal_error;
425     return IP_DONE;
426
427     fatal_error:
428     return IP_FATAL_ERROR;
429 }
430
431
432
433 /*****************************************************************************\
434  *
435  * table_getHeaderBufSize- Returns size of input buf needed to hold header
436  *
437 \*****************************************************************************/
438
439 static WORD table_getHeaderBufSize (
440     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
441     DWORD           *pdwInBufLen)    /* out: buf size for parsing header */
442 {
443     /* since input is raw pixels, there is no header, so set it to zero */
444     *pdwInBufLen = 0;
445     return IP_DONE;
446 }
447
448
449
450 /*****************************************************************************\
451  *
452  * table_getActualTraits - Parses header, and returns input & output traits
453  *
454 \*****************************************************************************/
455
456 static WORD table_getActualTraits (
457     IP_XFORM_HANDLE  hXform,         /* in:  handle for xform */
458     DWORD            dwInputAvail,   /* in:  # avail bytes in input buf */
459     PBYTE            pbInputBuf,     /* in:  ptr to input buffer */
460     PDWORD           pdwInputUsed,   /* out: # bytes used from input buf */
461     PDWORD           pdwInputNextPos,/* out: file-pos to read from next */
462     PIP_IMAGE_TRAITS pIntraits,      /* out: input image traits */
463     PIP_IMAGE_TRAITS pOutTraits)     /* out: output image traits */
464 {
465     PTBL_INST g;
466
467     HANDLE_TO_PTR (hXform, g);
468
469     /* Since there is no header, we'll report no usage of input */
470     *pdwInputUsed    = 0;
471     *pdwInputNextPos = 0;
472
473     *pIntraits  = g->traits;   /* structure copies */
474     *pOutTraits = g->traits;
475
476     return IP_DONE | IP_READY_FOR_DATA;
477
478     fatal_error:
479     return IP_FATAL_ERROR;
480 }
481
482
483
484 /****************************************************************************\
485  *
486  * table_getActualBufSizes - Returns buf sizes needed for remainder of job
487  *
488 \****************************************************************************/
489
490 static WORD table_getActualBufSizes (
491     IP_XFORM_HANDLE hXform,          /* in:  handle for xform */
492     PDWORD          pdwMinInBufLen,  /* out: min input buf size */
493     PDWORD          pdwMinOutBufLen) /* out: min output buf size */
494 {
495     PTBL_INST g;
496
497     HANDLE_TO_PTR (hXform, g);
498
499     *pdwMinInBufLen = *pdwMinOutBufLen = g->dwBytesPerRow;
500     return IP_DONE;
501
502     fatal_error:
503     return IP_FATAL_ERROR;
504 }
505
506
507
508 /*****************************************************************************\
509  *
510  * table_convert - Converts one row
511  *
512 \*****************************************************************************/
513
514 static WORD table_convert (
515     IP_XFORM_HANDLE hXform,
516     DWORD           dwInputAvail,     /* in:  # avail bytes in in-buf */
517     PBYTE           pbInputBuf,       /* in:  ptr to in-buffer */
518     PDWORD          pdwInputUsed,     /* out: # bytes used from in-buf */
519     PDWORD          pdwInputNextPos,  /* out: file-pos to read from next */
520     DWORD           dwOutputAvail,    /* in:  # avail bytes in out-buf */
521     PBYTE           pbOutputBuf,      /* in:  ptr to out-buffer */
522     PDWORD          pdwOutputUsed,    /* out: # bytes written in out-buf */
523     PDWORD          pdwOutputThisPos) /* out: file-pos to write the data */
524 {
525     PTBL_INST g;
526     int       nBytes, nTable;
527     PBYTE     pIn, pOut, pOutAfter;
528
529     HANDLE_TO_PTR (hXform, g);
530
531     /**** Check if we were told to flush ****/
532
533     if (pbInputBuf == NULL) {
534         PRINT (_T("table_convert: Told to flush.\n"), 0, 0);
535         *pdwInputUsed = *pdwOutputUsed = 0;
536         *pdwInputNextPos  = g->dwInNextPos;
537         *pdwOutputThisPos = g->dwOutNextPos;
538         return IP_DONE;
539     }
540
541     /**** Output a Row ****/
542
543     nBytes = g->dwBytesPerRow;
544     INSURE (dwInputAvail  >= (DWORD)nBytes);
545     INSURE (dwOutputAvail >= (DWORD)nBytes);
546
547     pIn  = pbInputBuf;
548     pOut = pbOutputBuf;
549     pOutAfter = pOut + nBytes;
550
551     if (g->bWhich == IP_TABLE_PASS_THRU)
552     {
553         memcpy (pOut, pIn, nBytes);
554     }
555     else if (g->traits.iBitsPerPixel==16 || g->traits.iBitsPerPixel==48)
556     {
557         /* 16 bits per channel -- interpolate between table-entries */
558         int   x, xHi, y1, y2;
559         WORD *pwTable, *pwIn, *pwOut, *pwOutAfter;
560         BYTE *pbTable;
561
562         pwIn       = (WORD*)pIn;
563         pwOut      = (WORD*)pOut;
564         pwOutAfter = (WORD*)pOutAfter;
565
566         if (g->bBigTable)
567         {
568             /* we're using 12-bit table(s) */
569             while (pwOut < pwOutAfter) {
570                 for (nTable=0; nTable<g->nTables; nTable++) {
571                     pwTable = g->pwTables[nTable];
572                     x = (unsigned)(*pwIn++);
573                     xHi = x >> 4;  /* hi 12 bits is used for indexing into the table */
574                     y1 = (unsigned)pwTable[xHi  ];  /* index is in 0..4095 */
575                     y2 = (unsigned)pwTable[xHi+1];  /* extra entry in table is for index=4096 */
576                     /* interpolate the lowest 4 bits */
577                     *pwOut++ = (WORD)(((y2-y1)*(x&0x0f)>>4) + y1);
578                 }
579             }
580         }
581         else   /* we're using 8-bit table(s) */
582         {
583             while (pwOut < pwOutAfter) {
584                 for (nTable=0; nTable<g->nTables; nTable++) {
585                     pbTable = g->bTables[nTable];
586                     x = (unsigned)(*pwIn++);
587                     xHi = x >> 8;  /* hi 8 bits is used for indexing into the table */
588                     y1 = (unsigned)pbTable[xHi];  /* index is in 0..255 for both */
589                     y2 = (unsigned)pbTable[xHi==255 ? 255 : xHi+1];
590                     /* interpolate the lowest 8 bits */
591                     *pwOut++ = (WORD)((y2-y1)*(x&0x0ff) + (y1<<8));
592                 }
593             }
594         }
595     }
596     else   /* 8 bits per channel -- the normal case */
597     {
598         if (g->bBigTable)
599         {
600             /* using a big table for 8- or 24-bit data, for some reason */
601             while (pOut < pOutAfter)
602                 for (nTable=0; nTable<g->nTables; nTable++)
603                     *pOut++ = (BYTE)(g->pwTables[nTable][(unsigned)(*pIn++)<<4] >> 8);
604         }
605         else if (g->nTables == 3)
606         {
607             while (pOut < pOutAfter) {
608                 /* process two pixels at a time for improved speed */
609                 pOut[0] = g->bTables[0][pIn[0]];
610                 pOut[1] = g->bTables[1][pIn[1]];
611                 pOut[2] = g->bTables[2][pIn[2]];
612                 pOut[3] = g->bTables[0][pIn[3]];
613                 pOut[4] = g->bTables[1][pIn[4]];
614                 pOut[5] = g->bTables[2][pIn[5]];
615
616                 pIn  += 6;
617                 pOut += 6;
618             }
619         }
620         else   /* using a single table */
621         {
622             while (pOut < pOutAfter) {
623                 /* process eight pixels at a time for improved speed */
624                 pOut[0] = g->bTables[0][pIn[0]];
625                 pOut[1] = g->bTables[0][pIn[1]];
626                 pOut[2] = g->bTables[0][pIn[2]];
627                 pOut[3] = g->bTables[0][pIn[3]];
628                 pOut[4] = g->bTables[0][pIn[4]];
629                 pOut[5] = g->bTables[0][pIn[5]];
630                 pOut[6] = g->bTables[0][pIn[6]];
631                 pOut[7] = g->bTables[0][pIn[7]];
632
633                 pIn  += 8;
634                 pOut += 8;
635             }
636         }
637     }
638
639     *pdwInputUsed     = nBytes;
640     g->dwInNextPos   += nBytes;
641     *pdwInputNextPos  = g->dwInNextPos;
642
643     *pdwOutputUsed    = nBytes;
644     *pdwOutputThisPos = g->dwOutNextPos;
645     g->dwOutNextPos  += nBytes;
646
647     g->dwRowsDone += 1;
648
649     return IP_CONSUMED_ROW | IP_PRODUCED_ROW | IP_READY_FOR_DATA;
650
651     fatal_error:
652     return IP_FATAL_ERROR;
653 }
654
655
656
657 /*****************************************************************************\
658  *
659  * table_insertedData - client inserted into our output stream
660  *
661 \*****************************************************************************/
662
663 static WORD table_insertedData (
664     IP_XFORM_HANDLE hXform,
665     DWORD           dwNumBytes)
666 {
667     fatalBreakPoint ();
668     return IP_FATAL_ERROR;   /* must never be called (can't insert data) */
669 }
670
671
672
673 /*****************************************************************************\
674  *
675  * table_newPage - Tells us to flush this page, and start a new page
676  *
677 \*****************************************************************************/
678
679 static WORD table_newPage (
680     IP_XFORM_HANDLE hXform)
681 {
682     PTBL_INST g;
683
684     HANDLE_TO_PTR (hXform, g);
685     /* todo: return fatal error if convert is called again? */
686     return IP_DONE;   /* can't insert page-breaks, so ignore this call */
687
688     fatal_error:
689     return IP_FATAL_ERROR;
690
691 }
692
693
694
695 /*****************************************************************************\
696  *
697  * table_closeXform - Destroys this instance
698  *
699 \*****************************************************************************/
700
701 static WORD table_closeXform (IP_XFORM_HANDLE hXform)
702 {
703     PTBL_INST g;
704     int       i;
705
706     HANDLE_TO_PTR (hXform, g);
707
708     for (i=0; i<3; i++)
709         if (g->pwTables[i] != NULL)
710             IP_MEM_FREE (g->pwTables[i]);
711
712     g->dwValidChk = 0;
713     IP_MEM_FREE (g);       /* free memory for the instance */
714
715     return IP_DONE;
716
717     fatal_error:
718     return IP_FATAL_ERROR;
719 }
720
721
722
723 /*****************************************************************************\
724  *
725  * tableTbl - Jump-table for transform driver
726  *
727 \*****************************************************************************/
728
729 IP_XFORM_TBL tableTbl = {
730     table_openXform,
731     table_setDefaultInputTraits,
732     table_setXformSpec,
733     table_getHeaderBufSize,
734     table_getActualTraits,
735     table_getActualBufSizes,
736     table_convert,
737     table_newPage,
738     table_insertedData,
739     table_closeXform
740 };
741
742 /* End of File */