mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-05 17:36:25 +00:00
X11TK: Add Arabic/Hebrew/Farsi support by increasing font size slightly and using FriBidi. (#14134)
This commit is contained in:
@@ -347,6 +347,8 @@ dep_option(SDL_X11_XSCRNSAVER "Enable Xscrnsaver support" ON SDL_X11 OFF)
|
|||||||
dep_option(SDL_X11_XSHAPE "Enable XShape support" ON SDL_X11 OFF)
|
dep_option(SDL_X11_XSHAPE "Enable XShape support" ON SDL_X11 OFF)
|
||||||
dep_option(SDL_X11_XSYNC "Enable Xsync support" ON SDL_X11 OFF)
|
dep_option(SDL_X11_XSYNC "Enable Xsync support" ON SDL_X11 OFF)
|
||||||
dep_option(SDL_X11_XTEST "Enable XTest support" ON SDL_X11 OFF)
|
dep_option(SDL_X11_XTEST "Enable XTest support" ON SDL_X11 OFF)
|
||||||
|
dep_option(SDL_FRIBIDI "Enable Fribidi support" ON SDL_X11 OFF)
|
||||||
|
dep_option(SDL_FRIBIDI_SHARED "Dynamically load Fribidi support" ON "SDL_FRIBIDI;SDL_DEPS_SHARED" OFF)
|
||||||
dep_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
|
dep_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS} "SDL_VIDEO" OFF)
|
||||||
dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
|
dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
|
||||||
dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
|
dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
|
||||||
@@ -1776,6 +1778,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
|||||||
# Need to check for ROCKCHIP platform and get rid of "Can't window GBM/EGL surfaces on window creation."
|
# Need to check for ROCKCHIP platform and get rid of "Can't window GBM/EGL surfaces on window creation."
|
||||||
CheckROCKCHIP()
|
CheckROCKCHIP()
|
||||||
CheckX11()
|
CheckX11()
|
||||||
|
CheckFribidi()
|
||||||
# Need to check for EGL first because KMSDRM and Wayland depend on it.
|
# Need to check for EGL first because KMSDRM and Wayland depend on it.
|
||||||
CheckEGL()
|
CheckEGL()
|
||||||
CheckKMSDRM()
|
CheckKMSDRM()
|
||||||
@@ -1925,7 +1928,6 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
|
|||||||
set(HAVE_LIBURING TRUE)
|
set(HAVE_LIBURING TRUE)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if((FREEBSD OR NETBSD) AND NOT HAVE_INOTIFY)
|
if((FREEBSD OR NETBSD) AND NOT HAVE_INOTIFY)
|
||||||
set(LibInotify_PKG_CONFIG_SPEC libinotify)
|
set(LibInotify_PKG_CONFIG_SPEC libinotify)
|
||||||
pkg_check_modules(PC_LIBINOTIFY IMPORTED_TARGET ${LibInotify_PKG_CONFIG_SPEC})
|
pkg_check_modules(PC_LIBINOTIFY IMPORTED_TARGET ${LibInotify_PKG_CONFIG_SPEC})
|
||||||
|
@@ -511,6 +511,35 @@ macro(CheckX11)
|
|||||||
cmake_pop_check_state()
|
cmake_pop_check_state()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
macro(CheckFribidi)
|
||||||
|
if(SDL_FRIBIDI)
|
||||||
|
set(FRIBIDI_PKG_CONFIG_SPEC fribidi)
|
||||||
|
set(PC_FRIBIDI_FOUND FALSE)
|
||||||
|
if(PKG_CONFIG_FOUND)
|
||||||
|
pkg_check_modules(PC_FRIBIDI IMPORTED_TARGET ${FRIBIDI_PKG_CONFIG_SPEC})
|
||||||
|
endif()
|
||||||
|
if(PC_FRIBIDI_FOUND)
|
||||||
|
set(HAVE_FRIBIDI TRUE)
|
||||||
|
set(HAVE_FRIBIDI_H 1)
|
||||||
|
sdl_sources(
|
||||||
|
"${SDL3_SOURCE_DIR}/src/core/unix/SDL_fribidi.c"
|
||||||
|
"${SDL3_SOURCE_DIR}/src/core/unix/SDL_fribidi.h"
|
||||||
|
)
|
||||||
|
if(SDL_FRIBIDI_SHARED AND NOT HAVE_SDL_LOADSO)
|
||||||
|
message(WARNING "You must have SDL_LoadObject() support for dynamic fribidi loading")
|
||||||
|
endif()
|
||||||
|
FindLibraryAndSONAME("fribidi" LIBDIRS ${PC_FRIBIDI_LIBRARY_DIRS})
|
||||||
|
if(SDL_FRIBIDI_SHARED AND FRIBIDI_LIB AND HAVE_SDL_LOADSO)
|
||||||
|
set(SDL_FRIBIDI_DYNAMIC "\"${FRIBIDI_LIB_SONAME}\"")
|
||||||
|
set(HAVE_FRIBIDI_SHARED TRUE)
|
||||||
|
sdl_include_directories(PRIVATE SYSTEM $<TARGET_PROPERTY:PkgConfig::PC_FRIBIDI,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||||
|
else()
|
||||||
|
sdl_link_dependency(fribidi LIBS PkgConfig::PC_FRIBIDI PKG_CONFIG_PREFIX PC_FRIBIDI PKG_CONFIG_SPECS ${FRIBIDI_PKG_CONFIG_SPEC})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
|
macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL)
|
||||||
set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
|
set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
|
||||||
set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
|
set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
|
||||||
|
@@ -216,6 +216,8 @@
|
|||||||
#cmakedefine HAVE_LIBUDEV_H 1
|
#cmakedefine HAVE_LIBUDEV_H 1
|
||||||
#cmakedefine HAVE_LIBDECOR_H 1
|
#cmakedefine HAVE_LIBDECOR_H 1
|
||||||
#cmakedefine HAVE_LIBURING_H 1
|
#cmakedefine HAVE_LIBURING_H 1
|
||||||
|
#cmakedefine HAVE_FRIBIDI_H 1
|
||||||
|
#cmakedefine SDL_FRIBIDI_DYNAMIC @SDL_FRIBIDI_DYNAMIC@
|
||||||
|
|
||||||
#cmakedefine HAVE_DDRAW_H 1
|
#cmakedefine HAVE_DDRAW_H 1
|
||||||
#cmakedefine HAVE_DSOUND_H 1
|
#cmakedefine HAVE_DSOUND_H 1
|
||||||
|
160
src/core/unix/SDL_fribidi.c
Normal file
160
src/core/unix/SDL_fribidi.c
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
#include "SDL_fribidi.h"
|
||||||
|
#include <fribidi.h>
|
||||||
|
|
||||||
|
SDL_FriBidi *SDL_FriBidi_Create(void) {
|
||||||
|
SDL_FriBidi *fribidi;
|
||||||
|
|
||||||
|
fribidi = (SDL_FriBidi *)SDL_malloc(sizeof(SDL_FriBidi));
|
||||||
|
if (!fribidi) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_FRIBIDI_DYNAMIC
|
||||||
|
#define SDL_FRIBIDI_LOAD_SYM(x, n, t) x = ((t)SDL_LoadFunction(fribidi->lib, n)); if (!x) { SDL_UnloadObject(fribidi->lib); SDL_free(fribidi); return NULL; }
|
||||||
|
|
||||||
|
fribidi->lib = SDL_LoadObject(SDL_FRIBIDI_DYNAMIC);
|
||||||
|
if (!fribidi->lib) {
|
||||||
|
SDL_free(fribidi);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->unicode_to_charset, "fribidi_unicode_to_charset", SDL_FriBidiUnicodeToCharset);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->charset_to_unicode, "fribidi_charset_to_unicode", SDL_FriBidiCharsetToUnicode);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->get_bidi_types, "fribidi_get_bidi_types", SDL_FriBidiGetBidiTypes);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->get_par_direction, "fribidi_get_par_direction", SDL_FriBidiGetParDirection);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->get_par_embedding_levels, "fribidi_get_par_embedding_levels", SDL_FriBidiGetParEmbeddingLevels);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->get_joining_types, "fribidi_get_joining_types", SDL_FriBidiGetJoiningTypes);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->join_arabic, "fribidi_join_arabic", SDL_FriBidiJoinArabic);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->shape, "fribidi_shape", SDL_FriBidiShape);
|
||||||
|
SDL_FRIBIDI_LOAD_SYM(fribidi->reorder_line, "fribidi_reorder_line", SDL_FriBidiReorderLine);
|
||||||
|
#else
|
||||||
|
fribidi->unicode_to_charset = fribidi_unicode_to_charset;
|
||||||
|
fribidi->charset_to_unicode = fribidi_charset_to_unicode;
|
||||||
|
fribidi->get_bidi_types = fribidi_get_bidi_types;
|
||||||
|
fribidi->get_par_direction = fribidi_get_par_direction;
|
||||||
|
fribidi->get_par_embedding_levels = fribidi_get_par_embedding_levels;
|
||||||
|
fribidi->get_joining_types = fribidi_get_joining_types;
|
||||||
|
fribidi->join_arabic = fribidi_join_arabic;
|
||||||
|
fribidi->shape = fribidi_shape;
|
||||||
|
fribidi->reorder_line = fribidi_reorder_line;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return fribidi;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SDL_FriBidi_Process(SDL_FriBidi *fribidi, char *utf8, ssize_t utf8_len, bool shaping, FriBidiParType *out_par_type) {
|
||||||
|
FriBidiCharType *types;
|
||||||
|
FriBidiLevel *levels;
|
||||||
|
FriBidiArabicProp *props;
|
||||||
|
FriBidiChar *str;
|
||||||
|
char *result;
|
||||||
|
FriBidiStrIndex len;
|
||||||
|
FriBidiLevel max_level;
|
||||||
|
FriBidiLevel start;
|
||||||
|
FriBidiLevel end;
|
||||||
|
FriBidiParType direction;
|
||||||
|
FriBidiParType str_direction;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int c;
|
||||||
|
|
||||||
|
if (!fribidi || !utf8) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert to UTF32 */
|
||||||
|
if (utf8_len < 0) {
|
||||||
|
utf8_len = SDL_strlen(utf8);
|
||||||
|
}
|
||||||
|
str = SDL_calloc(SDL_utf8strnlen(utf8, utf8_len), sizeof(FriBidiChar));
|
||||||
|
len = fribidi->charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, utf8, utf8_len, str);
|
||||||
|
|
||||||
|
/* Setup various BIDI structures */
|
||||||
|
direction = FRIBIDI_PAR_LTR;
|
||||||
|
types = NULL;
|
||||||
|
levels = NULL;
|
||||||
|
props = SDL_calloc(len + 1, sizeof(FriBidiArabicProp));
|
||||||
|
levels = SDL_calloc(len + 1, sizeof(FriBidiLevel));
|
||||||
|
types = SDL_calloc(len + 1, sizeof(FriBidiCharType));
|
||||||
|
|
||||||
|
/* Shape */
|
||||||
|
fribidi->get_bidi_types(str, len, types);
|
||||||
|
str_direction = fribidi->get_par_direction(types, len);
|
||||||
|
max_level = fribidi->get_par_embedding_levels(types, len, &direction, levels);
|
||||||
|
if (shaping) {
|
||||||
|
fribidi->get_joining_types(str, len, props);
|
||||||
|
fribidi->join_arabic(types, len, levels, props);
|
||||||
|
fribidi->shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, levels, len, props, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BIDI */
|
||||||
|
for (end = 0, start = 0; end < len; end++) {
|
||||||
|
if (str[end] == '\n' || str[end] == '\r' || str[end] == '\f' || str[end] == '\v' || end == len - 1) {
|
||||||
|
max_level = fribidi->reorder_line(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC, types, end - start + 1, start, direction, levels, str, NULL);
|
||||||
|
start = end + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Silence warning */
|
||||||
|
(void)max_level;
|
||||||
|
|
||||||
|
/* Remove fillers */
|
||||||
|
for (i = 0, c = 0; i < len; i++) {
|
||||||
|
if (str[i] != FRIBIDI_CHAR_FILL) {
|
||||||
|
str[c++] = str[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = c;
|
||||||
|
|
||||||
|
/* Convert back to UTF8 */
|
||||||
|
result = SDL_malloc(len * 4 + 1);
|
||||||
|
fribidi->unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, str, len, result);
|
||||||
|
|
||||||
|
/* Cleanup */
|
||||||
|
SDL_free(levels);
|
||||||
|
SDL_free(props);
|
||||||
|
SDL_free(types);
|
||||||
|
|
||||||
|
/* Return */
|
||||||
|
if (out_par_type) {
|
||||||
|
*out_par_type = str_direction;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDL_FriBidi_Destroy(SDL_FriBidi *fribidi) {
|
||||||
|
if (!fribidi) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SDL_FRIBIDI_DYNAMIC
|
||||||
|
SDL_UnloadObject(fribidi->lib);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_free(fribidi);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
58
src/core/unix/SDL_fribidi.h
Normal file
58
src/core/unix/SDL_fribidi.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Simple DirectMedia Layer
|
||||||
|
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
3. This notice may not be removed or altered from any source distribution.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
#include <fribidi.h>
|
||||||
|
|
||||||
|
#ifndef SDL_fribidi_h_
|
||||||
|
#define SDL_fribidi_h_
|
||||||
|
|
||||||
|
typedef FriBidiStrIndex (*SDL_FriBidiUnicodeToCharset)(FriBidiCharSet, const FriBidiChar *, FriBidiStrIndex, char *);
|
||||||
|
typedef FriBidiStrIndex (*SDL_FriBidiCharsetToUnicode)(FriBidiCharSet, const char *, FriBidiStrIndex, FriBidiChar *);
|
||||||
|
typedef void (*SDL_FriBidiGetBidiTypes)(const FriBidiChar *, const FriBidiStrIndex, FriBidiCharType *);
|
||||||
|
typedef FriBidiParType (*SDL_FriBidiGetParDirection)(const FriBidiCharType *, const FriBidiStrIndex);
|
||||||
|
typedef FriBidiLevel (*SDL_FriBidiGetParEmbeddingLevels)(const FriBidiCharType *, const FriBidiStrIndex, FriBidiParType *, FriBidiLevel *);
|
||||||
|
typedef void (*SDL_FriBidiGetJoiningTypes)(const FriBidiChar *, const FriBidiStrIndex, FriBidiJoiningType *);
|
||||||
|
typedef void (*SDL_FriBidiJoinArabic)(const FriBidiCharType *, const FriBidiStrIndex, const FriBidiLevel *, FriBidiArabicProp *);
|
||||||
|
typedef void (*SDL_FriBidiShape)(FriBidiFlags flags, const FriBidiLevel *, const FriBidiStrIndex, FriBidiArabicProp *, FriBidiChar *str);
|
||||||
|
typedef FriBidiLevel (*SDL_FriBidiReorderLine)(FriBidiFlags flags, const FriBidiCharType *, const FriBidiStrIndex, const FriBidiStrIndex, const FriBidiParType, FriBidiLevel *, FriBidiChar *, FriBidiStrIndex *);
|
||||||
|
|
||||||
|
typedef struct SDL_FriBidi {
|
||||||
|
SDL_SharedObject *lib;
|
||||||
|
SDL_FriBidiUnicodeToCharset unicode_to_charset;
|
||||||
|
SDL_FriBidiCharsetToUnicode charset_to_unicode;
|
||||||
|
SDL_FriBidiGetBidiTypes get_bidi_types;
|
||||||
|
SDL_FriBidiGetParDirection get_par_direction;
|
||||||
|
SDL_FriBidiGetParEmbeddingLevels get_par_embedding_levels;
|
||||||
|
SDL_FriBidiGetJoiningTypes get_joining_types;
|
||||||
|
SDL_FriBidiJoinArabic join_arabic;
|
||||||
|
SDL_FriBidiShape shape;
|
||||||
|
SDL_FriBidiReorderLine reorder_line;
|
||||||
|
} SDL_FriBidi;
|
||||||
|
|
||||||
|
extern SDL_FriBidi *SDL_FriBidi_Create(void);
|
||||||
|
extern char *SDL_FriBidi_Process(SDL_FriBidi *fribidi, char *utf8, ssize_t utf8_len, bool shaping, FriBidiParType *out_par_type);
|
||||||
|
extern void SDL_FriBidi_Destroy(SDL_FriBidi *fribidi);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // SDL_fribidi_h_
|
@@ -235,8 +235,10 @@ SDL_X11_SYM(int,Xutf8TextExtents,(XFontSet a, _Xconst char* b, int c, XRectangle
|
|||||||
SDL_X11_SYM(char*,XSetLocaleModifiers,(const char *a))
|
SDL_X11_SYM(char*,XSetLocaleModifiers,(const char *a))
|
||||||
SDL_X11_SYM(char*,Xutf8ResetIC,(XIC a))
|
SDL_X11_SYM(char*,Xutf8ResetIC,(XIC a))
|
||||||
SDL_X11_SYM(XFontSetExtents*,XExtentsOfFontSet,(XFontSet a))
|
SDL_X11_SYM(XFontSetExtents*,XExtentsOfFontSet,(XFontSet a))
|
||||||
|
SDL_X11_SYM(Bool,XContextDependentDrawing,(XFontSet a))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef NO_SHARED_MEMORY
|
#ifndef NO_SHARED_MEMORY
|
||||||
SDL_X11_MODULE(SHM)
|
SDL_X11_MODULE(SHM)
|
||||||
SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b))
|
SDL_X11_SYM(Status,XShmAttach,(Display* a,XShmSegmentInfo* b))
|
||||||
|
@@ -28,6 +28,9 @@
|
|||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
#include "../../core/linux/SDL_system_theme.h"
|
#include "../../core/linux/SDL_system_theme.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
#include "../../core/unix/SDL_fribidi.h"
|
||||||
|
#endif
|
||||||
#include "SDL_x11dyn.h"
|
#include "SDL_x11dyn.h"
|
||||||
#include "SDL_x11toolkit.h"
|
#include "SDL_x11toolkit.h"
|
||||||
#include "SDL_x11settings.h"
|
#include "SDL_x11settings.h"
|
||||||
@@ -76,6 +79,10 @@ typedef struct SDL_ToolkitButtonControlX11
|
|||||||
int text_a;
|
int text_a;
|
||||||
int text_d;
|
int text_d;
|
||||||
int str_sz;
|
int str_sz;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
char *text;
|
||||||
|
bool free_text;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Callback */
|
/* Callback */
|
||||||
void *cb_data;
|
void *cb_data;
|
||||||
@@ -90,6 +97,12 @@ typedef struct SDL_ToolkitLabelControlX11
|
|||||||
int *y;
|
int *y;
|
||||||
size_t *szs;
|
size_t *szs;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
int *x;
|
||||||
|
int *w;
|
||||||
|
bool *free_lines;
|
||||||
|
FriBidiParType *par_types;
|
||||||
|
#endif
|
||||||
} SDL_ToolkitLabelControlX11;
|
} SDL_ToolkitLabelControlX11;
|
||||||
|
|
||||||
typedef struct SDL_ToolkitMenuBarControlX11
|
typedef struct SDL_ToolkitMenuBarControlX11
|
||||||
@@ -109,7 +122,7 @@ typedef struct SDL_ToolkitMenuControlX11
|
|||||||
|
|
||||||
/* Font for icon control */
|
/* Font for icon control */
|
||||||
static const char *g_IconFont = "-*-*-bold-r-normal-*-%d-*-*-*-*-*-iso8859-1[33 88 105]";
|
static const char *g_IconFont = "-*-*-bold-r-normal-*-%d-*-*-*-*-*-iso8859-1[33 88 105]";
|
||||||
#define G_ICONFONT_SIZE 18
|
#define G_ICONFONT_SIZE 22
|
||||||
|
|
||||||
/* General UI font */
|
/* General UI font */
|
||||||
static const char g_ToolkitFontLatin1[] =
|
static const char g_ToolkitFontLatin1[] =
|
||||||
@@ -128,7 +141,7 @@ static const char *g_ToolkitFont[] = {
|
|||||||
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1,*", // just give me anything latin1.
|
"-*-*-*-*-*--*-*-*-*-*-*-iso8859-1,*", // just give me anything latin1.
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
#define G_TOOLKITFONT_SIZE 120
|
#define G_TOOLKITFONT_SIZE 140
|
||||||
|
|
||||||
static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = {
|
static const SDL_MessageBoxColor g_default_colors[SDL_MESSAGEBOX_COLOR_COUNT] = {
|
||||||
{ 191, 184, 191 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
|
{ 191, 184, 191 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND,
|
||||||
@@ -399,6 +412,10 @@ static void X11Toolkit_InitWindowFonts(SDL_ToolkitWindowX11 *window)
|
|||||||
|
|
||||||
if (!window->font_set) {
|
if (!window->font_set) {
|
||||||
goto load_font_traditional;
|
goto load_font_traditional;
|
||||||
|
} else {
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
window->do_shaping = !X11_XContextDependentDrawing(window->font_set);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
@@ -549,27 +566,40 @@ static void X11Toolkit_GetTextWidthHeightForFont(XFontStruct *font, const char *
|
|||||||
*ascent = text_structure.ascent;
|
*ascent = text_structure.ascent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent, int *font_descent)
|
static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char *str, int nbytes, int *pwidth, int *pheight, int *ascent, int *descent, int *font_height)
|
||||||
{
|
{
|
||||||
#ifdef X_HAVE_UTF8_STRING
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
if (data->utf8) {
|
if (data->utf8) {
|
||||||
XRectangle overall_ink, overall_logical;
|
XRectangle overall_ink, overall_logical;
|
||||||
|
|
||||||
X11_Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
|
X11_Xutf8TextExtents(data->font_set, str, nbytes, &overall_ink, &overall_logical);
|
||||||
*pwidth = overall_logical.width;
|
*pwidth = overall_logical.width;
|
||||||
*pheight = overall_logical.height;
|
*pheight = overall_logical.height;
|
||||||
*ascent = -overall_logical.y;
|
*ascent = -overall_logical.y;
|
||||||
*font_descent = overall_logical.height - *ascent;
|
*descent = overall_logical.height - *ascent;
|
||||||
|
|
||||||
|
if (font_height) {
|
||||||
|
XFontSetExtents *extents;
|
||||||
|
|
||||||
|
extents = X11_XExtentsOfFontSet(data->font_set);
|
||||||
|
*font_height = extents->max_logical_extent.height;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
XCharStruct text_structure;
|
XCharStruct text_structure;
|
||||||
int font_direction, font_ascent;
|
int font_direction, font_ascent, font_descent;
|
||||||
X11_XTextExtents(data->font_struct, str, nbytes,
|
X11_XTextExtents(data->font_struct, str, nbytes,
|
||||||
&font_direction, &font_ascent, font_descent,
|
&font_direction, &font_ascent, &font_descent,
|
||||||
&text_structure);
|
&text_structure);
|
||||||
*pwidth = text_structure.width;
|
*pwidth = text_structure.width;
|
||||||
*pheight = text_structure.ascent + text_structure.descent;
|
*pheight = text_structure.ascent + text_structure.descent;
|
||||||
*ascent = text_structure.ascent;
|
*ascent = text_structure.ascent;
|
||||||
|
*descent = text_structure.descent;
|
||||||
|
|
||||||
|
if (font_height) {
|
||||||
|
*font_height = font_ascent + font_descent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,6 +809,9 @@ SDL_ToolkitWindowX11 *X11Toolkit_CreateWindowStruct(SDL_Window *parent, SDL_Tool
|
|||||||
/* Menu windows */
|
/* Menu windows */
|
||||||
window->popup_windows = NULL;
|
window->popup_windows = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
window->fribidi = SDL_FriBidi_Create();
|
||||||
|
#endif
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1653,7 +1686,7 @@ static void X11Toolkit_CalculateButtonControl(SDL_ToolkitControlX11 *control) {
|
|||||||
int text_d;
|
int text_d;
|
||||||
|
|
||||||
button_control = (SDL_ToolkitButtonControlX11 *)control;
|
button_control = (SDL_ToolkitButtonControlX11 *)control;
|
||||||
X11Toolkit_GetTextWidthHeight(control->window, button_control->data->text, button_control->str_sz, &button_control->text_rect.w, &button_control->text_rect.h, &button_control->text_a, &text_d);
|
X11Toolkit_GetTextWidthHeight(control->window, button_control->data->text, button_control->str_sz, &button_control->text_rect.w, &button_control->text_rect.h, &button_control->text_a, &text_d, NULL);
|
||||||
if (control->do_size) {
|
if (control->do_size) {
|
||||||
control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.w;
|
control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.w;
|
||||||
control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.h;
|
control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * control->window->iscale + button_control->text_rect.h;
|
||||||
@@ -1665,8 +1698,16 @@ static void X11Toolkit_CalculateButtonControl(SDL_ToolkitControlX11 *control) {
|
|||||||
|
|
||||||
static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
|
static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
|
||||||
SDL_ToolkitButtonControlX11 *button_control;
|
SDL_ToolkitButtonControlX11 *button_control;
|
||||||
|
char *text;
|
||||||
|
|
||||||
button_control = (SDL_ToolkitButtonControlX11 *)control;
|
button_control = (SDL_ToolkitButtonControlX11 *)control;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
text = button_control->text;
|
||||||
|
#else
|
||||||
|
text = (char *)button_control->data->text;
|
||||||
|
#endif
|
||||||
|
|
||||||
X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
|
X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
|
||||||
/* Draw bevel */
|
/* Draw bevel */
|
||||||
if (control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED || control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED_HELD) {
|
if (control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED || control->state == SDL_TOOLKIT_CONTROL_STATE_X11_PRESSED_HELD) {
|
||||||
@@ -1754,13 +1795,13 @@ static void X11Toolkit_DrawButtonControl(SDL_ToolkitControlX11 *control) {
|
|||||||
X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
|
X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
|
||||||
control->rect.x + button_control->text_rect.x,
|
control->rect.x + button_control->text_rect.x,
|
||||||
control->rect.y + button_control->text_rect.y,
|
control->rect.y + button_control->text_rect.y,
|
||||||
button_control->data->text, button_control->str_sz);
|
text, button_control->str_sz);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
|
X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
|
||||||
control->rect.x + button_control->text_rect.x, control->rect.y + button_control->text_rect.y,
|
control->rect.x + button_control->text_rect.x, control->rect.y + button_control->text_rect.y,
|
||||||
button_control->data->text, button_control->str_sz);
|
text, button_control->str_sz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1773,7 +1814,15 @@ static void X11Toolkit_OnButtonControlStateChange(SDL_ToolkitControlX11 *control
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void X11Toolkit_DestroyGenericControl(SDL_ToolkitControlX11 *control) {
|
static void X11Toolkit_DestroyButtonControl(SDL_ToolkitControlX11 *control) {
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
SDL_ToolkitButtonControlX11 *button_control;
|
||||||
|
|
||||||
|
button_control = (SDL_ToolkitButtonControlX11 *)control;
|
||||||
|
if (button_control->free_text) {
|
||||||
|
SDL_free(button_control->text);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
SDL_free(control);
|
SDL_free(control);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1793,7 +1842,7 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *wind
|
|||||||
base_control->func_calc_size = X11Toolkit_CalculateButtonControl;
|
base_control->func_calc_size = X11Toolkit_CalculateButtonControl;
|
||||||
base_control->func_draw = X11Toolkit_DrawButtonControl;
|
base_control->func_draw = X11Toolkit_DrawButtonControl;
|
||||||
base_control->func_on_state_change = X11Toolkit_OnButtonControlStateChange;
|
base_control->func_on_state_change = X11Toolkit_OnButtonControlStateChange;
|
||||||
base_control->func_free = X11Toolkit_DestroyGenericControl;
|
base_control->func_free = X11Toolkit_DestroyButtonControl;
|
||||||
base_control->func_on_scale_change = NULL;
|
base_control->func_on_scale_change = NULL;
|
||||||
base_control->state = SDL_TOOLKIT_CONTROL_STATE_X11_NORMAL;
|
base_control->state = SDL_TOOLKIT_CONTROL_STATE_X11_NORMAL;
|
||||||
base_control->selected = false;
|
base_control->selected = false;
|
||||||
@@ -1810,8 +1859,23 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateButtonControl(SDL_ToolkitWindowX11 *wind
|
|||||||
base_control->do_size = false;
|
base_control->do_size = false;
|
||||||
control->data = data;
|
control->data = data;
|
||||||
control->str_sz = SDL_strlen(control->data->text);
|
control->str_sz = SDL_strlen(control->data->text);
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
control->text = SDL_FriBidi_Process(base_control->window->fribidi, (char *)control->data->text, control->str_sz, base_control->window->do_shaping, NULL);
|
||||||
|
if (control->text) {
|
||||||
|
control->free_text = true;
|
||||||
|
control->str_sz = SDL_strlen(control->text);
|
||||||
|
} else {
|
||||||
|
control->text = (char *)control->data->text;
|
||||||
|
control->free_text = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
control->text = (char *)control->data->text;
|
||||||
|
control->free_text = false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
control->cb = NULL;
|
control->cb = NULL;
|
||||||
X11Toolkit_GetTextWidthHeight(base_control->window, control->data->text, control->str_sz, &control->text_rect.w, &control->text_rect.h, &control->text_a, &text_d);
|
X11Toolkit_GetTextWidthHeight(base_control->window, control->data->text, control->str_sz, &control->text_rect.w, &control->text_rect.h, &control->text_a, &text_d, NULL);
|
||||||
base_control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.w;
|
base_control->rect.w = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.w;
|
||||||
base_control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.h;
|
base_control->rect.h = SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * 2 * window->iscale + control->text_rect.h;
|
||||||
control->text_rect.x = control->text_rect.y = 0;
|
control->text_rect.x = control->text_rect.y = 0;
|
||||||
@@ -1923,6 +1987,10 @@ void X11Toolkit_DestroyWindow(SDL_ToolkitWindowX11 *data) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
SDL_FriBidi_Destroy(data->fribidi);
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1940,20 +2008,27 @@ static int X11Toolkit_CountLinesOfText(const char *text)
|
|||||||
static void X11Toolkit_DrawLabelControl(SDL_ToolkitControlX11 *control) {
|
static void X11Toolkit_DrawLabelControl(SDL_ToolkitControlX11 *control) {
|
||||||
SDL_ToolkitLabelControlX11 *label_control;
|
SDL_ToolkitLabelControlX11 *label_control;
|
||||||
int i;
|
int i;
|
||||||
|
int x;
|
||||||
|
|
||||||
label_control = (SDL_ToolkitLabelControlX11 *)control;
|
label_control = (SDL_ToolkitLabelControlX11 *)control;
|
||||||
X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
|
X11_XSetForeground(control->window->display, control->window->ctx, control->window->xcolor[SDL_MESSAGEBOX_COLOR_TEXT].pixel);
|
||||||
for (i = 0; i < label_control->sz; i++) {
|
for (i = 0; i < label_control->sz; i++) {
|
||||||
|
x = control->rect.x;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (control->window->fribidi) {
|
||||||
|
x += label_control->x[i];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef X_HAVE_UTF8_STRING
|
#ifdef X_HAVE_UTF8_STRING
|
||||||
if (control->window->utf8) {
|
if (control->window->utf8) {
|
||||||
X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
|
X11_Xutf8DrawString(control->window->display, control->window->drawable, control->window->font_set, control->window->ctx,
|
||||||
control->rect.x, control->rect.y + label_control->y[i],
|
x, control->rect.y + label_control->y[i],
|
||||||
label_control->lines[i], label_control->szs[i]);
|
label_control->lines[i], label_control->szs[i]);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
|
X11_XDrawString(control->window->display, control->window->drawable, control->window->ctx,
|
||||||
control->rect.x, control->rect.y + label_control->y[i],
|
x, control->rect.y + label_control->y[i],
|
||||||
label_control->lines[i], label_control->szs[i]);
|
label_control->lines[i], label_control->szs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1963,6 +2038,21 @@ static void X11Toolkit_DestroyLabelControl(SDL_ToolkitControlX11 *control) {
|
|||||||
SDL_ToolkitLabelControlX11 *label_control;
|
SDL_ToolkitLabelControlX11 *label_control;
|
||||||
|
|
||||||
label_control = (SDL_ToolkitLabelControlX11 *)control;
|
label_control = (SDL_ToolkitLabelControlX11 *)control;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (control->window->fribidi) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < label_control->sz; i++) {
|
||||||
|
if (label_control->free_lines[i]) {
|
||||||
|
SDL_free(label_control->lines[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_free(label_control->x);
|
||||||
|
SDL_free(label_control->free_lines);
|
||||||
|
SDL_free(label_control->w);
|
||||||
|
SDL_free(label_control->par_types);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
SDL_free(label_control->lines);
|
SDL_free(label_control->lines);
|
||||||
SDL_free(label_control->szs);
|
SDL_free(label_control->szs);
|
||||||
SDL_free(label_control->y);
|
SDL_free(label_control->y);
|
||||||
@@ -1974,17 +2064,23 @@ static void X11Toolkit_CalculateLabelControl(SDL_ToolkitControlX11 *base_control
|
|||||||
int last_h;
|
int last_h;
|
||||||
int ascent;
|
int ascent;
|
||||||
int descent;
|
int descent;
|
||||||
|
int font_h;
|
||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
int i;
|
int i;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
FriBidiParType first_ndn_dir;
|
||||||
|
int last_ndn;
|
||||||
|
#endif
|
||||||
|
|
||||||
last_h = 0;
|
last_h = 0;
|
||||||
control = (SDL_ToolkitLabelControlX11 *)base_control;
|
control = (SDL_ToolkitLabelControlX11 *)base_control;
|
||||||
for (i = 0; i < control->sz; i++) {
|
for (i = 0; i < control->sz; i++) {
|
||||||
X11Toolkit_GetTextWidthHeight(base_control->window, control->lines[i], control->szs[i], &w, &h, &ascent, &descent);
|
X11Toolkit_GetTextWidthHeight(base_control->window, control->lines[i], control->szs[i], &w, &h, &ascent, &descent, &font_h);
|
||||||
|
base_control->rect.w = SDL_max(base_control->rect.w, w);
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
control->y[i] = ascent + descent + control->y[i-1];
|
control->y[i] = font_h + control->y[i-1];
|
||||||
} else {
|
} else {
|
||||||
control->y[i] = ascent;
|
control->y[i] = ascent;
|
||||||
}
|
}
|
||||||
@@ -1992,11 +2088,55 @@ static void X11Toolkit_CalculateLabelControl(SDL_ToolkitControlX11 *base_control
|
|||||||
last_h = h;
|
last_h = h;
|
||||||
}
|
}
|
||||||
base_control->rect.h = control->y[control->sz -1] + last_h;
|
base_control->rect.h = control->y[control->sz -1] + last_h;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
first_ndn_dir = FRIBIDI_PAR_LTR;
|
||||||
|
for (i = 0; i < control->sz; i++) {
|
||||||
|
if (control->par_types[i] != FRIBIDI_PAR_ON) {
|
||||||
|
first_ndn_dir = control->par_types[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_ndn = -1;
|
||||||
|
for (i = 0; i < control->sz; i++) {
|
||||||
|
switch (control->par_types[i]) {
|
||||||
|
case FRIBIDI_PAR_LTR:
|
||||||
|
control->x[i] = 0;
|
||||||
|
last_ndn = i;
|
||||||
|
break;
|
||||||
|
case FRIBIDI_PAR_RTL:
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
last_ndn = i;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (last_ndn != -1) {
|
||||||
|
if (control->par_types[last_ndn] == FRIBIDI_PAR_RTL) {
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
} else {
|
||||||
|
control->x[i] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (first_ndn_dir == FRIBIDI_PAR_RTL) {
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
} else {
|
||||||
|
control->x[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8) {
|
SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *window, char *utf8) {
|
||||||
SDL_ToolkitLabelControlX11 *control;
|
SDL_ToolkitLabelControlX11 *control;
|
||||||
SDL_ToolkitControlX11 *base_control;
|
SDL_ToolkitControlX11 *base_control;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
FriBidiParType first_ndn_dir;
|
||||||
|
int last_ndn;
|
||||||
|
#endif
|
||||||
|
int font_h;
|
||||||
int last_h;
|
int last_h;
|
||||||
int ascent;
|
int ascent;
|
||||||
int descent;
|
int descent;
|
||||||
@@ -2028,6 +2168,14 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *windo
|
|||||||
control->lines = (char **)SDL_malloc(sizeof(char *) * control->sz);
|
control->lines = (char **)SDL_malloc(sizeof(char *) * control->sz);
|
||||||
control->y = (int *)SDL_calloc(control->sz, sizeof(int));
|
control->y = (int *)SDL_calloc(control->sz, sizeof(int));
|
||||||
control->szs = (size_t *)SDL_calloc(control->sz, sizeof(size_t));
|
control->szs = (size_t *)SDL_calloc(control->sz, sizeof(size_t));
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
control->x = (int *)SDL_calloc(control->sz, sizeof(int));
|
||||||
|
control->free_lines = (bool *)SDL_calloc(control->sz, sizeof(bool));
|
||||||
|
control->par_types = (FriBidiParType *)SDL_calloc(control->sz, sizeof(FriBidiParType));
|
||||||
|
control->w = (int *)SDL_calloc(control->sz, sizeof(int));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
last_h = 0;
|
last_h = 0;
|
||||||
for (i = 0; i < control->sz; i++) {
|
for (i = 0; i < control->sz; i++) {
|
||||||
const char *lf = SDL_strchr(utf8, '\n');
|
const char *lf = SDL_strchr(utf8, '\n');
|
||||||
@@ -2035,17 +2183,34 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *windo
|
|||||||
int w;
|
int w;
|
||||||
int h;
|
int h;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
control->lines[i] = SDL_FriBidi_Process(base_control->window->fribidi, utf8, length, base_control->window->do_shaping, &control->par_types[i]);
|
||||||
|
control->szs[i] = SDL_strlen(control->lines[i]);
|
||||||
|
control->free_lines[i] = true;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
control->lines[i] = utf8;
|
control->lines[i] = utf8;
|
||||||
X11Toolkit_GetTextWidthHeight(window, utf8, length, &w, &h, &ascent, &descent);
|
control->szs[i] = length;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
control->free_lines[i] = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
X11Toolkit_GetTextWidthHeight(window, control->lines[i], control->szs[i], &w, &h, &ascent, &descent, &font_h);
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
control->w[i] = w;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
base_control->rect.w = SDL_max(base_control->rect.w, w);
|
base_control->rect.w = SDL_max(base_control->rect.w, w);
|
||||||
|
|
||||||
control->szs[i] = length;
|
if (lf && (lf > control->lines[i]) && (lf[-1] == '\r')) {
|
||||||
if (lf && (lf > utf8) && (lf[-1] == '\r')) {
|
|
||||||
control->szs[i]--;
|
control->szs[i]--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
control->y[i] = ascent + descent + control->y[i-1];
|
control->y[i] = font_h + control->y[i-1];
|
||||||
} else {
|
} else {
|
||||||
control->y[i] = ascent;
|
control->y[i] = ascent;
|
||||||
}
|
}
|
||||||
@@ -2057,6 +2222,44 @@ SDL_ToolkitControlX11 *X11Toolkit_CreateLabelControl(SDL_ToolkitWindowX11 *windo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
base_control->rect.h = control->y[control->sz -1] + last_h;
|
base_control->rect.h = control->y[control->sz -1] + last_h;
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
if (base_control->window->fribidi) {
|
||||||
|
first_ndn_dir = FRIBIDI_PAR_LTR;
|
||||||
|
for (i = 0; i < control->sz; i++) {
|
||||||
|
if (control->par_types[i] != FRIBIDI_PAR_ON) {
|
||||||
|
first_ndn_dir = control->par_types[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
last_ndn = -1;
|
||||||
|
for (i = 0; i < control->sz; i++) {
|
||||||
|
switch (control->par_types[i]) {
|
||||||
|
case FRIBIDI_PAR_LTR:
|
||||||
|
control->x[i] = 0;
|
||||||
|
last_ndn = i;
|
||||||
|
break;
|
||||||
|
case FRIBIDI_PAR_RTL:
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
last_ndn = i;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (last_ndn != -1) {
|
||||||
|
if (control->par_types[last_ndn] == FRIBIDI_PAR_RTL) {
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
} else {
|
||||||
|
control->x[i] = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (first_ndn_dir == FRIBIDI_PAR_RTL) {
|
||||||
|
control->x[i] = base_control->rect.w - control->w[i];
|
||||||
|
} else {
|
||||||
|
control->x[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
X11Toolkit_AddControlToWindow(window, base_control);
|
X11Toolkit_AddControlToWindow(window, base_control);
|
||||||
|
|
||||||
|
@@ -29,6 +29,9 @@
|
|||||||
#include "SDL_x11settings.h"
|
#include "SDL_x11settings.h"
|
||||||
#include "SDL_x11toolkit.h"
|
#include "SDL_x11toolkit.h"
|
||||||
#include "xsettings-client.h"
|
#include "xsettings-client.h"
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
#include "../../core/unix/SDL_fribidi.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_X11
|
#ifdef SDL_VIDEO_DRIVER_X11
|
||||||
|
|
||||||
@@ -95,7 +98,6 @@ typedef struct SDL_ToolkitWindowX11
|
|||||||
Bool shm_pixmap;
|
Bool shm_pixmap;
|
||||||
#endif
|
#endif
|
||||||
bool utf8;
|
bool utf8;
|
||||||
|
|
||||||
/* Atoms */
|
/* Atoms */
|
||||||
Atom wm_protocols;
|
Atom wm_protocols;
|
||||||
Atom wm_delete_message;
|
Atom wm_delete_message;
|
||||||
@@ -155,6 +157,12 @@ typedef struct SDL_ToolkitWindowX11
|
|||||||
bool draw;
|
bool draw;
|
||||||
bool close;
|
bool close;
|
||||||
long event_mask;
|
long event_mask;
|
||||||
|
|
||||||
|
#ifdef HAVE_FRIBIDI_H
|
||||||
|
/* BIDI engine */
|
||||||
|
SDL_FriBidi *fribidi;
|
||||||
|
bool do_shaping;
|
||||||
|
#endif
|
||||||
} SDL_ToolkitWindowX11;
|
} SDL_ToolkitWindowX11;
|
||||||
|
|
||||||
typedef enum SDL_ToolkitControlStateX11
|
typedef enum SDL_ToolkitControlStateX11
|
||||||
|
@@ -213,6 +213,15 @@ int main(int argc, char *argv[])
|
|||||||
quit(1);
|
quit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||||
|
"Arabic (multi line)",
|
||||||
|
"سطر طويل جدًا من النص\nخط قصير\nسطر طويل للغاية من النص مذهل بشكل لا يصدق في اللغة العربية التي يتم التحدث بها في منطقة الشرق الأوسط وشمال أفريقيا",
|
||||||
|
NULL);
|
||||||
|
if (!success) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error Presenting MessageBox: %s", SDL_GetError());
|
||||||
|
quit(1);
|
||||||
|
}
|
||||||
|
|
||||||
success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||||
"Cyrillic (Ukranian)",
|
"Cyrillic (Ukranian)",
|
||||||
"Для запису людської мови використовуються системи письма.",
|
"Для запису людської мови використовуються системи письма.",
|
||||||
|
Reference in New Issue
Block a user