Add ICU (ICUPlugin) 71/318371/5
authorBowon Ryu <bowon.ryu@samsung.com>
Thu, 16 Jan 2025 06:27:18 +0000 (15:27 +0900)
committerBowon Ryu <bowon.ryu@samsung.com>
Thu, 6 Mar 2025 06:09:33 +0000 (15:09 +0900)
Use ICU to support linebreaks in languages that unibreak cannot support.
This patch generates libdali2-icu-plugin.so.
TextAbstraction::ICU dynamically loads icu-plugin.so if needed.

Change-Id: I74fb0b5c0f8b5bcd6a7889213e71c3528d4a0124
Signed-off-by: Bowon Ryu <bowon.ryu@samsung.com>
build/tizen/configure.ac
build/tizen/icu/Makefile.am [new file with mode: 0755]
build/tizen/icu/configure.ac [new file with mode: 0755]
build/ubuntu/CMakeLists.txt
build/ubuntu/icu/CMakeLists.txt [new file with mode: 0644]
dali-extension/icu/file-ubuntu.list [new file with mode: 0755]
dali-extension/icu/file.list [new file with mode: 0755]
dali-extension/icu/icu.cpp [new file with mode: 0644]
dali-extension/icu/icu.h [new file with mode: 0644]
packaging/dali-extension.spec

index f44eea5fa50a8a5ada9c88d800590778e98ad3cb..183640123f076bd79ce45bd58a59b00f0bb4b429 100755 (executable)
@@ -86,6 +86,7 @@ fi
 
 if test "x$with_tizen_65_or_greater" = "xyes"; then
   AC_CONFIG_SUBDIRS(camera-player)
+  AC_CONFIG_SUBDIRS(icu)
   AC_CONFIG_SUBDIRS(rive-animation-view)
 fi
 
diff --git a/build/tizen/icu/Makefile.am b/build/tizen/icu/Makefile.am
new file mode 100755 (executable)
index 0000000..e0eed48
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Copyright (c) 2025 Samsung Electronics Co., Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# 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.
+#
+
+# Build the Dali feedback plugin
+
+extension_src_dir = ../../../dali-extension
+
+include ../../../dali-extension/icu/file.list
+
+lib_LTLIBRARIES =
+
+lib_LTLIBRARIES += libdali2-icu-plugin.la
+
+libdali2_icu_plugin_la_includes =
+
+libdali2_icu_plugin_la_SOURCES = \
+                     $(icu_plugin_src_files)
+
+libdali2_icu_plugin_la_DEPENDENCIES =
+
+libdali2_icu_plugin_la_CXXFLAGS = \
+                      $(DLOG_CFLAGS) \
+                      $(DALI_CFLAGS) \
+                      $(ICU_CFLAGS) \
+                      -Werror -Wall
+
+libdali2_icu_plugin_la_CXXFLAGS+= \
+                      -I../../../dali-extension/icu
+
+libdali2_icu_plugin_la_LIBADD = \
+                      $(DLOG_LIBS) \
+                      $(DALI_LIBS) \
+                      $(ICU_LIBS)
+
+libdali2_icu_plugin_la_LDFLAGS = \
+                      -rdynamic
+
diff --git a/build/tizen/icu/configure.ac b/build/tizen/icu/configure.ac
new file mode 100755 (executable)
index 0000000..49356d7
--- /dev/null
@@ -0,0 +1,34 @@
+4_define([dali_version],[0.1.0])
+AC_INIT([dali], [dali_version])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+AC_CONFIG_MACRO_DIRS([m4 ../m4])
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AX_CXX_COMPILE_STDCXX([17], [noext], [mandatory])
+
+LT_INIT
+
+DALI_EXTENSION_VERSION=dali_version
+AC_SUBST(DALI_EXTENSION_VERSION)
+
+if test "x$enable_debug" = "xyes"; then
+  DALI_CFLAGS="$DALI_CFLAGS -DDEBUG_ENABLED"
+fi
+
+PKG_CHECK_MODULES([DALI], [dali2-core dali2-adaptor dali2-toolkit])
+PKG_CHECK_MODULES([ICU], [icu-i18n icu-uc])
+
+devincludepath=${includedir}
+AC_SUBST(devincludepath)
+AC_SUBST(DALI_CFLAGS)
+
+AC_CONFIG_FILES([
+Makefile
+])
+
+AC_OUTPUT
index 94b070c57b71c1f71b4758f0ea8e842b76b88c62..ad79378ee304b06f53aa52464d92e8d795cadc31 100644 (file)
@@ -22,3 +22,4 @@ SET(ROOT_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../..)
 GET_FILENAME_COMPONENT(ROOT_SRC_DIR ${ROOT_SRC_DIR} ABSOLUTE)
 
 ADD_SUBDIRECTORY(vector-animation-renderer)
+ADD_SUBDIRECTORY(icu)
diff --git a/build/ubuntu/icu/CMakeLists.txt b/build/ubuntu/icu/CMakeLists.txt
new file mode 100644 (file)
index 0000000..af5948c
--- /dev/null
@@ -0,0 +1,161 @@
+SET(name "dali2-icu-plugin")
+
+SET(CMAKE_C_STANDARD 99)
+SET(CMAKE_CXX_STANDARD 17)
+PROJECT(${name})
+SET(PKG_NAME ${name})
+
+SET(GCC_COMPILER_VERSION_REQUIRED "6")
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+  IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS GCC_COMPILER_VERSION_REQUIRED)
+    MESSAGE(FATAL_ERROR "The GCC required compiler version is " ${GCC_COMPILER_VERSION_REQUIRED})
+  ENDIF()
+ENDIF()
+
+IF( ENABLE_PKG_CONFIGURE )
+  FIND_PACKAGE( PkgConfig REQUIRED )
+  PKG_CHECK_MODULES(DALICORE REQUIRED dali2-core)
+  PKG_CHECK_MODULES(DALIADAPTOR REQUIRED dali2-adaptor)
+  PKG_CHECK_MODULES(DALITOOLKIT REQUIRED dali2-toolkit)
+  PKG_CHECK_MODULES(ICU REQUIRED icu-i18n)
+  PKG_CHECK_MODULES(ICU REQUIRED icu-uc)
+ENDIF()
+
+# Deployment folder should come from spec file or command line:
+SET( PREFIX ${CMAKE_INSTALL_PREFIX})
+SET( EXEC_PREFIX ${CMAKE_INSTALL_PREFIX})
+
+# Set up the include dir
+SET( INCLUDE_DIR $ENV{includedir} )
+IF( NOT INCLUDE_DIR )
+  SET( INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR} )
+ENDIF()
+IF( NOT INCLUDE_DIR )
+  SET( INCLUDE_DIR ${PREFIX}/include )
+ENDIF()
+
+# Set up the lib dir
+SET( LIB_DIR $ENV{libdir} )
+IF( NOT LIB_DIR )
+  SET( LIB_DIR ${CMAKE_INSTALL_LIBDIR} )
+ENDIF()
+IF( NOT LIB_DIR )
+  SET( LIB_DIR ${PREFIX}/lib )
+ENDIF()
+
+# Set up the bin dir
+SET( BIN_DIR $ENV{bindir} )
+IF( NOT BIN_DIR )
+  SET( BIN_DIR ${CMAKE_INSTALL_BINDIR} )
+ENDIF()
+IF( NOT BIN_DIR )
+  SET( BIN_DIR ${PREFIX}/bin )
+ENDIF()
+
+IF( ENABLE_DEBUG )
+  MESSAGE( STATUS "CMAKE_BUILD_TYPE: " Debug )
+  ADD_DEFINITIONS( "-DDEBUG_ENABLED" )
+  SET( ENABLE_EXPORTALL ON )
+ELSE()
+  MESSAGE( STATUS "CMAKE_BUILD_TYPE: " Release )
+ENDIF()
+
+IF( ENABLE_TRACE )
+  ADD_DEFINITIONS("-DTRACE_ENABLED")
+ENDIF()
+
+# Hijack the information of tizen version here
+ADD_DEFINITIONS("-DOVER_TIZEN_VERSION_9")
+
+INCLUDE(CheckCXXCompilerFlag)
+
+ADD_COMPILE_OPTIONS( -Werror -Wall -Wextra -Wno-unused-parameter -Wfloat-equal )
+CHECK_CXX_COMPILER_FLAG(-Wno-class-memaccess HAVE_NO_CLASS_MEMACCESS)
+IF (HAVE_NO_CLASS_MEMACCESS)
+  ADD_COMPILE_OPTIONS( -Wno-class-memaccess )
+ENDIF()
+
+CHECK_CXX_COMPILER_FLAG(-Wno-cast-function-type HAVE_NO_CAST_FUNCTION_TYPE)
+IF (HAVE_NO_CAST_FUNCTION_TYPE)
+  ADD_COMPILE_OPTIONS( -Wno-cast-function-type )
+ENDIF()
+
+IF( NOT ${ENABLE_EXPORTALL} )
+  ADD_COMPILE_OPTIONS( "-fvisibility=hidden" )
+ENDIF()
+
+SET(SOURCE_DIR "${ROOT_SRC_DIR}/dali-extension/icu")
+
+SET(SOURCES "")
+
+INCLUDE_DIRECTORIES(
+  ${ROOT_SRC_DIR}
+  ${DALICORE_INCLUDE_DIRS}
+  ${DALIADAPTOR_INCLUDE_DIRS}
+  ${INCLUDE_DIR}
+  ${SOURCE_DIR}
+)
+
+INCLUDE( ${ROOT_SRC_DIR}/dali-extension/icu/file-ubuntu.list )
+
+SET(LIBTYPE SHARED)
+IF(DEFINED STATIC)
+  SET(LIBTYPE STATIC)
+ENDIF()
+
+ADD_LIBRARY( ${name} ${LIBTYPE} ${SOURCES} )
+
+SET(OPTIONAL_LIBS ${OPTIONAL_LIBS} -lpthread)
+
+TARGET_LINK_LIBRARIES( ${name}
+  ${OPTIONAL_LIBS}
+  ${DALICORE_LDFLAGS}
+  ${DALIADAPTOR_LDFLAGS}
+  ${ICU_LDFLAGS}
+)
+
+IF( INSTALL_CMAKE_MODULES )
+  IF( ENABLE_DEBUG )
+    SET( BIN_DIR "${BIN_DIR}/debug" )
+    SET( LIB_DIR "${LIB_DIR}/debug" )
+  ENDIF()
+
+  # Install the library files.
+  INSTALL( TARGETS ${name}
+    EXPORT ${name}-targets
+    LIBRARY DESTINATION ${LIB_DIR}
+    ARCHIVE DESTINATION ${LIB_DIR}
+    RUNTIME DESTINATION ${BIN_DIR}
+  )
+
+  # Install the cmake modules.
+  INSTALL(
+    EXPORT ${name}-targets
+    NAMESPACE ${name}::
+    FILE ${name}-targets.cmake
+    DESTINATION share/${name}
+  )
+
+  FILE( WRITE ${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake "
+    include(CMakeFindDependencyMacro)
+    include(\${CMAKE_CURRENT_LIST_DIR}/${name}-targets.cmake)
+  ")
+  INSTALL( FILES ${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake DESTINATION share/${name} )
+
+ELSE()
+  # Install the library so file and symlinks.
+  INSTALL( TARGETS ${name} DESTINATION ${LIB_DIR} )
+ENDIF()
+
+# Configuration Messages
+MESSAGE( STATUS "Configuration:\n" )
+MESSAGE( STATUS "Prefix:                " ${PREFIX} )
+MESSAGE( STATUS "Lib Dir:               " ${LIB_DIR} )
+MESSAGE( STATUS "Bin Dir:               " ${BIN_DIR} )
+MESSAGE( STATUS "Include Dir:           " ${INCLUDE_DIR} )
+MESSAGE( STATUS "Debug build:           " ${ENABLE_DEBUG} )
+MESSAGE( STATUS "Export all symbols:    " ${ENABLE_EXPORTALL} )
+MESSAGE( STATUS "Trace:                 " ${ENABLE_TRACE} )
+MESSAGE( STATUS "Use pkg configure:     " ${ENABLE_PKG_CONFIGURE} )
+MESSAGE( STATUS "CXXFLAGS:              " ${CMAKE_CXX_FLAGS} )
+MESSAGE( STATUS "LDFLAGS:               " ${CMAKE_SHARED_LINKER_FLAGS_INIT}${CMAKE_SHARED_LINKER_FLAGS} )
diff --git a/dali-extension/icu/file-ubuntu.list b/dali-extension/icu/file-ubuntu.list
new file mode 100755 (executable)
index 0000000..8f85839
--- /dev/null
@@ -0,0 +1,5 @@
+SET( root_dir ${ROOT_SRC_DIR}/dali-extension/icu )
+
+SET( SOURCES ${SOURCES}
+  ${root_dir}/icu.cpp
+)
diff --git a/dali-extension/icu/file.list b/dali-extension/icu/file.list
new file mode 100755 (executable)
index 0000000..294cce0
--- /dev/null
@@ -0,0 +1,2 @@
+icu_plugin_src_files = \
+   $(extension_src_dir)/icu/icu.cpp
diff --git a/dali-extension/icu/icu.cpp b/dali-extension/icu/icu.cpp
new file mode 100644 (file)
index 0000000..f83076a
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ *
+ */
+
+// CLASS HEADER
+#include <icu.h>
+
+// EXTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+#include <unicode/brkiter.h>
+#include <unicode/unistr.h>
+#include <unicode/ustream.h>
+
+// INTERNAL INCLUDES
+
+// The plugin factories
+extern "C" DALI_EXPORT_API Dali::TextAbstraction::ICUPlugin *CreateICUPlugin()
+{
+  return new Dali::Plugin::ICU();
+}
+
+extern "C" DALI_EXPORT_API void DestroyICUPlugin(Dali::TextAbstraction::ICUPlugin *plugin)
+{
+  if (plugin != nullptr)
+  {
+    delete plugin;
+  }
+}
+
+namespace Dali
+{
+namespace Plugin
+{
+namespace
+{
+} // unnamed namespace
+
+ICU::ICU()
+{
+
+}
+
+ICU::~ICU()
+{
+
+}
+
+void ICU::UpdateLineBreakInfoByLocale(const std::string&              text,
+                                      TextAbstraction::Length         numberOfCharacters,
+                                      const char*                     locale,
+                                      TextAbstraction::LineBreakInfo* breakInfo)
+{
+  icu::UnicodeString unicodeText = icu::UnicodeString::fromUTF8(text);
+  if(static_cast<uint32_t>(unicodeText.length()) != numberOfCharacters)
+  {
+    DALI_LOG_ERROR("UnicodeString len : %lu, numberOfCharacters : %lu\n", static_cast<uint32_t>(unicodeText.length()), numberOfCharacters);
+    return;
+  }
+
+  icu::Locale icuLocale(locale);
+
+  UErrorCode status = U_ZERO_ERROR;
+  std::unique_ptr<icu::BreakIterator> lineIterator(icu::BreakIterator::createLineInstance(icuLocale, status));
+
+  if(U_FAILURE(status))
+  {
+    DALI_LOG_ERROR("Failed to create BreakIterator: %s\n", u_errorName(status));
+    return;
+  }
+
+  lineIterator->setText(unicodeText);
+
+  for(int32_t pos = lineIterator->first(); pos != icu::BreakIterator::DONE; pos = lineIterator->next())
+  {
+    if(pos != 0 && breakInfo[pos - 1] != TextAbstraction::LINE_MUST_BREAK)
+    {
+      breakInfo[pos - 1] = TextAbstraction::LINE_ALLOW_BREAK;
+    }
+  }
+}
+
+} // namespace Plugin
+} // namespace Dali
diff --git a/dali-extension/icu/icu.h b/dali-extension/icu/icu.h
new file mode 100644 (file)
index 0000000..6246885
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef DALI_ICU_PLUGIN_H
+#define DALI_ICU_PLUGIN_H
+
+/*
+ * Copyright (c) 2025 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/devel-api/text-abstraction/icu-plugin.h>
+
+namespace Dali
+{
+namespace Plugin
+{
+
+/**
+ * @brief Implementation of the ICU class which has Tizen platform dependency.
+ */
+class ICU : public Dali::TextAbstraction::ICUPlugin
+{
+public:
+
+  /**
+   * @brief Constructor.
+   */
+  ICU();
+
+  /**
+   * @brief Destructor.
+   */
+  virtual ~ICU();
+
+  /**
+   * @copydoc Dali::TextAbstraction::ICUPlugin::UpdateLineBreakInfoByLocale()
+   */
+  void UpdateLineBreakInfoByLocale(const std::string&              text,
+                                   TextAbstraction::Length         numberOfCharacters,
+                                   const char*                     locale,
+                                   TextAbstraction::LineBreakInfo* breakInfo) override;
+};
+
+} // namespace Plugin
+} // namespace Dali
+
+#endif // DALI_ICU_PLUGIN_H
index 72cff60adcd785ec2ea8a13e721e0569fb811586..c768d3962c78930c2a63b816096398b893058b5a 100755 (executable)
@@ -219,6 +219,19 @@ Requires: dali2-extension-rive-animation-view = %{version}-%{release}
 %description rive-animation-view-devel
 Header & package configuration of rive-animation-view
 
+##############################
+# Dali ICU Plugin
+##############################
+
+%package icu-plugin
+Summary:    Plugin to use an International Components for Unicode for Dali
+Group:      System/Libraries
+BuildRequires: pkgconfig(icu-i18n)
+BuildRequires: pkgconfig(icu-uc)
+
+%description icu-plugin
+ICU plugin to use an International Components for Unicode for Dali
+
 ##############################
 # Preparation
 ##############################
@@ -335,6 +348,10 @@ exit 0
 /sbin/ldconfig
 exit 0
 
+%post icu-plugin
+/sbin/ldconfig
+exit 0
+
 %if 0%{?tizen_55_or_greater} && 0%{?enable_web_engine_plugin} == 1
 %post web-engine-chromium-plugin
 pushd %{_libdir}
@@ -399,6 +416,10 @@ exit 0
 /sbin/ldconfig
 exit 0
 
+%postun icu-plugin
+/sbin/ldconfig
+exit 0
+
 %if 0%{?tizen_55_or_greater} && 0%{?enable_web_engine_plugin} == 1
 %postun web-engine-chromium-plugin
 /sbin/ldconfig
@@ -471,6 +492,14 @@ exit 0
 %license LICENSE
 %endif
 
+%if 0%{?tizen_65_or_greater}
+%files icu-plugin
+%manifest dali-extension.manifest
+%defattr(-,root,root,-)
+%{_libdir}/libdali2-icu-plugin.so*
+%license LICENSE
+%endif
+
 %if 0%{?tizen_55_or_greater} && 0%{?enable_web_engine_plugin} == 1
 %files web-engine-chromium-plugin
 %manifest dali-extension.manifest