1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-10 10:16:00 +02:00

FontEffect support - outlined fonts

This commit is contained in:
Brian Fiete 2025-01-26 07:04:26 -08:00
parent 474bad09b2
commit 89bf475045
10 changed files with 385 additions and 8 deletions

View file

@ -10,6 +10,7 @@
#include "util/Vector.h"
#include "util/PerfTimer.h"
#include "util/TLSingleton.h"
#include "img/ImgEffects.h"
#include "util/AllocDebug.h"
@ -474,12 +475,12 @@ BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_LoadTexture(const char* fileName, int
BF_EXPORT void BF_CALLTYPE Gfx_Texture_SetBits(TextureSegment* textureSegment, int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{
textureSegment->mTexture->SetBits(destX, destY, destWidth, destHeight, srcPitch, bits);
textureSegment->SetBits(destX, destY, destWidth, destHeight, srcPitch, bits);
}
BF_EXPORT void BF_CALLTYPE Gfx_Texture_GetBits(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits)
{
textureSegment->mTexture->GetBits(srcX, srcY, srcWidth, srcHeight, destPitch, bits);
textureSegment->GetBits(srcX, srcY, srcWidth, srcHeight, destPitch, bits);
}
BF_EXPORT void BF_CALLTYPE Gfx_Texture_Delete(TextureSegment* textureSegment)
@ -516,6 +517,93 @@ BF_EXPORT void BF_CALLTYPE Gfx_ModifyTextureSegment(TextureSegment* destTextureS
destTextureSegment->mScaleY = (float)abs(srcHeight);
}
int32 FormatI32(const StringView& str)
{
String val = String(str);
if (val.StartsWith('#'))
{
return (int32)strtoll(val.c_str() + 1, NULL, 16);
}
if (val.StartsWith("0x"))
{
return (int32)strtoll(val.c_str() + 2, NULL, 16);
}
return atoi(val.c_str());
}
BF_EXPORT void BF_CALLTYPE Gfx_ApplyEffect(TextureSegment* destTextureSegment, TextureSegment* srcTextureSegment, char* optionsPtr)
{
BaseImageEffect* effect = NULL;
defer({
delete effect;
});
bool needsPremultiply = false;
String options = optionsPtr;
for (auto line : options.Split('\n'))
{
int eqPos = (int)line.IndexOf('=');
if (eqPos != -1)
{
StringView cmd = StringView(line, 0, eqPos);
StringView value = StringView(line, eqPos + 1);
if (cmd == "Effect")
{
if (value == "Stroke")
{
auto strokeEffect = new ImageStrokeEffect();
effect = strokeEffect;
strokeEffect->mPosition = 'OutF';
strokeEffect->mSize = 1;
strokeEffect->mColorFill.mColor = 0xFF000000;
}
}
if (cmd == "Size")
{
int32 size = FormatI32(value);
if (auto strokeEffect = dynamic_cast<ImageStrokeEffect*>(effect))
{
strokeEffect->mSize = size;
}
}
if (cmd == "Color")
{
uint32 color = (uint32)FormatI32(value);
if (auto strokeEffect = dynamic_cast<ImageStrokeEffect*>(effect))
{
strokeEffect->mColorFill.mColor = color;
if ((color & 0x00FFFFFF) != 0)
needsPremultiply = true;
}
}
}
}
if (effect != NULL)
{
ImageData destImageData;
ImageData srcImageData;
Rect srcRect = srcTextureSegment->GetRect();
Rect destRect = destTextureSegment->GetRect();
destTextureSegment->GetImageData(destImageData);
srcImageData.CreateNew(destImageData.mWidth, destImageData.mHeight);
srcTextureSegment->GetImageData(srcImageData,
(int)(destRect.mWidth - srcRect.mWidth) / 2,
(int)(destRect.mHeight - srcRect.mHeight) / 2);
effect->Apply(NULL, &srcImageData, &destImageData);
if (needsPremultiply)
destImageData.PremultiplyAlpha();
destTextureSegment->SetImageData(destImageData);
}
}
BF_EXPORT TextureSegment* BF_CALLTYPE Gfx_CreateTextureSegment(TextureSegment* textureSegment, int srcX, int srcY, int srcWidth, int srcHeight)
{
Texture* texture = textureSegment->mTexture;

View file

@ -1,6 +1,7 @@
#include "Texture.h"
#include "util/AllocDebug.h"
#include "img/ImageData.h"
USING_NS_BF;
@ -31,3 +32,50 @@ void TextureSegment::InitFromTexture(Texture* texture)
mScaleX = (float) mTexture->mWidth;
mScaleY = (float) mTexture->mHeight;
}
void TextureSegment::SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits)
{
int x1 = (int)(mU1 * mTexture->mWidth + 0.5f);
int y1 = (int)(mV1 * mTexture->mHeight + 0.5f);
mTexture->SetBits(destX + x1, destY + y1, destWidth, destHeight, srcPitch, bits);
}
void TextureSegment::GetBits(int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits)
{
int x1 = (int)(mU1 * mTexture->mWidth + 0.5f);
int y1 = (int)(mV1 * mTexture->mHeight + 0.5f);
mTexture->GetBits(srcX + x1, srcY + y1, srcWidth, srcHeight, destPitch, bits);
}
void TextureSegment::GetImageData(ImageData& imageData)
{
int x1 = (int)(mU1 * mTexture->mWidth + 0.5f);
int x2 = (int)(mU2 * mTexture->mWidth + 0.5f);
int y1 = (int)(mV1 * mTexture->mHeight + 0.5f);
int y2 = (int)(mV2 * mTexture->mHeight + 0.5f);
imageData.CreateNew(x2 - x1, y2 - y1);
mTexture->GetBits(x1, y1, x2 - x1, y2 - y1, x2 - x1, imageData.mBits);
}
void TextureSegment::GetImageData(ImageData& imageData, int destX, int destY)
{
int x1 = (int)(mU1 * mTexture->mWidth + 0.5f);
int x2 = (int)(mU2 * mTexture->mWidth + 0.5f);
int y1 = (int)(mV1 * mTexture->mHeight + 0.5f);
int y2 = (int)(mV2 * mTexture->mHeight + 0.5f);
mTexture->GetBits(x1, y1, x2 - x1, y2 - y1, imageData.mWidth, imageData.mBits + destX + destY * imageData.mWidth);
}
void TextureSegment::SetImageData(ImageData& imageData)
{
SetBits(0, 0, imageData.mWidth, imageData.mHeight, imageData.mStride, imageData.mBits);
}
Rect TextureSegment::GetRect()
{
float x1 = mU1 * mTexture->mWidth;
float x2 = mU2 * mTexture->mWidth;
float y1 = mV1 * mTexture->mHeight;
float y2 = mV2 * mTexture->mHeight;
return Rect(x1, y1, x2 - x1, y2 - y1);
}

View file

@ -2,6 +2,7 @@
#include "Common.h"
#include "RenderTarget.h"
#include "../util/Rect.h"
NS_BF_BEGIN;
@ -38,6 +39,15 @@ public:
public:
void InitFromTexture(Texture* texture);
virtual void SetBits(int destX, int destY, int destWidth, int destHeight, int srcPitch, uint32* bits);
virtual void GetBits(int srcX, int srcY, int srcWidth, int srcHeight, int destPitch, uint32* bits);
void GetImageData(ImageData& imageData);
void GetImageData(ImageData& imageData, int destX, int destY);
void SetImageData(ImageData& imageData);
Rect GetRect();
};
NS_BF_END;

View file

@ -16,6 +16,7 @@ ImageData::ImageData()
mY = 0;
mWidth = 0;
mHeight = 0;
mStride = 0;
mWantsAlphaPremultiplied = true;
mAlphaPremultiplied = false;
mIsAdditive = false;
@ -67,7 +68,7 @@ void ImageData::CreateNew(int x, int y, int width, int height, bool clear)
void ImageData::CreateNew(int width, int height, bool clear)
{
mWidth = width;
mWidth = mStride = width;
mHeight = height;
mBits = new uint32[mWidth*mHeight];
if (clear)
@ -89,7 +90,7 @@ void ImageData::CopyFrom(ImageData* img, int x, int y)
{
for (int x = destStartX; x < destEndX; x++)
{
mBits[x + y * mWidth] = img->mBits[(x + srcXOfs) + (y + srcYOfs)*img->mWidth];
mBits[x + y * mStride] = img->mBits[(x + srcXOfs) + (y + srcYOfs)*img->mStride];
}
}
}

View file

@ -20,6 +20,7 @@ public:
int mY;
int mWidth;
int mHeight;
int mStride;
void* mHWBits;
int mHWBitsLength;
int mHWBitsType;

View file

@ -241,6 +241,7 @@ ImageData* ImageEffects::GetDestImage(ImageData* usingImage)
return mSwapImages[1];
ImageData* anImage = new ImageData();
anImage->mStride = usingImage->mStride;
anImage->mWidth = usingImage->mWidth;
anImage->mHeight = usingImage->mHeight;
anImage->mBits = new uint32[anImage->mWidth*anImage->mHeight];

View file

@ -21,6 +21,14 @@ public:
mHeight = 0;
}
Rect(float x, float y, float width, float height)
{
mX = x;
mY = y;
mWidth = width;
mHeight = height;
}
bool operator!=(const Rect& r2)
{
return (mX != r2.mX) || (mY != r2.mY) || (mWidth != r2.mWidth) || (mHeight != r2.mHeight);