-
Notifications
You must be signed in to change notification settings - Fork 70
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
base: main
Are you sure you want to change the base?
Changes from all commits
d420b9f
8aecd42
044dcc7
29d6acd
89e3111
f2cb00d
5e695ba
5172467
46eff0a
89d2962
cd1b226
ea79d6f
03351f9
ba97d37
e45554f
6559c09
2f5cb4d
578fb4e
7c1349b
d19f59c
ecf6dfd
049d00c
92f7863
e775c30
93ce0a3
db206f9
922820d
776637e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// 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 <sstream> | ||
#include "tgfx/core/Canvas.h" | ||
#include "tgfx/core/Rect.h" | ||
#include "tgfx/gpu/Context.h" | ||
|
||
namespace tgfx { | ||
class SVGExportingContext; | ||
|
||
struct ExportingOptions { | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ExportingOptions() = default; | ||
ExportingOptions(bool convertTextToPaths, bool prettyXML) | ||
: convertTextToPaths(convertTextToPaths), prettyXML(prettyXML) { | ||
} | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* Convert text to paths in the exported SVG text, only applicable to outline fonts. Emoji and | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* web fonts will only be exported as text. | ||
*/ | ||
bool convertTextToPaths = false; | ||
/** | ||
* Format SVG text with spaces('/t') and newlines('/n'). | ||
*/ | ||
bool prettyXML = true; | ||
}; | ||
|
||
/** | ||
* SVGExporter is a class used to export SVG text, converting drawing commands in the Canvas to | ||
* SVG text. | ||
*/ | ||
class SVGExporter { | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public: | ||
/** | ||
* Creates an SVGExporter object pointer, which can be used to export SVG text. | ||
* | ||
* @param svgStream The string stream to store the SVG text. | ||
* @param context used to convert some rendering commands into image data. | ||
* @param viewBox viewBox of SVG, and content that exceeds the display area in the | ||
* SVG will be clipped. | ||
* @param options Options for exporting SVG text. | ||
*/ | ||
static std::shared_ptr<SVGExporter> Make(std::stringstream& svgStream, Context* context, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里不能直接用std::stringsteam, 这个会一直在内存里,我们之所以要支持stream就是为了可以减少内存占用,背后可以包装一个FILE对象,直接写入磁盘。这里应该像Skia一样定义一个WStream基类,但是提供一些基本的实现,有FileWStream,也可以创建MemoryWStream,内部实现再包装std::stringstream |
||
const Rect& viewBox, ExportingOptions options); | ||
|
||
/** | ||
* Destroys the SVGExporter object, equivalent to calling close(). | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
~SVGExporter(); | ||
|
||
/** | ||
* Get the canvas if the SVGExporter is not closed.if closed, return nullptr. | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
Canvas* getCanvas() const; | ||
|
||
/** | ||
* Closes the SVGExporter.Finalizing any unfinished drawing commands and writing the SVG end tag. | ||
YGaurora marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
void close(); | ||
|
||
private: | ||
/** | ||
* Construct a SVGExporter object | ||
*/ | ||
SVGExporter(std::stringstream& svgStream, Context* context, const Rect& viewBox, | ||
ExportingOptions options); | ||
|
||
bool closed = false; | ||
SVGExportingContext* drawContext = nullptr; | ||
Canvas* canvas = nullptr; | ||
}; | ||
|
||
} // namespace tgfx |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// 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. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include "Caster.h" | ||
|
||
namespace tgfx { | ||
std::shared_ptr<const ColorShader> ShaderCaster::AsColorShader( | ||
const std::shared_ptr<Shader>& shader) { | ||
if (shader->type() == Shader::Type::Color) { | ||
return std::static_pointer_cast<const ColorShader>(shader); | ||
} | ||
return nullptr; | ||
} | ||
|
||
std::shared_ptr<const ImageShader> ShaderCaster::AsImageShader( | ||
const std::shared_ptr<Shader>& shader) { | ||
if (shader->type() == Shader::Type::Image) { | ||
return std::static_pointer_cast<const ImageShader>(shader); | ||
} | ||
return nullptr; | ||
} | ||
|
||
std::shared_ptr<const GradientShader> ShaderCaster::AsGradientShader( | ||
const std::shared_ptr<Shader>& shader) { | ||
if (shader->type() == Shader::Type::Gradient) { | ||
return std::static_pointer_cast<const GradientShader>(shader); | ||
} | ||
return nullptr; | ||
} | ||
|
||
std::shared_ptr<const BlurImageFilter> ImageFilterCaster::AsBlurImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter) { | ||
if (imageFilter->type() == ImageFilter::Type::Blur) { | ||
return std::static_pointer_cast<const BlurImageFilter>(imageFilter); | ||
} | ||
return nullptr; | ||
} | ||
std::shared_ptr<const DropShadowImageFilter> ImageFilterCaster::AsDropShadowImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter) { | ||
if (imageFilter->type() == ImageFilter::Type::DropShadow) { | ||
return std::static_pointer_cast<const DropShadowImageFilter>(imageFilter); | ||
} | ||
return nullptr; | ||
} | ||
|
||
std::shared_ptr<const InnerShadowImageFilter> ImageFilterCaster::AsInnerShadowImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter) { | ||
if (imageFilter->type() == ImageFilter::Type::InnerShadow) { | ||
return std::static_pointer_cast<const InnerShadowImageFilter>(imageFilter); | ||
} | ||
return nullptr; | ||
} | ||
|
||
} // namespace tgfx |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
// | ||
// 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. | ||
// | ||
///////////////////////////////////////////////////////////////////////////////////////////////// | ||
|
||
#include <memory> | ||
#include "core/filters/BlurImageFilter.h" | ||
#include "core/filters/DropShadowImageFilter.h" | ||
#include "core/filters/InnerShadowImageFilter.h" | ||
#include "core/shaders/ColorShader.h" | ||
#include "core/shaders/GradientShader.h" | ||
#include "core/shaders/ImageShader.h" | ||
|
||
#pragma once | ||
|
||
namespace tgfx { | ||
|
||
class ShaderCaster { | ||
public: | ||
static std::shared_ptr<const ColorShader> AsColorShader(const std::shared_ptr<Shader>& shader); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个方法有地方使用吗?没搜索到调用的地方,下面的几个方法都看看是在哪些地方使用的。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
static std::shared_ptr<const ImageShader> AsImageShader(const std::shared_ptr<Shader>& shader); | ||
|
||
static std::shared_ptr<const GradientShader> AsGradientShader( | ||
const std::shared_ptr<Shader>& shader); | ||
}; | ||
|
||
class ImageFilterCaster { | ||
public: | ||
static std::shared_ptr<const BlurImageFilter> AsBlurImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter); | ||
|
||
static std::shared_ptr<const DropShadowImageFilter> AsDropShadowImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter); | ||
|
||
static std::shared_ptr<const InnerShadowImageFilter> AsInnerShadowImageFilter( | ||
const std::shared_ptr<ImageFilter>& imageFilter); | ||
}; | ||
|
||
} // namespace tgfx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里的vector表示了两层含义,替代了map的作用,理解上不是太直观
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
它这里要兼顾性能,GlyphID是连续线性,直接构造vector的查性能最高,用map会很慢。Skia也是这么处理。