|
|
/*==============================================================================
This source file contains routines for chaingon decompression of glyphs.
29-Dec-93 RajeevD Integrated into unified resource executor. ==============================================================================*/ #include <ifaxos.h>
#include <memory.h>
#include "resexec.h"
#include "constant.h"
#include "jtypes.h" // type definition used in cartridge
#include "jres.h" // cartridge resource data type definition
#include "hretype.h" // define data structure used by hre.c and rpgen.c
#define CEIL32(val) (((val) + 31) & ~31)
#define RUN_FLAG ((short) 0x8000)
// Bit Stream Object
typedef class FAR BITIO { private: UINT uBit; public: LPBYTE lpb;
BITIO (LPBYTE lpbInit) {lpb = lpbInit, uBit = 0;} BITIO () {uBit = 0;}
short Read2 (void); short Read4 (void); short Read6 (void); short Read8 (void); WORD Read8U (void); short Read16 (void); WORD ReadU (void);
short DecodeDelta (void); } FAR *LPBITIO;
//==============================================================================
short BITIO::Read2 (void) { short s;
// Mask and shift 2-bit field.
s = (*lpb >> (6 - uBit)) & 0x03;
// Advance stream pointer.
uBit += 2; if (uBit == 8) {lpb++; uBit = 0;}
#ifndef BITIO_NOSIGNEXT
if (s >= 2) s -= 4; // Sign extend into short.
#endif
return s; }
//========================================================================
short BITIO::Read4 (void) { LPBYTE lpbVal; short s; if (uBit == 6) { lpbVal = (LPBYTE) &s; lpbVal[1] = *lpb++; lpbVal[0] = *lpb; s >>= 6; s &= 0x000F; uBit = 2; }
else { s = (*lpb >> (4 - uBit)) & 0x0F; uBit += 4; if (uBit == 8) { lpb++; uBit = 0; } }
#ifndef BITIO_NOSIGNEXT
if (s >= 8) s -= 16; // Sign extend into short.
#endif
return s; }
//========================================================================
short BITIO::Read6 (void) { LPBYTE lpbVal; short s; switch (uBit/2) { case 0: s = (short) (*lpb >> 2); uBit = 6; break; case 1: s = (short) *lpb++; uBit = 0; break; case 2: lpbVal = (LPBYTE) &s; lpbVal[1] = *lpb++; lpbVal[0] = *lpb; s >>= 6; uBit = 2; break; case 3: lpbVal = (BYTE *) &s; lpbVal[1] = *lpb++; lpbVal[0] = *lpb; s >>= 4; uBit = 4; break; }
s &= 0x003F; #ifndef BITIO_NOSIGNEXT
if (s >= 32) s -= 64; // Sign extend into short.
#endif
return s; }
//========================================================================
short BITIO::Read8 (void) { short s; LPBYTE lpbVal;
if (uBit == 0) s = (short) *lpb++;
else { lpbVal = (LPBYTE) &s; lpbVal[1] = *lpb++; lpbVal[0] = *lpb; s >>= (8 - uBit); s &= 0x00FF; }
#ifndef BITIO_NOSIGNEXT
if (s >= 128) s -= 256; // Sign extend into short.
#endif
return s; }
//========================================================================
WORD BITIO::Read8U (void) { short s; LPBYTE lpbVal;
if (uBit == 0) s = (short) *lpb++;
else { lpbVal = (LPBYTE) &s; lpbVal[1] = *lpb++; lpbVal[0] = *lpb; s >>= (8 - uBit); s &= 0x00FF; }
return s; }
//========================================================================
short BITIO::Read16 (void) { short s; LPBYTE lpbVal = (LPBYTE) &s;
lpbVal[1] = *lpb++; lpbVal[0] = *lpb++;
switch (uBit/2) { case 0: break; case 1: s <<= 2; s |= (*lpb >> 6) & 0x03; break; case 2: s <<= 4; s |= (*lpb >> 4) & 0x0F; break; case 3: s <<= 6; s |= (*lpb >> 2) & 0x3F; break; }
return s; }
//==============================================================================
WORD BITIO::ReadU (void) { WORD w = Read8U(); if (w == 0xFF) w = Read16(); return w; }
/*==============================================================================
This utility procedure uses an OR operation to fill runs in a scan buffer. ==============================================================================*/ LPBYTE FillRun // Returns next scan line
( LPBYTE lpbLine, // first output scan line
UINT cbLine, // width of a scan line
UINT xLeft, // left column, inclusive
UINT xRight, // right column, exclusive
UINT cLines = 1 // number of scan lines
) { const static WORD wFill[16] = { 0xFFFF, 0xFF7F, 0xFF3F, 0xFF1F, 0xFF0F, 0xFF07, 0xFF03, 0xFF01, 0xFF00, 0x7F00, 0x3F00, 0x1F00, 0x0F00, 0x0700, 0x0300, 0x0100, };
UINT iwLeft, iwRight; WORD wLeft, wRight; // masks
LPWORD lpwLine = (LPWORD) lpbLine; UINT cwLine = cbLine / 2;
iwLeft = xLeft / 16; iwRight = xRight / 16; wLeft = wFill [xLeft & 15]; wRight = ~wFill [xRight & 15]; if (iwLeft == iwRight) { while (cLines--) { // Run is within a single WORD.
lpwLine[iwLeft] |= wLeft & wRight; lpwLine += cwLine; } } else { UINT cbMiddle = 2 * (iwRight - iwLeft - 1);
while (cLines--) { // Run spans more than one WORD.
lpwLine[iwLeft] |= wLeft; _fmemset (lpwLine + iwLeft + 1, 0xFF, cbMiddle); if (wRight) // Don't access beyond output!
lpwLine[iwRight] |= wRight; lpwLine += cwLine; } }
return (LPBYTE) lpwLine; }
//==============================================================================
UINT // unpacked size
UnpackGlyph ( LPBYTE lpbIn, // packed glyph
LPBYTE lpbOut // output buffer
) { BITIO bitio (lpbIn); // input bit stream
LPWORD lpwOut; // alias for lpbOut
WORD xExt, yExt; // glyph dimensions
UINT cbLine; // scan line width
// Decode glyph header.
xExt = bitio.ReadU(); yExt = bitio.ReadU(); cbLine = CEIL32(xExt) / 8; // Write glyph dimensions.
lpwOut = (LPWORD) lpbOut; *lpwOut++ = yExt; *lpwOut++ = xExt; lpbOut = (LPBYTE) lpwOut;
// Clear output buffer.
_fmemset (lpbOut, 0x00, cbLine * yExt);
// Unpack each chain.
while (1) { LPBYTE lpbScan; // output buffer
UINT yTop; // top of chaingon
UINT xLeft, xRight; // left and right bound
short dxLeft, dxRight; // left and right delta
UINT cLine, cRun; // line counters
// Decode chain header.
xRight = bitio.ReadU(); if (!xRight) // termination
goto done; cLine = bitio.ReadU(); xLeft = bitio.ReadU(); yTop = bitio.ReadU(); lpbScan = lpbOut + yTop * cbLine; xRight += xLeft; // Fill first row.
lpbScan = FillRun (lpbScan, cbLine, xLeft, xRight); cLine--;
// Fill remaining rows.
while (cLine) { dxLeft = bitio.DecodeDelta ();
if (dxLeft == RUN_FLAG) { // Decode run of repeated lines.
cRun = (bitio.Read4() & 0xF) + 3; lpbScan = FillRun (lpbScan, cbLine, xLeft, xRight, cRun); cLine -= cRun; } else { // Adjust by deltas.
dxRight = bitio.DecodeDelta(); xLeft += dxLeft; xRight += dxRight; lpbScan = FillRun (lpbScan, cbLine, xLeft, xRight); cLine--; }
} // while (cLine--)
} // while (1)
done: return 2 * sizeof(WORD) + yExt * cbLine; } //==============================================================================
void WINAPI UnpackGlyphSet (LPVOID lpIn, LPVOID lpOut) { LPJG_GS_HDR lpSetIn = (LPJG_GS_HDR) lpIn; LPJG_GS_HDR lpSetOut = (LPJG_GS_HDR) lpOut; LPBYTE lpbOut; WORD iGlyph;
// Copy header.
_fmemcpy (lpSetOut, lpSetIn, sizeof(JG_RES_HDR) + sizeof(WORD));
// Create pointer to end of offset tables.
lpbOut = ((LPBYTE) lpSetOut) + lpSetIn->ausOffset[0];
// Unpack the glyphs.
for (iGlyph=0; iGlyph<lpSetIn->usGlyphs; iGlyph++) { lpSetOut->ausOffset[iGlyph] = (USHORT)(lpbOut - (LPBYTE) lpSetOut); lpbOut += UnpackGlyph ((LPBYTE) lpSetIn + lpSetIn->ausOffset[iGlyph], lpbOut); } }
//==============================================================================
short // Returns delta (or RUN_FLAG)
BITIO::DecodeDelta (void) { short s;
s = Read2(); if (s != -2) // Trap -1, 0, +1.
return s;
s = Read4(); // Get 4-bit prefix.
switch (s) { case 0: // run of zeros
return RUN_FLAG;
case 1: // 6-bit literal
s = Read6(); return (s >= 0? s + 8 : s - 7);
case -1: // 8-bit literal
s = Read8(); return (s >= 0? s + 40 : s - 39);
case -8: // 16-bit literal
return Read16();
default: // 4-bit literal
return s; } }
|