diff --git a/res/font/DMSans.otf b/res/font/DMSans.otf new file mode 100644 index 0000000..98e18d8 Binary files /dev/null and b/res/font/DMSans.otf differ diff --git a/res/font/NanumGothicCoding.otf b/res/font/NanumGothicCoding.otf new file mode 100644 index 0000000..ec69dc0 Binary files /dev/null and b/res/font/NanumGothicCoding.otf differ diff --git a/res/font/Pretendard.otf b/res/font/Pretendard.otf new file mode 100644 index 0000000..1bbac38 Binary files /dev/null and b/res/font/Pretendard.otf differ diff --git a/res/font/SentyCloud.otf b/res/font/SentyCloud.otf new file mode 100644 index 0000000..afd468c Binary files /dev/null and b/res/font/SentyCloud.otf differ diff --git a/src/TextOtf.cpp b/src/TextOtf.cpp new file mode 100644 index 0000000..43a1e84 --- /dev/null +++ b/src/TextOtf.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2026 ThorVG project. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "Example.h" + +/************************************************************************/ +/* ThorVG Drawing Contents */ +/************************************************************************/ + +struct UserExample : tvgexam::Example +{ + bool content(tvg::Canvas* canvas, uint32_t w, uint32_t h) override + { + //Background + auto shape = tvg::Shape::gen(); + shape->appendRect(0, 0, w, h); + shape->fill(75, 75, 75); + canvas->add(shape); + + //Load a necessary font data. + //The loaded font will be released when the Initializer::term() is called. + //Otherwise, you can immediately unload the font data. + //Please check Text::unload() APIs. + if (!tvgexam::verify(tvg::Text::load(EXAMPLE_DIR"/font/DMSans.otf"))) return false; + if (!tvgexam::verify(tvg::Text::load(EXAMPLE_DIR"/font/Pretendard.otf"))) return false; + if (!tvgexam::verify(tvg::Text::load(EXAMPLE_DIR"/font/NanumGothicCoding.otf"))) return false; + + //Load from memory + ifstream file(EXAMPLE_DIR"/font/SentyCloud.otf", ios::binary); + if (!file.is_open()) return false; + file.seekg(0, std::ios::end); + auto size = file.tellg(); + file.seekg(0, std::ios::beg); + auto data = (char*)malloc(size); + if (data && file.read(data, size)) { + if (!tvgexam::verify(tvg::Text::load("SentyCloud", data, size, "otf", true))) return false; + } + file.close(); + free(data); + + auto text = tvg::Text::gen(); + text->font("DMSans"); + text->size(60); + text->text("THORVG OpenType Font"); + text->fill(255, 255, 255); + canvas->add(text); + + auto text2 = tvg::Text::gen(); + text2->font("DMSans"); + text2->size(30); + text2->italic(); + text2->text("Font = \"DMSans\", Size = 30, Style = Italic"); + text2->translate(0, 120); + text2->fill(255, 255, 255); + canvas->add(text2); + + auto text3 = tvg::Text::gen(); + text3->font(nullptr); //Use any font + text3->size(40); + text3->text("Kerning Test: VA, AV, TJ, JT"); + text3->fill(255, 255, 255); + text3->translate(0, 195); + canvas->add(text3); + + auto text4 = tvg::Text::gen(); + text4->font("DMSans"); + text4->size(25); + text4->text("Purple Text"); + text4->fill(255, 0, 255); + text4->translate(0, 280); + canvas->add(text4); + + auto text5 = tvg::Text::gen(); + text5->font("DMSans"); + text5->size(25); + text5->text("Gray Text"); + text5->fill(150, 150, 150); + text5->translate(220, 280); + canvas->add(text5); + + auto text6 = tvg::Text::gen(); + text6->font("DMSans"); + text6->size(25); + text6->text("Yellow Text"); + text6->fill(255, 255, 0); + text6->translate(400, 280); + canvas->add(text6); + + auto text7 = tvg::Text::gen(); + text7->font("Pretendard"); + text7->size(15); + text7->text("Transformed Text - 30'"); + text7->fill(0, 0, 0); + text7->translate(600, 370); + text7->rotate(30); + canvas->add(text7); + + auto text8 = tvg::Text::gen(); + text8->font("Pretendard"); + text8->size(15); + text8->fill(0, 0, 0); + text8->text("Transformed Text - 90'"); + text8->translate(600, 370); + text8->rotate(90); + canvas->add(text8); + + auto text9 = tvg::Text::gen(); + text9->font("Pretendard"); + text9->size(15); + text9->fill(0, 0, 0); + text9->text("Transformed Text - 180'"); + text9->translate(800, 370); + text9->rotate(180); + canvas->add(text9); + + //gradient texts + float x, y, w2, h2; + + auto text10 = tvg::Text::gen(); + text10->font("Pretendard"); + text10->size(50); + text10->text("Linear Text"); + text10->bounds(&x, &y, &w2, &h2); + + //LinearGradient + auto fill = tvg::LinearGradient::gen(); + fill->linear(x, y + h2 * 0.5f, x + w2, y + h2 * 0.5f); + + //Gradient Color Stops + tvg::Fill::ColorStop colorStops[3]; + colorStops[0] = {0, 255, 0, 0, 255}; + colorStops[1] = {0.5, 255, 255, 0, 255}; + colorStops[2] = {1, 255, 255, 255, 255}; + fill->colorStops(colorStops, 3); + text10->fill(fill); + text10->translate(0, 320); + + canvas->add(text10); + + auto text11 = tvg::Text::gen(); + text11->font("NanumGothicCoding"); + text11->size(40); + text11->text("\xeb\x82\x98\xeb\x88\x94\xea\xb3\xa0\xeb\x94\x95\xec\xbd\x94\xeb\x94\xa9\x28\x55\x54\x46\x2d\x38\x29"); + text11->bounds(&x, &y, &w2, &h2); + + //RadialGradient + auto fill2 = tvg::RadialGradient::gen(); + fill2->radial(x + w2 * 0.5f, y + h2 * 0.5f, w2 * 0.5f, x + w2 * 0.5f, y + h2 * 0.5f, 0.0f); + + //Gradient Color Stops + tvg::Fill::ColorStop colorStops2[3]; + colorStops2[0] = {0, 0, 255, 255, 255}; + colorStops2[1] = {0.5, 255, 255, 0, 255}; + colorStops2[2] = {1, 255, 255, 255, 255}; + + fill2->colorStops(colorStops2, 3); + + text11->fill(fill2); + text11->translate(0, 420); + + canvas->add(text11); + + auto text12 = tvg::Text::gen(); + text12->font("SentyCloud"); + text12->size(50); + text12->fill(255, 25, 25); + text12->outline(3, 255, 200, 200); + text12->text("\xe4\xb8\x8d\xe5\x88\xb0\xe9\x95\xbf\xe5\x9f\x8e\xe9\x9d\x9e\xe5\xa5\xbd\xe6\xb1\x89\xef\xbc\x81"); + text12->translate(0, 495); + canvas->add(text12); + + auto text13 = tvg::Text::gen(); + text13->font("DMSans"); + text13->size(20); + text13->fill(255, 255, 255); + text13->text("LINE-FEED TEST. THIS IS THE FIRST LINE - \nTHIS IS THE SECOND LINE."); + text13->translate(0, 595); + canvas->add(text13); + + auto text14 = tvg::Text::gen(); + text14->font("DMSans"); + text14->size(20); + text14->fill(255, 255, 255); + text14->spacing(1.5f, 1.5f); + text14->text("1.5x SPACING TEST. THIS IS THE FIRST LINE - \nTHIS IS THE SECOND LINE."); + text14->translate(0, 670); + canvas->add(text14); + + return true; + } +}; + + +/************************************************************************/ +/* Entry Point */ +/************************************************************************/ + +int main(int argc, char **argv) +{ + return tvgexam::main(new UserExample, argc, argv, false, 1024, 1024); +} \ No newline at end of file diff --git a/src/Text.cpp b/src/TextTtf.cpp similarity index 92% rename from src/Text.cpp rename to src/TextTtf.cpp index 0331f17..20e089f 100644 --- a/src/Text.cpp +++ b/src/TextTtf.cpp @@ -59,8 +59,8 @@ struct UserExample : tvgexam::Example auto text = tvg::Text::gen(); text->font("PublicSans-Regular"); - text->size(80); - text->text("THORVG Text"); + text->size(60); + text->text("THORVG TrueType Font"); text->fill(255, 255, 255); canvas->add(text); @@ -68,8 +68,8 @@ struct UserExample : tvgexam::Example text2->font("PublicSans-Regular"); text2->size(30); text2->italic(); - text2->text("Font = \"PublicSans-Regular\", Size = 40, Style = Italic"); - text2->translate(0, 150); + text2->text("Font = \"PublicSans-Regular\", Size = 30, Style = Italic"); + text2->translate(0, 120); text2->fill(255, 255, 255); canvas->add(text2); @@ -78,7 +78,7 @@ struct UserExample : tvgexam::Example text3->size(40); text3->text("Kerning Test: VA, AV, TJ, JT"); text3->fill(255, 255, 255); - text3->translate(0, 225); + text3->translate(0, 195); canvas->add(text3); auto text4 = tvg::Text::gen(); @@ -86,7 +86,7 @@ struct UserExample : tvgexam::Example text4->size(25); text4->text("Purple Text"); text4->fill(255, 0, 255); - text4->translate(0, 310); + text4->translate(0, 280); canvas->add(text4); auto text5 = tvg::Text::gen(); @@ -94,7 +94,7 @@ struct UserExample : tvgexam::Example text5->size(25); text5->text("Gray Text"); text5->fill(150, 150, 150); - text5->translate(220, 310); + text5->translate(220, 280); canvas->add(text5); auto text6 = tvg::Text::gen(); @@ -102,7 +102,7 @@ struct UserExample : tvgexam::Example text6->size(25); text6->text("Yellow Text"); text6->fill(255, 255, 0); - text6->translate(400, 310); + text6->translate(400, 280); canvas->add(text6); auto text7 = tvg::Text::gen(); @@ -110,7 +110,7 @@ struct UserExample : tvgexam::Example text7->size(15); text7->text("Transformed Text - 30'"); text7->fill(0, 0, 0); - text7->translate(600, 400); + text7->translate(600, 370); text7->rotate(30); canvas->add(text7); @@ -119,7 +119,7 @@ struct UserExample : tvgexam::Example text8->size(15); text8->fill(0, 0, 0); text8->text("Transformed Text - 90'"); - text8->translate(600, 400); + text8->translate(600, 370); text8->rotate(90); canvas->add(text8); @@ -128,7 +128,7 @@ struct UserExample : tvgexam::Example text9->size(15); text9->fill(0, 0, 0); text9->text("Transformed Text - 180'"); - text9->translate(800, 400); + text9->translate(800, 370); text9->rotate(180); canvas->add(text9); @@ -153,7 +153,7 @@ struct UserExample : tvgexam::Example fill->colorStops(colorStops, 3); text10->fill(fill); - text10->translate(0, 350); + text10->translate(0, 320); canvas->add(text10); @@ -176,7 +176,7 @@ struct UserExample : tvgexam::Example fill2->colorStops(colorStops2, 3); text11->fill(fill2); - text11->translate(0, 450); + text11->translate(0, 420); canvas->add(text11); @@ -186,7 +186,7 @@ struct UserExample : tvgexam::Example text12->fill(255, 25, 25); text12->outline(3, 255, 200, 200); text12->text("\xe4\xb8\x8d\xe5\x88\xb0\xe9\x95\xbf\xe5\x9f\x8e\xe9\x9d\x9e\xe5\xa5\xbd\xe6\xb1\x89\xef\xbc\x81"); - text12->translate(0, 525); + text12->translate(0, 495); canvas->add(text12); auto text13 = tvg::Text::gen(); @@ -194,7 +194,7 @@ struct UserExample : tvgexam::Example text13->size(20); text13->fill(255, 255, 255); text13->text("LINE-FEED TEST. THIS IS THE FIRST LINE - \nTHIS IS THE SECOND LINE."); - text13->translate(0, 625); + text13->translate(0, 595); canvas->add(text13); auto text14 = tvg::Text::gen(); @@ -203,7 +203,7 @@ struct UserExample : tvgexam::Example text14->fill(255, 255, 255); text14->spacing(1.5f, 1.5f); text14->text("1.5x SPACING TEST. THIS IS THE FIRST LINE - \nTHIS IS THE SECOND LINE."); - text14->translate(0, 700); + text14->translate(0, 670); canvas->add(text14); return true; diff --git a/src/meson.build b/src/meson.build index adfd67f..e827416 100644 --- a/src/meson.build +++ b/src/meson.build @@ -76,7 +76,8 @@ source_file = [ 'StrokeLine.cpp', 'StrokeMiterlimit.cpp', 'Svg.cpp', - 'Text.cpp', + 'TextOtf.cpp', + 'TextTtf.cpp', 'TextEffects.cpp', 'TextLayout.cpp', 'TextLineWrap.cpp',