mirror of
https://github.com/love2d/love.git
synced 2026-08-12 16:40:57 +02:00
161 lines
3.8 KiB
C++
161 lines
3.8 KiB
C++
/**
|
|
* Copyright (c) 2006-2013 LOVE Development Team
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event will the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software
|
|
* in a product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
**/
|
|
|
|
// LOVE
|
|
#include "ImageRasterizer.h"
|
|
|
|
#include "common/Exception.h"
|
|
#include <string.h>
|
|
|
|
namespace love
|
|
{
|
|
namespace font
|
|
{
|
|
|
|
inline bool equal(const love::image::pixel &a, const love::image::pixel &b)
|
|
{
|
|
return (a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a);
|
|
}
|
|
|
|
ImageRasterizer::ImageRasterizer(love::image::ImageData *data, uint32 *glyphs, int numglyphs)
|
|
: imageData(data)
|
|
, glyphs(glyphs)
|
|
, numglyphs(numglyphs)
|
|
{
|
|
imageData->retain();
|
|
load();
|
|
}
|
|
|
|
ImageRasterizer::~ImageRasterizer()
|
|
{
|
|
imageData->release();
|
|
}
|
|
|
|
int ImageRasterizer::getLineHeight() const
|
|
{
|
|
return getHeight();
|
|
}
|
|
|
|
GlyphData *ImageRasterizer::getGlyphData(uint32 glyph) const
|
|
{
|
|
GlyphMetrics gm;
|
|
memset(&gm, 0, sizeof(GlyphMetrics));
|
|
|
|
// Set relevant glyph metrics if the glyph is in this ImageFont
|
|
std::map<uint32, ImageGlyphData>::const_iterator it = imageGlyphs.find(glyph);
|
|
if (it != imageGlyphs.end())
|
|
{
|
|
gm.width = it->second.width;
|
|
gm.advance = it->second.width + it->second.spacing;
|
|
}
|
|
|
|
gm.height = metrics.height;
|
|
|
|
GlyphData *g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA);
|
|
|
|
if (gm.width == 0)
|
|
return g;
|
|
|
|
love::image::pixel *gdpixels = (love::image::pixel *) g->getData();
|
|
love::image::pixel *imagepixels = (love::image::pixel *) imageData->getData();
|
|
|
|
// copy glyph pixels from imagedata to glyphdata
|
|
for (int i = 0; i < g->getWidth() * g->getHeight(); i++)
|
|
{
|
|
love::image::pixel p = imagepixels[ it->second.x + (i % gm.width) + (imageData->getWidth() * (i / gm.width)) ];
|
|
|
|
// Use transparency instead of the spacer color
|
|
if (equal(p, spacer))
|
|
gdpixels[i].r = gdpixels[i].g = gdpixels[i].b = gdpixels[i].a = 0;
|
|
else
|
|
gdpixels[i] = p;
|
|
}
|
|
|
|
return g;
|
|
}
|
|
|
|
void ImageRasterizer::load()
|
|
{
|
|
love::image::pixel *pixels = (love::image::pixel *) imageData->getData();
|
|
|
|
int imgw = imageData->getWidth();
|
|
int imgh = imageData->getHeight();
|
|
|
|
// Set the only metric that matters
|
|
metrics.height = imgh;
|
|
|
|
// Reading texture data begins
|
|
spacer = pixels[0];
|
|
|
|
int start = 0;
|
|
int end = 0;
|
|
|
|
for (int i = 0; i < numglyphs; ++i)
|
|
{
|
|
start = end;
|
|
|
|
// Finds out where the first character starts
|
|
while (start < imgw && equal(pixels[start], spacer))
|
|
++start;
|
|
|
|
// set previous glyph's spacing
|
|
if (i > 0 && imageGlyphs.size() > 0)
|
|
imageGlyphs[glyphs[i - 1]].spacing = (start > end) ? (start - end) : 0;
|
|
|
|
end = start;
|
|
|
|
// Find where glyph ends.
|
|
while (end < imgw && !equal(pixels[end], spacer))
|
|
++end;
|
|
|
|
if (start >= end)
|
|
break;
|
|
|
|
ImageGlyphData imageGlyph;
|
|
imageGlyph.x = start;
|
|
imageGlyph.width = end - start;
|
|
|
|
imageGlyphs[glyphs[i]] = imageGlyph;
|
|
}
|
|
|
|
// Find spacing of last glyph
|
|
if (numglyphs > 0)
|
|
{
|
|
start = end;
|
|
while (start < imgw && equal(pixels[start], spacer))
|
|
++start;
|
|
|
|
imageGlyphs[glyphs[numglyphs - 1]].spacing = (start > end) ? (start - end) : 0;
|
|
}
|
|
}
|
|
|
|
int ImageRasterizer::getGlyphCount() const
|
|
{
|
|
return numglyphs;
|
|
}
|
|
|
|
bool ImageRasterizer::hasGlyph(uint32 glyph) const
|
|
{
|
|
return imageGlyphs.find(glyph) != imageGlyphs.end();
|
|
}
|
|
|
|
} // font
|
|
} // love
|