1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 12:48:10 +00:00

FontEditor: Support selection ranges

This makes editing much easier, e.g. you don't need longer to copy
hundreds of glyphs one by one.

It has some flaws, e.g. it's not integrated with undo stack,
but we need to start with something!
This commit is contained in:
Maciej 2022-01-04 18:24:06 +01:00 committed by Andreas Kling
parent ad2551e6b8
commit 1d98499234
6 changed files with 283 additions and 163 deletions

View file

@ -33,98 +33,6 @@ void GlyphEditorWidget::set_glyph(int glyph)
update();
}
void GlyphEditorWidget::delete_glyph()
{
if (on_undo_event)
on_undo_event();
auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap();
for (int x = 0; x < font().max_glyph_width(); x++)
for (int y = 0; y < font().glyph_height(); y++)
bitmap.set_bit_at(x, y, false);
font().set_glyph_width(m_glyph, 0);
if (on_glyph_altered)
on_glyph_altered(m_glyph);
update();
}
void GlyphEditorWidget::cut_glyph()
{
copy_glyph();
delete_glyph();
}
void GlyphEditorWidget::copy_glyph()
{
auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap();
u8 bits[bitmap.width()][bitmap.height()];
for (int x = 0; x < bitmap.width(); x++) {
for (int y = 0; y < bitmap.height(); y++) {
bits[x][y] = bitmap.bit_at(x, y);
}
}
StringBuilder glyph_builder;
if (AK::UnicodeUtils::is_unicode_control_code_point(m_glyph))
glyph_builder.append(AK::UnicodeUtils::get_unicode_control_code_point_alias(m_glyph).value());
else if (Gfx::get_char_bidi_class(m_glyph) == Gfx::BidirectionalClass::STRONG_RTL)
glyph_builder.append_code_point(0xFFFD);
else
glyph_builder.append_code_point(m_glyph);
HashMap<String, String> metadata;
metadata.set("char", glyph_builder.to_string());
metadata.set("width", String::number(bitmap.width()));
metadata.set("height", String::number(bitmap.height()));
GUI::Clipboard::the().set_data(ReadonlyBytes(&bits[0], bitmap.width() * bitmap.height()), "glyph/x-fonteditor", metadata);
}
void GlyphEditorWidget::paste_glyph()
{
auto [data, mime_type, metadata] = GUI::Clipboard::the().fetch_data_and_type();
if (!mime_type.starts_with("glyph/"))
return;
auto byte_buffer = data.data();
auto buffer_height = metadata.get("height").value_or("0").to_int().value_or(0);
auto buffer_width = metadata.get("width").value_or("0").to_int().value_or(0);
if (buffer_height <= 0 || buffer_width <= 0 || buffer_height > 128 || buffer_width > 128) {
dbgln("Refusing to receive glyph of dimensions {}x{}", buffer_width, buffer_height);
return;
}
if (data.size() != static_cast<size_t>(buffer_width * buffer_height)) {
dbgln("Refusing to receive glyph with mismatching buffer sizes: Expected {}x{}={} bytes, received {} bytes.",
buffer_width, buffer_height, buffer_width * buffer_height, data.size());
return;
}
if (on_undo_event)
on_undo_event();
u8 bits[buffer_width][buffer_height];
int i = 0;
for (int x = 0; x < buffer_width; x++) {
for (int y = 0; y < buffer_height; y++) {
bits[x][y] = byte_buffer[i];
i++;
}
}
auto bitmap = font().raw_glyph(m_glyph).glyph_bitmap();
if (bitmap.width() < buffer_width)
font().set_glyph_width(m_glyph, min(buffer_width, font().max_glyph_width()));
for (int x = 0; x < min(buffer_width, font().max_glyph_width()); x++) {
for (int y = 0; y < min(buffer_height, font().glyph_height()); y++) {
bitmap.set_bit_at(x, y, bits[x][y]);
}
}
if (on_glyph_altered)
on_glyph_altered(m_glyph);
update();
}
void GlyphEditorWidget::paint_event(GUI::PaintEvent& event)
{
GUI::Frame::paint_event(event);