xref: /aosp_15_r20/external/skia/modules/svg/utils/SvgTool.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 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 
8 #include <iostream>
9 
10 #include "include/core/SkMatrix.h"
11 #include "include/core/SkStream.h"
12 #include "include/core/SkSurface.h"
13 #include "include/encode/SkPngEncoder.h"
14 #include "modules/skresources/include/SkResources.h"
15 #include "modules/skshaper/utils/FactoryHelpers.h"
16 #include "modules/svg/include/SkSVGDOM.h"
17 #include "src/utils/SkOSPath.h"
18 #include "tools/CodecUtils.h"
19 #include "tools/flags/CommandLineFlags.h"
20 #include "tools/fonts/FontToolUtils.h"
21 
22 #if defined(SK_BUILD_FOR_MAC)
23 #include "include/ports/SkFontMgr_mac_ct.h"
24 #else
25 #include "include/ports/SkFontMgr_empty.h"
26 #endif
27 
28 static DEFINE_string2(input , i, nullptr, "Input SVG file.");
29 static DEFINE_string2(output, o, nullptr, "Output PNG file.");
30 
31 static DEFINE_int(width , 1024, "Output width.");
32 static DEFINE_int(height, 1024, "Output height.");
33 
main(int argc,char ** argv)34 int main(int argc, char** argv) {
35     CommandLineFlags::Parse(argc, argv);
36 
37     if (FLAGS_input.isEmpty() || FLAGS_output.isEmpty()) {
38         std::cerr << "Missing required 'input' and 'output' args.\n";
39         return 1;
40     }
41 
42     if (FLAGS_width <= 0 || FLAGS_height <= 0) {
43         std::cerr << "Invalid width/height.\n";
44         return 1;
45     }
46 
47     SkFILEStream in(FLAGS_input[0]);
48     if (!in.isValid()) {
49         std::cerr << "Could not open " << FLAGS_input[0] << "\n";
50         return 1;
51     }
52 
53     // If necessary, clients should use a font manager that would load fonts from the system.
54 #if defined(SK_BUILD_FOR_MAC)
55     sk_sp<SkFontMgr> fontMgr = SkFontMgr_New_CoreText(nullptr);
56 #else
57     sk_sp<SkFontMgr> fontMgr = SkFontMgr_New_Custom_Empty();
58 #endif
59 
60     CodecUtils::RegisterAllAvailable();
61 
62     auto predecode = skresources::ImageDecodeStrategy::kPreDecode;
63     auto rp = skresources::DataURIResourceProviderProxy::Make(
64             skresources::FileResourceProvider::Make(SkOSPath::Dirname(FLAGS_input[0]), predecode),
65             predecode,
66             fontMgr);
67 
68     auto svg_dom = SkSVGDOM::Builder()
69                            .setFontManager(fontMgr)
70                            .setResourceProvider(std::move(rp))
71                            .setTextShapingFactory(SkShapers::BestAvailable())
72                            .make(in);
73 
74     if (!svg_dom) {
75         std::cerr << "Could not parse " << FLAGS_input[0] << "\n";
76         return 1;
77     }
78 
79     auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(FLAGS_width, FLAGS_height));
80 
81     svg_dom->setContainerSize(SkSize::Make(FLAGS_width, FLAGS_height));
82     svg_dom->render(surface->getCanvas());
83 
84     SkPixmap pixmap;
85     surface->peekPixels(&pixmap);
86 
87     SkFILEWStream out(FLAGS_output[0]);
88     if (!out.isValid()) {
89         std::cerr << "Could not open " << FLAGS_output[0] << " for writing.\n";
90         return 1;
91     }
92 
93     // Use default encoding options.
94     SkPngEncoder::Options png_options;
95 
96     if (!SkPngEncoder::Encode(&out, pixmap, png_options)) {
97         std::cerr << "PNG encoding failed.\n";
98         return 1;
99     }
100 
101     return 0;
102 }
103