Browse Source

LibGfx: Support italic BitmapFonts

BitmapFont header now contains a slope byte. Slope is used to
indicate slant style and is mapped in LibGfx/FontStyleMapping.h
thankyouverycool 3 years ago
parent
commit
fff89ad769

+ 9 - 7
Userland/Libraries/LibGfx/BitmapFont.cpp

@@ -24,9 +24,9 @@ struct [[gnu::packed]] FontFileHeader {
     u8 mean_line;
     u8 presentation_size;
     u16 weight;
+    u8 slope;
     char name[32];
     char family[32];
-    u8 unused;
 };
 
 static_assert(AssertSize<FontFileHeader, 80>());
@@ -43,7 +43,7 @@ NonnullRefPtr<Font> BitmapFont::clone() const
     memcpy(new_rows, m_rows, bytes_per_glyph * m_glyph_count);
     auto* new_widths = static_cast<u8*>(malloc(m_glyph_count));
     memcpy(new_widths, m_glyph_widths, m_glyph_count);
-    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, m_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, true));
+    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, m_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, m_slope, true));
 }
 
 NonnullRefPtr<BitmapFont> BitmapFont::create(u8 glyph_height, u8 glyph_width, bool fixed, size_t glyph_count)
@@ -59,7 +59,7 @@ NonnullRefPtr<BitmapFont> BitmapFont::create(u8 glyph_height, u8 glyph_width, bo
     size_t bytes_per_glyph = sizeof(u32) * glyph_height;
     auto* new_rows = static_cast<u32*>(calloc(glyph_count, bytes_per_glyph));
     auto* new_widths = static_cast<u8*>(calloc(glyph_count, 1));
-    return adopt_ref(*new BitmapFont("Untitled", "Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1, range_mask_size, new_range_mask, 0, 0, 0, 400, true));
+    return adopt_ref(*new BitmapFont("Untitled", "Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1, range_mask_size, new_range_mask, 0, 0, 0, 400, 0, true));
 }
 
 NonnullRefPtr<BitmapFont> BitmapFont::unmasked_character_set() const
@@ -77,7 +77,7 @@ NonnullRefPtr<BitmapFont> BitmapFont::unmasked_character_set() const
             memcpy(&new_rows[code_point * glyph_height()], &m_rows[index.value() * glyph_height()], bytes_per_glyph);
         }
     }
-    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, s_max_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, true));
+    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, s_max_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, m_slope, true));
 }
 
 NonnullRefPtr<BitmapFont> BitmapFont::masked_character_set() const
@@ -107,10 +107,10 @@ NonnullRefPtr<BitmapFont> BitmapFont::masked_character_set() const
         memcpy(&new_widths[i - j * 256], &m_glyph_widths[i], 1);
         memcpy(&new_rows[(i - j * 256) * glyph_height()], &m_rows[i * glyph_height()], bytes_per_glyph);
     }
-    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, new_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, true));
+    return adopt_ref(*new BitmapFont(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, new_range_mask_size, new_range_mask, m_baseline, m_mean_line, m_presentation_size, m_weight, m_slope, true));
 }
 
-BitmapFont::BitmapFont(String name, String family, u32* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, u16 range_mask_size, u8* range_mask, u8 baseline, u8 mean_line, u8 presentation_size, u16 weight, bool owns_arrays)
+BitmapFont::BitmapFont(String name, String family, u32* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, u16 range_mask_size, u8* range_mask, u8 baseline, u8 mean_line, u8 presentation_size, u16 weight, u8 slope, bool owns_arrays)
     : m_name(name)
     , m_family(family)
     , m_range_mask_size(range_mask_size)
@@ -126,6 +126,7 @@ BitmapFont::BitmapFont(String name, String family, u32* rows, u8* widths, bool i
     , m_mean_line(mean_line)
     , m_presentation_size(presentation_size)
     , m_weight(weight)
+    , m_slope(slope)
     , m_fixed_width(is_fixed_width)
     , m_owns_arrays(owns_arrays)
 {
@@ -191,7 +192,7 @@ RefPtr<BitmapFont> BitmapFont::load_from_memory(const u8* data)
         glyph_count += 256 * __builtin_popcount(range_mask[i]);
     u32* rows = (u32*)(range_mask + header.range_mask_size);
     u8* widths = (u8*)(rows) + glyph_count * bytes_per_glyph;
-    return adopt_ref(*new BitmapFont(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, header.range_mask_size, range_mask, header.baseline, header.mean_line, header.presentation_size, header.weight));
+    return adopt_ref(*new BitmapFont(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, header.range_mask_size, range_mask, header.baseline, header.mean_line, header.presentation_size, header.weight, header.slope));
 }
 
 RefPtr<BitmapFont> BitmapFont::load_from_file(String const& path)
@@ -225,6 +226,7 @@ bool BitmapFont::write_to_file(String const& path)
     header.glyph_spacing = m_glyph_spacing;
     header.presentation_size = m_presentation_size;
     header.weight = m_weight;
+    header.slope = m_slope;
     memcpy(header.name, m_name.characters(), min(m_name.length(), sizeof(header.name) - 1));
     memcpy(header.family, m_family.characters(), min(m_family.length(), sizeof(header.family) - 1));
 

+ 5 - 1
Userland/Libraries/LibGfx/BitmapFont.h

@@ -36,6 +36,9 @@ public:
     u16 weight() const override { return m_weight; }
     void set_weight(u16 weight) { m_weight = weight; }
 
+    u8 slope() const { return m_slope; }
+    void set_slope(u8 slope) { m_slope = slope; }
+
     Glyph glyph(u32 code_point) const override;
     Glyph raw_glyph(u32 code_point) const;
     bool contains_glyph(u32 code_point) const override;
@@ -104,7 +107,7 @@ public:
 private:
     BitmapFont(String name, String family, u32* rows, u8* widths, bool is_fixed_width,
         u8 glyph_width, u8 glyph_height, u8 glyph_spacing, u16 range_mask_size, u8* range_mask,
-        u8 baseline, u8 mean_line, u8 presentation_size, u16 weight, bool owns_arrays = false);
+        u8 baseline, u8 mean_line, u8 presentation_size, u16 weight, u8 slope, bool owns_arrays = false);
 
     static RefPtr<BitmapFont> load_from_memory(u8 const*);
 
@@ -136,6 +139,7 @@ private:
     u8 m_mean_line { 0 };
     u8 m_presentation_size { 0 };
     u16 m_weight { 0 };
+    u8 m_slope { 0 };
 
     bool m_fixed_width { false };
     bool m_owns_arrays { false };

+ 78 - 0
Userland/Libraries/LibGfx/FontStyleMapping.h

@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, the SerenityOS developers.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+namespace Gfx {
+
+struct FontStyleMapping {
+    constexpr FontStyleMapping(int s, const char* n)
+        : style(s)
+        , name(n)
+    {
+    }
+    int style { 0 };
+    StringView name;
+};
+
+static constexpr FontStyleMapping font_weight_names[] = {
+    { 100, "Thin" },
+    { 200, "Extra Light" },
+    { 300, "Light" },
+    { 400, "Regular" },
+    { 500, "Medium" },
+    { 600, "Semi Bold" },
+    { 700, "Bold" },
+    { 800, "Extra Bold" },
+    { 900, "Black" },
+    { 950, "Extra Black" },
+};
+
+static constexpr FontStyleMapping font_slope_names[] = {
+    { 0, "Regular" },
+    { 1, "Italic" },
+    { 2, "Oblique" },
+    { 3, "Reclined" }
+};
+
+static constexpr StringView weight_to_name(int weight)
+{
+    for (auto& it : font_weight_names) {
+        if (it.style == weight)
+            return it.name;
+    }
+    return {};
+}
+
+static constexpr int name_to_weight(StringView name)
+{
+    for (auto& it : font_weight_names) {
+        if (it.name == name)
+            return it.style;
+    }
+    return {};
+}
+
+static constexpr StringView slope_to_name(int slope)
+{
+    for (auto& it : font_slope_names) {
+        if (it.style == slope)
+            return it.name;
+    }
+    return {};
+}
+
+static constexpr int name_to_slope(StringView name)
+{
+    for (auto& it : font_slope_names) {
+        if (it.name == name)
+            return it.style;
+    }
+    return {};
+}
+
+}