子像素绘制
This commit is contained in:
parent
4d0dbbe6c5
commit
9be39399d9
@ -10,6 +10,8 @@
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "sokol_gfx.h"
|
||||
|
||||
/**
|
||||
* @brief 像素格式信息命名空间
|
||||
* 提供sg_pixel_format格式的辅助函数
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include "freetype_interface.h"
|
||||
|
||||
#include "pixel.h"
|
||||
#include "freetype/ftcolor.h"
|
||||
#include "freetype/ftglyph.h"
|
||||
#include "interface/image_interface.h"
|
||||
|
||||
@ -64,14 +66,17 @@ std::shared_ptr<image_heap_t> freetype_interface::get_glyph_image(int32_t in_gly
|
||||
if (face_->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
return nullptr;
|
||||
}
|
||||
// FT_Render_Glyph(face_->glyph, FT_RENDER_MODE_LCD);
|
||||
|
||||
auto& bitmap = face_->glyph->bitmap;
|
||||
|
||||
// 创建位图
|
||||
// 这里使用了一个自定义的删除器来释放位图数据
|
||||
std::shared_ptr<image_heap_t> image(new image_heap_t(), freetype_bitmap_deleter);
|
||||
image->width = face_->glyph->bitmap.width;
|
||||
image->height = face_->glyph->bitmap.rows;
|
||||
image->pixel_format = SG_PIXELFORMAT_R8;
|
||||
image->data = new uint8_t[image->width * image->height];
|
||||
image->width = bitmap.width;
|
||||
image->height = bitmap.rows;
|
||||
image->pixel_format = SG_PIXELFORMAT_R8;
|
||||
image->data = new uint8_t[image->width * image->height];
|
||||
std::memcpy(image->data, face_->glyph->bitmap.buffer, image->width * image->height);
|
||||
|
||||
return image;
|
||||
@ -83,19 +88,25 @@ std::shared_ptr<image_heap_t> freetype_interface::get_emoji_image(int32_t in_gly
|
||||
}
|
||||
|
||||
// 加载字形
|
||||
FT_Load_Glyph(face_, in_glyph_id, FT_LOAD_COLOR);
|
||||
FT_Load_Glyph(face_, in_glyph_id, FT_LOAD_RENDER | FT_LOAD_COLOR);
|
||||
if (face_->glyph->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FT_Bitmap& bitmap = face_->glyph->bitmap;
|
||||
|
||||
// 创建位图
|
||||
// 这里使用了一个自定义的删除器来释放位图数据
|
||||
std::shared_ptr<image_heap_t> image(new image_heap_t(), freetype_bitmap_deleter);
|
||||
image->width = face_->glyph->bitmap.width;
|
||||
image->height = face_->glyph->bitmap.rows;
|
||||
image->width = bitmap.width;
|
||||
image->height = bitmap.rows;
|
||||
image->pixel_format = SG_PIXELFORMAT_RGBA8;
|
||||
image->data = new uint8_t[image->width * image->height * 4];
|
||||
std::memcpy(image->data, face_->glyph->bitmap.buffer, image->width * image->height);
|
||||
|
||||
// 其他格式,初始化为透明
|
||||
clear_bitmap(image.get());
|
||||
attach_bitmap(bitmap, image.get());
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@ -143,6 +154,49 @@ void freetype_interface::on_set_font_size(float in_size) {
|
||||
FT_Set_Pixel_Sizes(face_, 0, static_cast<FT_UInt>(in_size));
|
||||
}
|
||||
|
||||
void freetype_interface::clear_bitmap(image_heap_t* in_image) {
|
||||
memset(in_image->data, 0, in_image->width * in_image->height * 4);
|
||||
}
|
||||
|
||||
void freetype_interface::attach_bitmap(const FT_Bitmap& in_bitmap, image_heap_t* in_image) {
|
||||
// 将FreeType位图数据复制到新分配的内存中
|
||||
switch (in_bitmap.pixel_mode) {
|
||||
case FT_PIXEL_MODE_BGRA:
|
||||
// 彩色emoji (BGRA -> RGBA)
|
||||
for (unsigned int y = 0; y < in_bitmap.rows; y++) {
|
||||
for (unsigned int x = 0; x < in_bitmap.width; x++) {
|
||||
unsigned char* src = in_bitmap.buffer + (y * in_bitmap.pitch + x * 4);
|
||||
unsigned char* dst = (uint8_t*)in_image->data + (y * in_image->width + x) * 4;
|
||||
|
||||
// BGRA -> RGBA
|
||||
dst[0] += src[2]; // R <- B
|
||||
dst[1] += src[1]; // G <- G
|
||||
dst[2] += src[0]; // B <- R
|
||||
dst[3] += src[3]; // A <- A
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PIXEL_MODE_GRAY:
|
||||
// 灰度图转RGBA
|
||||
for (unsigned int y = 0; y < in_bitmap.rows; y++) {
|
||||
for (unsigned int x = 0; x < in_bitmap.width; x++) {
|
||||
unsigned char gray = in_bitmap.buffer[y * in_bitmap.pitch + x];
|
||||
unsigned char* dst = (uint8_t*) in_image->data + (y * in_image->width + x) * 4;
|
||||
|
||||
dst[0] = gray; // R
|
||||
dst[1] = gray; // G
|
||||
dst[2] = gray; // B
|
||||
dst[3] = gray; // A
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool init_font_system() {
|
||||
if (FT_Init_FreeType(&library_)) {
|
||||
return false;
|
||||
|
@ -18,6 +18,9 @@ public:
|
||||
protected:
|
||||
bool on_load() override;
|
||||
void on_set_font_size(float in_size) override;
|
||||
// 附加位图
|
||||
static void clear_bitmap(image_heap_t* in_image);
|
||||
static void attach_bitmap(const FT_Bitmap& in_bitmap, image_heap_t* in_image);
|
||||
protected:
|
||||
FT_Face face_{};
|
||||
};
|
||||
|
@ -140,7 +140,7 @@ std::shared_ptr<image_heap_t> stb_font_face_t::get_glyph_image(int32_t in_glyph_
|
||||
int32_t width, height, xoff, yoff;
|
||||
|
||||
// 获取字形图像
|
||||
const auto bitmap = stbtt_GetGlyphBitmap(&font_info_, scale_, scale_, in_glyph_id, &width, &height, &xoff, &yoff);
|
||||
const auto bitmap = stbtt_GetGlyphBitmapSubpixel(&font_info_, scale_, scale_, 0.33, 0, in_glyph_id, &width, &height, &xoff, &yoff);
|
||||
|
||||
// 创建位图
|
||||
std::shared_ptr<image_heap_t> image(new image_heap_t(), stb_truetype_deleter);
|
||||
@ -169,7 +169,7 @@ glyph_shaped_t stb_font_face_t::shape_glyph(uint32_t in_glyph_id) const {
|
||||
stbtt_GetGlyphHMetrics(&font_info_, in_glyph_id, &advance, &lsb);
|
||||
// 获取字形的边界框
|
||||
int32_t x0, y0, x1, y1;
|
||||
stbtt_GetGlyphBitmapBox(&font_info_, in_glyph_id, scale_, scale_, &x0, &y0, &x1, &y1);
|
||||
stbtt_GetGlyphBitmapBoxSubpixel(&font_info_, in_glyph_id, scale_, scale_, 0.33, 0, &x0, &y0, &x1, &y1);
|
||||
|
||||
glyph_shaped_t out{};
|
||||
out.glyph_index = in_glyph_id;
|
||||
|
@ -251,7 +251,8 @@ void render_elements::make_image(const Eigen::Vector2f& in_pos, const Eigen::Vec
|
||||
void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vector2f& in_pos,
|
||||
const Eigen::Vector2f& in_size, const geometry_t& in_geometry, const rect_color& in_color,
|
||||
float in_rotation_radians, const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) {
|
||||
const auto& sampler = texture_sampler_builder::get_sampler(sampler_type::pixel_art);
|
||||
const auto& glyph_sampler = texture_sampler_builder::get_sampler(sampler_type::pixel_art);
|
||||
const auto& emoji_sampler = texture_sampler_builder::get_sampler(sampler_type::pixel_art);
|
||||
|
||||
for (const auto& position : in_layout.glyphs) {
|
||||
const auto& p = position;
|
||||
@ -264,7 +265,7 @@ void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vec
|
||||
batch_key new_key;
|
||||
new_key.pipeline = position.is_emoji ? image_pipeline_ : text_pipeline_;
|
||||
new_key.image = texture->get_image();
|
||||
new_key.sampler = *sampler;
|
||||
new_key.sampler = position.is_emoji ? *emoji_sampler : *glyph_sampler;
|
||||
|
||||
Eigen::Vector2f real_pos = p.position.array() + in_pos.array();
|
||||
// snap to pixel grid
|
||||
|
Loading…
x
Reference in New Issue
Block a user