You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
422 lines
8.5 KiB
422 lines
8.5 KiB
/*==============================================================================
|
|
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;
|
|
}
|
|
}
|
|
|
|
|