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

SVG export module, converting drawing commands to SVG text #367

Open
wants to merge 41 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
d420b9f
export to svg
YGaurora Nov 8, 2024
8aecd42
update code
YGaurora Nov 27, 2024
044dcc7
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Nov 28, 2024
29d6acd
modify method
YGaurora Nov 28, 2024
89e3111
format code
YGaurora Nov 28, 2024
f2cb00d
format
YGaurora Nov 28, 2024
5e695ba
blur and shadow export
YGaurora Dec 4, 2024
5172467
remove unused code
YGaurora Dec 4, 2024
46eff0a
modify state stack
YGaurora Dec 4, 2024
89d2962
save
YGaurora Dec 4, 2024
cd1b226
...
YGaurora Dec 6, 2024
ea79d6f
...
YGaurora Dec 6, 2024
03351f9
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 6, 2024
ba97d37
refactor
YGaurora Dec 6, 2024
e45554f
remove unused code
YGaurora Dec 6, 2024
6559c09
unit test
YGaurora Dec 6, 2024
2f5cb4d
format
YGaurora Dec 6, 2024
578fb4e
fix code problem and export text as text
YGaurora Dec 11, 2024
7c1349b
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 11, 2024
d19f59c
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 11, 2024
ecf6dfd
...
YGaurora Dec 11, 2024
049d00c
format
YGaurora Dec 12, 2024
92f7863
optimize code and remove mistake
YGaurora Dec 17, 2024
e775c30
。。。
YGaurora Dec 17, 2024
93ce0a3
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 17, 2024
db206f9
format code
YGaurora Dec 17, 2024
922820d
fix compile error
YGaurora Dec 17, 2024
776637e
fix
YGaurora Dec 17, 2024
510050a
。。。
YGaurora Dec 19, 2024
89cfa3c
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 19, 2024
e40d4cf
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 19, 2024
70b168b
implement write stream and exporting flags
YGaurora Dec 19, 2024
8baff71
...
YGaurora Dec 19, 2024
8637e94
...
YGaurora Dec 20, 2024
ee42709
Merge remote-tracking branch 'origin/main' into feature/yg_drawcall_t…
YGaurora Dec 23, 2024
fa93f01
write stream
YGaurora Dec 23, 2024
9b061a0
support matrix color shader
YGaurora Dec 23, 2024
324c85a
optimize comment
YGaurora Dec 23, 2024
1968596
fix auto test
YGaurora Dec 23, 2024
7fce6b1
format code
YGaurora Dec 23, 2024
a1d73fc
format code
YGaurora Dec 23, 2024
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
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ if (MACOS AND CLION_IDE AND NOT HasParent)
option(TGFX_BUILD_TESTS "Build tgfx tests" ON)
endif ()

if (TGFX_BUILD_SVG)
set(TGFX_USE_PNG_ENCODE ON)
endif ()

if (TGFX_BUILD_TESTS)
set(TGFX_USE_FREETYPE ON)
set(TGFX_BUILD_DRAWERS ON)
Expand Down Expand Up @@ -204,6 +208,11 @@ if (TGFX_USE_ZLIB)
list(APPEND TGFX_STATIC_VENDORS zlib)
endif ()

if (TGFX_BUILD_SVG)
# SVG and PDF exports require glyphs to be convertible back to Unicode.
list(APPEND TGFX_DEFINES TGFX_USE_GLYPH_TO_UNICODE)
endif ()

if (TGFX_USE_FREETYPE)
list(APPEND TGFX_DEFINES TGFX_USE_FREETYPE)
list(APPEND TGFX_STATIC_VENDORS freetype)
Expand Down
2 changes: 2 additions & 0 deletions include/tgfx/core/Canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "tgfx/core/SamplingOptions.h"
#include "tgfx/core/Shape.h"
#include "tgfx/core/TextBlob.h"
#include "tgfx/svg/SVGExporter.h"

namespace tgfx {
class Surface;
Expand Down Expand Up @@ -430,5 +431,6 @@ class Canvas {
friend class Surface;
friend class Picture;
friend class Recorder;
friend class SVGExporter;
};
} // namespace tgfx
9 changes: 9 additions & 0 deletions include/tgfx/core/ColorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,21 @@ class ColorFilter {
return false;
}

protected:
enum class Type { Blend, Matrix, AlphaThreshold, Compose };

/**
* Returns the type of this color filter.
*/
virtual Type type() const = 0;

private:
virtual std::unique_ptr<FragmentProcessor> asFragmentProcessor() const = 0;

friend class RenderContext;
friend class ColorFilterShader;
friend class ComposeColorFilter;
friend class ColorImageFilter;
friend class ColorFilterCaster;
};
} // namespace tgfx
1 change: 1 addition & 0 deletions include/tgfx/core/ImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,6 @@ class ImageFilter {
friend class InnerShadowImageFilter;
friend class ComposeImageFilter;
friend class FilterImage;
friend class ImageFilterCaster;
};
} // namespace tgfx
2 changes: 2 additions & 0 deletions include/tgfx/core/Picture.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace tgfx {
class Record;
class Canvas;
class DrawContext;
class SVGExportingContext;
class MCState;
class Image;

Expand Down Expand Up @@ -64,6 +65,7 @@ class Picture {
friend class MeasureContext;
friend class RenderContext;
friend class RecordingContext;
friend class SVGExportingContext;
friend class Image;
friend class PictureImage;
friend class Canvas;
Expand Down
1 change: 1 addition & 0 deletions include/tgfx/core/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,5 +151,6 @@ class Shader {

friend class FragmentProcessor;
friend class Canvas;
friend class ShaderCaster;
};
} // namespace tgfx
9 changes: 9 additions & 0 deletions include/tgfx/core/Typeface.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <mutex>
#include <unordered_map>
#include <vector>
#include "tgfx/core/Data.h"

namespace tgfx {
Expand Down Expand Up @@ -131,11 +132,19 @@ class Typeface {
virtual std::shared_ptr<Data> copyTableData(FontTableTag tag) const = 0;

protected:
/**
* Gets the mapping from GlyphID to unicode. The array index is GlyphID, and the array value is
* unicode. The array length is glyphsCount().
* This method is only implemented when compiling the SVG or PDF export module.
*/
virtual std::vector<Unichar> getGlyphToUnicodeMap() const;

mutable std::mutex locker = {};

private:
std::unordered_map<float, std::weak_ptr<ScalerContext>> scalerContexts = {};

friend class ScalerContext;
friend class GlyphConverter;
};
} // namespace tgfx
125 changes: 125 additions & 0 deletions include/tgfx/svg/SVGExporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// 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/Rect.h"
#include "tgfx/core/WriteStream.h"
#include "tgfx/gpu/Context.h"

namespace tgfx {
class SVGExportingContext;

/**
* Defines flags for SVG exporting that influence the readability and functionality of the exported
* SVG.
*/
class SVGExportFlags {
public:
/**
* Converts text to paths in the exported SVG.
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
* By default, text is exported as text elements.
*
* Note:
* This only applies to fonts with outlines. Fonts without outlines, such as emoji and web fonts,
* will still be exported as text.
*/
static constexpr uint32_t ConvertTextToPaths = 1 << 0;

/**
* Disable pretty XML formatting in the exported SVG.
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
* By default, spaces ('\t') and newlines ('\n') are included in the exported SVG text for
* improved
*/
static constexpr uint32_t DisablePrettyXML = 1 << 1;

/**
* Disable unsupported attribute warnings.
* By default, warnings are logged to the console when exporting attributes that are not supported
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
* by the SVG standard.
*/
static constexpr uint32_t DisableWarnings = 1 << 2;
};

/**
* SVGExporter is a class used to export SVG text, converting drawing commands in the Canvas to
* SVG text.
*
* Unsupported SVG standard attributes:
* - Blend modes:
* Clear, Src, Dst, DstOver, SrcIn, DstIn, SrcOut, DstOut, SrcATop, DstATop, Xor, and Modulate are
* not supported.
*
* - Image filters:
* Compose and Runtime are not supported.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些可以渲染成图片,应该算能导出的,只是注释说一下不能按滤镜导出就行了。

*
* - Color filters:
* Blend is partially supported, similar to blend modes.
*
* - Shaders:
* ColorFilter,Blend,Matrix are not supported.Gradient shaders are partially supported.
*
* - Gradient shaders:
* Conic gradients are not supported.
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
*/
class SVGExporter {
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
public:
/**
* Creates a shared pointer to an SVG exporter object, which can be used to export SVG text.
*
* @param svgStream The stream to store the SVG text.
* @param context The context used to convert some rendering commands into image data.
* @param viewBox The viewBox of the SVG. Content that exceeds this area will be clipped.
* @param exportFlags Flags for exporting SVG text.
* @return A shared pointer to the SVG exporter object. If svgStream is nullptr, context is
* nullptr, or viewBox is empty, nullptr is returned.
*/
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
static std::shared_ptr<SVGExporter> Make(const std::shared_ptr<WriteStream>& svgStream,
Context* context, const Rect& viewBox,
uint32_t exportFlags = 0);

/**
* Destroys the SVG exporter object. If close() hasn't been called, it will be invoked
* automatically.It will finalize any unfinished drawing commands and write the SVG end tag.
YGaurora marked this conversation as resolved.
Show resolved Hide resolved
*/
~SVGExporter();

/**
* Returns the canvas for exporting if the SVGExporter is not closed; otherwise, returns nullptr.
*/
Canvas* getCanvas() const;

/**
* Closes the SVG exporter,finalizing any unfinished drawing commands and writing the SVG end tag.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

逗号后也要加空格,全部检查一遍吧。

*/
void close();

private:
/**
* Construct a SVG exporter object
*/
SVGExporter(const std::shared_ptr<WriteStream>& svgStream, Context* context, const Rect& viewBox,
uint32_t exportFlags);

SVGExportingContext* drawContext = nullptr;
Canvas* canvas = nullptr;
};

} // namespace tgfx
1 change: 0 additions & 1 deletion qt/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include "qobject.h"

int main(int argc, char* argv[]) {

QApplication::setApplicationName("Hello2D");
QApplication::setOrganizationName("org.tgfx");
QSurfaceFormat defaultFormat = QSurfaceFormat();
Expand Down
11 changes: 11 additions & 0 deletions src/core/Typeface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/////////////////////////////////////////////////////////////////////////////////////////////////

#include "tgfx/core/Typeface.h"
#include <vector>
#include "core/utils/UniqueID.h"
#include "tgfx/core/UTF.h"

Expand Down Expand Up @@ -63,6 +64,11 @@ class EmptyTypeface : public Typeface {
return nullptr;
}

protected:
std::vector<Unichar> getGlyphToUnicodeMap() const override {
return {};
}

private:
uint32_t _uniqueID = UniqueID::Next();
};
Expand All @@ -84,4 +90,9 @@ GlyphID Typeface::getGlyphID(const std::string& name) const {
auto unichar = UTF::NextUTF8(&start, start + name.size());
return getGlyphID(unichar);
}

std::vector<Unichar> Typeface::getGlyphToUnicodeMap() const {
return {};
};

} // namespace tgfx
5 changes: 5 additions & 0 deletions src/core/filters/AlphaThresholdColorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ class AlphaThresholdColorFilter : public ColorFilter {
public:
explicit AlphaThresholdColorFilter(float threshold) : threshold(threshold){};

protected:
Type type() const override {
return Type::AlphaThreshold;
};

private:
std::unique_ptr<FragmentProcessor> asFragmentProcessor() const override;

Expand Down
5 changes: 5 additions & 0 deletions src/core/filters/ComposeColorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ class ComposeColorFilter : public ColorFilter {

bool isAlphaUnchanged() const override;

protected:
Type type() const override {
return Type::Compose;
};

private:
std::shared_ptr<ColorFilter> inner = nullptr;
std::shared_ptr<ColorFilter> outer = nullptr;
Expand Down
8 changes: 7 additions & 1 deletion src/core/filters/MatrixColorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ class MatrixColorFilter : public ColorFilter {
return alphaIsUnchanged;
}

private:
std::array<float, 20> matrix;

protected:
Type type() const override {
return Type::Matrix;
};

private:
bool alphaIsUnchanged;

std::unique_ptr<FragmentProcessor> asFragmentProcessor() const override;
Expand Down
7 changes: 6 additions & 1 deletion src/core/filters/ModeColorFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ class ModeColorFilter : public ColorFilter {

bool asColorMode(Color* color, BlendMode* mode) const override;

private:
Color color;
BlendMode mode;

protected:
Type type() const override {
return Type::Blend;
};

private:
std::unique_ptr<FragmentProcessor> asFragmentProcessor() const override;
};
} // namespace tgfx
Loading
Loading