Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkSVGOpenTypeSVGDecoder.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
13#include "include/core/SkSpan.h"
23#include "src/base/SkBase64.h"
25
26#include <memory>
27
28using namespace skia_private;
29
30namespace {
31class DataResourceProvider final : public skresources::ResourceProvider {
32public:
34 return sk_sp<skresources::ResourceProvider>(new DataResourceProvider());
35 }
36
38 const char rname[],
39 const char rid[]) const override {
40 if (auto data = decode_datauri("data:image/", rname)) {
41 std::unique_ptr<SkCodec> codec = nullptr;
42 if (SkPngDecoder::IsPng(data->bytes(), data->size())) {
43 codec = SkPngDecoder::Decode(data, nullptr);
44 } else if (SkJpegDecoder::IsJpeg(data->bytes(), data->size())) {
45 codec = SkJpegDecoder::Decode(data, nullptr);
46 } else {
47 // The spec says only JPEG or PNG should be used to encode the embedded data.
48 // https://learn.microsoft.com/en-us/typography/opentype/spec/svg#svg-capability-requirements-and-restrictions
49 SkDEBUGFAIL("Unsupported codec");
50 return nullptr;
51 }
52 if (!codec) {
53 return nullptr;
54 }
55 return skresources::MultiFrameImageAsset::Make(std::move(codec));
56 }
57 return nullptr;
58 }
59
60private:
61 DataResourceProvider() = default;
62
63 static sk_sp<SkData> decode_datauri(const char prefix[], const char uri[]) {
64 // We only handle B64 encoded image dataURIs: data:image/<type>;base64,<data>
65 // (https://en.wikipedia.org/wiki/Data_URI_scheme)
66 static constexpr char kDataURIEncodingStr[] = ";base64,";
67
68 const size_t prefixLen = strlen(prefix);
69 if (strncmp(uri, prefix, prefixLen) != 0) {
70 return nullptr;
71 }
72
73 const char* encoding = strstr(uri + prefixLen, kDataURIEncodingStr);
74 if (!encoding) {
75 return nullptr;
76 }
77
78 const char* b64Data = encoding + std::size(kDataURIEncodingStr) - 1;
79 size_t b64DataLen = strlen(b64Data);
80 size_t dataLen;
81 if (SkBase64::Decode(b64Data, b64DataLen, nullptr, &dataLen) != SkBase64::kNoError) {
82 return nullptr;
83 }
84
86 void* rawData = data->writable_data();
87 if (SkBase64::Decode(b64Data, b64DataLen, rawData, &dataLen) != SkBase64::kNoError) {
88 return nullptr;
89 }
90
91 return data;
92 }
93
95};
96} // namespace
97
98SkSVGOpenTypeSVGDecoder::SkSVGOpenTypeSVGDecoder(sk_sp<SkSVGDOM> skSvg, size_t approximateSize)
99 : fSkSvg(std::move(skSvg))
100 , fApproximateSize(approximateSize)
101{}
102
104
105std::unique_ptr<SkOpenTypeSVGDecoder> SkSVGOpenTypeSVGDecoder::Make(const uint8_t* svg,
106 size_t svgLength) {
107 std::unique_ptr<SkStreamAsset> stream = SkMemoryStream::MakeDirect(svg, svgLength);
108 if (!stream) {
109 return nullptr;
110 }
111 SkSVGDOM::Builder builder;
112 builder.setResourceProvider(DataResourceProvider::Make());
113 // We shouldn't need to set this builder's font manager or shaping utils because hopefully
114 // the SVG we are decoding doesn't itself have <text> tags.
115 sk_sp<SkSVGDOM> skSvg = builder.make(*stream);
116 if (!skSvg) {
117 return nullptr;
118 }
119 return std::unique_ptr<SkOpenTypeSVGDecoder>(
120 new SkSVGOpenTypeSVGDecoder(std::move(skSvg), svgLength));
121}
122
124 // TODO
125 return fApproximateSize;
126}
127
128bool SkSVGOpenTypeSVGDecoder::render(SkCanvas& canvas, int upem, SkGlyphID glyphId,
129 SkColor foregroundColor, SkSpan<SkColor> palette) {
130 SkSize emSize = SkSize::Make(SkScalar(upem), SkScalar(upem));
131 fSkSvg->setContainerSize(emSize);
132
134 pctx.fInherited.fColor.set(foregroundColor);
135
137 if (!palette.empty()) {
138 for (auto&& [i, color] : SkMakeEnumerate(palette)) {
139 constexpr const size_t colorStringLen = sizeof("color") - 1;
140 char colorIdString[colorStringLen + kSkStrAppendU32_MaxSize + 1] = "color";
141 *SkStrAppendU32(colorIdString + colorStringLen, i) = 0;
142
143 namedColors.set(SkString(colorIdString), color);
144 }
145 pctx.fNamedColors = &namedColors;
146 }
147
148 constexpr const size_t glyphStringLen = sizeof("glyph") - 1;
149 char glyphIdString[glyphStringLen + kSkStrAppendU32_MaxSize + 1] = "glyph";
150 *SkStrAppendU32(glyphIdString + glyphStringLen, glyphId) = 0;
151
152 fSkSvg->renderNode(&canvas, pctx, glyphIdString);
153 return true;
154}
SkColor4f color
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
uint32_t SkColor
Definition SkColor.h:37
constexpr SkEnumerate< Iter > SkMakeEnumerate(C &c)
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
#define INHERITED(method,...)
static constexpr int kSkStrAppendU32_MaxSize
Definition SkString.h:84
char * SkStrAppendU32(char buffer[], uint32_t)
Definition SkString.cpp:100
uint16_t SkGlyphID
Definition SkTypes.h:179
skresources::ResourceProvider ResourceProvider
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition SkData.cpp:116
static std::unique_ptr< SkMemoryStream > MakeDirect(const void *data, size_t length)
Definition SkStream.cpp:310
void renderNode(SkCanvas *, SkSVGPresentationContext &, const char *id) const
Definition SkSVGDOM.cpp:467
void setContainerSize(const SkSize &)
Definition SkSVGDOM.cpp:488
~SkSVGOpenTypeSVGDecoder() override
static std::unique_ptr< SkOpenTypeSVGDecoder > Make(const uint8_t *svg, size_t svgLength)
bool render(SkCanvas &, int upem, SkGlyphID glyphId, SkColor foregroundColor, SkSpan< SkColor > palette) override
void set(SkSVGPropertyState state)
Definition SkSVGTypes.h:70
constexpr bool empty() const
Definition SkSpan_impl.h:96
V * set(K key, V val)
Definition SkTHash.h:472
static sk_sp< MultiFrameImageAsset > Make(sk_sp< SkData >, ImageDecodeStrategy=ImageDecodeStrategy::kLazyDecode)
virtual sk_sp< ImageAsset > loadImageAsset(const char[], const char[], const char[]) const
float SkScalar
Definition extension.cpp:12
SK_API bool IsJpeg(const void *, size_t)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API std::unique_ptr< SkCodec > Decode(std::unique_ptr< SkStream >, SkCodec::Result *, SkCodecs::DecodeContext=nullptr)
SK_API bool IsPng(const void *, size_t)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switches.h:41
static sk_sp< SkData > decode_datauri(const char prefix[], const char uri[])
Definition ref_ptr.h:256
static Error Decode(const void *src, size_t srcLength, void *dst, size_t *dstLength)
Definition SkBase64.cpp:37
@ kNoError
Definition SkBase64.h:16
SkSVGProperty< SkSVGColorType, true > fColor
SkSVGPresentationAttributes fInherited
const skia_private::THashMap< SkString, SkSVGColorType > * fNamedColors
static constexpr SkSize Make(SkScalar w, SkScalar h)
Definition SkSize.h:56
const char * svg