diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/CMakeLists.txt index 70937f551aef..5d0674b314d2 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/CMakeLists.txt @@ -53,3 +53,8 @@ target_link_libraries(react_renderer_textlayoutmanager ) target_compile_reactnative_options(react_renderer_textlayoutmanager PRIVATE) target_compile_options(react_renderer_textlayoutmanager PRIVATE -Wpedantic) + +if(NOT ANDROID) + target_compile_definitions(react_renderer_textlayoutmanager PRIVATE RCT_USE_PANGO=1) + target_link_libraries(react_renderer_textlayoutmanager pango pangoft2) +endif() diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.cpp index 0444a94b25cc..7cfdfc55d8f2 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.cpp @@ -7,12 +7,409 @@ #include "TextLayoutManager.h" +#ifdef RCT_USE_PANGO + +#include +#include + +#include +#include +#include + +namespace facebook::react { + +namespace { + +PangoWeight toPangoWeight(std::optional fontWeight) { + if (!fontWeight.has_value()) { + return PANGO_WEIGHT_NORMAL; + } + switch (fontWeight.value()) { + case FontWeight::Weight100: + return PANGO_WEIGHT_THIN; + case FontWeight::Weight200: + return PANGO_WEIGHT_ULTRALIGHT; + case FontWeight::Weight300: + return PANGO_WEIGHT_LIGHT; + case FontWeight::Weight400: + return PANGO_WEIGHT_NORMAL; + case FontWeight::Weight500: + return PANGO_WEIGHT_MEDIUM; + case FontWeight::Weight600: + return PANGO_WEIGHT_SEMIBOLD; + case FontWeight::Weight700: + return PANGO_WEIGHT_BOLD; + case FontWeight::Weight800: + return PANGO_WEIGHT_ULTRABOLD; + case FontWeight::Weight900: + return PANGO_WEIGHT_HEAVY; + default: + return PANGO_WEIGHT_NORMAL; + } +} + +PangoStyle toPangoStyle(std::optional fontStyle) { + if (!fontStyle.has_value()) { + return PANGO_STYLE_NORMAL; + } + switch (fontStyle.value()) { + case FontStyle::Normal: + return PANGO_STYLE_NORMAL; + case FontStyle::Italic: + return PANGO_STYLE_ITALIC; + case FontStyle::Oblique: + return PANGO_STYLE_OBLIQUE; + default: + return PANGO_STYLE_NORMAL; + } +} + +PangoAlignment toPangoAlignment(std::optional alignment) { + if (!alignment.has_value()) { + return PANGO_ALIGN_LEFT; + } + switch (alignment.value()) { + case TextAlignment::Natural: + case TextAlignment::Left: + return PANGO_ALIGN_LEFT; + case TextAlignment::Center: + return PANGO_ALIGN_CENTER; + case TextAlignment::Right: + return PANGO_ALIGN_RIGHT; + case TextAlignment::Justified: + return PANGO_ALIGN_LEFT; + default: + return PANGO_ALIGN_LEFT; + } +} + +PangoEllipsizeMode toPangoEllipsizeMode(EllipsizeMode mode) { + switch (mode) { + case EllipsizeMode::Clip: + return PANGO_ELLIPSIZE_NONE; + case EllipsizeMode::Head: + return PANGO_ELLIPSIZE_START; + case EllipsizeMode::Tail: + return PANGO_ELLIPSIZE_END; + case EllipsizeMode::Middle: + return PANGO_ELLIPSIZE_MIDDLE; + default: + return PANGO_ELLIPSIZE_NONE; + } +} + +PangoFontDescription* createFontDescription( + const TextAttributes& textAttributes) { + auto* fontDesc = pango_font_description_new(); + + if (!textAttributes.fontFamily.empty()) { + pango_font_description_set_family( + fontDesc, textAttributes.fontFamily.c_str()); + } + + if (!std::isnan(textAttributes.fontSize)) { + pango_font_description_set_absolute_size( + fontDesc, static_cast(textAttributes.fontSize * PANGO_SCALE)); + } else { + pango_font_description_set_absolute_size(fontDesc, 14 * PANGO_SCALE); + } + + pango_font_description_set_weight( + fontDesc, toPangoWeight(textAttributes.fontWeight)); + pango_font_description_set_style( + fontDesc, toPangoStyle(textAttributes.fontStyle)); + + return fontDesc; +} + +std::string applyTextTransform( + const std::string& text, + std::optional textTransform) { + if (!textTransform.has_value() || + textTransform.value() == TextTransform::None || + textTransform.value() == TextTransform::Unset) { + return text; + } + + std::string result = text; + switch (textTransform.value()) { + case TextTransform::Uppercase: + std::transform(result.begin(), result.end(), result.begin(), ::toupper); + break; + case TextTransform::Lowercase: + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + break; + case TextTransform::Capitalize: + if (!result.empty()) { + result[0] = static_cast(::toupper(result[0])); + } + break; + default: + break; + } + return result; +} + +struct PangoLayoutSetup { + PangoLayout* layout; + std::string concatenatedText; + std::vector attachmentByteOffsets; +}; + +PangoLayoutSetup createPangoLayout( + PangoContext* pangoContext, + const AttributedString& attributedString, + const ParagraphAttributes& paragraphAttributes, + float maxWidth) { + auto* layout = pango_layout_new(pangoContext); + + // Set width + if (!std::isnan(maxWidth) && maxWidth > 0) { + pango_layout_set_width(layout, static_cast(maxWidth * PANGO_SCALE)); + } + + // Set alignment + pango_layout_set_alignment( + layout, + toPangoAlignment(attributedString.getBaseTextAttributes().alignment)); + + // Set ellipsize mode + pango_layout_set_ellipsize( + layout, toPangoEllipsizeMode(paragraphAttributes.ellipsizeMode)); + + // Set max lines + if (paragraphAttributes.maximumNumberOfLines > 0) { + pango_layout_set_height(layout, -paragraphAttributes.maximumNumberOfLines); + } + + // Set justify + if (attributedString.getBaseTextAttributes().alignment.has_value() && + attributedString.getBaseTextAttributes().alignment.value() == + TextAlignment::Justified) { + pango_layout_set_justify(layout, TRUE); + } + + // Set default font description from base text attributes + auto* baseFontDesc = + createFontDescription(attributedString.getBaseTextAttributes()); + pango_layout_set_font_description(layout, baseFontDesc); + pango_font_description_free(baseFontDesc); + + if (attributedString.isEmpty()) { + // For empty text, just set empty text with the font description + // already set above. pango_layout_get_size() will return {0, lineHeight}. + pango_layout_set_text(layout, "", 0); + return {layout, "", {}}; + } + + // Build concatenated text and attribute list from fragments + std::string concatenatedText; + std::vector attachmentByteOffsets; + auto* attrList = pango_attr_list_new(); + + for (const auto& fragment : attributedString.getFragments()) { + auto startByte = static_cast(concatenatedText.size()); + + if (fragment.isAttachment()) { + // Use U+FFFC (OBJECT REPLACEMENT CHARACTER) for attachments + concatenatedText += "\xEF\xBF\xBC"; // U+FFFC in UTF-8 + attachmentByteOffsets.push_back(startByte); + } else { + auto transformedText = applyTextTransform( + fragment.string, fragment.textAttributes.textTransform); + concatenatedText += transformedText; + } + + auto endByte = static_cast(concatenatedText.size()); + + // Create font description for this fragment + auto* fontDesc = createFontDescription(fragment.textAttributes); + auto* fontAttr = pango_attr_font_desc_new(fontDesc); + fontAttr->start_index = static_cast(startByte); + fontAttr->end_index = static_cast(endByte); + pango_attr_list_insert(attrList, fontAttr); + pango_font_description_free(fontDesc); + + // Letter spacing + if (!std::isnan(fragment.textAttributes.letterSpacing)) { + auto* spacingAttr = pango_attr_letter_spacing_new( + static_cast( + fragment.textAttributes.letterSpacing * PANGO_SCALE)); + spacingAttr->start_index = static_cast(startByte); + spacingAttr->end_index = static_cast(endByte); + pango_attr_list_insert(attrList, spacingAttr); + } + + // Line height (as absolute height) + if (!std::isnan(fragment.textAttributes.lineHeight)) { + auto* lineHeightAttr = pango_attr_line_height_new_absolute( + static_cast(fragment.textAttributes.lineHeight * PANGO_SCALE)); + lineHeightAttr->start_index = static_cast(startByte); + lineHeightAttr->end_index = static_cast(endByte); + pango_attr_list_insert(attrList, lineHeightAttr); + } + } + + pango_layout_set_text( + layout, + concatenatedText.c_str(), + static_cast(concatenatedText.size())); + pango_layout_set_attributes(layout, attrList); + pango_attr_list_unref(attrList); + + return { + layout, std::move(concatenatedText), std::move(attachmentByteOffsets)}; +} + +} // namespace + +TextLayoutManager::TextLayoutManager( + const std::shared_ptr& /*contextContainer*/) + : textMeasureCache_(kSimpleThreadSafeCacheSizeCap), + lineMeasureCache_(kSimpleThreadSafeCacheSizeCap) { + fontMap_ = pango_ft2_font_map_new(); + pangoContext_ = pango_font_map_create_context(fontMap_); +} + +TextLayoutManager::~TextLayoutManager() { + if (pangoContext_ != nullptr) { + g_object_unref(pangoContext_); + } + if (fontMap_ != nullptr) { + g_object_unref(fontMap_); + } +} + +TextMeasurement TextLayoutManager::measure( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& /*layoutContext*/, + const LayoutConstraints& layoutConstraints) const { + const auto& attributedString = attributedStringBox.getValue(); + + auto cacheKey = TextMeasureCacheKey{ + attributedString, paragraphAttributes, layoutConstraints}; + + return textMeasureCache_.get(cacheKey, [&]() { + std::lock_guard lock(pangoMutex_); + + auto setup = createPangoLayout( + pangoContext_, + attributedString, + paragraphAttributes, + layoutConstraints.maximumSize.width); + + int pangoWidth = 0; + int pangoHeight = 0; + pango_layout_get_size(setup.layout, &pangoWidth, &pangoHeight); + + auto size = Size{ + static_cast(pangoWidth) / PANGO_SCALE, + static_cast(pangoHeight) / PANGO_SCALE}; + + // Build attachment frames + TextMeasurement::Attachments attachments; + for (size_t i = 0; i < setup.attachmentByteOffsets.size(); i++) { + PangoRectangle cursorPos; + pango_layout_get_cursor_pos( + setup.layout, setup.attachmentByteOffsets[i], &cursorPos, nullptr); + attachments.push_back( + TextMeasurement::Attachment{ + .frame = + {.origin = + {.x = static_cast(cursorPos.x) / PANGO_SCALE, + .y = static_cast(cursorPos.y) / PANGO_SCALE}, + .size = {.width = 0, .height = 0}}, + .isClipped = false}); + } + + g_object_unref(setup.layout); + + return TextMeasurement{ + .size = layoutConstraints.clamp(size), + .attachments = std::move(attachments)}; + }); +} + +LinesMeasurements TextLayoutManager::measureLines( + const AttributedStringBox& attributedStringBox, + const ParagraphAttributes& paragraphAttributes, + const Size& size) const { + const auto& attributedString = attributedStringBox.getValue(); + + auto cacheKey = + LineMeasureCacheKey{attributedString, paragraphAttributes, size}; + + return lineMeasureCache_.get(cacheKey, [&]() { + std::lock_guard lock(pangoMutex_); + + auto setup = createPangoLayout( + pangoContext_, attributedString, paragraphAttributes, size.width); + + LinesMeasurements lines; + auto* iter = pango_layout_get_iter(setup.layout); + + do { + auto* layoutLine = pango_layout_iter_get_line_readonly(iter); + PangoRectangle logicalRect; + pango_layout_iter_get_line_extents(iter, nullptr, &logicalRect); + int baseline = pango_layout_iter_get_baseline(iter); + + Float ascender = + static_cast(baseline - logicalRect.y) / PANGO_SCALE; + Float descender = + static_cast(logicalRect.y + logicalRect.height - baseline) / + PANGO_SCALE; + Float lineCapHeight = ascender; + Float lineXHeight = ascender * 0.5f; + + // Get text for this line + auto lineStartIndex = static_cast(layoutLine->start_index); + auto lineLength = static_cast(layoutLine->length); + std::string lineText; + if (lineStartIndex < setup.concatenatedText.size()) { + lineText = setup.concatenatedText.substr( + lineStartIndex, + std::min( + lineLength, setup.concatenatedText.size() - lineStartIndex)); + } + + auto frame = Rect{ + .origin = + {.x = static_cast(logicalRect.x) / PANGO_SCALE, + .y = static_cast(logicalRect.y) / PANGO_SCALE}, + .size = { + .width = static_cast(logicalRect.width) / PANGO_SCALE, + .height = static_cast(logicalRect.height) / PANGO_SCALE}}; + + lines.emplace_back( + std::move(lineText), + frame, + descender, + lineCapHeight, + ascender, + lineXHeight); + } while (pango_layout_iter_next_line(iter)); + + pango_layout_iter_free(iter); + g_object_unref(setup.layout); + + return lines; + }); +} + +} // namespace facebook::react + +#else // !RCT_USE_PANGO + namespace facebook::react { TextLayoutManager::TextLayoutManager( const std::shared_ptr& /*contextContainer*/) : textMeasureCache_(kSimpleThreadSafeCacheSizeCap) {} +TextLayoutManager::~TextLayoutManager() = default; + TextMeasurement TextLayoutManager::measure( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& /*paragraphAttributes*/, @@ -37,3 +434,5 @@ TextMeasurement TextLayoutManager::measure( } } // namespace facebook::react + +#endif // RCT_USE_PANGO diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.h index 63f2c1afcbc9..c3eafde2af72 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/react/renderer/textlayoutmanager/TextLayoutManager.h @@ -15,6 +15,13 @@ #include #include +#ifdef RCT_USE_PANGO +#include + +struct _PangoFontMap; +struct _PangoContext; +#endif + namespace facebook::react { class TextLayoutManager; @@ -26,7 +33,7 @@ class TextLayoutManager; class TextLayoutManager { public: explicit TextLayoutManager(const std::shared_ptr &contextContainer); - virtual ~TextLayoutManager() = default; + virtual ~TextLayoutManager(); /* * Not copyable. @@ -49,9 +56,31 @@ class TextLayoutManager { const TextLayoutContext &layoutContext, const LayoutConstraints &layoutConstraints) const; +#ifdef RCT_USE_PANGO + /* + * Measures individual lines of `attributedString`. + * Detected by TextLayoutManagerExtended via C++20 concepts. + */ + LinesMeasurements measureLines( + const AttributedStringBox &attributedStringBox, + const ParagraphAttributes ¶graphAttributes, + const Size &size) const; +#endif + protected: std::shared_ptr contextContainer_; TextMeasureCache textMeasureCache_; + +#ifdef RCT_USE_PANGO + LineMeasureCache lineMeasureCache_; +#endif + + private: +#ifdef RCT_USE_PANGO + _PangoFontMap *fontMap_{nullptr}; + _PangoContext *pangoContext_{nullptr}; + mutable std::mutex pangoMutex_; +#endif }; } // namespace facebook::react diff --git a/private/react-native-fantom/build.gradle.kts b/private/react-native-fantom/build.gradle.kts index f9c12fee63d1..9a8c0908ed6d 100644 --- a/private/react-native-fantom/build.gradle.kts +++ b/private/react-native-fantom/build.gradle.kts @@ -40,6 +40,14 @@ fun getSDKPath(): String { val FOLLY_VERSION = libs.versions.folly.get() val GFLAGS_VERSION = libs.versions.gflags.get() val NLOHMANNJSON_VERSION = libs.versions.nlohmannjson.get() +val PANGO_VERSION = "1.50.12" +val GLIB_VERSION = "2.78.3" +val FRIBIDI_VERSION = "1.0.13" +val HARFBUZZ_VERSION = "8.3.0" +val FREETYPE_VERSION = "2.13.2" +val FONTCONFIG_VERSION = "2.14.2" +val EXPAT_VERSION = "2.6.0" +val LIBFFI_VERSION = "3.4.6" val buildDir = project.layout.buildDirectory.get().asFile val downloadsDir = @@ -135,6 +143,194 @@ val prepareNlohmannJson by into("$thirdParty/nlohmann_json") } +// --- Pango and its dependencies --- + +val downloadFreetypeDest = File(downloadsDir, "freetype-${FREETYPE_VERSION}.tar.gz") +val downloadFreetype by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src("https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz") + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadFreetypeDest) + } +val prepareFreetype by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadFreetype)) + from(tarTree(downloadFreetypeDest)) + from("tester/third-party/freetype/") + include("freetype-${FREETYPE_VERSION}/**/*", "CMakeLists.txt") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/freetype") + } + +val downloadHarfbuzzDest = File(downloadsDir, "harfbuzz-${HARFBUZZ_VERSION}.tar.gz") +val downloadHarfbuzz by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src( + "https://github.com/harfbuzz/harfbuzz/releases/download/${HARFBUZZ_VERSION}/harfbuzz-${HARFBUZZ_VERSION}.tar.gz" + ) + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadHarfbuzzDest) + } +val prepareHarfbuzz by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadHarfbuzz)) + from(tarTree(downloadHarfbuzzDest)) + from("tester/third-party/harfbuzz/") + include("harfbuzz-${HARFBUZZ_VERSION}/**/*", "CMakeLists.txt") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/harfbuzz") + } + +val downloadExpatDest = File(downloadsDir, "expat-${EXPAT_VERSION}.tar.gz") +val downloadExpat by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src( + "https://github.com/libexpat/libexpat/releases/download/R_2_6_0/expat-${EXPAT_VERSION}.tar.gz" + ) + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadExpatDest) + } +val prepareExpat by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadExpat)) + from(tarTree(downloadExpatDest)) + from("tester/third-party/expat/") + include("expat-${EXPAT_VERSION}/**/*", "CMakeLists.txt") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/expat") + } + +val downloadLibffiDest = File(downloadsDir, "libffi-${LIBFFI_VERSION}.tar.gz") +val downloadLibffi by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src( + "https://github.com/libffi/libffi/releases/download/v${LIBFFI_VERSION}/libffi-${LIBFFI_VERSION}.tar.gz" + ) + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadLibffiDest) + } +val prepareLibffi by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadLibffi)) + from(tarTree(downloadLibffiDest)) + from("tester/third-party/libffi/") + include("libffi-${LIBFFI_VERSION}/**/*", "CMakeLists.txt") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/libffi") + } + +val downloadFribidiDest = File(downloadsDir, "fribidi-${FRIBIDI_VERSION}.tar.gz") +val downloadFribidi by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src( + "https://github.com/fribidi/fribidi/releases/download/v${FRIBIDI_VERSION}/fribidi-${FRIBIDI_VERSION}.tar.gz" + ) + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadFribidiDest) + } +val prepareFribidi by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadFribidi)) + from(tarTree(downloadFribidiDest)) + from("tester/third-party/fribidi/") + include("fribidi-${FRIBIDI_VERSION}/**/*", "CMakeLists.txt", "fribidi-config.h") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/fribidi") + } + +val downloadGlibDest = File(downloadsDir, "glib-${GLIB_VERSION}.tar.gz") +val downloadGlib by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src("https://download.gnome.org/sources/glib/2.78/glib-${GLIB_VERSION}.tar.gz") + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadGlibDest) + } +val prepareGlib by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadGlib)) + from(tarTree(downloadGlibDest)) + from("tester/third-party/glib/") + include("glib-${GLIB_VERSION}/**/*", "CMakeLists.txt", "glibconfig.h", "config.h") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/glib") + } + +val downloadFontconfigDest = File(downloadsDir, "fontconfig-${FONTCONFIG_VERSION}.tar.gz") +val downloadFontconfig by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src( + "https://www.freedesktop.org/software/fontconfig/release/fontconfig-${FONTCONFIG_VERSION}.tar.gz" + ) + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadFontconfigDest) + } +val prepareFontconfig by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadFontconfig)) + from(tarTree(downloadFontconfigDest)) + from("tester/third-party/fontconfig/") + include("fontconfig-${FONTCONFIG_VERSION}/**/*", "CMakeLists.txt", "fcstdint.h", "config.h") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/fontconfig") + } + +val downloadPangoDest = File(downloadsDir, "pango-${PANGO_VERSION}.tar.gz") +val downloadPango by + tasks.registering(Download::class) { + dependsOn(createNativeDepsDirectories) + src("https://download.gnome.org/sources/pango/1.50/pango-${PANGO_VERSION}.tar.gz") + onlyIfModified(true) + overwrite(false) + retries(5) + quiet(true) + dest(downloadPangoDest) + } +val preparePango by + tasks.registering(Copy::class) { + dependsOn(listOf(downloadPango)) + from(tarTree(downloadPangoDest)) + from("tester/third-party/pango/") + include("pango-${PANGO_VERSION}/**/*", "CMakeLists.txt", "config.h", "pango-features.h") + eachFile { path = path.substringAfter("/") } + includeEmptyDirs = false + into("$thirdParty/pango") + } + var codegenSrcDir = File("$reactAndroidBuildDir/generated/source/codegen/jni") var codegenOutDir = File("$buildDir/codegen") val prepareRNCodegen by @@ -170,6 +366,14 @@ val prepareNative3pDependencies by prepareGflags, prepareNlohmannJson, prepareFolly, + prepareFreetype, + prepareHarfbuzz, + prepareExpat, + prepareLibffi, + prepareFribidi, + prepareGlib, + prepareFontconfig, + preparePango, ":packages:react-native:ReactAndroid:prepareBoost", ":packages:react-native:ReactAndroid:prepareDoubleConversion", ":packages:react-native:ReactAndroid:prepareFastFloat", diff --git a/private/react-native-fantom/tester/CMakeLists.txt b/private/react-native-fantom/tester/CMakeLists.txt index 235f744e6202..991335b1ea93 100644 --- a/private/react-native-fantom/tester/CMakeLists.txt +++ b/private/react-native-fantom/tester/CMakeLists.txt @@ -38,6 +38,16 @@ add_fantom_third_party_subdir(folly) add_fantom_third_party_subdir(gflags) add_fantom_third_party_subdir(nlohmann_json) +# Pango and its dependencies (order matters for dep resolution) +add_fantom_third_party_subdir(freetype) +add_fantom_third_party_subdir(expat) +add_fantom_third_party_subdir(libffi) +add_fantom_third_party_subdir(fribidi) +add_fantom_third_party_subdir(glib) +add_fantom_third_party_subdir(fontconfig) +add_fantom_third_party_subdir(harfbuzz) +add_fantom_third_party_subdir(pango) + add_subdirectory(${FANTOM_CODEGEN_DIR} codegen) add_library(glog_init INTERFACE) diff --git a/private/react-native-fantom/tester/third-party/expat/CMakeLists.txt b/private/react-native-fantom/tester/third-party/expat/CMakeLists.txt new file mode 100644 index 000000000000..1c4bafd55e48 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/expat/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(EXPAT_BUILD_TOOLS OFF CACHE BOOL "" FORCE) +set(EXPAT_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) +set(EXPAT_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(EXPAT_BUILD_DOCS OFF CACHE BOOL "" FORCE) +set(EXPAT_SHARED_LIBS OFF CACHE BOOL "" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +add_subdirectory(expat-2.6.0/expat) diff --git a/private/react-native-fantom/tester/third-party/fontconfig/CMakeLists.txt b/private/react-native-fantom/tester/third-party/fontconfig/CMakeLists.txt new file mode 100644 index 000000000000..b73ed15831b4 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/fontconfig/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(FC_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/fontconfig-2.14.2) + +file(GLOB FC_SOURCES ${FC_SRC_DIR}/src/*.c) +# Exclude Windows-specific files +list(FILTER FC_SOURCES EXCLUDE REGEX "fcwindows") + +add_library(fontconfig STATIC ${FC_SOURCES}) + +target_include_directories(fontconfig + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${FC_SRC_DIR} + ${FC_SRC_DIR}/src +) + +target_compile_definitions(fontconfig + PRIVATE + HAVE_CONFIG_H=1 + FC_CACHEDIR="/tmp/fontconfig-cache" + FC_TEMPLATEDIR="/etc/fonts/conf.d" + FONTCONFIG_PATH="/etc/fonts" + _GNU_SOURCE=1 + FLEXIBLE_ARRAY_MEMBER=/**/ +) + +target_compile_options(fontconfig + PRIVATE + -Wno-sign-compare + -Wno-unused-parameter + -Wno-missing-field-initializers + -Wno-pointer-sign +) + +target_link_libraries(fontconfig PUBLIC freetype expat) diff --git a/private/react-native-fantom/tester/third-party/fontconfig/config.h b/private/react-native-fantom/tester/third-party/fontconfig/config.h new file mode 100644 index 000000000000..127a9072fd93 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/fontconfig/config.h @@ -0,0 +1,48 @@ +/* config.h - generated for fontconfig Fantom build (Linux x86_64) */ +#ifndef FC_CONFIG_H +#define FC_CONFIG_H + +#define HAVE_DIRENT_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TYPES_H 1 + +#define HAVE_MKSTEMP 1 +#define HAVE_MKOSTEMP 1 +#define HAVE_GETOPT 1 +#define HAVE_GETOPT_LONG 1 +#define HAVE_LINK 1 +#define HAVE_LSTAT 1 +#define HAVE_MKDTEMP 1 +#define HAVE_MMAP 1 +#define HAVE_POSIX_FADV_WILLNEED 1 +#define HAVE_READLINK 1 +#define HAVE_RAND_R 1 +#define HAVE_RANDOM_R 1 +#define HAVE_RANDOM 1 +#define HAVE_VPRINTF 1 + +#define HAVE_FT_GET_BDF_PROPERTY 1 +#define HAVE_FT_GET_PS_FONT_INFO 1 +#define HAVE_FT_HAS_PS_GLYPH_NAMES 1 +#define HAVE_FT_GET_X11_FONT_FORMAT 1 +#define HAVE_FT_DONE_MM_VAR 1 + +#define HAVE_STDATOMIC_PRIMITIVES 1 +#define HAVE_PTHREAD 1 + +#define SIZEOF_VOID_P 8 + +#define ALIGNOF_DOUBLE 8 +#define ALIGNOF_VOID_P 8 + +#define FC_GPERF_SIZE_T unsigned int + +#define FC_DEFAULT_FONTS "/usr/share/fonts" +#define CONFIGDIR "/etc/fonts/conf.d" + +#endif /* FC_CONFIG_H */ diff --git a/private/react-native-fantom/tester/third-party/fontconfig/fcstdint.h b/private/react-native-fantom/tester/third-party/fontconfig/fcstdint.h new file mode 100644 index 000000000000..d09de3a5f658 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/fontconfig/fcstdint.h @@ -0,0 +1,9 @@ +/* fcstdint.h - generated for fontconfig Fantom build */ +#ifndef FCSTDINT_H +#define FCSTDINT_H + +#include + +typedef int32_t FcChar32; + +#endif /* FCSTDINT_H */ diff --git a/private/react-native-fantom/tester/third-party/freetype/CMakeLists.txt b/private/react-native-fantom/tester/third-party/freetype/CMakeLists.txt new file mode 100644 index 000000000000..6342ebc75390 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/freetype/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE) +set(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE) +set(FT_DISABLE_PNG ON CACHE BOOL "" FORCE) +set(FT_DISABLE_BZIP2 ON CACHE BOOL "" FORCE) +set(FT_DISABLE_ZLIB ON CACHE BOOL "" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +add_subdirectory(freetype-2.13.2) diff --git a/private/react-native-fantom/tester/third-party/fribidi/CMakeLists.txt b/private/react-native-fantom/tester/third-party/fribidi/CMakeLists.txt new file mode 100644 index 000000000000..8ec991866a76 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/fribidi/CMakeLists.txt @@ -0,0 +1,43 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(FRIBIDI_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/fribidi-1.0.13) + +add_library(fribidi STATIC + ${FRIBIDI_SRC_DIR}/lib/fribidi.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-arabic.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-bidi.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-bidi-types.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-brackets.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-cap-rtl.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-cp1255.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-cp1256.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-iso8859-6.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-iso8859-8.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-char-sets-utf8.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-deprecated.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-joining.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-joining-types.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-mirroring.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-run.c + ${FRIBIDI_SRC_DIR}/lib/fribidi-shape.c +) + +target_include_directories(fribidi + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${FRIBIDI_SRC_DIR}/lib +) + +target_compile_definitions(fribidi + PRIVATE + HAVE_STRING_H=1 + HAVE_STRINGS_H=1 + HAVE_STDLIB_H=1 + HAVE_MEMORY_H=1 + HAVE_STRINGIZE=1 + FRIBIDI_LIB_STATIC=1 +) diff --git a/private/react-native-fantom/tester/third-party/fribidi/fribidi-config.h b/private/react-native-fantom/tester/third-party/fribidi/fribidi-config.h new file mode 100644 index 000000000000..6b1107ae6273 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/fribidi/fribidi-config.h @@ -0,0 +1,20 @@ +/* fribidi-config.h - generated for Fantom build */ +#ifndef FRIBIDI_CONFIG_H +#define FRIBIDI_CONFIG_H + +#define FRIBIDI_VERSION_MAJOR 1 +#define FRIBIDI_VERSION_MINOR 0 +#define FRIBIDI_VERSION_MICRO 13 + +#define FRIBIDI_VERSION_INFO "1.0.13" + +#define FRIBIDI_INTERFACE_VERSION_MAJOR 4 +#define FRIBIDI_INTERFACE_VERSION_MINOR 0 +#define FRIBIDI_INTERFACE_VERSION_MICRO 2 +#define FRIBIDI_INTERFACE_VERSION_STRING "4.0.2" + +#define FRIBIDI_CHARSETS 1 +#define FRIBIDI_USE_GLIB 0 +#define FRIBIDI_SIZEOF_INT 4 + +#endif /* FRIBIDI_CONFIG_H */ diff --git a/private/react-native-fantom/tester/third-party/glib/CMakeLists.txt b/private/react-native-fantom/tester/third-party/glib/CMakeLists.txt new file mode 100644 index 000000000000..c3e6902df17e --- /dev/null +++ b/private/react-native-fantom/tester/third-party/glib/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(GLIB_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/glib-2.78.3) + +# glib core sources +file(GLOB GLIB_CORE_SOURCES + ${GLIB_SRC_DIR}/glib/*.c +) + +# Exclude platform-specific and unnecessary files +list(FILTER GLIB_CORE_SOURCES EXCLUDE REGEX "glib/tests/") +list(FILTER GLIB_CORE_SOURCES EXCLUDE REGEX "win32") +list(FILTER GLIB_CORE_SOURCES EXCLUDE REGEX "glib/gspawn-helper") + +# gobject sources +file(GLOB GOBJECT_SOURCES + ${GLIB_SRC_DIR}/gobject/*.c +) +list(FILTER GOBJECT_SOURCES EXCLUDE REGEX "gobject/tests/") + +add_library(glib_core STATIC ${GLIB_CORE_SOURCES}) +target_include_directories(glib_core + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${GLIB_SRC_DIR} + ${GLIB_SRC_DIR}/glib +) +target_compile_definitions(glib_core + PUBLIC + GLIB_COMPILATION=1 + G_LOG_DOMAIN="GLib" + _GNU_SOURCE=1 + _POSIX_C_SOURCE=200809L + PRIVATE + HAVE_CONFIG_H=1 +) +target_compile_options(glib_core + PRIVATE + -Wno-sign-compare + -Wno-unused-parameter + -Wno-implicit-fallthrough + -Wno-missing-field-initializers +) +target_link_libraries(glib_core PUBLIC ffi pthread) + +add_library(gobject STATIC ${GOBJECT_SOURCES}) +target_include_directories(gobject + PUBLIC + ${GLIB_SRC_DIR} + ${GLIB_SRC_DIR}/gobject +) +target_compile_definitions(gobject + PUBLIC + GOBJECT_COMPILATION=1 + G_LOG_DOMAIN="GLib-GObject" + PRIVATE + HAVE_CONFIG_H=1 + _GNU_SOURCE=1 +) +target_compile_options(gobject + PRIVATE + -Wno-sign-compare + -Wno-unused-parameter + -Wno-implicit-fallthrough + -Wno-missing-field-initializers +) +target_link_libraries(gobject PUBLIC glib_core ffi) + +# Convenience alias matching what pango expects +add_library(glib ALIAS glib_core) diff --git a/private/react-native-fantom/tester/third-party/glib/config.h b/private/react-native-fantom/tester/third-party/glib/config.h new file mode 100644 index 000000000000..167e406e883b --- /dev/null +++ b/private/react-native-fantom/tester/third-party/glib/config.h @@ -0,0 +1,126 @@ +/* config.h - generated for glib Fantom build (Linux x86_64) */ +#ifndef GLIB_CONFIG_H +#define GLIB_CONFIG_H + +#define HAVE_ALLOCA_H 1 +#define HAVE_ALLOCA 1 +#define HAVE_MMAP 1 +#define HAVE_POSIX_MEMALIGN 1 +#define HAVE_MEMALIGN 1 +#define HAVE_VALLOC 1 + +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_RESOURCE_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_SYSCTL_H 1 +#define HAVE_SYS_MOUNT_H 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_DIRENT_H 1 +#define HAVE_DLFCN_H 1 +#define HAVE_LOCALE_H 1 +#define HAVE_LANGINFO_H 1 +#define HAVE_FLOAT_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_POLL_H 1 +#define HAVE_PWD_H 1 +#define HAVE_SCHED_H 1 +#define HAVE_SPAWN_H 1 +#define HAVE_STRING_H 1 +#define HAVE_STRINGS_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_TERMIOS_H 1 +#define HAVE_WCHAR_H 1 +#define HAVE_XLOCALE_H 0 +#define HAVE_SYS_INOTIFY_H 1 + +#define HAVE_CLOCK_GETTIME 1 +#define HAVE_CODESET 1 +#define HAVE_ENDMNTENT 1 +#define HAVE_ENDSERVENT 1 +#define HAVE_FALLOCATE 1 +#define HAVE_FCHMOD 1 +#define HAVE_FCHOWN 1 +#define HAVE_FDWALK 0 +#define HAVE_FSYNC 1 +#define HAVE_GETC_UNLOCKED 1 +#define HAVE_GETMNTENT_R 1 +#define HAVE_GETRESUID 1 +#define HAVE_GETRESGID 1 +#define HAVE_GMTIME_R 1 +#define HAVE_HASMNTOPT 1 +#define HAVE_IF_INDEXTONAME 1 +#define HAVE_IF_NAMETOINDEX 1 +#define HAVE_INOTIFY_INIT1 1 +#define HAVE_ISSETUGID 0 +#define HAVE_LCHMOD 0 +#define HAVE_LCHOWN 1 +#define HAVE_LSTAT 1 +#define HAVE_LINK 1 +#define HAVE_LOCALTIME_R 1 +#define HAVE_MEMMOVE 1 +#define HAVE_NEWLOCALE 1 +#define HAVE_PIPE2 1 +#define HAVE_POLL 1 +#define HAVE_PRLIMIT 1 +#define HAVE_READLINK 1 +#define HAVE_RECVMMSG 1 +#define HAVE_SENDMMSG 1 +#define HAVE_SETENV 1 +#define HAVE_SETMNTENT 1 +#define HAVE_SNPRINTF 1 +#define HAVE_SPLICE 1 +#define HAVE_STATFS 1 +#define HAVE_STATVFS 1 +#define HAVE_STPCOPY 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRERROR_R 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_STRNLEN 1 +#define HAVE_STRSIGNAL 1 +#define HAVE_STRTOD_L 1 +#define HAVE_STRTOLL_L 1 +#define HAVE_STRTOULL_L 1 +#define HAVE_SYMLINK 1 +#define HAVE_TIMEGM 1 +#define HAVE_UNSETENV 1 +#define HAVE_USELOCALE 1 +#define HAVE_UTIMES 1 +#define HAVE_VASPRINTF 1 +#define HAVE_VSNPRINTF 1 + +#define HAVE_UNIX98_PRINTF 1 +#define HAVE_STRLCPY 0 + +#define HAVE_PROC_SELF_CMDLINE 1 + +#define THREADS_POSIX 1 +#define USE_STATFS 1 + +#define _GLIB_EXTERN __attribute__((visibility("default"))) +#define GLIB_HAVE_GROWING_STACK 0 +#define G_ATOMIC_LOCK_FREE 1 + +/* Alignment */ +#define ALIGNOF_UNSIGNED_LONG 8 + +/* Sizes */ +#define SIZEOF_CHAR 1 +#define SIZEOF_INT 4 +#define SIZEOF_LONG 8 +#define SIZEOF_LONG_LONG 8 +#define SIZEOF_SHORT 2 +#define SIZEOF_SIZE_T 8 +#define SIZEOF_SSIZE_T 8 +#define SIZEOF_VOID_P 8 +#define SIZEOF_WCHAR_T 4 + +#define GETTEXT_PACKAGE "glib20" + +#endif /* GLIB_CONFIG_H */ diff --git a/private/react-native-fantom/tester/third-party/glib/glibconfig.h b/private/react-native-fantom/tester/third-party/glib/glibconfig.h new file mode 100644 index 000000000000..b78f8dd9e0ef --- /dev/null +++ b/private/react-native-fantom/tester/third-party/glib/glibconfig.h @@ -0,0 +1,143 @@ +/* glibconfig.h - generated for Fantom build (Linux x86_64) */ +#ifndef GLIBCONFIG_H +#define GLIBCONFIG_H + +#include +#include +#include +#include + +#define GLIB_HAVE_ALLOCA_H 1 + +typedef int8_t gint8; +typedef uint8_t guint8; +typedef int16_t gint16; +typedef uint16_t guint16; +typedef int32_t gint32; +typedef uint32_t guint32; +typedef int64_t gint64; +typedef uint64_t guint64; + +#define G_GINT16_MODIFIER "h" +#define G_GINT16_FORMAT "hi" +#define G_GUINT16_FORMAT "hu" +#define G_GINT32_MODIFIER "" +#define G_GINT32_FORMAT "i" +#define G_GUINT32_FORMAT "u" +#define G_GINT64_MODIFIER "l" +#define G_GINT64_FORMAT "li" +#define G_GUINT64_FORMAT "lu" +#define G_GINT64_CONSTANT(val) (val##L) +#define G_GUINT64_CONSTANT(val) (val##UL) + +#define GLIB_SIZEOF_VOID_P 8 +#define GLIB_SIZEOF_LONG 8 +#define GLIB_SIZEOF_SIZE_T 8 +#define GLIB_SIZEOF_SSIZE_T 8 + +typedef signed long gssize; +typedef unsigned long gsize; +#define G_GSIZE_MODIFIER "l" +#define G_GSSIZE_MODIFIER "l" +#define G_GSIZE_FORMAT "lu" +#define G_GSSIZE_FORMAT "li" +#define G_MAXSIZE G_MAXULONG + +#define GPOINTER_TO_INT(p) ((gint)(glong)(p)) +#define GPOINTER_TO_UINT(p) ((guint)(gulong)(p)) +#define GINT_TO_POINTER(i) ((gpointer)(glong)(i)) +#define GUINT_TO_POINTER(u) ((gpointer)(gulong)(u)) + +typedef signed long gintptr; +typedef unsigned long guintptr; +#define G_GINTPTR_MODIFIER "l" +#define G_GINTPTR_FORMAT "li" +#define G_GUINTPTR_FORMAT "lu" + +#define GLIB_MAJOR_VERSION 2 +#define GLIB_MINOR_VERSION 78 +#define GLIB_MICRO_VERSION 3 + +#define G_OS_UNIX 1 + +#define G_VA_COPY va_copy + +#ifdef __LP64__ +#define GLIB_SIZEOF_LONG 8 +#define GLIB_SIZEOF_SIZE_T 8 +#define GLIB_SIZEOF_SSIZE_T 8 +#endif + +typedef unsigned int GQuark; + +#define G_BYTE_ORDER G_LITTLE_ENDIAN + +#define GINT16_TO_LE(val) ((gint16)(val)) +#define GUINT16_TO_LE(val) ((guint16)(val)) +#define GINT16_TO_BE(val) ((gint16)GUINT16_SWAP_LE_BE(val)) +#define GUINT16_TO_BE(val) (GUINT16_SWAP_LE_BE(val)) +#define GINT32_TO_LE(val) ((gint32)(val)) +#define GUINT32_TO_LE(val) ((guint32)(val)) +#define GINT32_TO_BE(val) ((gint32)GUINT32_SWAP_LE_BE(val)) +#define GUINT32_TO_BE(val) (GUINT32_SWAP_LE_BE(val)) +#define GINT64_TO_LE(val) ((gint64)(val)) +#define GUINT64_TO_LE(val) ((guint64)(val)) +#define GINT64_TO_BE(val) ((gint64)GUINT64_SWAP_LE_BE(val)) +#define GUINT64_TO_BE(val) (GUINT64_SWAP_LE_BE(val)) + +#define GLONG_TO_LE(val) ((glong)GINT64_TO_LE(val)) +#define GULONG_TO_LE(val) ((gulong)GUINT64_TO_LE(val)) +#define GLONG_TO_BE(val) ((glong)GINT64_TO_BE(val)) +#define GULONG_TO_BE(val) ((gulong)GUINT64_TO_BE(val)) +#define GINT_TO_LE(val) ((gint)GINT32_TO_LE(val)) +#define GUINT_TO_LE(val) ((guint)GUINT32_TO_LE(val)) +#define GINT_TO_BE(val) ((gint)GINT32_TO_BE(val)) +#define GUINT_TO_BE(val) ((guint)GUINT32_TO_BE(val)) +#define GSIZE_TO_LE(val) ((gsize)GUINT64_TO_LE(val)) +#define GSSIZE_TO_LE(val) ((gssize)GINT64_TO_LE(val)) +#define GSIZE_TO_BE(val) ((gsize)GUINT64_TO_BE(val)) +#define GSSIZE_TO_BE(val) ((gssize)GINT64_TO_BE(val)) + +#define G_HAVE_GINT64 1 + +#define G_MODULE_SUFFIX "so" + +typedef int GPid; +#define G_PID_FORMAT "i" + +#define GLIB_SYSDEF_POLLIN =1 +#define GLIB_SYSDEF_POLLOUT =4 +#define GLIB_SYSDEF_POLLPRI =2 +#define GLIB_SYSDEF_POLLHUP =16 +#define GLIB_SYSDEF_POLLERR =8 +#define GLIB_SYSDEF_POLLNVAL =32 + +#define G_HAVE_GROWING_STACK 0 +#define G_GNUC_INTERNAL __attribute__((visibility("hidden"))) + +#define G_THREADS_ENABLED 1 +#define G_THREADS_IMPL_POSIX 1 + +typedef struct _GMutex { + union { + void *p; + unsigned int i[2]; + }; +} GMutex; + +typedef union _GSystemThread { + char data[8]; + double dummy_double; + void *dummy_pointer; + long dummy_long; +} GSystemThread; + +#define GLIB_HAVE_SYSTEM_THREAD_STRUCT 1 + +#define G_ATOMIC_LOCK_FREE 1 + +#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#define G_GNUC_END_IGNORE_DEPRECATIONS _Pragma("GCC diagnostic pop") + +#endif /* GLIBCONFIG_H */ diff --git a/private/react-native-fantom/tester/third-party/harfbuzz/CMakeLists.txt b/private/react-native-fantom/tester/third-party/harfbuzz/CMakeLists.txt new file mode 100644 index 000000000000..47c886aa7619 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/harfbuzz/CMakeLists.txt @@ -0,0 +1,12 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(HB_HAVE_FREETYPE ON CACHE BOOL "" FORCE) +set(HB_BUILD_SUBSET OFF CACHE BOOL "" FORCE) +set(HB_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(HB_BUILD_UTILS OFF CACHE BOOL "" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +add_subdirectory(harfbuzz-8.3.0) diff --git a/private/react-native-fantom/tester/third-party/libffi/CMakeLists.txt b/private/react-native-fantom/tester/third-party/libffi/CMakeLists.txt new file mode 100644 index 000000000000..21174de4371d --- /dev/null +++ b/private/react-native-fantom/tester/third-party/libffi/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) + +add_subdirectory(libffi-3.4.6/cmake) diff --git a/private/react-native-fantom/tester/third-party/pango/CMakeLists.txt b/private/react-native-fantom/tester/third-party/pango/CMakeLists.txt new file mode 100644 index 000000000000..ad8bfa38c8f0 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/pango/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set(PANGO_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/pango-1.50.12) + +# Core pango sources (excluding pangocairo, pangoxft, pangowin32) +file(GLOB PANGO_CORE_SOURCES ${PANGO_SRC_DIR}/pango/*.c) +list(FILTER PANGO_CORE_SOURCES EXCLUDE REGEX "pangocairo") +list(FILTER PANGO_CORE_SOURCES EXCLUDE REGEX "pangoxft") +list(FILTER PANGO_CORE_SOURCES EXCLUDE REGEX "pangowin32") +list(FILTER PANGO_CORE_SOURCES EXCLUDE REGEX "pango-utils-system") +list(FILTER PANGO_CORE_SOURCES EXCLUDE REGEX "test") + +add_library(pango STATIC ${PANGO_CORE_SOURCES}) + +target_include_directories(pango + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${PANGO_SRC_DIR} + ${PANGO_SRC_DIR}/pango +) + +target_compile_definitions(pango + PUBLIC + PANGO_COMPILATION=1 + G_LOG_DOMAIN="Pango" + PRIVATE + HAVE_CONFIG_H=1 + _POSIX_C_SOURCE=200809L + _GNU_SOURCE=1 + SYSCONFDIR="/etc" + LIBDIR="/usr/lib" +) + +target_compile_options(pango + PRIVATE + -Wno-sign-compare + -Wno-unused-parameter + -Wno-missing-field-initializers + -Wno-deprecated-declarations +) + +target_link_libraries(pango + PUBLIC + glib_core + gobject + fribidi + harfbuzz + fontconfig +) + +# PangoFT2 sources +file(GLOB PANGOFT2_SOURCES ${PANGO_SRC_DIR}/pango/pangoft2*.c) +# Also include pango-ot sources +file(GLOB PANGO_OT_SOURCES ${PANGO_SRC_DIR}/pango/pango-ot*.c) + +add_library(pangoft2 STATIC ${PANGOFT2_SOURCES} ${PANGO_OT_SOURCES}) + +target_include_directories(pangoft2 + PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${PANGO_SRC_DIR} + ${PANGO_SRC_DIR}/pango +) + +target_compile_definitions(pangoft2 + PRIVATE + PANGO_COMPILATION=1 + G_LOG_DOMAIN="Pango" + HAVE_CONFIG_H=1 + _POSIX_C_SOURCE=200809L + _GNU_SOURCE=1 +) + +target_compile_options(pangoft2 + PRIVATE + -Wno-sign-compare + -Wno-unused-parameter + -Wno-missing-field-initializers + -Wno-deprecated-declarations +) + +target_link_libraries(pangoft2 + PUBLIC + pango + freetype +) diff --git a/private/react-native-fantom/tester/third-party/pango/config.h b/private/react-native-fantom/tester/third-party/pango/config.h new file mode 100644 index 000000000000..a8cfadb1793c --- /dev/null +++ b/private/react-native-fantom/tester/third-party/pango/config.h @@ -0,0 +1,29 @@ +/* config.h - generated for pango Fantom build (Linux x86_64) */ +#ifndef PANGO_BUILD_CONFIG_H +#define PANGO_BUILD_CONFIG_H + +#define HAVE_CAIRO 0 +#define HAVE_CAIRO_FREETYPE 0 +#define HAVE_CAIRO_PDF 0 +#define HAVE_CAIRO_PNG 0 +#define HAVE_CAIRO_PS 0 +#define HAVE_CAIRO_WIN32 0 +#define HAVE_CAIRO_XLIB 0 +#define HAVE_CAIRO_QUARTZ 0 +#define HAVE_CORE_TEXT 0 +#define HAVE_DIRENT_H 1 +#define HAVE_FREETYPE 1 +#define HAVE_DLOPEN 1 +#define HAVE_FLOCKFILE 1 +#define HAVE_GETPAGESIZE 1 +#define HAVE_MMAP 1 +#define HAVE_SYSCONF 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 + +#define PANGO_BINARY_AGE 5012 +#define PANGO_INTERFACE_AGE 12 + +#endif /* PANGO_BUILD_CONFIG_H */ diff --git a/private/react-native-fantom/tester/third-party/pango/pango-features.h b/private/react-native-fantom/tester/third-party/pango/pango-features.h new file mode 100644 index 000000000000..c58406b50c27 --- /dev/null +++ b/private/react-native-fantom/tester/third-party/pango/pango-features.h @@ -0,0 +1,15 @@ +/* pango-features.h - generated for pango 1.50.12 Fantom build */ +#ifndef PANGO_FEATURES_H +#define PANGO_FEATURES_H + +#define PANGO_VERSION_MAJOR 1 +#define PANGO_VERSION_MINOR 50 +#define PANGO_VERSION_MICRO 12 + +#define PANGO_VERSION_STRING "1.50.12" + +#define PANGO_API_VERSION "1.0" + +#define PANGO_HAS_CAIRO 0 + +#endif /* PANGO_FEATURES_H */