Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SVG import and rendering features #419

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
af6427b
svg to dom,and svg render
YGaurora Nov 14, 2024
b1db872
commit before context structure refactor
YGaurora Nov 15, 2024
f44ade3
debug and unit test
YGaurora Nov 20, 2024
7ed7413
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Nov 25, 2024
2d7b6ae
debug render
YGaurora Nov 25, 2024
ab8d893
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Nov 28, 2024
e24c3e9
format
YGaurora Nov 28, 2024
ccbed6f
typo
YGaurora Nov 28, 2024
0634b65
modify SVGFeGaussianBlur sigma scale
YGaurora Dec 2, 2024
1c6d8f8
save
YGaurora Dec 2, 2024
77ae5bc
formate code
YGaurora Dec 5, 2024
89ad985
...
YGaurora Dec 6, 2024
b481e14
format
YGaurora Dec 12, 2024
6a5cd29
format code
YGaurora Dec 12, 2024
a482430
format
YGaurora Dec 17, 2024
fff9fa5
...
YGaurora Dec 18, 2024
348f70e
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Dec 18, 2024
0d86fbb
...
YGaurora Dec 18, 2024
dc52e04
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Dec 23, 2024
e4e18a8
save
YGaurora Dec 24, 2024
19c3c4a
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Dec 26, 2024
de6c97f
...
YGaurora Dec 26, 2024
4061f68
Merge remote-tracking branch 'origin/main' into feature/svg_parse_to_dom
YGaurora Dec 27, 2024
e5160a5
...
YGaurora Dec 30, 2024
ac521d1
...
YGaurora Dec 30, 2024
13c0a7b
interface for user and base attribute class define
YGaurora Dec 30, 2024
966e60b
...
YGaurora Dec 30, 2024
0a88c2b
。。。
YGaurora Jan 2, 2025
a0083fc
Merge branch 'feature/SVG_parser_interface_base_attr' into feature/sv…
YGaurora Jan 3, 2025
ad18a8c
...
YGaurora Jan 3, 2025
cb1e492
...
YGaurora Jan 3, 2025
bccd2c7
typo
YGaurora Jan 3, 2025
9f60098
typo
YGaurora Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions include/tgfx/svg/SVGAttribute.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making tgfx available.
//
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// unless required by applicable law or agreed to in writing, software distributed under the
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
// either express or implied. see the license for the specific language governing permissions
// and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "tgfx/svg/SVGTypes.h"

namespace tgfx {
enum class SVGAttribute {
ClipRule,
Color,
ColorInterpolation,
ColorInterpolationFilters,
Cx, // <circle>, <ellipse>, <radialGradient>: center x position
Cy, // <circle>, <ellipse>, <radialGradient>: center y position
Fill,
FillOpacity,
FillRule,
Filter,
FilterUnits,
FontFamily,
FontSize,
FontStyle,
FontWeight,
Fx, // <radialGradient>: focal point x position
Fy, // <radialGradient>: focal point y position
GradientUnits,
GradientTransform,
Height,
Href,
Opacity,
Points,
PreserveAspectRatio,
R, // <circle>, <radialGradient>: radius
Rx, // <ellipse>,<rect>: horizontal (corner) radius
Ry, // <ellipse>,<rect>: vertical (corner) radius
SpreadMethod,
Stroke,
StrokeDashArray,
StrokeDashOffset,
StrokeOpacity,
StrokeLineCap,
StrokeLineJoin,
StrokeMiterLimit,
StrokeWidth,
Transform,
Text,
TextAnchor,
ViewBox,
Visibility,
Width,
X,
X1, // <line>: first endpoint x
X2, // <line>: second endpoint x
Y,
Y1, // <line>: first endpoint y
Y2, // <line>: second endpoint y

Unknown,
};

struct SVGPresentationAttributes {
static SVGPresentationAttributes MakeInitial();

SVGProperty<SVGPaint, true> Fill;
SVGProperty<SVGNumberType, true> FillOpacity;
SVGProperty<SVGFillRule, true> FillRule;
SVGProperty<SVGFillRule, true> ClipRule;

SVGProperty<SVGPaint, true> Stroke;
SVGProperty<SVGDashArray, true> StrokeDashArray;
SVGProperty<SVGLength, true> StrokeDashOffset;
SVGProperty<SVGLineCap, true> StrokeLineCap;
SVGProperty<SVGLineJoin, true> StrokeLineJoin;
SVGProperty<SVGNumberType, true> StrokeMiterLimit;
SVGProperty<SVGNumberType, true> StrokeOpacity;
SVGProperty<SVGLength, true> StrokeWidth;

SVGProperty<SVGVisibility, true> Visibility;

SVGProperty<SVGColorType, true> Color;
SVGProperty<SVGColorspace, true> ColorInterpolation;
SVGProperty<SVGColorspace, true> ColorInterpolationFilters;

SVGProperty<SVGFontFamily, true> FontFamily;
SVGProperty<SVGFontStyle, true> FontStyle;
SVGProperty<SVGFontSize, true> FontSize;
SVGProperty<SVGFontWeight, true> FontWeight;
SVGProperty<SVGTextAnchor, true> TextAnchor;

// uninherited
SVGProperty<SVGNumberType, false> Opacity;
SVGProperty<SVGFuncIRI, false> ClipPath;
SVGProperty<SVGDisplay, false> Display;
SVGProperty<SVGFuncIRI, false> Mask;
SVGProperty<SVGFuncIRI, false> Filter;
SVGProperty<SVGColor, false> StopColor;
SVGProperty<SVGNumberType, false> StopOpacity;
SVGProperty<SVGColor, false> FloodColor;
SVGProperty<SVGNumberType, false> FloodOpacity;
SVGProperty<SVGColor, false> LightingColor;
};
} // namespace tgfx
100 changes: 100 additions & 0 deletions include/tgfx/svg/SVGDOM.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making tgfx available.
//
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// unless required by applicable law or agreed to in writing, software distributed under the
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
// either express or implied. see the license for the specific language governing permissions
// and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <memory>
#include "tgfx/core/Canvas.h"
#include "tgfx/core/Data.h"
#include "tgfx/core/Picture.h"
#include "tgfx/core/Size.h"
#include "tgfx/svg/SVGFontManager.h"
#include "tgfx/svg/node/SVGSVG.h"

namespace tgfx {

class SVGNode;
using SVGIDMapper = std::unordered_map<std::string, std::shared_ptr<SVGNode>>;

/**
* The SVGDOM class represents an SVG Document Object Model (DOM). It provides functionality to
* traverse the SVG DOM tree and render the SVG.
*
* Usage:
*
* 1. Traversing the SVG DOM tree:
* - Use getRoot() to obtain the root node. From the root node, you can access its attributes
* and child nodes, and then visit the child nodes.
*
* 2. Rendering the SVG:
* - The simplest way to render is by calling render(canvas,nullptr). If you need to render text
* with specific fonts or set the size of the SVG, you can use the following methods.
* - If text rendering is required, use collectRenderFonts() to gather the necessary typefaces.
* Traverse the typefaces collected by the fontManager and set the typeface objects.
* - Render the SVG using the render() method. If text rendering is needed, pass in the
* fontManager object. Otherwise, you can pass in nullptr.
* - To set the size of the SVG, use setContainerSize(). If not set, the size of the root SVG
* node will be used.
*/
class SVGDOM {
public:
/**
* Creates an SVGDOM object from the provided data.
*/
static std::shared_ptr<SVGDOM> Make(const std::shared_ptr<Data>& data);

/**
* Returns the root SVG node.
*/
const std::shared_ptr<SVGSVG>& getRoot() const;

/**
* Collects the font families and styles used for rendering and saves them in the font manager.
*/
void collectRenderFonts(const std::shared_ptr<SVGFontManager>& fontManager);

/**
* Renders the SVG to the provided canvas.
* @param canvas The canvas to render to.
* @param fontManager The font manager for rendering SVG text. If no text rendering is needed,
* this can be nullptr, and text will not be rendered. If no specific font is set, the default
* font will be used for rendering.
*/
void render(Canvas* canvas, const std::shared_ptr<SVGFontManager>& fontManager = nullptr);

/**
* Sets the size of the container that the SVG will be rendered into.
*/
void setContainerSize(const Size& size);

/**
* Returns the size of the container that the SVG will be rendered into.
*/
const Size& getContainerSize() const;

private:
/**
* Construct a new SVGDOM object
*/
SVGDOM(std::shared_ptr<SVGSVG> root, SVGIDMapper&& mapper);

const std::shared_ptr<SVGSVG> root = nullptr;
const SVGIDMapper nodeIDMapper = {};
Size containerSize = {};
};
} // namespace tgfx
114 changes: 114 additions & 0 deletions include/tgfx/svg/SVGFontManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tencent is pleased to support the open source community by making tgfx available.
//
// Copyright (C) 2024 THL A29 Limited, a Tencent company. All rights reserved.
//
// Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// https://opensource.org/licenses/BSD-3-Clause
//
// unless required by applicable law or agreed to in writing, software distributed under the
// license is distributed on an "as is" basis, without warranties or conditions of any kind,
// either express or implied. see the license for the specific language governing permissions
// and limitations under the license.
//
/////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include <algorithm>
#include <memory>
#include <unordered_map>
#include <vector>
#include "tgfx/core/Typeface.h"
#include "tgfx/svg/SVGTypes.h"
#include "tgfx/svg/node/SVGNode.h"
namespace tgfx {

/**
* Information about SVG fonts, including weight and style (Oblique, Italic, Normal).
*/
class SVGFontInfo {
public:
struct Hash {
std::size_t operator()(const SVGFontInfo& info) const {
return std::hash<int>()(static_cast<int>(info._weight)) ^
std::hash<int>()(static_cast<int>(info._style));
}
};

SVGFontInfo(SVGFontWeight::Type weight, SVGFontStyle::Type style)
: _weight(weight), _style(style) {
}

bool operator==(const SVGFontInfo& other) const {
return _weight == other._weight && _style == other._style;
}

SVGFontWeight::Type weight() const {
return _weight;
}
SVGFontStyle::Type style() const {
return _style;
}

private:
SVGFontWeight::Type _weight;
SVGFontStyle::Type _style;
};

/**
* Manages fonts for SVG rendering, using fontFamily and SVGFontInfo as keys to store Typeface
* objects.
*/
class SVGFontManager {
public:
/**
* Creates an SVGFontManager object with the default typeface. If the default typeface is nullptr,
* retrun nullptr.
*/
static std::shared_ptr<SVGFontManager> Make(const std::shared_ptr<Typeface>& defaultTypeface);

/**
* Destructor.
*/
~SVGFontManager() = default;

/**
* Adds a font style to the font manager. If the font family and style already exist, this method
* does nothing and returns false.
*/
bool setTypeface(const std::string& fontFamily, SVGFontInfo info,
const std::shared_ptr<Typeface>& typeface);

/**
* Get the font families stored in the font manager.
*/
std::vector<std::string> getFontFamilies() const;

/**
* Get the font styles stored in the font manager for the specified font family.
*/
std::vector<SVGFontInfo> getFontInfos(const std::string& fontFamily) const;

protected:
void addFontStyle(const std::string& fontFamily, SVGFontInfo info);

std::shared_ptr<Typeface> getTypefaceForRendering(const std::string& fontFamily,
SVGFontInfo info) const;

private:
explicit SVGFontManager(const std::shared_ptr<Typeface>& typeface);

std::unordered_map<std::string,
std::unordered_map<SVGFontInfo, std::shared_ptr<Typeface>, SVGFontInfo::Hash>>
typefaceMap;
std::shared_ptr<Typeface> defaultTypeface;

friend class SVGRenderContext;
friend class SVGDOM;
};

} // namespace tgfx
Loading
Loading