整理代码
This commit is contained in:
commit
c7b4e178ec
364 changed files with 59691 additions and 0 deletions
279
video/core/Image.cpp
Normal file
279
video/core/Image.cpp
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* INCLUDE
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "Image.h"
|
||||
#include "Logger.h"
|
||||
#include "util/Math.h"
|
||||
#include <freetype/ftglyph.h>
|
||||
#include <freetype/fterrors.h>
|
||||
#include <Poco/Exception.h>
|
||||
#include <Poco/Format.h>
|
||||
#include <Poco/UnicodeConverter.h>
|
||||
|
||||
namespace Video
|
||||
{
|
||||
namespace Core
|
||||
{
|
||||
/*
|
||||
*******************************************************************************
|
||||
* CLASS DECLARE
|
||||
*******************************************************************************
|
||||
*/
|
||||
void Image::drawText(const std::string& text, const std::string& font, int size, Color foreColor, Color bgColor)
|
||||
{
|
||||
get_shared_channel(0).fill(bgColor.r);
|
||||
get_shared_channel(1).fill(bgColor.g);
|
||||
get_shared_channel(2).fill(bgColor.b);
|
||||
get_shared_channel(3).fill(bgColor.a);
|
||||
|
||||
int x = 0, y = 0;
|
||||
|
||||
y = height() - y;
|
||||
|
||||
std::wstring wtext;
|
||||
convertText(text, wtext);
|
||||
runOnFreeType(font, size,
|
||||
[&](FT_Face& face) -> void
|
||||
{
|
||||
FT_BBox bbox;
|
||||
|
||||
computeStringBBox(wtext, face, bbox);
|
||||
|
||||
FT_Vector pen;
|
||||
pen.x = (x - bbox.xMin) * 64;
|
||||
pen.y = (y - bbox.yMax) * 64;
|
||||
|
||||
for (size_t i = 0; i < wtext.length(); i++)
|
||||
{
|
||||
FT_Set_Transform(face, 0, &pen);
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(face, wtext.at(i));
|
||||
int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
|
||||
if (error)
|
||||
{
|
||||
throw Poco::InvalidAccessException("字形加载失败", error);
|
||||
}
|
||||
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (error)
|
||||
{
|
||||
throw Poco::InvalidAccessException("字形渲染失败", error);
|
||||
}
|
||||
|
||||
int offsetX = face->glyph->bitmap_left;
|
||||
int offsetY = height() - face->glyph->bitmap_top;
|
||||
for (size_t y = 0; y < face->glyph->bitmap.rows; y++)
|
||||
{
|
||||
for (size_t x = 0; x < face->glyph->bitmap.width; x++)
|
||||
{
|
||||
uint8_t c = face->glyph->bitmap.buffer[y * face->glyph->bitmap.width + x];
|
||||
if (c < 50)
|
||||
continue;
|
||||
|
||||
(*this)(x + offsetX, y + offsetY, 0) = foreColor.r * c / 255;
|
||||
(*this)(x + offsetX, y + offsetY, 1) = foreColor.g * c / 255;
|
||||
(*this)(x + offsetX, y + offsetY, 2) = foreColor.b * c / 255;
|
||||
(*this)(x + offsetX, y + offsetY, 3) = foreColor.a * c / 255;
|
||||
}
|
||||
}
|
||||
|
||||
pen.x += face->glyph->advance.x;
|
||||
pen.y += face->glyph->advance.y;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Image::drawRectangle(const Rect& rect, Color& color, int border)
|
||||
{
|
||||
if (border <= 0)
|
||||
{
|
||||
get_shared_channel(0).fill(color.r);
|
||||
get_shared_channel(1).fill(color.g);
|
||||
get_shared_channel(2).fill(color.b);
|
||||
get_shared_channel(3).fill(color.a);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_shared_channel(3).fill(0);
|
||||
|
||||
uint8_t c[4] = {color.r, color.g, color.b, color.a};
|
||||
|
||||
draw_rectangle(rect.x, rect.y, rect.x + rect.width, rect.y + border, c);
|
||||
draw_rectangle(rect.x, rect.y + border, rect.x + border, rect.y + rect.height, c);
|
||||
draw_rectangle(rect.x + rect.width - border, rect.y + border, rect.x + rect.width, rect.y + rect.height, c);
|
||||
draw_rectangle(rect.x + border, rect.y + rect.height - border, rect.x + rect.width - border,
|
||||
rect.y + rect.height, c);
|
||||
}
|
||||
}
|
||||
|
||||
void Image::drawImage(int x, int y, Ptr pImage)
|
||||
{
|
||||
const int width = pImage->width();
|
||||
const int height = pImage->height();
|
||||
|
||||
for (int sy = 0; sy < height; ++sy)
|
||||
{
|
||||
for (int sx = 0; sx < width; ++sx)
|
||||
{
|
||||
const int dx = x + sx;
|
||||
const int dy = y + sy;
|
||||
|
||||
if (dx >= 0 && dx < this->width() && dy >= 0 && dy < this->height())
|
||||
{
|
||||
Color color;
|
||||
pImage->getPixel(sx, sy, color);
|
||||
|
||||
(*this)(dx, dy, 0, 0) = color.r;
|
||||
(*this)(dx, dy, 0, 1) = color.g;
|
||||
(*this)(dx, dy, 0, 2) = color.b;
|
||||
(*this)(dx, dy, 0, 3) = color.a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Image::getPixel(int x, int y, Color& color)
|
||||
{
|
||||
uint8_t originAlpha = 0xff;
|
||||
|
||||
if (spectrum() == 1)
|
||||
{
|
||||
color.r = (*this)(x, y, 0, 0);
|
||||
color.g = color.r;
|
||||
color.b = color.r;
|
||||
}
|
||||
else if (spectrum() == 2)
|
||||
{
|
||||
color.r = (*this)(x, y, 0, 0);
|
||||
color.g = (*this)(x, y, 0, 1);
|
||||
color.b = 0;
|
||||
}
|
||||
|
||||
else if (spectrum() == 3)
|
||||
{
|
||||
color.r = (*this)(x, y, 0, 0);
|
||||
color.g = (*this)(x, y, 0, 1);
|
||||
color.b = (*this)(x, y, 0, 2);
|
||||
}
|
||||
else if (spectrum() == 4)
|
||||
{
|
||||
color.r = (*this)(x, y, 0, 0);
|
||||
color.g = (*this)(x, y, 0, 1);
|
||||
color.b = (*this)(x, y, 0, 2);
|
||||
originAlpha = (*this)(x, y, 0, 3);
|
||||
}
|
||||
|
||||
if (_forceAlphaEnabled && originAlpha > _forceAlphaValue)
|
||||
color.a = _forceAlphaValue;
|
||||
else
|
||||
color.a = originAlpha;
|
||||
}
|
||||
|
||||
void Image::forceAlpha(uint8_t alpha)
|
||||
{
|
||||
_forceAlphaEnabled = true;
|
||||
_forceAlphaValue = alpha;
|
||||
}
|
||||
|
||||
void Image::computeStringSize(const std::string& text, const std::string& font, int fontsz, Size& size)
|
||||
{
|
||||
runOnFreeType(font, fontsz,
|
||||
[&](FT_Face& face) -> void
|
||||
{
|
||||
FT_BBox bbox;
|
||||
std::wstring wstr;
|
||||
convertText(text, wstr);
|
||||
|
||||
computeStringBBox(wstr, face, bbox);
|
||||
size.width = bbox.xMax - bbox.xMin;
|
||||
size.height = bbox.yMax - bbox.yMin;
|
||||
|
||||
size.width = Util::Math::alignup(size.width, 2);
|
||||
size.height = Util::Math::alignup(size.height, 2);
|
||||
});
|
||||
}
|
||||
|
||||
int Image::computeStringBBox(std::wstring text, FT_Face face, FT_BBox& bbox)
|
||||
{
|
||||
size_t i;
|
||||
int error;
|
||||
FT_BBox glyph_bbox;
|
||||
FT_Vector pen;
|
||||
FT_Glyph glyph;
|
||||
FT_GlyphSlot slot = face->glyph;
|
||||
|
||||
bbox.xMin = bbox.yMin = 32000;
|
||||
bbox.xMax = bbox.yMax = -32000;
|
||||
|
||||
pen.x = 0;
|
||||
pen.y = 0;
|
||||
|
||||
for (i = 0; i < text.length(); i++)
|
||||
{
|
||||
FT_Set_Transform(face, 0, &pen);
|
||||
|
||||
error = FT_Load_Char(face, text.at(i), FT_LOAD_RENDER);
|
||||
if (error)
|
||||
{
|
||||
logger().error("FT_Load_Char error: %d(%s)", error, std::string(FT_Error_String(error)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
error = FT_Get_Glyph(face->glyph, &glyph);
|
||||
if (error)
|
||||
{
|
||||
logger().error("FT_Get_Glyph error: %d(%s)", error, std::string(FT_Error_String(error)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox);
|
||||
|
||||
if (glyph_bbox.xMin < bbox.xMin)
|
||||
bbox.xMin = glyph_bbox.xMin;
|
||||
|
||||
if (glyph_bbox.yMin < bbox.yMin)
|
||||
bbox.yMin = glyph_bbox.yMin;
|
||||
|
||||
if (glyph_bbox.xMax > bbox.xMax)
|
||||
bbox.xMax = glyph_bbox.xMax;
|
||||
|
||||
if (glyph_bbox.yMax > bbox.yMax)
|
||||
bbox.yMax = glyph_bbox.yMax;
|
||||
|
||||
FT_Done_Glyph(glyph);
|
||||
|
||||
pen.x += slot->advance.x;
|
||||
pen.y += slot->advance.y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Image::convertText(const std::string& from, std::wstring& to)
|
||||
{
|
||||
Poco::UnicodeConverter::toUTF16(from, to);
|
||||
}
|
||||
|
||||
void Image::runOnFreeType(const std::string& font, int size, std::function<void(FT_Face&)> func)
|
||||
{
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Error error;
|
||||
|
||||
error = FT_Init_FreeType(&library);
|
||||
if (error)
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("FreeType init error: %d(%s)", error, std::string(FT_Error_String(error))), error);
|
||||
error = FT_New_Face(library, font.c_str(), 0, &face);
|
||||
if (error)
|
||||
throw Poco::InvalidAccessException(
|
||||
Poco::format("FreeType new face error: %d(%s)", error, std::string(FT_Error_String(error))), error);
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
func(face);
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(library);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue