Jelajahi Sumber

LibGfx: Remove Gfx::Painter::draw_text() and helpers

Andreas Kling 1 tahun lalu
induk
melakukan
345ae18929

+ 0 - 1
Userland/Libraries/LibGfx/CMakeLists.txt

@@ -66,7 +66,6 @@ set(SOURCES
     ShareableBitmap.cpp
     ShareableBitmap.cpp
     Size.cpp
     Size.cpp
     SystemTheme.cpp
     SystemTheme.cpp
-    TextDirection.cpp
     TextLayout.cpp
     TextLayout.cpp
     Triangle.cpp
     Triangle.cpp
     VectorGraphic.cpp
     VectorGraphic.cpp

+ 0 - 305
Userland/Libraries/LibGfx/Painter.cpp

@@ -12,26 +12,18 @@
 
 
 #include "Painter.h"
 #include "Painter.h"
 #include "Bitmap.h"
 #include "Bitmap.h"
-#include "Font/Emoji.h"
 #include "Font/Font.h"
 #include "Font/Font.h"
 #include <AK/Assertions.h>
 #include <AK/Assertions.h>
-#include <AK/Debug.h>
 #include <AK/Function.h>
 #include <AK/Function.h>
 #include <AK/Math.h>
 #include <AK/Math.h>
 #include <AK/Memory.h>
 #include <AK/Memory.h>
-#include <AK/Queue.h>
-#include <AK/QuickSort.h>
 #include <AK/Stack.h>
 #include <AK/Stack.h>
 #include <AK/StdLibExtras.h>
 #include <AK/StdLibExtras.h>
-#include <AK/StringBuilder.h>
 #include <AK/Utf8View.h>
 #include <AK/Utf8View.h>
 #include <LibGfx/Palette.h>
 #include <LibGfx/Palette.h>
 #include <LibGfx/Path.h>
 #include <LibGfx/Path.h>
 #include <LibGfx/Quad.h>
 #include <LibGfx/Quad.h>
-#include <LibGfx/TextDirection.h>
 #include <LibGfx/TextLayout.h>
 #include <LibGfx/TextLayout.h>
-#include <LibUnicode/CharacterTypes.h>
-#include <LibUnicode/Emoji.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
 #if defined(AK_COMPILER_GCC)
 #if defined(AK_COMPILER_GCC)
@@ -882,303 +874,6 @@ void Painter::draw_emoji(IntPoint point, Gfx::Bitmap const& emoji, Font const& f
     draw_scaled_bitmap(dst_rect, emoji, emoji.rect());
     draw_scaled_bitmap(dst_rect, emoji, emoji.rect());
 }
 }
 
 
-void Painter::draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font, Color color)
-{
-    auto draw_glyph_or_emoji = prepare_draw_glyph_or_emoji(point, it, font);
-    if (draw_glyph_or_emoji.has<DrawGlyph>()) {
-        auto& glyph = draw_glyph_or_emoji.get<DrawGlyph>();
-        draw_glyph(glyph.position, glyph.code_point, *glyph.font, color);
-    } else {
-        auto& emoji = draw_glyph_or_emoji.get<DrawEmoji>();
-        draw_emoji(emoji.position.to_type<int>(), *emoji.emoji, *emoji.font);
-    }
-}
-
-template<typename DrawGlyphFunction>
-void draw_text_line(FloatRect const& a_rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextDirection direction, DrawGlyphFunction draw_glyph)
-{
-    auto rect = a_rect;
-
-    switch (alignment) {
-    case TextAlignment::TopLeft:
-    case TextAlignment::CenterLeft:
-    case TextAlignment::BottomLeft:
-        break;
-    case TextAlignment::TopRight:
-    case TextAlignment::CenterRight:
-    case TextAlignment::BottomRight:
-        rect.set_x(rect.right() - 1 - font.width(text));
-        break;
-    case TextAlignment::TopCenter:
-    case TextAlignment::BottomCenter:
-    case TextAlignment::Center: {
-        auto shrunken_rect = rect;
-        shrunken_rect.set_width(font.width(text));
-        shrunken_rect.center_within(rect);
-        rect = shrunken_rect;
-        break;
-    }
-    default:
-        VERIFY_NOT_REACHED();
-    }
-
-    auto point = rect.location();
-    auto space_width = font.glyph_width(' ');
-
-    if (direction == TextDirection::RTL) {
-        point.translate_by(rect.width(), 0); // Start drawing from the end
-        space_width = -space_width;          // Draw spaces backwards
-    }
-
-    u32 last_code_point { 0 };
-    for (auto it = text.begin(); it != text.end(); ++it) {
-        auto code_point = *it;
-        if (should_paint_as_space(code_point)) {
-            point.translate_by(space_width, 0);
-            last_code_point = code_point;
-            continue;
-        }
-
-        auto kerning = font.glyphs_horizontal_kerning(last_code_point, code_point);
-        if (kerning != 0.0f)
-            point.translate_by(direction == TextDirection::LTR ? kerning : -kerning, 0);
-
-        auto it_copy = it; // The callback function will advance the iterator, so create a copy for this lookup.
-        FloatSize glyph_size(font.glyph_or_emoji_width(it_copy), font.pixel_size());
-
-        if (direction == TextDirection::RTL)
-            point.translate_by(-glyph_size.width(), 0); // If we are drawing right to left, we have to move backwards before drawing the glyph
-        draw_glyph({ point, glyph_size }, it);
-        if (direction == TextDirection::LTR)
-            point.translate_by(glyph_size.width(), 0);
-        // The callback function might have exhausted the iterator.
-        if (it == text.end())
-            break;
-        last_code_point = code_point;
-    }
-}
-
-static inline size_t draw_text_get_length(Utf8View const& text)
-{
-    return text.byte_length();
-}
-
-Vector<DirectionalRun> Painter::split_text_into_directional_runs(Utf8View const& text, TextDirection initial_direction)
-{
-    // FIXME: This is a *very* simplified version of the UNICODE BIDIRECTIONAL ALGORITHM (https://www.unicode.org/reports/tr9/), that can render most bidirectional text
-    //  but also produces awkward results in a large amount of edge cases. This should probably be replaced with a fully spec compliant implementation at some point.
-
-    // FIXME: Support HTML "dir" attribute (how?)
-    u8 paragraph_embedding_level = initial_direction == TextDirection::LTR ? 0 : 1;
-    Vector<u8> embedding_levels;
-    embedding_levels.ensure_capacity(text.length());
-    for (size_t i = 0; i < text.length(); i++)
-        embedding_levels.unchecked_append(paragraph_embedding_level);
-
-    // FIXME: Support Explicit Directional Formatting Characters
-
-    Vector<BidirectionalClass> character_classes;
-    character_classes.ensure_capacity(text.length());
-    for (u32 code_point : text)
-        character_classes.unchecked_append(get_char_bidi_class(code_point));
-
-    // resolving weak types
-    BidirectionalClass paragraph_class = initial_direction == TextDirection::LTR ? BidirectionalClass::STRONG_LTR : BidirectionalClass::STRONG_RTL;
-    for (size_t i = 0; i < character_classes.size(); i++) {
-        if (character_classes[i] != BidirectionalClass::WEAK_SEPARATORS)
-            continue;
-        for (ssize_t j = i - 1; j >= 0; j--) {
-            auto character_class = character_classes[j];
-            if (character_class != BidirectionalClass::STRONG_RTL && character_class != BidirectionalClass::STRONG_LTR)
-                continue;
-            character_classes[i] = character_class;
-            break;
-        }
-        if (character_classes[i] == BidirectionalClass::WEAK_SEPARATORS)
-            character_classes[i] = paragraph_class;
-    }
-
-    // resolving neutral types
-    auto left_side = BidirectionalClass::NEUTRAL;
-    auto sequence_length = 0;
-    for (size_t i = 0; i < character_classes.size(); i++) {
-        auto character_class = character_classes[i];
-        if (left_side == BidirectionalClass::NEUTRAL) {
-            if (character_class != BidirectionalClass::NEUTRAL)
-                left_side = character_class;
-            else
-                character_classes[i] = paragraph_class;
-            continue;
-        }
-        if (character_class != BidirectionalClass::NEUTRAL) {
-            BidirectionalClass sequence_class;
-            if (bidi_class_to_direction(left_side) == bidi_class_to_direction(character_class)) {
-                sequence_class = left_side == BidirectionalClass::STRONG_RTL ? BidirectionalClass::STRONG_RTL : BidirectionalClass::STRONG_LTR;
-            } else {
-                sequence_class = paragraph_class;
-            }
-            for (auto j = 0; j < sequence_length; j++) {
-                character_classes[i - j - 1] = sequence_class;
-            }
-            sequence_length = 0;
-            left_side = character_class;
-        } else {
-            sequence_length++;
-        }
-    }
-    for (auto i = 0; i < sequence_length; i++)
-        character_classes[character_classes.size() - i - 1] = paragraph_class;
-
-    // resolving implicit levels
-    for (size_t i = 0; i < character_classes.size(); i++) {
-        auto character_class = character_classes[i];
-        if ((embedding_levels[i] % 2) == 0) {
-            if (character_class == BidirectionalClass::STRONG_RTL)
-                embedding_levels[i] += 1;
-            else if (character_class == BidirectionalClass::WEAK_NUMBERS || character_class == BidirectionalClass::WEAK_SEPARATORS)
-                embedding_levels[i] += 2;
-        } else {
-            if (character_class == BidirectionalClass::STRONG_LTR || character_class == BidirectionalClass::WEAK_NUMBERS || character_class == BidirectionalClass::WEAK_SEPARATORS)
-                embedding_levels[i] += 1;
-        }
-    }
-
-    // splitting into runs
-    auto run_code_points_start = text.begin();
-    auto next_code_points_slice = [&](auto length) {
-        Vector<u32> run_code_points;
-        run_code_points.ensure_capacity(length);
-        for (size_t j = 0; j < length; ++j, ++run_code_points_start)
-            run_code_points.unchecked_append(*run_code_points_start);
-        return run_code_points;
-    };
-    Vector<DirectionalRun> runs;
-    size_t start = 0;
-    u8 level = embedding_levels[0];
-    for (size_t i = 1; i < embedding_levels.size(); ++i) {
-        if (embedding_levels[i] == level)
-            continue;
-        auto code_points_slice = next_code_points_slice(i - start);
-        runs.append({ move(code_points_slice), level });
-        start = i;
-        level = embedding_levels[i];
-    }
-    auto code_points_slice = next_code_points_slice(embedding_levels.size() - start);
-    runs.append({ move(code_points_slice), level });
-
-    // reordering resolved levels
-    // FIXME: missing special cases for trailing whitespace characters
-    u8 minimum_level = 128;
-    u8 maximum_level = 0;
-    for (auto& run : runs) {
-        minimum_level = min(minimum_level, run.embedding_level());
-        maximum_level = max(minimum_level, run.embedding_level());
-    }
-    if ((minimum_level % 2) == 0)
-        minimum_level++;
-    auto runs_count = runs.size() - 1;
-    while (maximum_level <= minimum_level) {
-        size_t run_index = 0;
-        while (run_index < runs_count) {
-            while (run_index < runs_count && runs[run_index].embedding_level() < maximum_level)
-                run_index++;
-            auto reverse_start = run_index;
-            while (run_index <= runs_count && runs[run_index].embedding_level() >= maximum_level)
-                run_index++;
-            auto reverse_end = run_index - 1;
-            while (reverse_start < reverse_end) {
-                swap(runs[reverse_start], runs[reverse_end]);
-                reverse_start++;
-                reverse_end--;
-            }
-        }
-        maximum_level--;
-    }
-
-    // mirroring RTL mirror characters
-    for (auto& run : runs) {
-        if (run.direction() == TextDirection::LTR)
-            continue;
-        for (auto& code_point : run.code_points()) {
-            code_point = get_mirror_char(code_point);
-        }
-    }
-
-    return runs;
-}
-
-bool Painter::text_contains_bidirectional_text(Utf8View const& text, TextDirection initial_direction)
-{
-    for (u32 code_point : text) {
-        auto char_class = get_char_bidi_class(code_point);
-        if (char_class == BidirectionalClass::NEUTRAL)
-            continue;
-        if (bidi_class_to_direction(char_class) != initial_direction)
-            return true;
-    }
-    return false;
-}
-
-template<typename DrawGlyphFunction>
-void Painter::do_draw_text(FloatRect const& rect, Utf8View const& text, Font const& font, TextAlignment alignment, TextElision elision, TextWrapping wrapping, DrawGlyphFunction draw_glyph)
-{
-    if (draw_text_get_length(text) == 0)
-        return;
-
-    TextLayout layout(font, text, rect);
-
-    auto line_height = font.preferred_line_height();
-
-    auto lines = layout.lines(elision, wrapping);
-    auto bounding_rect = layout.bounding_rect(wrapping);
-
-    bounding_rect.align_within(rect, alignment);
-
-    for (size_t i = 0; i < lines.size(); ++i) {
-        auto line = Utf8View { lines[i] };
-
-        FloatRect line_rect { bounding_rect.x(), bounding_rect.y() + i * line_height, bounding_rect.width(), line_height };
-
-        TextDirection line_direction = get_text_direction(line);
-        if (text_contains_bidirectional_text(line, line_direction)) { // Slow Path: The line contains mixed BiDi classes
-            auto directional_runs = split_text_into_directional_runs(line, line_direction);
-            auto current_dx = line_direction == TextDirection::LTR ? 0 : line_rect.width();
-            for (auto& directional_run : directional_runs) {
-                // NOTE: DirectionalRun returns Utf32View which isn't
-                // compatible with draw_text_line.
-                StringBuilder builder;
-                builder.append(directional_run.text());
-                auto line_text = Utf8View { builder.string_view() };
-
-                auto run_width = font.width(line_text);
-                if (line_direction == TextDirection::RTL)
-                    current_dx -= run_width;
-                auto run_rect = line_rect.translated(current_dx, 0);
-                run_rect.set_width(run_width);
-
-                draw_text_line(run_rect, line_text, font, alignment, directional_run.direction(), draw_glyph);
-                if (line_direction == TextDirection::LTR)
-                    current_dx += run_width;
-            }
-        } else {
-            draw_text_line(line_rect, line, font, alignment, line_direction, draw_glyph);
-        }
-    }
-}
-
-void Painter::draw_text(FloatRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
-{
-    Utf8View text { raw_text };
-    do_draw_text(rect, text, font, alignment, elision, wrapping, [&](FloatRect const& r, Utf8CodePointIterator& it) {
-        draw_glyph_or_emoji(r.location(), it, font, color);
-    });
-}
-
-void Painter::draw_text(IntRect const& rect, StringView raw_text, Font const& font, TextAlignment alignment, Color color, TextElision elision, TextWrapping wrapping)
-{
-    draw_text(rect.to_type<float>(), raw_text, font, alignment, color, elision, wrapping);
-}
-
 void Painter::set_pixel(IntPoint p, Color color, bool blend)
 void Painter::set_pixel(IntPoint p, Color color, bool blend)
 {
 {
     auto point = p;
     auto point = p;

+ 0 - 15
Userland/Libraries/LibGfx/Painter.h

@@ -9,10 +9,8 @@
 #include <AK/Forward.h>
 #include <AK/Forward.h>
 #include <AK/Memory.h>
 #include <AK/Memory.h>
 #include <AK/NonnullRefPtr.h>
 #include <AK/NonnullRefPtr.h>
-#include <AK/Utf8View.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
 #include <LibGfx/Color.h>
 #include <LibGfx/Color.h>
-#include <LibGfx/Font/FontDatabase.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Gradients.h>
 #include <LibGfx/Gradients.h>
 #include <LibGfx/GrayscaleBitmap.h>
 #include <LibGfx/GrayscaleBitmap.h>
@@ -22,10 +20,6 @@
 #include <LibGfx/Rect.h>
 #include <LibGfx/Rect.h>
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/Size.h>
-#include <LibGfx/TextAlignment.h>
-#include <LibGfx/TextDirection.h>
-#include <LibGfx/TextElision.h>
-#include <LibGfx/TextWrapping.h>
 #include <LibGfx/WindingRule.h>
 #include <LibGfx/WindingRule.h>
 
 
 namespace Gfx {
 namespace Gfx {
@@ -71,11 +65,8 @@ public:
     void draw_triangle_wave(IntPoint, IntPoint, Color color, int amplitude, int thickness = 1);
     void draw_triangle_wave(IntPoint, IntPoint, Color color, int amplitude, int thickness = 1);
     void blit(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity = 1.0f, bool apply_alpha = true);
     void blit(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, float opacity = 1.0f, bool apply_alpha = true);
     void blit_filtered(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, Function<Color(Color)> const&, bool apply_alpha = true);
     void blit_filtered(IntPoint, Gfx::Bitmap const&, IntRect const& src_rect, Function<Color(Color)> const&, bool apply_alpha = true);
-    void draw_text(FloatRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
-    void draw_text(IntRect const&, StringView, Font const&, TextAlignment = TextAlignment::TopLeft, Color = Color::Black, TextElision = TextElision::None, TextWrapping = TextWrapping::DontWrap);
     void draw_emoji(IntPoint, Gfx::Bitmap const&, Font const&);
     void draw_emoji(IntPoint, Gfx::Bitmap const&, Font const&);
     void draw_glyph(FloatPoint, u32, Font const&, Color);
     void draw_glyph(FloatPoint, u32, Font const&, Color);
-    void draw_glyph_or_emoji(FloatPoint, Utf8CodePointIterator&, Font const&, Color);
 
 
     enum class CornerOrientation {
     enum class CornerOrientation {
         TopLeft,
         TopLeft,
@@ -142,12 +133,6 @@ protected:
     IntRect m_clip_origin;
     IntRect m_clip_origin;
     NonnullRefPtr<Gfx::Bitmap> m_target;
     NonnullRefPtr<Gfx::Bitmap> m_target;
     Vector<State, 4> m_state_stack;
     Vector<State, 4> m_state_stack;
-
-private:
-    Vector<DirectionalRun> split_text_into_directional_runs(Utf8View const&, TextDirection initial_direction);
-    bool text_contains_bidirectional_text(Utf8View const&, TextDirection);
-    template<typename DrawGlyphFunction>
-    void do_draw_text(FloatRect const&, Utf8View const& text, Font const&, TextAlignment, TextElision, TextWrapping, DrawGlyphFunction);
 };
 };
 
 
 class PainterStateSaver {
 class PainterStateSaver {

+ 0 - 34
Userland/Libraries/LibGfx/TextDirection.cpp

@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include <AK/Array.h>
-#include <LibGfx/TextDirection.h>
-
-namespace Gfx {
-
-// FIXME: These should be parsed from the official UnicodeData.txt that specifies the class for each character (this function doesn't take into account a large amount of characters)
-static consteval Array<BidirectionalClass, 0x1F000> generate_char_bidi_class_lookup_table()
-{
-    Array<BidirectionalClass, 0x1F000> lookup_table {};
-    for (u32 ch = 0; ch < 0x1F000; ch++) {
-        auto char_class = BidirectionalClass::STRONG_LTR;
-        if ((ch >= 0x600 && ch <= 0x7BF) || (ch >= 0x8A0 && ch <= 0x8FF) || (ch >= 0xFB50 && ch <= 0xFDCF) || (ch >= 0xFDF0 && ch <= 0xFDFF) || (ch >= 0xFE70 && ch <= 0xFEFF) || (ch >= 0x1EE00 && ch <= 0x1EEFF))
-            char_class = BidirectionalClass::STRONG_RTL; // Arabic RTL
-        if ((ch >= 0x590 && ch <= 0x5FF) || (ch >= 0x7C0 && ch <= 0x89F) || (ch == 0x200F) || (ch >= 0xFB1D && ch <= 0xFB4F) || (ch >= 0x10800 && ch <= 0x10FFF) || (ch >= 0x1E800 && ch <= 0x1EDFF) || (ch >= 0x1EF00 && ch <= 0x1EFFF))
-            char_class = BidirectionalClass::STRONG_RTL; // Hebrew RTL
-        if ((ch >= 0x30 && ch <= 0x39) || (ch >= 0x660 && ch <= 0x669) || (ch >= 0x10D30 && ch <= 0x10E7E))
-            char_class = BidirectionalClass::WEAK_NUMBERS; // Numerals
-        if ((ch >= 0x23 && ch <= 0x25) || (ch >= 0x2B && ch <= 0x2F) || (ch == 0x3A))
-            char_class = BidirectionalClass::WEAK_SEPARATORS; // Separators
-        if ((ch >= 0x9 && ch <= 0xD) || (ch >= 0x1C && ch <= 0x22) || (ch >= 0x26 && ch <= 0x2A) || (ch >= 0x3B && ch <= 0x40) || (ch >= 0x5B && ch <= 0x60) || (ch >= 0x7B && ch <= 0x7E))
-            char_class = BidirectionalClass::NEUTRAL;
-        lookup_table[ch] = char_class;
-    }
-    return lookup_table;
-}
-constexpr Array<BidirectionalClass, 0x1F000> char_bidi_class_lookup_table = generate_char_bidi_class_lookup_table();
-
-}

+ 0 - 104
Userland/Libraries/LibGfx/TextDirection.h

@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-#include <AK/Array.h>
-#include <AK/Utf32View.h>
-#include <AK/Vector.h>
-
-namespace Gfx {
-
-enum class BidirectionalClass {
-    STRONG_LTR,
-    STRONG_RTL,
-    WEAK_NUMBERS,
-    WEAK_SEPARATORS,
-    NEUTRAL,
-};
-
-extern Array<BidirectionalClass, 0x1F000> const char_bidi_class_lookup_table;
-
-constexpr BidirectionalClass get_char_bidi_class(u32 ch)
-{
-    if (ch >= char_bidi_class_lookup_table.size())
-        return BidirectionalClass::STRONG_LTR;
-    return char_bidi_class_lookup_table[ch];
-}
-
-// FIXME: These should be parsed from the official BidiMirroring.txt that specifies the mirroring character for each character (this function doesn't take into account a large amount of characters)
-constexpr u32 get_mirror_char(u32 ch)
-{
-    if (ch == 0x28)
-        return 0x29;
-    if (ch == 0x29)
-        return 0x28;
-    if (ch == 0x3C)
-        return 0x3E;
-    if (ch == 0x3E)
-        return 0x3C;
-    if (ch == 0x5B)
-        return 0x5D;
-    if (ch == 0x7B)
-        return 0x7D;
-    if (ch == 0x7D)
-        return 0x7B;
-    if (ch == 0xAB)
-        return 0xBB;
-    if (ch == 0xBB)
-        return 0xAB;
-    if (ch == 0x2039)
-        return 0x203A;
-    if (ch == 0x203A)
-        return 0x2039;
-    return ch;
-}
-
-enum class TextDirection {
-    LTR,
-    RTL,
-};
-
-constexpr TextDirection bidi_class_to_direction(BidirectionalClass class_)
-{
-    VERIFY(class_ != BidirectionalClass::NEUTRAL);
-    if (class_ == BidirectionalClass::STRONG_LTR || class_ == BidirectionalClass::WEAK_NUMBERS || class_ == BidirectionalClass::WEAK_SEPARATORS)
-        return TextDirection::LTR;
-    return TextDirection::RTL;
-}
-
-// Assumes the text has a homogeneous direction
-template<typename TextType>
-constexpr TextDirection get_text_direction(TextType text)
-{
-    for (u32 code_point : text) {
-        auto char_direction = get_char_bidi_class(code_point);
-        if (char_direction != BidirectionalClass::NEUTRAL)
-            return bidi_class_to_direction(char_direction);
-    }
-    return TextDirection::LTR;
-}
-
-class DirectionalRun {
-public:
-    DirectionalRun(Vector<u32> code_points, u8 embedding_level)
-        : m_code_points(move(code_points))
-        , m_embedding_level(embedding_level)
-    {
-    }
-
-    [[nodiscard]] Utf32View text() const { return { m_code_points.data(), m_code_points.size() }; }
-    [[nodiscard]] u8 embedding_level() const { return m_embedding_level; }
-    [[nodiscard]] TextDirection direction() const { return (m_embedding_level % 2) == 0 ? TextDirection::LTR : TextDirection::RTL; }
-
-    Vector<u32>& code_points() { return m_code_points; }
-
-private:
-    Vector<u32> m_code_points;
-    u8 m_embedding_level;
-};
-
-}

+ 0 - 16
Userland/Libraries/LibGfx/TextElision.h

@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-namespace Gfx {
-
-enum class TextElision {
-    None,
-    Right,
-};
-
-}

+ 0 - 179
Userland/Libraries/LibGfx/TextLayout.cpp

@@ -13,185 +13,6 @@
 
 
 namespace Gfx {
 namespace Gfx {
 
 
-enum class BlockType {
-    Newline,
-    Whitespace,
-    Word
-};
-
-struct Block {
-    BlockType type;
-    Utf8View characters;
-};
-
-FloatRect TextLayout::bounding_rect(TextWrapping wrapping) const
-{
-    auto lines = wrap_lines(TextElision::None, wrapping);
-    if (lines.is_empty()) {
-        return {};
-    }
-
-    FloatRect bounding_rect = {
-        0, 0, 0, (static_cast<float>(lines.size()) * (m_font_metrics.ascent + m_font_metrics.descent + m_font_metrics.line_gap)) - m_font_metrics.line_gap
-    };
-
-    for (auto& line : lines) {
-        auto line_width = m_font.width(line);
-        if (line_width > bounding_rect.width())
-            bounding_rect.set_width(line_width);
-    }
-
-    return bounding_rect;
-}
-
-Vector<ByteString, 32> TextLayout::wrap_lines(TextElision elision, TextWrapping wrapping) const
-{
-    Vector<Block> blocks;
-
-    Optional<BlockType> current_block_type;
-    size_t block_start_offset = 0;
-
-    size_t offset = 0;
-    for (auto it = m_text.begin(); !it.done(); ++it) {
-        offset = m_text.iterator_offset(it);
-
-        switch (*it) {
-        case '\t':
-        case ' ': {
-            if (current_block_type.has_value() && current_block_type.value() != BlockType::Whitespace) {
-                blocks.append({
-                    current_block_type.value(),
-                    m_text.substring_view(block_start_offset, offset - block_start_offset),
-                });
-                current_block_type.clear();
-            }
-
-            if (!current_block_type.has_value()) {
-                current_block_type = BlockType::Whitespace;
-                block_start_offset = offset;
-            }
-
-            continue;
-        }
-        case '\r':
-            if (it.peek(1) == static_cast<u32>('\n'))
-                ++it;
-            [[fallthrough]];
-        case '\n': {
-            if (current_block_type.has_value()) {
-                blocks.append({
-                    current_block_type.value(),
-                    m_text.substring_view(block_start_offset, offset - block_start_offset),
-                });
-                current_block_type.clear();
-            }
-
-            blocks.append({ BlockType::Newline, Utf8View {} });
-            continue;
-        }
-        default: {
-            if (current_block_type.has_value() && current_block_type.value() != BlockType::Word) {
-                blocks.append({
-                    current_block_type.value(),
-                    m_text.substring_view(block_start_offset, offset - block_start_offset),
-                });
-                current_block_type.clear();
-            }
-
-            if (!current_block_type.has_value()) {
-                current_block_type = BlockType::Word;
-                block_start_offset = offset;
-            }
-        }
-        }
-    }
-
-    if (current_block_type.has_value()) {
-        blocks.append({
-            current_block_type.value(),
-            m_text.substring_view(block_start_offset, m_text.byte_length() - block_start_offset),
-        });
-    }
-
-    Vector<ByteString> lines;
-    StringBuilder builder;
-    float line_width = 0;
-    for (Block& block : blocks) {
-        switch (block.type) {
-        case BlockType::Newline: {
-            lines.append(builder.to_byte_string());
-            builder.clear();
-            line_width = 0;
-            continue;
-        }
-        case BlockType::Whitespace:
-        case BlockType::Word: {
-            float block_width = m_font.width(block.characters);
-            // FIXME: This should look at the specific advance amount of the
-            //        last character, but we don't support that yet.
-
-            if (wrapping == TextWrapping::Wrap && line_width + block_width > m_rect.width()) {
-                lines.append(builder.to_byte_string());
-                builder.clear();
-                line_width = 0;
-            }
-
-            builder.append(block.characters.as_string());
-            line_width += block_width;
-        }
-        }
-    }
-
-    auto last_line = builder.to_byte_string();
-    if (!last_line.is_empty())
-        lines.append(last_line);
-
-    switch (elision) {
-    case TextElision::None:
-        break;
-    case TextElision::Right: {
-        lines.at(lines.size() - 1) = elide_text_from_right(Utf8View { lines.at(lines.size() - 1) });
-        break;
-    }
-    }
-
-    return lines;
-}
-
-ByteString TextLayout::elide_text_from_right(Utf8View text) const
-{
-    float text_width = m_font.width(text);
-    if (text_width > static_cast<float>(m_rect.width())) {
-        float ellipsis_width = m_font.width("..."sv);
-        float current_width = ellipsis_width;
-
-        // FIXME: This code will break when the font has glyphs with advance
-        //        amounts different from the actual width of the glyph
-        //        (which is the case with many TrueType fonts).
-        if (ellipsis_width < text_width) {
-            size_t offset = 0;
-            for (auto it = text.begin(); !it.done(); ++it) {
-                auto glyph_width = m_font.glyph_or_emoji_width(it);
-                // NOTE: Glyph spacing should not be added after the last glyph on the line,
-                //       but since we are here because the last glyph does not actually fit on the line,
-                //       we don't have to worry about spacing.
-                auto width_with_this_glyph_included = current_width + glyph_width;
-                if (width_with_this_glyph_included > m_rect.width())
-                    break;
-                current_width += glyph_width;
-                offset = text.iterator_offset(it);
-            }
-
-            StringBuilder builder;
-            builder.append(text.substring_view(0, offset).as_string());
-            builder.append("..."sv);
-            return builder.to_byte_string();
-        }
-    }
-
-    return text.as_string();
-}
-
 DrawGlyphOrEmoji prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font)
 DrawGlyphOrEmoji prepare_draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font)
 {
 {
     u32 code_point = *it;
     u32 code_point = *it;

+ 0 - 46
Userland/Libraries/LibGfx/TextLayout.h

@@ -17,55 +17,9 @@
 #include <LibGfx/FontCascadeList.h>
 #include <LibGfx/FontCascadeList.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Forward.h>
 #include <LibGfx/Rect.h>
 #include <LibGfx/Rect.h>
-#include <LibGfx/TextElision.h>
-#include <LibGfx/TextWrapping.h>
 
 
 namespace Gfx {
 namespace Gfx {
 
 
-// FIXME: This currently isn't an ideal way of doing things; ideally, TextLayout
-// would be doing the rendering by painting individual glyphs. However, this
-// would regress our Unicode bidirectional text support. Therefore, fixing this
-// requires:
-// - Moving the bidirectional algorithm either here, or some place TextLayout
-//   can access;
-// - Making TextLayout render the given text into something like a Vector<Line>
-//   where:
-//   using Line = Vector<DirectionalRun>;
-//   struct DirectionalRun {
-//       Utf32View glyphs;
-//       Vector<int> advance;
-//       TextDirection direction;
-//   };
-// - Either;
-//   a) Making TextLayout output these Lines directly using a given Painter, or
-//   b) Taking the Lines from TextLayout and painting each glyph.
-class TextLayout {
-public:
-    TextLayout(Gfx::Font const& font, Utf8View const& text, FloatRect const& rect)
-        : m_font(font)
-        , m_font_metrics(font.pixel_metrics())
-        , m_text(text)
-        , m_rect(rect)
-    {
-    }
-
-    Vector<ByteString, 32> lines(TextElision elision, TextWrapping wrapping) const
-    {
-        return wrap_lines(elision, wrapping);
-    }
-
-    FloatRect bounding_rect(TextWrapping) const;
-
-private:
-    Vector<ByteString, 32> wrap_lines(TextElision, TextWrapping) const;
-    ByteString elide_text_from_right(Utf8View) const;
-
-    Font const& m_font;
-    FontPixelMetrics m_font_metrics;
-    Utf8View m_text;
-    FloatRect m_rect;
-};
-
 inline bool should_paint_as_space(u32 code_point)
 inline bool should_paint_as_space(u32 code_point)
 {
 {
     return is_ascii_space(code_point) || code_point == 0xa0;
     return is_ascii_space(code_point) || code_point == 0xa0;

+ 0 - 17
Userland/Libraries/LibGfx/TextWrapping.h

@@ -1,17 +0,0 @@
-/*
- * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
- * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-namespace Gfx {
-
-enum class TextWrapping {
-    Wrap,
-    DontWrap,
-};
-
-}

+ 0 - 3
Userland/Libraries/LibWeb/Painting/Command.h

@@ -24,10 +24,7 @@
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/TextAlignment.h>
 #include <LibGfx/TextAlignment.h>
-#include <LibGfx/TextDirection.h>
-#include <LibGfx/TextElision.h>
 #include <LibGfx/TextLayout.h>
 #include <LibGfx/TextLayout.h>
-#include <LibGfx/TextWrapping.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>

+ 0 - 3
Userland/Libraries/LibWeb/Painting/CommandList.h

@@ -23,10 +23,7 @@
 #include <LibGfx/Rect.h>
 #include <LibGfx/Rect.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/TextAlignment.h>
 #include <LibGfx/TextAlignment.h>
-#include <LibGfx/TextDirection.h>
-#include <LibGfx/TextElision.h>
 #include <LibGfx/TextLayout.h>
 #include <LibGfx/TextLayout.h>
-#include <LibGfx/TextWrapping.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>

+ 0 - 3
Userland/Libraries/LibWeb/Painting/RecordingPainter.h

@@ -24,10 +24,7 @@
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/ScalingMode.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/Size.h>
 #include <LibGfx/TextAlignment.h>
 #include <LibGfx/TextAlignment.h>
-#include <LibGfx/TextDirection.h>
-#include <LibGfx/TextElision.h>
 #include <LibGfx/TextLayout.h>
 #include <LibGfx/TextLayout.h>
-#include <LibGfx/TextWrapping.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/CSS/Enums.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiiData.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>
 #include <LibWeb/Painting/BorderRadiusCornerClipper.h>