2019-10-23 23:20:58 +00:00
|
|
|
/*
|
|
|
|
** fontchars.cpp
|
|
|
|
** Texture class for font characters
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2004-2006 Randy Heit
|
|
|
|
** Copyright 2006-2018 Christoph Oelckers
|
|
|
|
** All rights reserved.
|
|
|
|
**
|
|
|
|
** Redistribution and use in source and binary forms, with or without
|
|
|
|
** modification, are permitted provided that the following conditions
|
|
|
|
** are met:
|
|
|
|
**
|
|
|
|
** 1. Redistributions of source code must retain the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer.
|
|
|
|
** 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
** notice, this list of conditions and the following disclaimer in the
|
|
|
|
** documentation and/or other materials provided with the distribution.
|
|
|
|
** 3. The name of the author may not be used to endorse or promote products
|
|
|
|
** derived from this software without specific prior written permission.
|
|
|
|
**
|
|
|
|
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2020-04-11 21:54:33 +00:00
|
|
|
#include "filesystem.h"
|
2019-10-23 23:20:58 +00:00
|
|
|
#include "bitmap.h"
|
|
|
|
#include "image.h"
|
|
|
|
#include "imagehelpers.h"
|
|
|
|
#include "fontchars.h"
|
|
|
|
#include "printf.h"
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FFontChar1 :: FFontChar1
|
|
|
|
//
|
|
|
|
// Used by fonts made from textures.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
FFontChar1::FFontChar1 (FTexture *sourcelump)
|
|
|
|
: BaseTexture(sourcelump), SourceRemap (nullptr)
|
|
|
|
{
|
|
|
|
// now copy all the properties from the base texture
|
|
|
|
assert(BaseTexture != nullptr);
|
|
|
|
CopySize(BaseTexture);
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FFontChar1 :: GetPixels
|
|
|
|
//
|
|
|
|
// Render style is not relevant for fonts. This must not use it!
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FFontChar1::Create8BitPixels (uint8_t *data)
|
|
|
|
{
|
|
|
|
// Make the texture as normal, then remap it so that all the colors
|
|
|
|
// are at the low end of the palette
|
|
|
|
// Why? It only creates unnecessary work!
|
|
|
|
BaseTexture->Create8BitPixels(data);
|
|
|
|
|
|
|
|
if (SourceRemap)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < GetWidth() * GetHeight(); ++x)
|
|
|
|
{
|
|
|
|
data[x] = SourceRemap[data[x]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FFontChar2 :: FFontChar2
|
|
|
|
//
|
|
|
|
// Used by FON1 and FON2 fonts.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2019-12-03 19:32:35 +00:00
|
|
|
FFontChar2::FFontChar2 (TArray<uint8_t>& sourcelump, int sourcepos, int width, int height, int leftofs, int topofs)
|
|
|
|
: sourceData (sourcelump), SourcePos (sourcepos), SourceRemap(nullptr)
|
2019-10-23 23:20:58 +00:00
|
|
|
{
|
|
|
|
Size.x = width;
|
|
|
|
Size.y = height;
|
|
|
|
PicAnim.xofs = leftofs;
|
|
|
|
PicAnim.yofs = topofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FFontChar2 :: SetSourceRemap
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FFontChar2::SetSourceRemap(const uint8_t *sourceremap)
|
|
|
|
{
|
|
|
|
SourceRemap = sourceremap;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// FFontChar2 :: Get8BitPixels
|
|
|
|
//
|
|
|
|
// Like for FontChar1, the render style has no relevance here as well.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FFontChar2::Create8BitPixels(uint8_t *Pixels)
|
|
|
|
{
|
2019-12-03 19:32:35 +00:00
|
|
|
FileReader lump;
|
|
|
|
lump.OpenMemory(sourceData.Data(), sourceData.Size());
|
2019-10-23 23:20:58 +00:00
|
|
|
int destSize = GetWidth() * GetHeight();
|
|
|
|
uint8_t max = 255;
|
|
|
|
bool rle = true;
|
|
|
|
|
|
|
|
// This is to "fix" bad fonts
|
|
|
|
{
|
|
|
|
uint8_t buff[16];
|
|
|
|
lump.Read (buff, 4);
|
|
|
|
if (buff[3] == '2')
|
|
|
|
{
|
|
|
|
lump.Read (buff, 7);
|
|
|
|
max = buff[6];
|
|
|
|
lump.Seek (SourcePos - 11, FileReader::SeekCur);
|
|
|
|
}
|
|
|
|
else if (buff[3] == 0x1A)
|
|
|
|
{
|
|
|
|
lump.Read(buff, 13);
|
|
|
|
max = buff[12] - 1;
|
|
|
|
lump.Seek (SourcePos - 17, FileReader::SeekCur);
|
|
|
|
rle = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lump.Seek (SourcePos - 4, FileReader::SeekCur);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int runlen = 0, setlen = 0;
|
|
|
|
uint8_t setval = 0; // Shut up, GCC!
|
|
|
|
uint8_t *dest_p = Pixels;
|
|
|
|
int dest_adv = GetHeight();
|
|
|
|
int dest_rew = destSize - 1;
|
|
|
|
|
|
|
|
if (rle)
|
|
|
|
{
|
|
|
|
for (int y = GetHeight(); y != 0; --y)
|
|
|
|
{
|
|
|
|
for (int x = GetWidth(); x != 0; )
|
|
|
|
{
|
|
|
|
if (runlen != 0)
|
|
|
|
{
|
|
|
|
uint8_t color = lump.ReadUInt8();
|
|
|
|
color = std::min(color, max);
|
|
|
|
if (SourceRemap != nullptr)
|
|
|
|
{
|
|
|
|
color = SourceRemap[color];
|
|
|
|
}
|
|
|
|
*dest_p = color;
|
|
|
|
dest_p += dest_adv;
|
|
|
|
x--;
|
|
|
|
runlen--;
|
|
|
|
}
|
|
|
|
else if (setlen != 0)
|
|
|
|
{
|
|
|
|
*dest_p = setval;
|
|
|
|
dest_p += dest_adv;
|
|
|
|
x--;
|
|
|
|
setlen--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int8_t code = lump.ReadInt8();
|
|
|
|
if (code >= 0)
|
|
|
|
{
|
|
|
|
runlen = code + 1;
|
|
|
|
}
|
|
|
|
else if (code != -128)
|
|
|
|
{
|
|
|
|
uint8_t color = lump.ReadUInt8();
|
|
|
|
setlen = (-code) + 1;
|
|
|
|
setval = std::min(color, max);
|
|
|
|
if (SourceRemap != nullptr)
|
|
|
|
{
|
|
|
|
setval = SourceRemap[setval];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dest_p -= dest_rew;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int y = GetHeight(); y != 0; --y)
|
|
|
|
{
|
2020-01-07 00:11:19 +00:00
|
|
|
for (int x = GetWidth(); x != 0; --x)
|
2019-10-23 23:20:58 +00:00
|
|
|
{
|
|
|
|
uint8_t color = lump.ReadUInt8();
|
|
|
|
if (color > max)
|
|
|
|
{
|
|
|
|
color = max;
|
|
|
|
}
|
|
|
|
if (SourceRemap != nullptr)
|
|
|
|
{
|
|
|
|
color = SourceRemap[color];
|
|
|
|
}
|
|
|
|
*dest_p = color;
|
|
|
|
dest_p += dest_adv;
|
|
|
|
}
|
|
|
|
dest_p -= dest_rew;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (destSize < 0)
|
|
|
|
{
|
2019-12-03 19:32:35 +00:00
|
|
|
I_Error ("The font %s is corrupt", GetName().GetChars());
|
2019-10-23 23:20:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-03 19:32:35 +00:00
|
|
|
FBitmap FFontChar2::GetBgraBitmap(const PalEntry* remap, int* ptrans)
|
|
|
|
{
|
|
|
|
FBitmap bmp;
|
|
|
|
TArray<uint8_t> buffer;
|
|
|
|
bmp.Create(Size.x, Size.y);
|
|
|
|
const uint8_t* ppix = Get8BitPixels();
|
|
|
|
if (!ppix)
|
|
|
|
{
|
|
|
|
// This is needed for tiles with a palette remap.
|
|
|
|
buffer.Resize(Size.x * Size.y);
|
|
|
|
Create8BitPixels(buffer.Data());
|
|
|
|
ppix = buffer.Data();
|
|
|
|
}
|
|
|
|
if (ppix) bmp.CopyPixelData(0, 0, ppix, Size.x, Size.y, Size.y, 1, 0, remap);
|
|
|
|
return bmp;
|
|
|
|
}
|