Coverage Report

Created: 2026-05-16 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibGfx/ImageFormats/TinyVGLoader.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2023, MacDue <macdue@dueutil.tech>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Forward.h>
10
#include <AK/OwnPtr.h>
11
#include <AK/Variant.h>
12
#include <AK/Vector.h>
13
#include <LibGfx/Color.h>
14
#include <LibGfx/Forward.h>
15
#include <LibGfx/ImageFormats/ImageDecoder.h>
16
#include <LibGfx/PaintStyle.h>
17
#include <LibGfx/Path.h>
18
#include <LibGfx/VectorGraphic.h>
19
20
namespace Gfx {
21
22
// Current recommended SVG to TVG conversion (without installing tools)
23
// (FIXME: Implement our own converter!)
24
// 1. (Optional) Convert strokes to fills
25
//  * Only round joins/linecaps exist in TVG, so for other stroke kinds converting
26
//    them to fills (that still beziers etc, so are scalable) works better.
27
//  * This site can do that: https://iconly.io/tools/svg-convert-stroke-to-fill
28
// 2. Scale your SVG's width/height to large size (e.g. 1024x?)
29
//  * Current converters deal poorly with small values in paths.
30
//  * This site can do that: https://www.iloveimg.com/resize-image/resize-svg
31
//    (or just edit the viewbox if it has one).
32
// 3. Convert the SVG to a TVG
33
//  * This site can do that: https://svg-to-tvg-server.fly.dev/
34
35
// Decoder from the "Tiny Vector Graphics" format (v1.0).
36
// https://tinyvg.tech/download/specification.pdf
37
38
struct TinyVGHeader;
39
40
class TinyVGDecodedImageData final : public VectorGraphic {
41
public:
42
    using Style = Variant<Color, NonnullRefPtr<SVGGradientPaintStyle>>;
43
44
    struct DrawCommand {
45
        Path path;
46
        Optional<Style> fill {};
47
        Optional<Style> stroke {};
48
        float stroke_width { 0.0f };
49
    };
50
51
    virtual IntSize intrinsic_size() const override
52
831
    {
53
831
        return m_size;
54
831
    }
55
56
    virtual void draw_transformed(Painter&, AffineTransform) const override;
57
58
    ReadonlySpan<DrawCommand> draw_commands() const
59
414
    {
60
414
        return m_draw_commands;
61
414
    }
62
63
    static ErrorOr<NonnullRefPtr<TinyVGDecodedImageData>> decode(Stream& stream);
64
    static ErrorOr<NonnullRefPtr<TinyVGDecodedImageData>> decode(Stream& stream, TinyVGHeader const& header);
65
66
private:
67
    TinyVGDecodedImageData(IntSize size, Vector<DrawCommand> draw_commands)
68
417
        : m_size(size)
69
417
        , m_draw_commands(move(draw_commands))
70
417
    {
71
417
    }
72
73
    IntSize m_size;
74
    Vector<DrawCommand> m_draw_commands;
75
};
76
77
struct TinyVGLoadingContext;
78
79
class TinyVGImageDecoderPlugin final : public ImageDecoderPlugin {
80
public:
81
    static bool sniff(ReadonlyBytes);
82
    static ErrorOr<NonnullOwnPtr<ImageDecoderPlugin>> create(ReadonlyBytes);
83
84
    virtual IntSize size() override;
85
    virtual ErrorOr<ImageFrameDescriptor> frame(size_t index, Optional<IntSize> ideal_size = {}) override;
86
87
0
    virtual NaturalFrameFormat natural_frame_format() const override { return NaturalFrameFormat::Vector; }
88
    virtual ErrorOr<VectorImageFrameDescriptor> vector_frame(size_t index) override;
89
90
    virtual ~TinyVGImageDecoderPlugin() override;
91
92
private:
93
    TinyVGImageDecoderPlugin(ReadonlyBytes);
94
95
    NonnullOwnPtr<TinyVGLoadingContext> m_context;
96
};
97
98
}