← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/arabic into lp:widelands

 

GunChleoc has proposed merging lp:~widelands-dev/widelands/arabic into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/arabic/+merge/272520

This branch implements ligatures and bidirectional rendering for Arabic script.

Note that right alignment only works properly with the new font handler (g_fh1). I plan to work on migrating more UI elements to the new font renderer in subsequent branches, so this problem will be fixed eventually.

There are also some space issues, because Arabic script needs more height. Fixing this will need more reworking of the UI (e.g. the Options menu needs a full overhaul). For now, I have added capability for buttons to resize themselves, and table header height is now dynamic everywhere. These changes can be seen in the game options menu, the production site window and the game summary screen. For Latin script, everything should still look pretty much the same (except for some dynamic table height that I added).
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/arabic into lp:widelands.
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2015-01-31 14:24:59 +0000
+++ CMakeLists.txt	2015-09-26 18:15:59 +0000
@@ -50,6 +50,7 @@
 find_package(SDL2_net REQUIRED)
 find_package(SDL2_ttf REQUIRED)
 find_package(ZLIB REQUIRED)
+find_package(ICU REQUIRED)
 if(OPTION_USE_GLBINDING)
   find_package(glbinding REQUIRED)
 else()

=== added file 'cmake/Modules/FindICU.cmake'
--- cmake/Modules/FindICU.cmake	1970-01-01 00:00:00 +0000
+++ cmake/Modules/FindICU.cmake	2015-09-26 18:15:59 +0000
@@ -0,0 +1,315 @@
+# Downloaded from https://github.com/julp/FindICU.cmake
+#
+# This module can find the International Components for Unicode (ICU) Library
+#
+# Requirements:
+# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
+#
+# The following variables will be defined for your use:
+#   - ICU_FOUND             : were all of your specified components found (include dependencies)?
+#   - ICU_INCLUDE_DIRS      : ICU include directory
+#   - ICU_LIBRARIES         : ICU libraries
+#   - ICU_VERSION           : complete version of ICU (x.y.z)
+#   - ICU_MAJOR_VERSION     : major version of ICU
+#   - ICU_MINOR_VERSION     : minor version of ICU
+#   - ICU_PATCH_VERSION     : patch version of ICU
+#   - ICU_<COMPONENT>_FOUND : were <COMPONENT> found? (FALSE for non specified component if it is not a dependency)
+#
+# For windows or non standard installation, define ICU_ROOT variable to point to the root installation of ICU. Two ways:
+#   - run cmake with -DICU_ROOT=<PATH>
+#   - define an environment variable with the same name before running cmake
+# With cmake-gui, before pressing "Configure":
+#   1) Press "Add Entry" button
+#   2) Add a new entry defined as:
+#     - Name: ICU_ROOT
+#     - Type: choose PATH in the selection list
+#     - Press "..." button and select the root installation of ICU
+#
+# Example Usage:
+#
+#   1. Copy this file in the root of your project source directory
+#   2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
+#     set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+#   3. Finally call find_package() once, here are some examples to pick from
+#
+#   Require ICU 4.4 or later
+#     find_package(ICU 4.4 REQUIRED)
+#
+#   if(ICU_FOUND)
+#      include_directories(${ICU_INCLUDE_DIRS})
+#      add_executable(myapp myapp.c)
+#      target_link_libraries(myapp ${ICU_LIBRARIES})
+#   endif(ICU_FOUND)
+
+#=============================================================================
+# Copyright (c) 2011-2013, julp
+#
+# Distributed under the OSI-approved BSD License
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#=============================================================================
+
+find_package(PkgConfig QUIET)
+
+########## Private ##########
+if(NOT DEFINED ICU_PUBLIC_VAR_NS)
+    set(ICU_PUBLIC_VAR_NS "ICU")                          # Prefix for all ICU relative public variables
+endif(NOT DEFINED ICU_PUBLIC_VAR_NS)
+if(NOT DEFINED ICU_PRIVATE_VAR_NS)
+    set(ICU_PRIVATE_VAR_NS "_${ICU_PUBLIC_VAR_NS}")       # Prefix for all ICU relative internal variables
+endif(NOT DEFINED ICU_PRIVATE_VAR_NS)
+if(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+    set(PC_ICU_PRIVATE_VAR_NS "_PC${ICU_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
+endif(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+
+function(icudebug _VARNAME)
+    if(${ICU_PUBLIC_VAR_NS}_DEBUG)
+        if(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+            message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ${${ICU_PUBLIC_VAR_NS}_${_VARNAME}}")
+        else(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+            message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = <UNDEFINED>")
+        endif(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+    endif(${ICU_PUBLIC_VAR_NS}_DEBUG)
+endfunction(icudebug)
+
+set(${ICU_PRIVATE_VAR_NS}_ROOT "")
+if(DEFINED ENV{ICU_ROOT})
+    set(${ICU_PRIVATE_VAR_NS}_ROOT "$ENV{ICU_ROOT}")
+endif(DEFINED ENV{ICU_ROOT})
+if (DEFINED ICU_ROOT)
+    set(${ICU_PRIVATE_VAR_NS}_ROOT "${ICU_ROOT}")
+endif(DEFINED ICU_ROOT)
+
+set(${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES )
+set(${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES )
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin64")
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib64")
+endif(CMAKE_SIZEOF_VOID_P EQUAL 8)
+list(APPEND ${ICU_PRIVATE_VAR_NS}_BIN_SUFFIXES "bin")
+list(APPEND ${ICU_PRIVATE_VAR_NS}_LIB_SUFFIXES "lib")
+
+set(${ICU_PRIVATE_VAR_NS}_COMPONENTS )
+# <icu component name> <library name 1> ... <library name N>
+macro(icu_declare_component _NAME)
+    list(APPEND ${ICU_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
+    set("${ICU_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
+endmacro(icu_declare_component)
+
+icu_declare_component(data icudata)
+icu_declare_component(uc   icuuc)         # Common and Data libraries
+icu_declare_component(i18n icui18n icuin) # Internationalization library
+icu_declare_component(io   icuio ustdio)  # Stream and I/O Library
+icu_declare_component(le   icule)         # Layout library
+icu_declare_component(lx   iculx)         # Paragraph Layout library
+
+########## Public ##########
+set(${ICU_PUBLIC_VAR_NS}_FOUND TRUE)
+set(${ICU_PUBLIC_VAR_NS}_LIBRARIES )
+set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS )
+set(${ICU_PUBLIC_VAR_NS}_C_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS "")
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+    string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+    set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the icu_declare_component macro
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Check components
+if(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS) # uc required at least
+    set(${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+else(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+    list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        if(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+            message(FATAL_ERROR "Unknown ICU component: ${${ICU_PRIVATE_VAR_NS}_COMPONENT}")
+        endif(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+    endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+
+# Includes
+find_path(
+    ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+    NAMES unicode/utypes.h utypes.h
+    HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+    PATH_SUFFIXES "include"
+    DOC "Include directories for ICU"
+)
+
+if(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    ########## <part to keep synced with tests/version/CMakeLists.txt> ##########
+    if(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h") # ICU >= 4
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uvernum.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h") # ICU [2;4[
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/uversion.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h") # ICU [1.4;2[
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/unicode/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h") # ICU 1.3
+        file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS}/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+    else()
+        message(FATAL_ERROR "ICU version header not found")
+    endif()
+
+    if(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *ICU_VERSION *\"([0-9]+)\".*") # ICU 1.3
+        # [1.3;1.4[ as #define ICU_VERSION "3" (no patch version, ie all 1.3.X versions will be detected as 1.3.0)
+        set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "1")
+        set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_1}")
+        set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+    elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*")
+        #
+        # Since version 4.9.1, ICU release version numbering was totaly changed, see:
+        # - http://site.icu-project.org/download/49
+        # - http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
+        #
+        set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+        string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+        string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+    elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION *\"(([0-9]+)(\\.[0-9]+)*)\".*") # ICU [1.4;1.8[
+        # [1.4;1.8[ as #define U_ICU_VERSION "1.4.1.2" but it seems that some 1.4.1(?:\.\d)? have releasing error and appears as 1.4.0
+        set(${ICU_PRIVATE_VAR_NS}_FULL_VERSION "${CMAKE_MATCH_1}") # copy CMAKE_MATCH_1, no longer valid on the following if
+        if(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)$")
+            set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+            set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+            set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "0")
+        elseif(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+            set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION "${CMAKE_MATCH_1}")
+            set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION "${CMAKE_MATCH_2}")
+            set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION "${CMAKE_MATCH_3}")
+        endif()
+    else()
+        message(FATAL_ERROR "failed to detect ICU version")
+    endif()
+    set(${ICU_PUBLIC_VAR_NS}_VERSION "${${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_MINOR_VERSION}.${${ICU_PUBLIC_VAR_NS}_PATCH_VERSION}")
+    ########## </part to keep synced with tests/version/CMakeLists.txt> ##########
+
+    # Check dependencies (implies pkg-config)
+    if(PKG_CONFIG_FOUND)
+        set(${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP})
+            pkg_check_modules(PC_ICU_PRIVATE_VAR_NS "icu-${${ICU_PRIVATE_VAR_NS}_COMPONENT}" QUIET)
+
+            if(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+                foreach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY ${PC_ICU_LIBRARIES})
+                    string(REGEX REPLACE "^icu" "" ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARY})
+                    list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY})
+                endforeach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY)
+            endif(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+        endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+        list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+    endif(PKG_CONFIG_FOUND)
+
+    # Check libraries
+    foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+        set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
+        set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
+        foreach(${ICU_PRIVATE_VAR_NS}_BASE_NAME ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}d")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}")
+            list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${ICU_MAJOR_VERSION}${ICU_MINOR_VERSION}d")
+        endforeach(${ICU_PRIVATE_VAR_NS}_BASE_NAME)
+
+        find_library(
+            ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+            NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
+            HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+            PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+            DOC "Release libraries for ICU"
+        )
+        find_library(
+            ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+            NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
+            HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT}
+            PATH_SUFFIXES ${_ICU_LIB_SUFFIXES}
+            DOC "Debug libraries for ICU"
+        )
+
+        string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+        if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # both not found
+            set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE)
+            set("${ICU_PUBLIC_VAR_NS}_FOUND" FALSE)
+        else(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # one or both found
+            set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
+            if(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # release not found => we are in debug
+                set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+            elseif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}) # debug not found => we are in release
+                set(${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT} "${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}")
+            else() # both found
+                set(
+                    ${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}
+                    optimized ${${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+                    debug ${${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+                )
+            endif()
+            list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${${ICU_PRIVATE_VAR_NS}_LIB_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+        endif(NOT ${ICU_PRIVATE_VAR_NS}_LIB_RELEASE_${${ICU_PRIVATE_VAR_NS}_COMPONENT} AND NOT ${ICU_PRIVATE_VAR_NS}_LIB_DEBUG_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+    endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+    # Try to find out compiler flags
+    find_program(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE icu-config HINTS ${${ICU_PRIVATE_VAR_NS}_ROOT})
+    if(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+        execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+    endif(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+
+    # Check find_package arguments
+    include(FindPackageHandleStandardArgs)
+    if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        find_package_handle_standard_args(
+            ${ICU_PUBLIC_VAR_NS}
+            REQUIRED_VARS ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+            VERSION_VAR ${ICU_PUBLIC_VAR_NS}_VERSION
+        )
+    else(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        find_package_handle_standard_args(${ICU_PUBLIC_VAR_NS} "ICU not found" ${ICU_PUBLIC_VAR_NS}_LIBRARIES ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+else(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+    if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+        message(FATAL_ERROR "Could not find ICU include directory")
+    endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+endif(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS)
+
+mark_as_advanced(
+    ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS
+    ${ICU_PUBLIC_VAR_NS}_LIBRARIES
+)
+
+# IN (args)
+icudebug("FIND_COMPONENTS")
+icudebug("FIND_REQUIRED")
+icudebug("FIND_QUIETLY")
+icudebug("FIND_VERSION")
+# OUT
+# Found
+icudebug("FOUND")
+icudebug("UC_FOUND")
+icudebug("I18N_FOUND")
+icudebug("IO_FOUND")
+icudebug("LE_FOUND")
+icudebug("LX_FOUND")
+icudebug("DATA_FOUND")
+# Flags
+icudebug("C_FLAGS")
+icudebug("CPP_FLAGS")
+icudebug("CXX_FLAGS")
+icudebug("C_SHARED_FLAGS")
+icudebug("CPP_SHARED_FLAGS")
+icudebug("CXX_SHARED_FLAGS")
+# Linking
+icudebug("INCLUDE_DIRS")
+icudebug("LIBRARIES")
+# Version
+icudebug("MAJOR_VERSION")
+icudebug("MINOR_VERSION")
+icudebug("PATCH_VERSION")
+icudebug("VERSION")

=== modified file 'cmake/WlFunctions.cmake'
--- cmake/WlFunctions.cmake	2014-12-27 09:46:38 +0000
+++ cmake/WlFunctions.cmake	2015-09-26 18:15:59 +0000
@@ -15,6 +15,7 @@
     USES_SDL2_NET
     USES_SDL2_TTF
     USES_ZLIB
+    USES_ICU
   )
   set(ONE_VALUE_ARG )
   set(MULTI_VALUE_ARGS SRCS DEPENDS)
@@ -142,6 +143,11 @@
     target_link_libraries(${NAME} ${Boost_LIBRARIES})
   endif()
 
+  if(ARG_USES_ICU)
+    wl_include_system_directories(${NAME} ${ICU_INCLUDE_DIRS})
+    target_link_libraries(${NAME} ${ICU_LIBRARIES})
+  endif()
+
   foreach(DEPENDENCY ${ARG_DEPENDS})
     target_link_libraries(${NAME} ${DEPENDENCY})
   endforeach(DEPENDENCY)

=== modified file 'i18n/fonts.lua'
--- i18n/fonts.lua	2015-01-31 07:09:50 +0000
+++ i18n/fonts.lua	2015-09-26 18:15:59 +0000
@@ -2,23 +2,21 @@
 --
 -- Define which fontset you wish to use for your language in locales.lua.
 --
--- The "default" font set covers all possible font styles.
---
--- Your font might not have all of these available. In this case, it is
--- sufficient to define "serif" at the least, a fallback scheme is in place.
--- But do define everything your fontset has.
---
 -- When adding a new fontset, also make sure you have all pertinent license
 -- and source information collected in its folder.
 
 
 return {
-   -- This is the default set and always needs to be complete.
+   -- This is the default set and always needs to be complete. It covers all possible font styles.
 	default = {
+		-- If your language doesn't distinguish between serif and sans serif fonts, please use the serif set.
+		 -- Your font set should always define "serif".
 		serif = "DejaVu/DejaVuSerif.ttf",
+		 -- Add bold and italic variants if your font set has them.
 		serif_bold = "DejaVu/DejaVuSerif-Bold.ttf",
 		serif_italic = "DejaVu/DejaVuSerif-Italic.ttf",
 		serif_bold_italic = "DejaVu/DejaVuSerif-BoldItalic.ttf",
+		-- If your font set doesn't have sans or condensed variants, serif will be used instead.
 		sans = "DejaVu/DejaVuSans.ttf",
 		sans_bold = "DejaVu/DejaVuSans-Bold.ttf",
 		sans_italic = "DejaVu/DejaVuSans-Oblique.ttf",
@@ -27,12 +25,19 @@
 		condensed_bold = "DejaVu/DejaVuSansCondensed-Bold.ttf",
 		condensed_italic = "DejaVu/DejaVuSansCondensed-Oblique.ttf",
 		condensed_bold_italic = "DejaVu/DejaVuSansCondensed-BoldOblique.ttf",
-		direction = "ltr"
+		-- If the diection isn't defined, your font set will default to "ltr" = left-to-right.
+		-- For right-to-left or bidirectional (BiDi) languages, use "rtl".
+		direction = "ltr",
+		size_offset = 0
 	},
 
 	arabic = {
-		serif = "FaKacstBook/FaKacstBook.ttf",
-		direction = "rtl"
+		serif = "amiri/amiri-regular.ttf",
+		serif_bold = "amiri/amiri-bold.ttf",
+		serif_italic = "amiri/amiri-slanted.ttf",
+		serif_bold_italic = "amiri/amiri-boldslanted.ttf",
+		direction = "rtl",
+		size_offset = 4
 	},
 
 	cjk = {

=== removed directory 'i18n/fonts/FaKacstBook'
=== removed file 'i18n/fonts/FaKacstBook/FaKacstBook.ttf'
Binary files i18n/fonts/FaKacstBook/FaKacstBook.ttf	2014-10-14 12:53:01 +0000 and i18n/fonts/FaKacstBook/FaKacstBook.ttf	1970-01-01 00:00:00 +0000 differ
=== removed file 'i18n/fonts/FaKacstBook/README'
--- i18n/fonts/FaKacstBook/README	2014-10-14 12:53:01 +0000
+++ i18n/fonts/FaKacstBook/README	1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-Downloaded from Persianize Free(GPL'ed) Arabic Fonts
-
-https://launchpad.net/cgaf
-
-Maintainer: Saeed Rasooli saeed.gnu@xxxxxxxxx

=== added directory 'i18n/fonts/amiri'
=== added file 'i18n/fonts/amiri/OFL-FAQ.txt'
--- i18n/fonts/amiri/OFL-FAQ.txt	1970-01-01 00:00:00 +0000
+++ i18n/fonts/amiri/OFL-FAQ.txt	2015-09-26 18:15:59 +0000
@@ -0,0 +1,369 @@
+OFL FAQ - Frequently Asked Questions about the SIL Open Font License (OFL)
+Version 1.1-update2 - 23 August 2010
+(See http://scripts.sil.org/OFL for updates)
+
+
+CONTENTS OF THIS FAQ
+1  USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL
+2  USING OFL FONTS FOR WEB PAGES AND ONLINE WEBFONT SERVICES
+3  MODIFYING OFL-LICENSED FONTS
+4  LICENSING YOUR ORIGINAL FONTS UNDER THE OFL
+5  CHOOSING RESERVED FONT NAMES
+6  ABOUT THE FONTLOG
+7  MAKING CONTRIBUTIONS TO OFL PROJECTS
+8  ABOUT THE LICENSE ITSELF
+9  ABOUT SIL INTERNATIONAL
+APPENDIX A - FONTLOG EXAMPLE
+
+
+1  USING AND DISTRIBUTING FONTS LICENSED UNDER THE OFL
+
+1.1  Can I use the fonts for a book or other print publication?
+Yes. You can mention the font and author in the book's colophon if you wish, but that is not required.
+
+1.2  Can the fonts be included with Free/Libre and Open Source Software collections such as GNU/Linux and BSD distributions?
+Yes! Fonts licensed under the OFL can be freely included alongside other software under FLOSS (Free/Libre and Open Source Software) licenses. Since fonts are typically aggregated with, not merged into, existing software, there is little need to be concerned about incompatibility with existing software licenses. You may also repackage the fonts and the accompanying components in a .rpm or .deb package and include them in distribution CD/DVDs and online repositories. (Also see section 5.9 about rebuilding from source.)
+
+1.3  I want to distribute the fonts with my program. Does this mean my program also has to be Free/Libre and Open Source Software?
+No. Only the portions based on the Font Software are required to be released under the OFL. The intent of the license is to allow aggregation or bundling with software under restricted licensing as well.
+
+1.4  Can I sell a software package that includes these fonts?
+Yes, you can do this with both the Original Version and a Modified Version of the fonts. Examples of bundling made possible by the OFL would include: word processors, design and publishing applications, training and educational software, games and entertainment software, mobile device applications, etc.
+
+1.5  Can I include the fonts on a CD of freeware or commercial fonts?
+Yes, as long some other font or software is also on the disk, so the OFL font is not sold by itself.
+
+1.6  Why won't the OFL let me sell the fonts alone?
+The intent is to keep people from making money by simply redistributing the fonts. The only people who ought to profit directly from the fonts should be the original authors, and those authors have kindly given up potential direct income to distribute their fonts under the OFL. Please honour and respect their contribution!
+
+1.7  What about sharing OFL fonts with friends on a CD, DVD or USB stick?
+You are very welcome to share open fonts with friends, family and colleagues through removable media. Just remember to include the full font package, including any copyright notices and licensing information as available in OFL.txt. In the case where you sell the font, it has to come bundled with software.
+
+1.8  Can I host the fonts on a web site for others to use?
+Yes, as long as you make the full font package available. In most cases it may be best to point users to the main site that distributes the Original Version so they always get the most recent stable and complete version. See also discussion of webfonts in Section 2.
+
+1.9  Can I host the fonts on a server for use over our internal network?
+Yes. If the fonts are transferred from the server to the client computer by means that allow them to be used even if the computer is no longer attached to the network, the full package (copyright notices, licensing information, etc.) should be included.
+
+1.10  Does the full OFL license text always need to accompany the font?
+The only situation in which an OFL font can be distributed without the text of the OFL (either in a separate file or in font metadata), is when a font is embedded in a document or bundled within a program. In the case of metadata included within a font, it is legally sufficient to include only a link to the text of the OFL on http://scripts.sil.org/OFL, but we strongly recommend against this. Most modern font formats include metadata fields that will accept the full OFL text, and full inclusion increases the likelihood that users will understand and properly apply the license.
+
+1.11  What do you mean by 'embedding'? How does that differ from other means of distribution?
+By 'embedding' we mean inclusion of the font in a document or file in a way that makes extraction (and redistribution) difficult or clearly discouraged. In many cases the names of embedded fonts might also not be obvious to those reading the document, the font data format might be altered, and only a subset of the font - only the glyphs required for the text - might be included. Any other means of delivering a font to another person is considered 'distribution', and needs to be accompanied by any copyright notices and licensing information available in OFL.txt.
+
+1.12  So can I embed OFL fonts in my document?
+Yes, either in full or a subset. The restrictions regarding font modification and redistribution do not apply, as the font is not intended for use outside the document.
+
+1.13  Does embedding alter the license of the document itself?
+No. Referencing or embedding an OFL font in any document does not change the license of the document itself. The requirement for fonts to remain under the OFL does not apply to any document created using the fonts and their derivatives. Similarly, creating any kind of graphic using a font under OFL does not make the resulting artwork subject to the OFL.
+
+1.14  If OFL fonts are extracted from a document in which they are embedded (such as a PDF file), what can be done with them? Is this a risk to author(s)?
+The few utilities that can extract fonts embedded in a PDF will typically output limited amounts of outlines - not a complete font. To create a working font from this method is much more difficult and time consuming than finding the source of the original OFL font. So there is little chance that an OFL font would be extracted and redistributed inappropriately through this method. Even so, copyright laws address any misrepresentation of authorship. All Font Software released under the OFL and marked as such by the author(s) is intended to remain under this license regardless of the distribution method, and cannot be redistributed under any other license. We strongly discourage any font extraction - we recommend directly using the font sources instead - but if you extract font outlines from a document, please be considerate: use your common sense and respect the work of the author(s) and the licensing model.
+
+1.15  What about distributing fonts with a document? Within a compressed folder structure? Is it distribution, bundling or embedding?
+Certain document formats may allow the inclusion of an unmodified font within their file structure which consists of a compressed folder containing the various resources forming the document (such as pictures and thumbnails). Including fonts within such a structure is understood as being different from embedding but rather similar to bundling (or mere aggregation) which the license explicitly allows. In this case the font is conveyed unchanged whereas embedding a font usually transforms it from the original format. The OFL does not allow anyone to extract the font from such a structure to then redistribute it under another license. The explicit permission to redistribute and embed does not cancel the requirement for the Font Software to remain under the license chosen by its author(s).
+
+1.16  What about ebooks shipping with open fonts?
+The requirements differ depending on whether the fonts are linked, embedded or distributed (bundled or aggregated). Some ebook formats use web technologies to do font linking via @font-face, others are designed for font embedding, some use fonts distributed with the document or reading software, and a few rely solely on the fonts already present on the target system. The license requirements depend on the type of inclusion as discussed in 1.15.
+
+1.17  Can Font Software released under the OFL be subject to URL-based access restrictions methods or DRM (Digital Rights Management) mechanisms?
+Yes, but these issues are out-of-scope for the OFL. The license itself neither encourages their use nor prohibits them since such mechanisms are not implemented in the components of the Font Software but through external software. Such restrictions are put in place for many different purposes corresponding to various usage scenarios. One common example is to limit potentially dangerous cross-site scripting attacks. However, in the spirit of libre/open fonts and unrestricted writing systems, we strongly encourage open sharing and reuse of OFL fonts, and the establishment of an environment where such restrictions are unnecessary. Note that whether you wish to use such mechanisms or you prefer not to, you must still abide by the rules set forth by the OFL when using fonts released by their authors under this license. Derivative fonts must be licensed under the OFL, even if they are part of a service for which you charge fees and/or for which access to source code is restricted. You may not sell the fonts on their own - they must be part of a larger software package, bundle or subscription plan. For example, even if the OFL font is distributed in a software package or via an online service using a DRM mechanism, the user would still have the right to extract that font, use, study, modify and redistribute it under the OFL.
+
+1.18  I've come across a font released under the OFL. How can I easily get more information about the Original Version? How can I know where it stands compared to the Original Version or other Modified Versions?
+Consult the copyright statement(s) in the license for ways to contact the original authors. Consult the FONTLOG for information on how the font differs from the Original Version, and get in touch with the various contributors via the information in the acknowledgement section. Please consider using the Original Versions of the fonts whenever possible.
+
+1.19  What do you mean in condition 4? Can you provide examples of abusive promotion / endorsement / advertisement vs. normal acknowledgement?
+The intent is that the goodwill and reputation of the author(s) should not be used in a way that makes it sound like the original author(s) endorse or approve of a specific Modified Version or software bundle. For example, it would not be right to advertise a word processor by naming the author(s) in a listing of software features, or to promote a Modified Version on a web site by saying "designed by ...". However, it would be appropriate to acknowledge the author(s) if your software package has a list of people who deserve thanks. We realize that this can seem to be a grey area, but the standard used to judge an acknowledgement is that if the acknowledgement benefits the author(s) it is allowed, but if it primarily benefits other parties, or could reflect poorly on the author(s), then it is not.
+
+
+2  USING OFL FONTS FOR WEBPAGES AND ONLINE WEBFONT SERVICES
+
+2.1  Can I make webpages using these fonts?
+Yes! Go ahead! Using CSS (Cascading Style Sheets) is recommended. Your three best options: 
+- referring directly in your stylesheet to open fonts which may be available on the user's system
+- providing links to download the full package of the font - either from your own website or from elsewhere - so users can install it themselves
+- using @font-face to distribute the font directly to browsers. This is recommended and explicitly allowed by the licensing model because it is distribution. The font file itself is distributed with other components of the webpage. It is not embedded in the webpage but referenced through a web address which will cause the browser to retrieve and use the corresponding font to render the webpage (see 1.11 and 1.15 for details related to embedding fonts into documents). As you take advantage of the @font-face cross-platform standard, be aware that webfonts are often tuned for a web environment and not intended for installation and use outside a browser. The reasons in favour of using webfonts are to allow design of dynamic text elements instead of static graphics, to make it easier for content to be localized and translated, indexed and searched, and all this with cross-platform open standards without depending on restricted extensions or plugins. You should check the CSS cascade (the order in which fonts are being called or delivered to your users) when testing.
+
+2.2  Can I make and use WOFF (Web Open Font Format) versions of OFL fonts?
+Yes, but you need to be careful. A change in font format normally is considered modification, and Reserved Font Names (RFNs) cannot be used. Because of the design of the WOFF format, however, it is possible to create a WOFF version that is not considered modification, and so would not require a name change. You are allowed to create, use and distribute a WOFF version of an OFL font without changing the font name, but only if:
+
+- the original font data remains unchanged except for WOFF compression, and
+- WOFF-specific metadata is either omitted altogether or present and includes, unaltered, the contents of all equivalent metadata in the original font.
+
+If the original font data or metadata is changed, or the WOFF-specific metadata is incomplete, the font must be considered a Modified Version, the OFL restrictions would apply and the name of the font must be changed: any RFNs cannot be used and copyright notices and licensing information must be included and cannot be deleted or modified. You must come up with a unique name - we recommend one corresponding to your domain or your particular web application. Be aware that only the original author(s) can use RFNs. This is to prevent collisions between a derivative tuned to your audience and the original upstream version and so to reduce confusion.
+
+Please note that most WOFF conversion tools and online services do not meet the two requirements listed above, and so their output must be considered a Modified Version. So be very careful and check to be sure that the tool or service you're using is compressing unchanged data and completely and accurately reflecting the original font metadata.
+
+2.3  What about other webfont formats such as EOT/EOTLite/CWT/etc.?
+In most cases these formats alter the original font data more than WOFF, and do not completely support appropriate metadata, so their use must be considered modification and RFNs may not be used.
+
+2.4  Can I make OFL fonts available through webfont online services?
+Yes, you are welcome to include OFL fonts in online webfont services as long as you properly meet all the conditions of the license. The origin and open status of the font should be clear among the other fonts you are hosting. Authorship, copyright notices and license information must be sufficiently visible to your users or subscribers so they know where the font comes from and the rights granted by the author(s). Make sure the font file contains the needed copyright notice(s) and licensing information in its metadata. Please double-check the accuracy of every field to prevent contradictory information. Other font formats, including EOT/EOTLite/CWT and superior alternatives like WOFF, already provide fields for this information. Remember that if you modify the font within your library or convert it to another format for any reason the OFL restrictions apply and you need to change the names accordingly. Please respect the author's wishes as expressed in the OFL and do not misrepresent original designers and their work. Don't lump quality open fonts together with dubious freeware or public domain fonts. Consider how you can best work with the original designers and foundries, support their efforts and generate goodwill that will benefit your service. (See 1.17 for details related to URL-based access restrictions methods or DRM mechanisms).
+
+2.5  Can I make and publish CMS themes or templates that use OFL fonts?  Can I include the fonts themselves in the themes or templates? Can I sell the whole package?
+Yes, you are very welcome to integrate open fonts into themes and templates for your preferred CMS and make them more widely available. Be aware that you can only sell the fonts and your CMS add-on as part of a software bundle. (See 1.4 for details and examples about selling bundles). 
+
+2.6  Some webfont formats and services provide ways of "optimising" the font for a particular website or web application; is that allowed? 
+Yes, it is permitted, but remember that these optimised versions are Modified Versions and so must follow OFL requirements like appropriate renaming. Also you need to bear in mind the other important parameters beyond compression, speed and responsiveness: you need to consider the audience of your particular website or web application, as choosing some optimisation parameters may turn out to be less than ideal for them. Subsetting by removing certain glyphs or features may seriously limit functionality of the font in various languages used by your users. It may also introduce degradation of quality in the rendering or specific bugs on the various platforms compared to the original font. In other words, remember that one person's optimised font may be another person's missing feature. Various advanced typographic features are also available through CSS and may provide the desired effects without the need to modify the font.
+
+
+3  MODIFYING OFL-LICENSED FONTS
+
+3.1  Can I change the fonts? Are there any limitations to what things I can and cannot change?
+You are allowed to change anything, as long as such changes do not violate the terms of the license. In other words, you are not allowed to remove the copyright statement(s) from the font, but you could put additional information into it that covers your contribution.
+
+3.2  I have a font that needs a few extra glyphs - can I take them from an OFL licensed font and copy them into mine?
+Yes, but if you distribute that font to others it must be under the OFL, and include the information mentioned in condition 2 of the license.
+
+3.3  Can I charge people for my additional work? In other words, if I add a bunch of special glyphs and/or OpenType/Graphite code, can I sell the enhanced font?
+Not by itself. Derivative fonts must be released under the OFL and cannot be sold by themselves. It is permitted, however, to include them in a larger software package (such as text editors, office suites or operating systems), even if the larger package is sold. In that case, you are strongly encouraged, but not required, to also make that derived font easily and freely available outside of the larger package.
+
+3.4  Can I pay someone to enhance the fonts for my use and distribution?
+Yes. This is a good way to fund the further development of the fonts. Keep in mind, however, that if the font is distributed to others it must be under the OFL. You won't be able to recover your investment by exclusively selling the font, but you will be making a valuable contribution to the community. Please remember how you have benefited from the contributions of others.
+
+3.5  I need to make substantial revisions to the font to make it work with my program. It will be a lot of work, and a big investment, and I want to be sure that it can only be distributed with my program. Can I restrict its use?
+No. If you redistribute a Modified Version of the font it must be under the OFL. You may not restrict it in any way beyond what the OFL permits and requires. This is intended to ensure that all released improvements to the fonts become available to everyone. But you will likely get an edge over competitors by being the first to distribute a bundle with the enhancements. Again, please remember how you have benefited from the contributions of others.
+
+3.6  Do I have to make any derivative fonts (including extended source files, build scripts, documentation, etc.) publicly available?
+No, but please consider sharing your improvements with others. You may find that you receive in return more than what you gave.
+
+3.7  If a trademark is claimed in the OFL font, does that trademark need to remain in modified fonts?
+Yes, any trademark notices must remain in any derivative fonts to respect trademark laws, but you may add any additional trademarks you claim, officially registered or not. For example if an OFL font called "Foo" contains a notice that "Foo is a trademark of Acme", then if you rename the font to "Bar" when creating a Modified Version, the new trademark notice could say "Foo is a trademark of Acme Inc. - Bar is a trademark of Roadrunner Technologies Ltd.". Trademarks work alongside the OFL and are not subject to the terms of the licensing agreement. Please refer to the appropriate trademark laws.
+
+
+4  LICENSING YOUR ORIGINAL FONTS UNDER THE OFL
+
+4.1  Can I use the SIL OFL for my own fonts?
+Yes! We heartily encourage everyone to use the OFL to distribute their own original fonts. It is a carefully constructed license that allows great freedom along with enough artistic integrity protection for the work of the authors as well as clear rules for other contributors and those who redistribute the fonts. The licensing model is used successfully by various organisations, both for-profit and not-for-profit, to release fonts of varying levels of scope and complexity.
+
+4.2  What do I have to do to apply the OFL to my font?
+If you want to release your fonts under the OFL, we recommend you do the following:
+
+4.2.1  Put your copyright and Reserved Font Names information at the beginning of the main OFL.txt file in place of the dedicated placeholders. Include this file in your release package.
+
+4.2.2  Put your copyright and the OFL text with Reserved Font Names into your font files (the copyright and license fields). A link to the OFL text on the OFL web site is an acceptable (but not recommended) alternative. Also add this information to any other components (build scripts, glyph databases, documentation, test files, etc). Depending on the format of your fonts and sources, you can use template human-readable headers or machine-readable metadata.
+
+4.2.3  Write an initial FONTLOG.txt for your font and include it in the release package.
+
+4.2.4  Include the relevant practical documentation on the license by including the OFL-FAQ.txt in your package.
+
+4.3  Will you make my font OFL for me?
+We won't do the work for you. We can, however, try to answer your questions, unfortunately we do not have the resources to review and check your font packages for correct use of the OFL.
+
+4.4  Will you distribute my OFL font for me?
+No, although if the font is of sufficient quality and general interest we may include a link to it on our partial list of OFL fonts on the OFL web site. You may wish to consider other open font catalogs or hosting services, such as the Unifont Font Guide (http://unifont.org/fontguide), The League of Movable Type (http://theleagueofmovabletype.com), Kernest (http://kernest.com/) or the Open Font Library (http://openfontlibrary.org/), which despite the name has no direct relationship to the OFL or SIL. We do not endorse any particular catalog or hosting service - it is your responsibility to determine if the service is right for you.
+
+4.5  Why should I use the OFL for my fonts?
+- to meet needs for fonts that can be modified to support minority languages
+- to provide a legal and clear way for people to respect your work but still use it (and reduce piracy)
+- to involve others in your font project
+- to enable your fonts to be expanded with new weights and improved writing system/language support
+- to allow more technical font developers to add features to your design (such as OpenType and Graphite support)
+- to renew the life of an old font lying on your hard drive with no business model
+- to allow your font to be included in Libre Software operating systems like Ubuntu
+- to give your font world status and wide, unrestricted distribution
+- to educate students about quality typeface and font design
+- to expand your test base and get more useful feedback 
+- to extend your reach to new markets when users see your metadata and go to your website
+- to get your font more easily into one of the webfont online services
+- to attract attention for your commercial fonts
+- to make money through webfont services
+- to make money by bundling fonts with applications
+- to make money adjusting and extending existing open fonts
+- to get a better chance that foundations/NGOs/charities/companies who commission fonts will pick you 
+- to be part of a sharing design and development community 
+- to give back and contribute to a growing body of font sources
+
+
+5  CHOOSING RESERVED FONT NAMES
+
+5.1  What are Reserved Font Names?
+These are font names, or portions of font names, that the author has chosen to reserve for use only with the Original Version of the font, or for Modified Version(s) created by the original author.
+
+5.2  Why can't I use the Reserved Font Names in my derivative font names? I'd like people to know where the design came from.
+The best way to acknowledge the source of the design is to thank the original authors and any other contributors in the files that are distributed with your revised font (although no acknowledgement is required). The FONTLOG is a natural place to do this. Reserved Font Names ensure that the only fonts that have the original names are the unmodified Original Versions. This allows designers to maintain artistic integrity while allowing collaboration to happen. It eliminates potential confusion and name conflicts. When choosing a name, be creative and avoid names that reuse almost all the same letters in the same order or sound like the original. It will help everyone if Original Versions and Modified Versions can easily be distinguished from one another and from other derivatives. Any substitution and matching mechanism is outside the scope of the license.
+
+5.3  What do you mean by "primary name as presented to the user"? Are you referring to the font menu name?
+Yes, this applies to the font menu name and other mechanisms that specify a font in a document. It would be fine, however, to keep a text reference to the original fonts in the description field, in your modified source file or in documentation provided alongside your derivative as long as no one could be confused that your modified source is the original. But you cannot use the Reserved Font Names in any way to identify the font to the user (unless the Copyright Holder(s) allow(s) it through a separate agreement). Users who install derivatives (Modified Versions) on their systems should not see any of the original Reserved Font Names in their font menus, for example. Again, this is to ensure that users are not confused and do not mistake one font for another and so expect features only another derivative or the Original Version can actually offer. 
+
+5.4  Am I not allowed to use any part of the Reserved Font Names?
+You may not use individual words from the Reserved Font Names, but you would be allowed to use parts of words, as long as you do not use any word from the Reserved Font Names entirely. We do not recommend using parts of words because of potential confusion, but it is allowed. For example, if "Foobar" was a Reserved Font Name, you would be allowed to use "Foo" or "bar", although we would not recommend it. Such an unfortunate choice would confuse the users of your fonts as well as make it harder for other designers to contribute.
+
+5.5  So what should I, as an author, identify as Reserved Font Names?
+Original authors are encouraged to name their fonts using clear, distinct names, and only declare the unique parts of the name as Reserved Font Names. For example, the author of a font called "Foobar Sans" would declare "Foobar" as a Reserved Font Name, but not "Sans", as that is a common typographical term, and may be a useful word to use in a derivative font name. Reserved Font Names should also be single words. A font called "Flowing River" should have Reserved Font Names "Flowing" and "River", not "Flowing River". You also need to be very careful about reserving font names which are already linked to trademarks (whether registered or not) which you do not own.
+
+5.6  Do I, as an author, have to identify any Reserved Font Names?
+No, but we strongly encourage you to do so. This is to avoid confusion between your work and Modified Versions.
+
+5.7  Are any names (such as the main font name) reserved by default?
+No. That is a change to the license as of version 1.1. If you want any names to be Reserved Font Names, they must be specified after the copyright statement(s).
+
+5.8  Is there any situation in which I can use Reserved Font Names for a Modified Version?
+The Copyright Holder(s) can give certain trusted parties the right to use any of the Reserved Font Names through separate written agreements. For example, even if "Foobar" is a RFN, you could write up an agreement to give company "XYZ" the right to distribute a modified version with a name that includes "Foobar". This allows for freedom without confusion.
+
+5.9  Do font rebuilds require a name change? Do I have to change the name of the font when my packaging workflow includes a full rebuild from source?
+Yes, all rebuilds which change the font data and the smart code are Modified Versions and the requirements of the OFL apply: you need to respect what the Author(s) have chosen in terms of Reserved Font Names. However if a package (or installer) is simply a wrapper or a compressed structure around the final font - leaving them intact on the inside - then no name change is required. Please get in touch with the author(s) and copyright holder(s) to inquire about the presence of font sources beyond the final font file(s) and the recommended build path. That build path may very well be non-trivial and hard to reproduce accurately by the maintainer. If a full font build path is made available by the upstream author(s) please be aware that any regressions and changes you may introduce when doing a rebuild for packaging purposes is your responsibility as a package maintainer since you are effectively creating a separate branch. You should make it very clear to your users that your rebuilt version is not the canonical one from upstream.
+
+5.10  Can I add other Reserved Font Names when making a derivative font?
+Yes. List your additional Reserved Font Names after your additional copyright statement, as indicated with example placeholders at the top of the OFL.txt file. Be sure you do not remove any exiting RFNs but only add your own.
+
+
+6  ABOUT THE FONTLOG
+
+6.1  What is this FONTLOG thing exactly?
+It has three purposes: 1) to provide basic information on the font to users and other developers, 2) to document changes that have been made to the font or accompanying files, either by the original authors or others, and 3) to provide a place to acknowledge authors and other contributors. Please use it!
+
+6.2  Is the FONTLOG required?
+It is not a requirement of the license, but we strongly recommend you have one.
+
+6.3  Am I required to update the FONTLOG when making Modified Versions?
+No, but users, designers and other developers might get very frustrated with you if you don't. People need to know how derivative fonts differ from the original, and how to take advantage of the changes, or build on them. There are utilities that can help create and maintain a FONTLOG, such as the FONTLOG support in FontForge.
+
+6.4  What should the FONTLOG look like?
+It is typically a separate text file (FONTLOG.txt), but can take other formats. It commonly includes these four sections:
+
+- brief header describing the FONTLOG itself and name of the font family
+- Basic Font Information - description of the font family, purpose and breadth
+- ChangeLog - chronological listing of changes
+- Acknowledgements - list of authors and contributors with contact information
+
+It could also include other sections, such as: where to find documentation, how to make contributions, information on contributing organizations, source code details, and a short design guide. See Appendix A for an example FONTLOG.
+
+
+7  MAKING CONTRIBUTIONS TO OFL PROJECTS
+
+7.1  Can I contribute work to OFL projects?
+In many cases, yes. It is common for OFL fonts to be developed by a team of people who welcome contributions from the wider community. Contact the original authors for specific information on how to participate in their projects.
+
+7.2  Why should I contribute my changes back to the original authors?
+It would benefit many people if you contributed back in response to what you've received. Your contributions and improvements to the fonts and other components could be a tremendous help and would encourage others to contribute as well and 'give back'. You will then benefit from other people's contributions as well. Sometimes maintaining your own separate version takes more effort than merging back with the original. Be aware that any contributions, however, must be either your own original creation or work that you own, and you may be asked to affirm that clearly when you contribute.
+
+7.3  I've made some very nice improvements to the font. Will you consider adopting them and putting them into future Original Versions?
+Most authors would be very happy to receive such contributions. Keep in mind that it is unlikely that they would want to incorporate major changes that would require additional work on their end. Any contributions would likely need to be made for all the fonts in a family and match the overall design and style. Authors are encouraged to include a guide to the design with the fonts. It would also help to have contributions submitted as patches or clearly marked changes - the use of smart source revision control systems like subversion, svk, mercurial, git or bzr is a good idea. Please follow the recommendations given by the author(s) in terms of preferred source formats and configuration parameters for sending contributions. If this is not indicated in a FONTLOG or other documentation of the font, consider asking them directly. Examples of useful contributions are bug fixes, additional glyphs, stylistic alternates (and the smart font code to access them) or improved hinting. Keep in mind that some kinds of changes (esp. hinting) may be technically difficult to integrate.
+
+7.4  How can I financially support the development of OFL fonts?
+It is likely that most authors of OFL fonts would accept financial contributions - contact them for instructions on how to do this. Such contributions would support future development. You can also pay for others to enhance the fonts and contribute the results back to the original authors for inclusion in the Original Version.
+
+
+8  ABOUT THE LICENSE ITSELF
+
+8.1  I see that this is version 1.1 of the license. Will there be later changes?
+Version 1.1 is the first minor revision of the OFL. We are confident that version 1.1 will meet most needs, but are open to future improvements. Any revisions would be for future font releases, and previously existing licenses would remain in effect. No retroactive changes are possible, although the Copyright Holder(s) can re-release the font under a revised OFL. All versions will be available on our web site: http://scripts.sil.org/OFL.
+
+8.2  Does this license restrict the rights of the Copyright Holder(s)?
+No. The Copyright Holder(s) still retain(s) all the rights to their creation; they are only releasing a portion of it for use in a specific way. For example, the Copyright Holder(s) may choose to release a 'basic' version of their font under the OFL, but sell a restricted 'enhanced' version. Only the Copyright Holder(s) can do this.
+
+8.3  Is the OFL a contract or a license?
+The OFL is a license and not a contract and so does not require you to sign it to have legal validity. By using, modifying and redistributing components under the OFL you indicate that you accept the license.
+
+8.4  I really like the terms of the OFL, but want to change it a little. Am I allowed to take ideas and actual wording from the OFL and put them into my own custom license for distributing my fonts?
+We strongly recommend against creating your very own unique open licensing model. Using a modified or derivative license will likely cut you off - along with the font(s) under that license - from the community of designers using the OFL, potentially expose you and your users to legal liabilities, and possibly put your work and rights at risk. The OFL went though a community and legal review process that took years of effort, and that review is only applicable to an unmodified OFL. The text of the OFL has been written by SIL (with review and consultation from the community) and is copyright (c) 2005-2010 SIL International. You may re-use the ideas and wording (in part, not in whole) in another non-proprietary license provided that you call your license by another unambiguous name, that you do not use the preamble, that you do not mention SIL and that you clearly present your license as different from the OFL so as not to cause confusion by being too similar to the original. If you feel the OFL does not meet your needs for an open license, please contact us.
+
+8.5  Can I translate the license and the FAQ into other languages?
+SIL certainly recognises the need for people who are not familiar with English to be able to understand the OFL and its use. Making the license very clear and readable has been a key goal for the OFL, but we know that people understand their own language best.
+
+If you are an experienced translator, you are very welcome to translate the OFL and OFL-FAQ so that designers and users in your language community can understand the license better. But only the original English version of the license has legal value and has been approved by the community. Translations do not count as legal substitutes and should only serve as a way to explain the original license. SIL - as the author and steward of the license for the community at large - does not approve any translation of the OFL as legally valid because even small translation ambiguities could be abused and create problems.
+
+SIL gives permission to publish unofficial translations into other languages provided that they comply with the following guidelines:
+
+- Put the following disclaimer in both English and the target language stating clearly that the translation is unofficial:
+
+"This is an unofficial translation of the SIL Open Font License into <language_name>. It was not published by SIL International, and does not legally state the distribution terms for fonts that use the OFL. A release under the OFL is only valid when using the original English text. However, we recognize that this unofficial translation will help users and designers not familiar with English to better understand and use the OFL. We encourage designers who consider releasing their creation under the OFL to read the OFL-FAQ in their own language if it is available. Please go to http://scripts.sil.org/OFL for the official version of the license and the accompanying OFL-FAQ."
+
+- Keep your unofficial translation current and update it at our request if needed, for example if there is any ambiguity which could lead to confusion.  
+
+If you start such a unofficial translation effort of the OFL and OFL-FAQ please let us know.
+
+
+9  ABOUT SIL INTERNATIONAL
+
+9.1  Who is SIL International and what do they do?
+SIL serves language communities worldwide, building their capacity for sustainable language development, by means of research, translation, training and materials development. SIL makes its services available to all without regard to religious belief, political ideology, gender, race, or ethnic background. SIL's members and volunteers share a Christian commitment.
+
+9.2  What does this have to do with font licensing?
+The ability to read, write, type and publish in one's own language is one of the most critical needs for millions of people around the world. This requires fonts that are widely available and support lesser-known languages. SIL develops - and encourages others to develop - a complete stack of writing systems implementation components available under open licenses. This open stack includes input methods, smart fonts, smart rendering libraries and smart applications. There has been a need for a common open license that is specifically applicable to fonts and related software (a crucial component of this stack), so SIL developed the SIL Open Font License with the help of the Free/Libre and Open Source Software community.
+
+9.3  How can I contact SIL?
+Our main web site is: http://www.sil.org/
+Our site about complex scripts is: http://scripts.sil.org/
+Information about this license (and contact information) is at: http://scripts.sil.org/OFL
+
+
+APPENDIX A - FONTLOG EXAMPLE
+
+Here is an example of the recommended format for a FONTLOG, although other formats are allowed.
+
+-----
+FONTLOG for the GlobalFontFamily fonts
+
+This file provides detailed information on the GlobalFontFamily Font Software. This information should be distributed along with the GlobalFontFamily fonts and any derivative works.
+
+Basic Font Information
+
+GlobalFontFamily is a Unicode typeface family that supports all languages that use the Latin script and its variants, and could be expanded to support other scripts.
+
+NewWorldFontFamily is based on the GlobalFontFamily and also supports Greek, Hebrew, Cyrillic and Armenian.
+
+More specifically, this release supports the following Unicode ranges...
+This release contains...
+Documentation can be found at...
+To contribute to the project...
+
+ChangeLog
+
+1 August 2008 (Tom Parker) GlobalFontFamily version 1.2.1
+- Tweaked the smart font code (Branch merged with trunk version)
+- Provided improved build and debugging environment for smart behaviours
+
+7 February 2007 (Pat Johnson) NewWorldFontFamily Version 1.3
+- Added Greek and Cyrillic glyphs
+
+7 March 2006 (Fred Foobar) NewWorldFontFamily Version 1.2
+- Tweaked contextual behaviours
+
+1 Feb 2005 (Jane Doe) NewWorldFontFamily Version 1.1
+- Improved build script performance and verbosity
+- Extended the smart code documentation
+- Corrected minor typos in the documentation
+- Fixed position of combining inverted breve below (U+032F)
+- Added OpenType/Graphite smart code for Armenian
+- Added Armenian glyphs (U+0531 -> U+0587) 
+- Released as "NewWorldFontFamily"
+
+1 Jan 2005 (Joe Smith) GlobalFontFamily Version 1.0
+- Initial release
+
+Acknowledgements
+
+If you make modifications be sure to add your name (N), email (E), web-address (if you have one) (W) and description (D). This list is in alphabetical order.
+
+N: Jane Doe
+E: jane@xxxxxxxxxxxxxx
+W: http://art.university.edu/projects/fonts
+D: Contributor - Armenian glyphs and code
+
+N: Fred Foobar
+E: fred@xxxxxxxxxx
+W: http://foobar.org
+D: Contributor - misc Graphite fixes
+
+N: Pat Johnson
+E: pat@xxxxxxxxxxxxxx
+W: http://pat.fontstudio.org
+D: Designer - Greek & Cyrillic glyphs based on Roman design
+
+N: Tom Parker
+E: tom@xxxxxxxxxxx
+W: http://www.company.com/tom/projects/fonts
+D: Engineer - original smart font code
+
+N: Joe Smith
+E: joe@xxxxxxxxxxxxxx
+W: http://joe.fontstudio.org
+D: Designer - original Roman glyphs
+
+Fontstudio.org is an not-for-profit design group whose purpose is...
+Foobar.org is a distributed community of developers...
+Company.com is a small business who likes to support community designers...
+University.edu is a renowed educational institution with a strong design department...
+-----

=== added file 'i18n/fonts/amiri/OFL.txt'
--- i18n/fonts/amiri/OFL.txt	1970-01-01 00:00:00 +0000
+++ i18n/fonts/amiri/OFL.txt	2015-09-26 18:15:59 +0000
@@ -0,0 +1,87 @@
+Copyright (c) 2010-2013, Khaled Hosny (<khaledhosny@xxxxxxxxx>)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+---------------------------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+---------------------------------------------------------------------------
+
+PREAMBLE
+
+The goals of the Open Font License (OFL) are to stimulate worldwide development
+of collaborative font projects, to support the font creation efforts of academic
+and linguistic communities, and to provide a free and open framework in which
+fonts may be shared and improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and redistributed
+freely as long as they are not sold by themselves. The fonts, including any
+derivative works, can be bundled, embedded, redistributed and/or sold with any
+software provided that any reserved names are not used by derivative works. The
+fonts and derivatives, however, cannot be released under any other type of license.
+The requirement for fonts to remain under this license does not apply to any
+document created using the fonts or their derivatives.
+
+DEFINITIONS
+
+"Font Software" refers to the set of files released by the Copyright Holder(s) under
+this license and clearly marked as such. This may include source files, build
+scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the copyright
+statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting, or
+substituting -- in part or in whole -- any of the components of the Original Version,
+by changing formats or by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer or other
+person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the
+Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell
+modified and unmodified copies of the Font Software, subject to the following
+conditions:
+
+1) Neither the Font Software nor any of its individual components, in Original or
+Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled, redistributed
+and/or sold with any software, provided that each copy contains the above copyright
+notice and this license. These can be included either as stand-alone text files,
+human-readable headers or in the appropriate machine-readable metadata fields within
+text or binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless
+explicit written permission is granted by the corresponding Copyright Holder. This
+restriction only applies to the primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall
+not be used to promote, endorse or advertise any Modified Version, except to
+acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with
+their explicit written permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed
+entirely under this license, and must not be distributed under any other license. The
+requirement for fonts to remain under this license does not apply to any document
+created using the Font Software.
+
+TERMINATION
+
+This license becomes null and void if any of the above conditions are not met.
+
+DISCLAIMER
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER
+RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR
+INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

=== added file 'i18n/fonts/amiri/README.txt'
--- i18n/fonts/amiri/README.txt	1970-01-01 00:00:00 +0000
+++ i18n/fonts/amiri/README.txt	2015-09-26 18:15:59 +0000
@@ -0,0 +1,8 @@
+designer: Khaled Hosny
+url: http://amirifont.org
+license: OFL
+description: Amiri is a classical Arabic typeface in Naskh style for
+typesetting books and other running text. Its design is a revival of the
+beautiful typeface pioneered in early 20th century by Bulaq Press in Cairo,
+also known as Amiria Press, after which the font is named.
+

=== added file 'i18n/fonts/amiri/amiri-bold.ttf'
Binary files i18n/fonts/amiri/amiri-bold.ttf	1970-01-01 00:00:00 +0000 and i18n/fonts/amiri/amiri-bold.ttf	2015-09-26 18:15:59 +0000 differ
=== added file 'i18n/fonts/amiri/amiri-boldslanted.ttf'
Binary files i18n/fonts/amiri/amiri-boldslanted.ttf	1970-01-01 00:00:00 +0000 and i18n/fonts/amiri/amiri-boldslanted.ttf	2015-09-26 18:15:59 +0000 differ
=== added file 'i18n/fonts/amiri/amiri-regular.ttf'
Binary files i18n/fonts/amiri/amiri-regular.ttf	1970-01-01 00:00:00 +0000 and i18n/fonts/amiri/amiri-regular.ttf	2015-09-26 18:15:59 +0000 differ
=== added file 'i18n/fonts/amiri/amiri-slanted.ttf'
Binary files i18n/fonts/amiri/amiri-slanted.ttf	1970-01-01 00:00:00 +0000 and i18n/fonts/amiri/amiri-slanted.ttf	2015-09-26 18:15:59 +0000 differ
=== modified file 'src/editor/ui_menus/editor_main_menu.cc'
--- src/editor/ui_menus/editor_main_menu.cc	2015-02-20 11:32:33 +0000
+++ src/editor/ui_menus/editor_main_menu.cc	2015-09-26 18:15:59 +0000
@@ -30,10 +30,7 @@
 
 //TODO(unknown): these should be defined globally for the whole UI
 #define width 200
-#define height 20
 #define margin 15
-#define hmargin margin
-#define vmargin margin
 #define vspacing 15
 
 inline EditorInteractive & EditorMainMenu::eia() {
@@ -46,58 +43,68 @@
 EditorMainMenu::EditorMainMenu
 	(EditorInteractive & parent, UI::UniqueWindow::Registry & registry)
 :
-	UI::UniqueWindow
-		(&parent, "main_menu", &registry, 2 * hmargin + width,
-		 260, _("Main Menu")),
-	m_button_new_map
-		(this, "new_map",
-		 hmargin, vmargin + 0 * (height + vspacing), width, height,
+	UI::UniqueWindow(&parent, "main_menu", &registry, 2 * margin + width, 0, _("Main Menu")),
+	box_(this, margin, margin, UI::Box::Vertical,
+		  width, get_h() - 2 * margin, vspacing),
+	button_new_map_
+		(&box_, "new_map",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("New Map")),
-	m_button_new_random_map
-		(this, "new_random_map",
-		 hmargin, vmargin + 1 * (height + vspacing), width, height,
+	button_new_random_map_
+		(&box_, "new_random_map",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("New Random Map")),
-	m_button_load_map
-		(this, "load_map",
-		 hmargin, vmargin + 2 * (height + vspacing), width, height,
+	button_load_map_
+		(&box_, "load_map",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("Load Map")),
-	m_button_save_map
-		(this, "save_map",
-		 hmargin, vmargin + 3 * (height + vspacing), width, height,
+	button_save_map_
+		(&box_, "save_map",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("Save Map")),
-	m_button_map_options
-		(this, "map_options",
-		 hmargin, vmargin + 4 * (height + vspacing), width, height,
+	button_map_options_
+		(&box_, "map_options",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("Map Options")),
-	m_button_view_readme
-		(this, "readme",
-		 hmargin, vmargin + 5 * (height + vspacing), width, height,
+	button_view_readme_
+		(&box_, "readme",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but1.png"),
 		 _("View Readme")),
-	m_button_exit_editor
-		(this, "exit",
-		 hmargin, vmargin + 6 * (height + vspacing), width, height,
+	button_exit_editor_
+		(&box_, "exit",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but0.png"),
 		 _("Exit Editor"))
 {
-	m_button_new_map.sigclicked.connect(boost::bind(&EditorMainMenu::new_map_btn, this));
-	m_button_new_random_map.sigclicked.connect(boost::bind(&EditorMainMenu::new_random_map_btn, this));
-	m_button_load_map.sigclicked.connect(boost::bind(&EditorMainMenu::load_btn, this));
-	m_button_save_map.sigclicked.connect(boost::bind(&EditorMainMenu::save_btn, this));
-	m_button_map_options.sigclicked.connect(boost::bind(&EditorMainMenu::map_options_btn, this));
-
-	m_window_readme.open_window = [this] {
-		fileview_window(eia(), m_window_readme, "txts/editor_readme.lua");
+	box_.add(&button_new_map_, UI::Box::AlignCenter);
+	box_.add(&button_new_random_map_, UI::Box::AlignCenter);
+	box_.add(&button_load_map_, UI::Box::AlignCenter);
+	box_.add(&button_save_map_, UI::Box::AlignCenter);
+	box_.add(&button_map_options_, UI::Box::AlignCenter);
+	box_.add(&button_view_readme_, UI::Box::AlignCenter);
+	box_.add(&button_exit_editor_, UI::Box::AlignCenter);
+	box_.set_size(width, 7 * button_new_map_.get_h()+ 6 * vspacing);
+	set_inner_size(get_inner_w(), box_.get_h() + 2 * margin);
+
+	button_new_map_.sigclicked.connect(boost::bind(&EditorMainMenu::new_map_btn, this));
+	button_new_random_map_.sigclicked.connect(boost::bind(&EditorMainMenu::new_random_map_btn, this));
+	button_load_map_.sigclicked.connect(boost::bind(&EditorMainMenu::load_btn, this));
+	button_save_map_.sigclicked.connect(boost::bind(&EditorMainMenu::save_btn, this));
+	button_map_options_.sigclicked.connect(boost::bind(&EditorMainMenu::map_options_btn, this));
+
+	window_readme_.open_window = [this] {
+		fileview_window(eia(), window_readme_, "txts/editor_readme.lua");
 	};
-	m_button_view_readme.sigclicked.connect(
-	   boost::bind(&UI::UniqueWindow::Registry::toggle, m_window_readme));
+	button_view_readme_.sigclicked.connect(
+		boost::bind(&UI::UniqueWindow::Registry::toggle, window_readme_));
 
-	m_button_exit_editor.sigclicked.connect(boost::bind(&EditorMainMenu::exit_btn, this));
+	button_exit_editor_.sigclicked.connect(boost::bind(&EditorMainMenu::exit_btn, this));
 
 	// Put in the default position, if necessary
 	if (get_usedefaultpos())

=== modified file 'src/editor/ui_menus/editor_main_menu.h'
--- src/editor/ui_menus/editor_main_menu.h	2014-09-10 14:08:25 +0000
+++ src/editor/ui_menus/editor_main_menu.h	2015-09-26 18:15:59 +0000
@@ -20,6 +20,7 @@
 #ifndef WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_H
 #define WL_EDITOR_UI_MENUS_EDITOR_MAIN_MENU_H
 
+#include "ui_basic/box.h"
 #include "ui_basic/button.h"
 #include "ui_basic/unique_window.h"
 
@@ -33,15 +34,16 @@
 
 private:
 	EditorInteractive & eia();
-	UI::Button m_button_new_map;
-	UI::Button m_button_new_random_map;
-	UI::Button m_button_load_map;
-	UI::Button m_button_save_map;
-	UI::Button m_button_map_options;
-	UI::Button m_button_view_readme;
-	UI::Button m_button_exit_editor;
+	UI::Box box_;
+	UI::Button button_new_map_;
+	UI::Button button_new_random_map_;
+	UI::Button button_load_map_;
+	UI::Button button_save_map_;
+	UI::Button button_map_options_;
+	UI::Button button_view_readme_;
+	UI::Button button_exit_editor_;
 
-	UI::UniqueWindow::Registry m_window_readme;
+	UI::UniqueWindow::Registry window_readme_;
 
 	void exit_btn       ();
 	void load_btn       ();

=== modified file 'src/editor/ui_menus/editor_main_menu_random_map.cc'
--- src/editor/ui_menus/editor_main_menu_random_map.cc	2015-09-04 06:16:58 +0000
+++ src/editor/ui_menus/editor_main_menu_random_map.cc	2015-09-26 18:15:59 +0000
@@ -42,7 +42,7 @@
 #include "ui_basic/window.h"
 
 using namespace Widelands;
-
+// TODO(GunChleoc): Arabic buttons need more height for Arabic.
 MainMenuNewRandomMap::MainMenuNewRandomMap(EditorInteractive& parent) :
 	UI::Window(&parent,
 				  "random_map_menu",

=== modified file 'src/editor/ui_menus/editor_main_menu_save_map.cc'
--- src/editor/ui_menus/editor_main_menu_save_map.cc	2015-09-25 05:48:06 +0000
+++ src/editor/ui_menus/editor_main_menu_save_map.cc	2015-09-26 18:15:59 +0000
@@ -50,6 +50,7 @@
 	return dynamic_cast<EditorInteractive&>(*get_parent());
 }
 
+// TODO(GunChleoc): Arabic Make directory dialog: buttons need more height for Arabic.
 
 MainMenuSaveMap::MainMenuSaveMap(EditorInteractive & parent)
 	: UI::Window(&parent, "save_map_menu", 0, 0, 560, 330, _("Save Map"))

=== modified file 'src/graphic/align.cc'
--- src/graphic/align.cc	2014-06-07 16:29:05 +0000
+++ src/graphic/align.cc	2015-09-26 18:15:59 +0000
@@ -19,8 +19,40 @@
 
 #include "graphic/align.h"
 
+#include "graphic/font_handler1.h"
+#include "graphic/text/font_set.h"
+
 namespace UI {
 
+// This mirrors the horizontal alignment for RTL languages.
+Align mirror_alignment(Align alignment) {
+	if (UI::g_fh1->fontset().is_rtl()) {
+		switch (alignment) {
+			case Align::Align_BottomLeft:
+				alignment = Align::Align_BottomRight;
+				break;
+			case Align::Align_BottomRight:
+				alignment = Align::Align_BottomLeft;
+				break;
+			case Align::Align_CenterLeft:
+				alignment = Align::Align_CenterRight;
+				break;
+			case Align::Align_CenterRight:
+				alignment = Align::Align_CenterLeft;
+				break;
+			case Align::Align_TopLeft:
+				alignment = Align::Align_TopRight;
+				break;
+			case Align::Align_TopRight:
+				alignment = Align::Align_TopLeft;
+				break;
+			default:
+				break;
+		}
+	}
+	return alignment;
+}
+
 void correct_for_align(Align align, uint32_t w, uint32_t h, Point* pt) {
 	//Vertical Align
 	if (align & (Align_VCenter | Align_Bottom)) {

=== modified file 'src/graphic/align.h'
--- src/graphic/align.h	2014-07-05 16:41:51 +0000
+++ src/graphic/align.h	2015-09-26 18:15:59 +0000
@@ -49,6 +49,7 @@
 	Align_BottomRight  = Align_Right|Align_Bottom,
 };
 
+Align mirror_alignment(Align alignment);
 void correct_for_align(Align, uint32_t w, uint32_t h, Point* pt);
 
 }

=== modified file 'src/graphic/font.cc'
--- src/graphic/font.cc	2014-11-27 12:02:08 +0000
+++ src/graphic/font.cc	2015-09-26 18:15:59 +0000
@@ -22,6 +22,7 @@
 #include <map>
 
 #include "base/utf8.h"
+#include "graphic/font_handler1.h" // We need the fontset for the size offset
 #include "graphic/text/font_set.h"
 #include "graphic/text_constants.h"
 #include "io/filesystem/layered_filesystem.h"
@@ -129,6 +130,7 @@
  */
 Font * Font::get(const std::string & name, int size)
 {
+	size += UI::g_fh1->fontset().size_offset();
 	FontDescr descr;
 	descr.name = name;
 	descr.size = size;

=== modified file 'src/graphic/font_handler.cc'
--- src/graphic/font_handler.cc	2014-12-07 20:52:55 +0000
+++ src/graphic/font_handler.cc	2015-09-26 18:15:59 +0000
@@ -26,11 +26,14 @@
 
 #include <SDL_ttf.h>
 #include <boost/algorithm/string.hpp>
+#include <boost/format.hpp>
 
 #include "base/log.h"
 #include "base/wexception.h"
+#include "graphic/font_handler1.h" // We need the fontset for the BiDi algorithm
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
+#include "graphic/text/bidi.h"
 #include "graphic/texture.h"
 #include "graphic/wordwrap.h"
 
@@ -174,11 +177,16 @@
 {
 	TTF_Font * font = lce.style.font->get_ttf_font();
 	SDL_Color sdl_fg = {lce.style.fg.r, lce.style.fg.g, lce.style.fg.b, SDL_ALPHA_OPAQUE};
+	std::string renderme = i18n::make_ligatures(lce.text.c_str());
+
+	if (i18n::has_rtl_character(lce.text.c_str())) {
+		renderme = i18n::line2bidi(renderme.c_str());
+	}
 
 	// Work around an Issue in SDL_TTF that dies when the surface
 	// has zero width
 	int width = 0;
-	if (TTF_SizeUTF8(font, lce.text.c_str(), &width, nullptr) < 0 || !width) {
+	if (TTF_SizeUTF8(font, renderme.c_str(), &width, nullptr) < 0 || !width) {
 		lce.width = 0;
 		lce.height = TTF_FontHeight(font);
 		return;
@@ -186,12 +194,12 @@
 
 	lce.style.setup();
 
-	SDL_Surface* text_surface = TTF_RenderUTF8_Blended(font, lce.text.c_str(), sdl_fg);
+	SDL_Surface* text_surface = TTF_RenderUTF8_Blended(font, renderme.c_str(), sdl_fg);
 	if (!text_surface) {
 		log
 			("FontHandler::render_line, an error : %s\n",
 			 TTF_GetError());
-		log("Text was: '%s'\n", lce.text.c_str());
+		log("Text was: '%s'\n", renderme.c_str());
 		return;
 	}
 
@@ -214,6 +222,7 @@
 	// Erase every backslash in front of brackets
 	std::string copytext = boost::replace_all_copy(text, "\\<", "<");
 	boost::replace_all(copytext, "\\>", ">");
+	copytext = i18n::make_ligatures(copytext.c_str());
 	const LineCacheEntry & lce = d->get_line(style, copytext);
 
 	UI::correct_for_align(align, lce.width + 2 * LINE_MARGIN, lce.height, &dstpoint);

=== modified file 'src/graphic/font_handler1.cc'
--- src/graphic/font_handler1.cc	2015-04-18 11:20:53 +0000
+++ src/graphic/font_handler1.cc	2015-09-26 18:15:59 +0000
@@ -132,6 +132,7 @@
 
 	void reinitialize_fontset() override {
 		fontset_.reset(new UI::FontSet(i18n::get_locale()));
+		texture_cache_.get()->flush();
 		rt_renderer_.reset(new RT::Renderer(image_cache_, texture_cache_.get(), fontset_.get()));
 	}
 

=== modified file 'src/graphic/richtext.cc'
--- src/graphic/richtext.cc	2014-12-06 12:22:35 +0000
+++ src/graphic/richtext.cc	2015-09-26 18:15:59 +0000
@@ -22,9 +22,11 @@
 #include "base/rect.h"
 #include "graphic/font.h"
 #include "graphic/font_handler.h"
+#include "graphic/font_handler1.h" // Needed for fontset's direction
 #include "graphic/graphic.h"
 #include "graphic/image.h"
 #include "graphic/rendertarget.h"
+#include "graphic/text/bidi.h"
 #include "graphic/text_layout.h"
 #include "graphic/text_parser.h"
 
@@ -32,7 +34,7 @@
 
 namespace {
 int32_t const h_space = 3;
-}
+} // namespace
 
 /**
  * Layouted rich text is essentially a bunch of drawable elements, each with a
@@ -73,19 +75,46 @@
 	void draw(RenderTarget & dst) override
 	{
 		assert(words.size());
-		uint32_t x = g_fh->draw_text_raw(dst, style, Point(0, 0), words[0]);
-
-		std::vector<std::string>::const_iterator it = words.begin() + 1;
-		if (it != words.end()) {
-			uint32_t spacewidth = style.calc_bare_width(" ");
-
+		uint32_t spacewidth = style.calc_bare_width(" ");
+
+		std::vector<std::string> result_words;
+		std::vector<std::string>::iterator it = result_words.begin();
+
+		// Reorder words for BiDi
+		if (UI::g_fh1->fontset().is_rtl() && i18n::has_rtl_character(words)) {
+			std::string previous_word;
+			for (std::vector<std::string>::iterator source_it = words.begin();
+				  source_it != words.end(); ++source_it) {
+				const std::string& word = *source_it;
+				if (source_it != words.end()) {
+					if (i18n::has_rtl_character(word.c_str()) || i18n::has_rtl_character(previous_word.c_str())) {
+						it = result_words.insert(result_words.begin(), word);
+					} else { // Sequences of Latin words go to the right from current position
+						if (it < result_words.end()) {
+							++it;
+						}
+						it = result_words.insert(it, word);
+					}
+					previous_word = word;
+				}
+			}
+		} else {
+			for (const std::string& word: words) {
+				result_words.push_back(word);
+			}
+		}
+		// Now render
+		uint32_t x = g_fh->draw_text_raw(dst, style, Point(0, 0), result_words[0]);
+
+		it = result_words.begin() + 1;
+		if (it != result_words.end()) {
 			do {
 				if (style.underline)
 					x += g_fh->draw_text_raw(dst, style, Point(x, 0), " ");
 				else
 					x += spacewidth;
 				x += g_fh->draw_text_raw(dst, style, Point(x, 0), *it++);
-			} while (it != words.end());
+			} while (it != result_words.end());
 		}
 	}
 
@@ -262,7 +291,7 @@
 			int32_t alignref_right = rti.width;
 
 			if (text_y < rti.height + images_height) {
-				if ((richtext->get_image_align() & Align_Horizontal) == Align_Right) {
+				if ((mirror_alignment(richtext->get_image_align()) & Align_Horizontal) == Align_Right) {
 					alignref_right -= images_width + h_space;
 				} else {
 					// Note: center image alignment with text is not properly supported
@@ -273,7 +302,7 @@
 
 			int32_t textleft;
 
-			switch (richtext->get_text_align() & Align_Horizontal) {
+			switch (mirror_alignment(richtext->get_text_align()) & Align_Horizontal) {
 			case Align_Right:
 				textleft = alignref_right - int32_t(linewidth);
 				break;
@@ -359,7 +388,7 @@
 
 		if ((text.richtext->get_image_align() & Align_Horizontal) == Align_HCenter)
 			imagealigndelta = (int32_t(m->width) - int32_t(text.images_width)) / 2;
-		else if ((text.richtext->get_image_align() & Align_Horizontal) == Align_Right)
+		else if ((mirror_alignment(text.richtext->get_image_align()) & Align_Horizontal) == Align_Right)
 			imagealigndelta = int32_t(m->width) - int32_t(text.images_width);
 
 		for (uint32_t idx = firstimageelement; idx < m->elements.size(); ++idx)
@@ -411,6 +440,7 @@
 				bbox.w = 0;
 				bbox.h = text.style.font->height();
 
+				// TODO(GunChleoc): Arabic width calculation for alignment is broken (Arabic)
 				do {
 					uint32_t wordwidth = text.style.calc_bare_width(words[word_cnt + nrwords]);
 

=== modified file 'src/graphic/text/CMakeLists.txt'
--- src/graphic/text/CMakeLists.txt	2015-01-31 16:03:59 +0000
+++ src/graphic/text/CMakeLists.txt	2015-09-26 18:15:59 +0000
@@ -2,6 +2,8 @@
 
 wl_library(graphic_text
   SRCS
+    bidi.cc
+    bidi.h
     font_io.cc
     font_io.h
     font_set.cc
@@ -18,6 +20,7 @@
     textstream.h
   USES_SDL2
   USES_SDL2_TTF
+  USES_ICU
   DEPENDS
     base_exceptions
     base_geometry

=== added file 'src/graphic/text/bidi.cc'
--- src/graphic/text/bidi.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/text/bidi.cc	2015-09-26 18:15:59 +0000
@@ -0,0 +1,593 @@
+/*
+ * Copyright (C) 2006-2015 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "graphic/text/bidi.h"
+
+#include <map>
+#include <string>
+
+#include <unicode/uchar.h>
+#include <unicode/unistr.h>
+#include <unicode/utypes.h>
+
+#include "base/log.h"
+
+namespace {
+// TODO(GunChleoc): Have a look at the ICU API to see which helper functions can be gained from there.
+// TODO(GunChleoc): Arabic Turn this into a proper class
+
+// Need to mirror () etc. for LTR languages, so we're sticking them in a map.
+const std::map<UChar, UChar> kSymmetricChars = {
+	{0x0028, 0x0029}, // ()
+	{0x0029, 0x0028}, // )(
+	{0x003C, 0x003E}, // <>
+	{0x003E, 0x003C}, // ><
+	{0x005B, 0x005D}, // []
+	{0x005D, 0x005B}, // ][
+	{0x007B, 0x007D}, // {}
+	{0x007D, 0x007B}, // }{
+	{0x201C, 0x201D}, // “”
+	{0x201D, 0x201C}, // ”“
+	{0x2018, 0x2019}, // ‘’
+	{0x2019, 0x2018}, // ’‘
+};
+
+bool is_symmetric_char(UChar c) {
+	return kSymmetricChars.count(c) == 1;
+}
+
+UChar mirror_symmetric_char(UChar c) {
+	if (kSymmetricChars.count(c) == 1) {
+		c = kSymmetricChars.at(c);
+	}
+	return c;
+}
+
+bool is_numeric_char(UChar c) {
+	return 0x0030 <= c && c <= 0x0039;  // 0-9
+}
+
+bool is_latin_char(UChar c) {
+	return (0x0061 <= c && c <= 0x007a) ||  // a-z
+			 (0x0041 <= c && c <= 0x005A);    // A-Z
+}
+
+bool is_punctuation_char(UChar c) {
+	return c == 0x0020 ||  // blank space
+			 c == 0x0021 ||  // !
+			 c == 0x002C ||  // ,
+			 c == 0x002D ||  // - // NOCOM " - " becomes "-  "
+			 c == 0x002E ||  // .
+			 c == 0x002F ||  // /
+			 c == 0x003A ||  // :
+			 c == 0x003B ||  // ;
+			 c == 0x003F ||  // ?
+			 c == 0x005C ||  // backslash
+			 (c >= 0x2000 && c <= 0x206F); // en-dash, em-dash etc.
+}
+
+
+// TODO(GunChleoc): Presentation forms A on demand
+// http://unicode-table.com/en/blocks/arabic-presentation-forms-a/
+const std::map<UChar, UChar> kArabicFinalChars = {
+	{0x0622, 0xFE82}, // ʾalif maddah
+	{0x0623, 0xFE84}, // ʾalif with hamza above
+	{0x0624, 0xFE86}, // wāw with hamza above
+	{0x0625, 0xFE88}, // ʾalif with hamza below
+	{0x0626, 0xFE8A}, // yāʾ with hamza above
+	{0x0627, 0xFE8E}, // ʾalif
+	{0x0628, 0xFE90}, // bāʾ
+	{0x0629, 0xFE94}, // tāʾ marbūṭah
+	{0x062A, 0xFE96}, // tāʾ
+	{0x062B, 0xFE9A}, // ṯāʾ
+	{0x062C, 0xFE9E}, // ǧīm
+	{0x062D, 0xFEA2}, // ḥāʾ
+	{0x062E, 0xFEA6}, // ḫāʾ
+	{0x062F, 0xFEAA}, // dāl
+	{0x0630, 0xFEAC}, // ḏāl
+	{0x0631, 0xFEAE}, // rāʾ
+	{0x0632, 0xFEB0}, // zayn/zāy
+	{0x0633, 0xFEB2}, // sīn
+	{0x0634, 0xFEB6}, // šīn
+	{0x0635, 0xFEBA}, // ṣād
+	{0x0636, 0xFEBE}, // ḍād
+	{0x0637, 0xFEC2}, // ṭāʾ
+	{0x0638, 0xFEC6}, // ẓāʾ
+	{0x0639, 0xFECA}, // ʿayn
+	{0x063A, 0xFECE}, // ġayn
+	/*
+	{0x063B, 0x}, // Keheh with Two Dots Above
+	{0x063C, 0x}, // Keheh with Three Dots Below
+	{0x063D, 0x}, // Farsi Yeh with Inverted V
+	{0x063E, 0x}, // Farsi Yeh with Two Dots Above
+	{0x063F, 0x}, // Farsi Yeh with Three Dots Above
+		*/
+	{0x0641, 0xFED2}, // fāʾ
+	{0x0642, 0xFED6}, // qāf
+	{0x0643, 0xFEDA}, // kāf
+	{0x0644, 0xFEDE}, // lām
+	{0x0645, 0xFEE2}, // mīm
+	{0x0646, 0xFEE6}, // nūn
+	{0x0647, 0xFEEA}, // hāʾ
+	{0x0648, 0xFEEE}, // wāw
+	{0x0649, 0xFEF0}, // ʾalif maqṣūrah
+	{0x064A, 0xFEF2}, // yāʾ
+	{0xFD3D, 0xFD3C}, // Ligature Alef with Fathatan
+	{0xFEF5, 0xFEF6}, // lām ʾalif maddah
+	{0xFEF7, 0xFEF8}, // lām ʾalif hamza above
+	{0xFEF9, 0xFEFA}, // lām ʾalif hamza below
+	{0xFEFB, 0xFEFC}, // lām ʾalif
+};
+
+const std::map<UChar, UChar> kArabicInitialChars = {
+	{0x0626, 0xFE8B}, // yāʾ with hamza above
+	{0x0628, 0xFE91}, // bāʾ
+	{0x062A, 0xFE97}, // tāʾ
+	{0x062B, 0xFE9B}, // ṯāʾ
+	{0x062C, 0xFE9F}, // ǧīm
+	{0x062D, 0xFEA3}, // ḥāʾ
+	{0x062E, 0xFEA7}, // ḫāʾ
+	{0x0633, 0xFEB3}, // sīn
+	{0x0634, 0xFEB7}, // šīn
+	{0x0635, 0xFEBB}, // ṣād
+	{0x0636, 0xFEBF}, // ḍād
+	{0x0637, 0xFEC3}, // ṭāʾ
+	{0x0638, 0xFEC7}, // ẓāʾ
+	{0x0639, 0xFECB}, // ʿayn
+	{0x063A, 0xFECF}, // ġayn
+	{0x0641, 0xFED3}, // fāʾ
+	{0x0642, 0xFED7}, // qāf
+	{0x0643, 0xFEDB}, // kāf
+	{0x0644, 0xFEDF}, // lām
+	{0x0645, 0xFEE3}, // mīm
+	{0x0646, 0xFEE7}, // nūn
+	{0x0647, 0xFEEB}, // hāʾ
+	{0x064A, 0xFEF3}, // yāʾ
+};
+
+const std::map<UChar, UChar> kArabicMedialChars = {
+	{0x0626, 0xFE8C}, // yāʾ with hamza above
+	{0x0628, 0xFE92}, // bāʾ
+	{0x062A, 0xFE98}, // tāʾ
+	{0x062B, 0xFE9C}, // ṯāʾ
+	{0x062C, 0xFEA0}, // ǧīm
+	{0x062D, 0xFEA4}, // ḥāʾ
+	{0x062E, 0xFEA8}, // ḫāʾ
+	{0x0633, 0xFEB4}, // sīn
+	{0x0634, 0xFEB8}, // šīn
+	{0x0635, 0xFEBC}, // ṣād
+	{0x0636, 0xFEC0}, // ḍād
+	{0x0637, 0xFEC4}, // ṭāʾ
+	{0x0638, 0xFEC8}, // ẓāʾ
+	{0x0639, 0xFECC}, // ʿayn
+	{0x063A, 0xFED0}, // ġayn
+	{0x0641, 0xFED4}, // fāʾ
+	{0x0642, 0xFED8}, // qāf
+	{0x0643, 0xFEDC}, // kāf
+	{0x0644, 0xFEE0}, // lām
+	{0x0645, 0xFEE4}, // mīm
+	{0x0646, 0xFEE8}, // nūn
+	{0x0647, 0xFEEC}, // hāʾ
+	{0x064A, 0xFEF4}, // yāʾ
+};
+
+
+// Special ligature forms combine 2 letters. lām-alif ligature is mandatory.
+// Diacritics also form ligatures.
+const std::map<std::pair<UChar, UChar>, UChar> kArabicLigatures = {
+	{{0x0644, 0x0622}, 0xFEF5}, // lām ʾalif maddah
+	{{0x0644, 0x0623}, 0xFEF7}, // lām ʾalif hamza above
+	{{0x0644, 0x0625}, 0xFEF9}, // lām ʾalif hamza below
+	{{0x0644, 0x0627}, 0xFEFB}, // lām ʾalif
+	{{0x0627, 0x064B}, 0xFD3D}, // Ligature Alef with Fathatan Isolated Form
+
+	// Basing these off the isolated forms; I don't know what will happen with canonical forms here
+	{{0xFE7C, 0xFE72}, 0xFC5E}, // Shadda with Dammatan Isolated Form
+	{{0xFE7C, 0xFE74}, 0xFC5F}, // Shadda with Kasratan Isolated Form
+	{{0xFE7C, 0x064D}, 0xFE76}, // Shadda with Fatha Isolated Form
+	{{0xFE7C, 0xFE78}, 0xFC61}, // Shadda with Damma Isolated Form
+	{{0xFE7C, 0xFE7A}, 0xFC62}, // Shadda with Kasra Isolated Form
+	{{0xFE7C, 0x0670}, 0xFC63}, // Shadda with Superscript Alef Isolated Form
+	{{0xFE7D, 0xFE77}, 0xFCF2}, // Shadda with Fatha Medial Form
+	{{0xFE7D, 0xFE79}, 0xFCF3}, // Shadda with Damma Medial Form
+	{{0xFE7D, 0xFE7B}, 0xFCF4}, // Shadda with Kasra Medial Form
+};
+
+
+/*
+ * The Arabic diacritics causes the game to add a space,
+ * for example "مَرحَب" which means hallo (written with 2 Fatḥah on it)
+ * will look like "مَـ ـرحَـ ـب", please notice that we only need
+ * Fatḥah (Fatha),
+ * Kasrah (Kasra),
+ * Ḍammah (Damma),
+ * Sukun (Sukun),
+ * Tanwin (the three of them) (Fathatan, Dammatan, Kasratan)
+ * Shaddah (Shadda).
+ */
+const std::set<UChar> kArabicDiacritics = {
+	{0x0670}, // Superscript Alef
+
+	{0x0618}, // Small Fatha
+	{0x064E}, // Fatha
+	{0x065E}, // Fatha with Two Dots
+	{0x08E4}, // Curly Fatha
+	{0x08F4}, // Fatha with Ring
+	{0x08F5}, // Fatha with Dot Above
+	{0xFE76}, // Fatha Isolated Form
+	{0xFE77}, // Fatha Medial Form
+
+	{0x061A}, // Small Kasra
+	{0x0650}, // Kasra
+	{0x08E6}, // Curly Kasra
+	{0x08F6}, // Kasra with Dot Below
+	{0xFE7A}, // Kasra Isolated Form
+	{0xFE7B}, // Kasra Medial Form
+
+	{0x0619}, // Small Damma
+	{0x064F}, // Damma
+	{0x0657}, // Inverted Damma
+	{0x065D}, // Reversed Damma
+	{0x08E5}, // Curly Damma
+	{0x08FE}, // Damma with Dot
+	{0xFE78}, // Damma Isolated Form
+	{0xFE79}, // Damma Medial Form
+
+	{0x0652}, // Sukun
+	{0xFE7E}, // Sukun Isolated Form
+	{0xFE7F}, // Sukun Medial Form
+
+	{0x08F0}, // Open Fathatan
+	{0x064B}, // Fathatan
+	{0x08E7}, // Curly Fathatan
+	{0xFE70}, // Fathatan Isolated Form
+	{0xFE71}, // Tatweel with Fathatan Above
+
+	{0x08F1}, // Open Dammatan
+	{0x064C}, // Dammatan
+	{0x08E8}, // Curly Dammatan
+	{0xFE72}, // Dammatan Isolated Form
+
+	{0x08F2}, // Open Kasratan
+	{0x064D}, // Kasratan
+	{0x08E9}, // Curly Kasratan
+	{0xFE74}, // Kasratan Isolated Form
+
+	{0x0651}, // Shadda
+	{0xFE7C}, // Shadda Isolated Form
+	{0xFE7D}, // Shadda Medial Form
+
+	{0xFC5E}, // Ligature Shadda with Dammatan Isolated Form
+	{0xFC5F}, // Ligature Shadda with Kasratan Isolated Form
+	{0xFC60}, // Ligature Shadda with Fatha Isolated Form
+	{0xFC61}, // Ligature Shadda with Damma Isolated Form
+	{0xFC62}, // Ligature Shadda with Kasra Isolated Form
+	{0xFC63}, // Ligature Shadda with Superscript Alef Isolated Form
+	{0xFCF2}, // Ligature Shadda with Fatha Medial Form
+	{0xFCF3}, // Ligature Shadda with Damma Medial Form
+	{0xFCF4}, // Ligature Shadda with Kasra Medial Form
+};
+
+
+// Map no longer used Arabic presentation forms to standard forms
+const std::map<UChar, UChar> kArabicLegacyDiacritics = {
+	// Isolated
+	{0xFE76, 0x064E}, // Fatha
+	{0xFE7A, 0x0650}, // Kasra
+	{0xFE78, 0x064F}, // Damma
+	{0xFE70, 0x064B}, // Fathatan
+	{0xFE72, 0x064C}, // Dammatan
+	{0xFE74, 0x064D}, // Kasratan
+	{0xFE7C, 0x0651}, // Shadda
+
+	// Medial
+	{0xFE77, 0x064E}, // Fatha
+	{0xFE7B, 0x0650}, // Kasra
+	{0xFE79, 0x064F}, // Damma
+	{0xFE7F, 0x0652}, // Sukun
+	{0xFE7D, 0x0651}, // Shadda
+
+	{0xFCF2, 0xFE76}, // Shadda with Fatha
+	{0xFCF3, 0xFC61}, // Shadda with Damma
+	{0xFCF4, 0xFC62}, // Shadda with Kasra
+};
+
+
+// Helper to printf ICU strings for testing
+const char* icustring2char(icu::UnicodeString convertme) {
+	std::string result;
+	convertme.toUTF8String(result);
+	return result.c_str();
+}
+const char* icuchar2char(UChar convertme) {
+	icu::UnicodeString temp(convertme);
+	return icustring2char(temp);
+}
+
+const std::set<std::string> kRTLScripts = {
+	{"arabic", "devanagari", "hebrew", "mandaic", "nko", "samaritan", "syriac", "thaana"},
+};
+
+// http://unicode.org/faq/blocks_ranges.html
+// http://unicode-table.com/en/blocks/
+// TODO(GunChleoc): We might need some more here - let's see how this goes.
+const std::map<std::string, std::set<UBlockCode>> kRTLCodeBlocks = {
+	{"arabic", {
+		 UBlockCode::UBLOCK_ARABIC,
+		 UBlockCode::UBLOCK_ARABIC_SUPPLEMENT,
+		 UBlockCode::UBLOCK_ARABIC_EXTENDED_A,
+		 UBlockCode::UBLOCK_ARABIC_PRESENTATION_FORMS_A,
+		 UBlockCode::UBLOCK_ARABIC_PRESENTATION_FORMS_B,
+		 UBlockCode::UBLOCK_ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS,
+	 }},
+	{"devanagari", {
+		 UBlockCode::UBLOCK_DEVANAGARI,
+		 UBlockCode::UBLOCK_DEVANAGARI_EXTENDED,
+	 }},
+	{"hebrew", {
+		 UBlockCode::UBLOCK_HEBREW,
+	 }},
+	{"mandaic", {
+		 UBlockCode::UBLOCK_MANDAIC,
+	 }},
+	{"nko", {
+		 UBlockCode::UBLOCK_NKO,
+	 }},
+	{"samaritan", {
+		 UBlockCode::UBLOCK_SAMARITAN,
+	 }},
+	{"syriac", {
+		 UBlockCode::UBLOCK_SYRIAC,
+	 }},
+	{"thaana", {
+		 UBlockCode::UBLOCK_THAANA,
+	 }},
+};
+
+bool is_rtl_character(UChar32 c) {
+	UBlockCode code = ublock_getCode(c);
+	for (std::string script : kRTLScripts) {
+		assert(kRTLCodeBlocks.count(script) == 1);
+		if ((kRTLCodeBlocks.at(script).count(code) == 1)) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool is_arabic_character(UChar32 c) {
+	UBlockCode code = ublock_getCode(c);
+	assert(kRTLCodeBlocks.count("arabic") == 1);
+	return (kRTLCodeBlocks.at("arabic").count(code) == 1);
+}
+
+
+// True if a string does not contain Latin characters
+bool has_arabic_character(const char* input) {
+	bool result = false;
+	const icu::UnicodeString parseme(input);
+	for (int32_t i = 0; i < parseme.length(); ++i) {
+		if (is_arabic_character(parseme.char32At(i))) {
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+
+// Helper function for make_ligatures.
+// Arabic word characters have 4 forms to connect to each other:
+// Isolated, Initial, Medial, and Final.
+// - Isolated forms are the "canonical" forms and have no connection.
+// - Initial forms have a connection to the following letter.
+// - Medial forms have connections to both sides.
+// - Final forms have a connection to the preceding letter.
+// - All characters have an Isolated and a Final form.
+// - All characters that have a Medial form also have a Initial form and vice versa.
+// If a letter is in the middle of a word and the preceding letter has no connection pointing
+// towards it, pick the Initial or Isolated form (depending on if it is followed by another
+// letter) etc.
+UChar find_arabic_letter_form(UChar c, UChar previous, UChar next) {
+	if (kArabicFinalChars.count(previous) == 0) {  // Start of word
+		if (kArabicInitialChars.count(c) == 1) {  // Link to next if character available
+			c = kArabicInitialChars.at(c);
+		}
+	} else if (kArabicFinalChars.count(next) == 0) {  // End of word
+		if (kArabicMedialChars.count(previous) == 1) {  // Link to previous if possible
+			c = kArabicFinalChars.at(c);
+		}
+	} else { // Middle of word
+		if (kArabicMedialChars.count(previous) == 1) {  // Link to previous if possible
+			if (kArabicMedialChars.count(c) == 1) {
+				c = kArabicMedialChars.at(c);
+			} else {
+				c = kArabicFinalChars.at(c);
+			}
+		} else {  // Link to next if character available
+			if (kArabicInitialChars.count(c) == 1) {
+				c = kArabicInitialChars.at(c);
+			}
+		}
+	}
+	return c;
+}
+
+
+} // namespace
+
+namespace i18n {
+
+
+// True if a string does not contain Latin characters
+bool has_rtl_character(const char* input) {
+	bool result = false;
+	const icu::UnicodeString parseme(input);
+	for (int32_t i = 0; i < parseme.length(); ++i) {
+		if (is_rtl_character(parseme.char32At(i))) {
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+// True if the strings do not contain Latin characters
+bool has_rtl_character(std::vector<std::string> input) {
+	bool result = false;
+	for (const std::string& string: input) {
+		if (has_rtl_character(string.c_str())) {
+			result = true;
+			break;
+		}
+	}
+	return result;
+}
+
+
+// Contracts glyphs into their ligatures
+std::string make_ligatures(const char* input) {
+	// We only have defined ligatures for Arabic at the moment.
+	if (!has_arabic_character(input)) {
+		return input;
+	}
+	const icu::UnicodeString parseme(input);
+	icu::UnicodeString queue;
+	UChar not_a_character = 0xFFFF;
+	UChar next = not_a_character;
+	UChar previous = not_a_character;
+	for (int i = parseme.length() - 1; i >= 0; --i) {
+		UChar c = parseme.charAt(i);
+
+		// Substitution for Arabic characters
+		previous = (i > 0) ? parseme.charAt(i - 1) : not_a_character;
+		next = (i < (parseme.length() - 1)) ? parseme.charAt(i + 1) : not_a_character;
+
+		if (kArabicDiacritics.count(c) == 1) {
+			try {
+				// Map legacy characters
+				if (kArabicLegacyDiacritics.count(c) == 1) {
+					c = kArabicLegacyDiacritics.at({c});
+				}
+				if (kArabicLegacyDiacritics.count(previous) == 1) {
+					previous = kArabicLegacyDiacritics.at({previous});
+				}
+				if (kArabicLegacyDiacritics.count(next) == 1) {
+					next = kArabicLegacyDiacritics.at({next});
+				}
+
+				// Special ligature forms combine 2 letters.
+				if (kArabicLigatures.count({previous, c}) == 1) {
+					c = kArabicLigatures.at({previous, c});
+					// Now skip 1 letter, since we have just combined 2 letters
+					--i;
+					previous = (i > 0) ? parseme.charAt(i - 1) : not_a_character;
+				}
+			} catch (std::out_of_range e) {
+				log("Error trying to fetch Arabic diacritic form: %s\n", e.what());
+				assert(false);
+			}
+		} else if (kArabicFinalChars.count(c) == 1) { // All Arabic characters have a final form
+			try {
+				// Skip diacritics for position analysis
+				for (int k = i - 2; k >= 0 && kArabicDiacritics.count(previous); --k) {
+					previous = parseme.charAt(k);
+				}
+				for (int k = i + 2; k < (parseme.length() - 1) && kArabicDiacritics.count(next); ++k) {
+					next = parseme.charAt(k);
+				}
+
+				// Special ligature forms combine 2 letters.
+				if (kArabicLigatures.count({previous, c}) == 1) {
+					c = kArabicLigatures.at({previous, c});
+					// Now skip 1 letter, since we have just combined 2 letters
+					--i;
+					previous = (i > 0) ? parseme.charAt(i - 1) : not_a_character;
+					// Skip diacritics for position analysis
+					for (int k = i - 2; k >= 0 && kArabicDiacritics.count(previous); --k) {
+						previous = parseme.charAt(k);
+					}
+				}
+				c = find_arabic_letter_form(c, previous, next);
+			} catch (std::out_of_range e) {
+				log("Error trying to fetch Arabic character form: %s\n", e.what());
+				assert(false);
+			}
+		}
+
+		// TODO(GunChleoc): We sometimes get "Not a Character" - find out why.
+		if (c != 0xFFFF) {
+			// Add the current RTL character
+			queue.insert(0, c);
+		}
+	}
+
+	std::string result;
+	queue.toUTF8String(result);
+	return result;
+}
+
+
+// BiDi support for RTL languages
+// This turns the logical order of the glyphs into the display order.
+std::string line2bidi(const char* input) {
+	const icu::UnicodeString parseme(input);
+	icu::UnicodeString stack;
+	icu::UnicodeString temp_stack;
+	UChar not_a_character = 0xFFFF;
+	UChar previous = not_a_character;
+	for (int i = parseme.length() - 1; i >= 0; --i) {
+		UChar c = parseme.charAt(i);
+		if (i > 0) {
+			previous = parseme.charAt(i - 1);
+		}
+		// LTR characters need to be turned around in a temp stack,
+		// because we will reverse everything on the bottom for RTL
+		temp_stack = "";
+		while (i >= 0 &&
+				(is_numeric_char(c) ||
+				 is_latin_char(c) ||
+				 is_symmetric_char(c) ||
+				 ((is_latin_char(previous) || is_punctuation_char(previous)) && is_punctuation_char(c)))) {
+			if (is_symmetric_char(c)) {
+				c = mirror_symmetric_char(c);
+			}
+			temp_stack += c;
+			c = parseme.charAt(--i);
+			if (i > 0) {
+				previous = parseme.charAt(i - 1);
+			}
+		}
+		for (int32_t j = temp_stack.length() - 1; j >= 0; --j) {
+			stack += temp_stack.charAt(j);
+		}
+
+		// TODO(GunChleoc): We sometimes get "Not a Character" - find out why.
+		if (c != 0xFFFF) {
+			// Add the current RTL character
+			stack += c;
+		}
+	}
+
+	std::string result;
+	stack.toUTF8String(result);
+	return result;
+}
+
+} // namespace UI

=== added file 'src/graphic/text/bidi.h'
--- src/graphic/text/bidi.h	1970-01-01 00:00:00 +0000
+++ src/graphic/text/bidi.h	2015-09-26 18:15:59 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006-2015 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef WL_GRAPHIC_TEXT_BIDI_H
+#define WL_GRAPHIC_TEXT_BIDI_H
+
+#include <string>
+#include <vector>
+
+#include "graphic/text/font_set.h"
+
+// BiDi support for RTL languages
+namespace i18n {
+	std::string make_ligatures(const char* input);
+	std::string line2bidi(const char* input);
+	bool has_rtl_character(const char* input);
+	bool has_rtl_character(std::vector<std::string> input);
+
+} // namespace UI
+
+#endif  // end of include guard: WL_GRAPHIC_TEXT_BIDI_H

=== modified file 'src/graphic/text/font_set.cc'
--- src/graphic/text/font_set.cc	2015-09-03 07:07:46 +0000
+++ src/graphic/text/font_set.cc	2015-09-26 18:15:59 +0000
@@ -61,13 +61,16 @@
 const std::string& FontSet::condensed_bold() const {return condensed_bold_;}
 const std::string& FontSet::condensed_italic() const {return condensed_italic_;}
 const std::string& FontSet::condensed_bold_italic() const {return condensed_bold_italic_;}
-const FontSet::Direction& FontSet::direction() const {return direction_;}
+uint16_t FontSet::size_offset() const {return size_offset_;}
+bool FontSet::is_rtl() const {return is_rtl_;}
+
 
 // Loads font info from config files, depending on the localename
 void FontSet::parse_font_for_locale(const std::string& localename) {
 	std::string fontsetname = "default";
 	std::string actual_localename = localename;
 	std::string direction_string;
+	size_offset_ = 0;
 	LuaInterface lua;
 
 	// Read default fontset. It defines the fallback fonts and needs to always be there and complete.
@@ -79,6 +82,7 @@
 
 	set_fonts(*default_font_table, kFallbackFont);
 	direction_string = default_font_table->get_string("direction");
+	size_offset_ = default_font_table->get_int("size_offset");
 
 	// Now try to get the fontset for the actual locale.
 	try  {
@@ -121,6 +125,9 @@
 
 					set_fonts(*font_set_table, serif_);
 					direction_string = get_string_with_default(*font_set_table, "direction", "ltr");
+					if (font_set_table->has_key("size_offset")) {
+						size_offset_ = font_set_table->get_int("size_offset");
+					}
 				} catch (LuaError& err) {
 					log("Could not read font set '%s': %s\n", fontsetname.c_str(), err.what());
 				}
@@ -132,13 +139,11 @@
 		log("Could not read locales information from file: %s\n", err.what());
 	}
 
-	if (direction_string == "ltr") {
-		direction_ = FontSet::Direction::kLeftToRight;
-	} else if (direction_string == "rtl") {
-		direction_ = FontSet::Direction::kRightToLeft;
-	} else {
+	is_rtl_ = false;
+	if (direction_string == "rtl") {
+		is_rtl_ = true;
+	} else if (direction_string != "ltr") {
 		log("Unknown script direction '%s'. Using to left-to-right rendering.\n", direction_string.c_str());
-		direction_ = FontSet::Direction::kLeftToRight;
 	}
 }
 

=== modified file 'src/graphic/text/font_set.h'
--- src/graphic/text/font_set.h	2014-12-12 18:00:50 +0000
+++ src/graphic/text/font_set.h	2015-09-26 18:15:59 +0000
@@ -29,12 +29,6 @@
 // Contains font information for a locale
 struct FontSet {
 
-	// Writing direction of a script
-	enum class Direction {
-		kLeftToRight,
-		kRightToLeft
-	};
-
 	static constexpr const char* kFallbackFont = "DejaVu/DejaVuSerif.ttf";
 
 	/// Create the fontset for a locale from configuration file
@@ -54,7 +48,8 @@
 	const std::string& condensed_bold() const;
 	const std::string& condensed_italic() const;
 	const std::string& condensed_bold_italic() const;
-	const FontSet::Direction& direction() const;
+	uint16_t size_offset() const;
+	bool is_rtl() const;
 
 private:
 	/// Parses font information for the given 'localename' from Lua files.
@@ -82,7 +77,8 @@
 	std::string condensed_bold_;
 	std::string condensed_italic_;
 	std::string condensed_bold_italic_;
-	FontSet::Direction direction_;
+	uint16_t    size_offset_;
+	bool is_rtl_;
 };
 
 }

=== modified file 'src/graphic/text/rt_render.cc'
--- src/graphic/text/rt_render.cc	2014-12-27 09:59:12 +0000
+++ src/graphic/text/rt_render.cc	2015-09-26 18:15:59 +0000
@@ -19,20 +19,24 @@
 
 #include "graphic/text/rt_render.h"
 
+#include <cmath>
 #include <memory>
 #include <queue>
 #include <string>
 #include <vector>
 
 #include <SDL.h>
+#include <boost/algorithm/string/predicate.hpp>
 #include <boost/format.hpp>
 
 #include "base/log.h"
 #include "base/macros.h"
 #include "base/point.h"
 #include "base/rect.h"
+#include "graphic/align.h"
 #include "graphic/image_cache.h"
 #include "graphic/image_io.h"
+#include "graphic/text/bidi.h"
 #include "graphic/text/font_io.h"
 #include "graphic/text/font_set.h"
 #include "graphic/text/rt_parse.h"
@@ -47,16 +51,6 @@
 static const uint16_t INFINITE_WIDTH = 65535; // 2^16-1
 
 // Helper Stuff
-enum HAlign {
-	HALIGN_LEFT,
-	HALIGN_RIGHT,
-	HALIGN_CENTER,
-};
-enum VAlign {
-	VALIGN_BOTTOM,
-	VALIGN_TOP,
-	VALIGN_CENTER,
-};
 struct Borders {
 	Borders() {left = top = right = bottom = 0;}
 	uint8_t left, top, right, bottom;
@@ -68,10 +62,11 @@
 	uint16_t font_size;
 	RGBColor font_color;
 	int font_style;
+	bool is_rtl;
 
 	uint8_t spacing;
-	HAlign halign;
-	VAlign valign;
+	UI::Align halign;
+	UI::Align valign;
 	string reference;
 };
 
@@ -120,10 +115,10 @@
 
 	Floating get_floating() {return m_floating;}
 	void set_floating(Floating f) {m_floating = f;}
-	HAlign halign() {return m_halign;}
-	void set_halign(HAlign ghalign) {m_halign = ghalign;}
-	VAlign valign() {return m_valign;}
-	void set_valign(VAlign gvalign) {m_valign = gvalign;}
+	UI::Align halign() {return m_halign;}
+	void set_halign(UI::Align ghalign) {m_halign = ghalign;}
+	UI::Align valign() {return m_valign;}
+	void set_valign(UI::Align gvalign) {m_valign = gvalign;}
 	void set_x(uint16_t nx) {m_x = nx;}
 	void set_y(uint16_t ny) {m_y = ny;}
 	uint16_t x() {return m_x;}
@@ -131,8 +126,8 @@
 
 private:
 	Floating m_floating;
-	HAlign m_halign;
-	VAlign m_valign;
+	UI::Align m_halign;
+	UI::Align m_valign;
 	uint16_t m_x, m_y;
 };
 
@@ -142,7 +137,7 @@
 	virtual ~Layout() {}
 
 	uint16_t height() {return m_h;}
-	uint16_t fit_nodes(vector<RenderNode*>& rv, uint16_t w, Borders p);
+	uint16_t fit_nodes(vector<RenderNode*>& rv, uint16_t w, Borders p, bool shrink_to_fit);
 
 private:
 	// Represents a change in the rendering constraints. For example when an
@@ -158,7 +153,7 @@
 		}
 	};
 
-	uint16_t m_fit_line(uint16_t w, const Borders&, vector<RenderNode*>* rv);
+	uint16_t m_fit_line(uint16_t w, const Borders&, vector<RenderNode*>* rv, bool shrink_to_fit);
 
 	uint16_t m_h;
 	size_t m_idx;
@@ -166,33 +161,48 @@
 	priority_queue<ConstraintChange> m_constraint_changes;
 };
 
-uint16_t Layout::m_fit_line(uint16_t w, const Borders& p, vector<RenderNode*>* rv) {
+uint16_t Layout::m_fit_line(uint16_t w, const Borders& p, vector<RenderNode*>* rv, bool shrink_to_fit) {
 	assert(rv->empty());
 
-	while (m_idx < m_all_nodes.size() && m_all_nodes[m_idx]->is_non_mandatory_space()) {
-		delete m_all_nodes[m_idx++];
+	// Remove leading spaces
+	while (m_idx < m_all_nodes.size()
+		&& m_all_nodes[m_idx]->is_non_mandatory_space()
+		&& shrink_to_fit) {
+			delete m_all_nodes[m_idx++];
 	}
 
 	uint16_t x = p.left;
+	std::size_t first_m_idx = m_idx;
+
+	// Calc fitting nodes
 	while (m_idx < m_all_nodes.size()) {
 		RenderNode* n = m_all_nodes[m_idx];
-		const uint16_t nw = n->width();
-		if (x + nw + p.right > w || n->get_floating()) {
-			break;
+		uint16_t nw = n->width();
+		if (x + nw + p.right > w || n->get_floating() != RenderNode::NO_FLOAT) {
+			if (m_idx == first_m_idx) {
+				nw = w - p.right - x;
+			} else {
+				break;
+			}
 		}
 		n->set_x(x); x += nw;
 		rv->push_back(n);
 		++m_idx;
 	}
-
-	if (!rv->empty() && rv->back()->is_non_mandatory_space()) {
+	// Remove trailing spaces
+	while (!rv->empty()
+			&& rv->back()->is_non_mandatory_space()
+			&& shrink_to_fit) {
 		x -= rv->back()->width();
 		delete rv->back();
 		rv->pop_back();
 	}
 
 	// Remaining space in this line
-	uint16_t rem_space = w - p.right - x;
+	uint16_t rem_space = 0;
+	if (w < INFINITE_WIDTH) {
+		rem_space = w - p.right - x;
+	}
 
 	// Find expanding nodes
 	vector<size_t> expanding_nodes;
@@ -209,8 +219,8 @@
 		}
 	} else {
 		// Take last elements style in this line and check horizontal alignment
-		if (!rv->empty() && (*rv->rbegin())->halign() != HALIGN_LEFT) {
-			if ((*rv->rbegin())->halign() == HALIGN_CENTER) {
+		if (!rv->empty() && (*rv->rbegin())->halign() != UI::Align::Align_Left) {
+			if ((*rv->rbegin())->halign() == UI::Align::Align_Center) {
 				rem_space /= 2;  // Otherwise, we align right
 			}
 			for (RenderNode* node : *rv)  {
@@ -231,7 +241,7 @@
  * Take ownership of all nodes, delete those that we do not render anyways (for
  * example unneeded spaces), append the rest to the vector we got.
  */
-uint16_t Layout::fit_nodes(vector<RenderNode*>& rv, uint16_t w, Borders p) {
+uint16_t Layout::fit_nodes(vector<RenderNode*>& rv, uint16_t w, Borders p, bool shrink_to_fit) {
 	assert(rv.empty());
 	m_h = p.top;
 
@@ -239,21 +249,26 @@
 	while (m_idx < m_all_nodes.size()) {
 		vector<RenderNode*> nodes_in_line;
 		size_t m_idx_before_iteration = m_idx;
-		uint16_t biggest_hotspot = m_fit_line(w, p, &nodes_in_line);
+		uint16_t biggest_hotspot = m_fit_line(w, p, &nodes_in_line, shrink_to_fit);
 
 		int line_height = 0;
+		int line_start = INFINITE_WIDTH;
+		// Compute real line height and width, taking into account alignement
 		for (RenderNode* n : nodes_in_line) {
 			line_height = max(line_height, biggest_hotspot - n->hotspot_y() + n->height());
 			n->set_y(m_h + biggest_hotspot - n->hotspot_y());
-			max_line_width = max<int>(max_line_width, n->x() + n->width() + p.right);
+			if (line_start >= INFINITE_WIDTH || n->x() < line_start) {
+				line_start = n->x() - p.left;
+			}
+			max_line_width = std::max<int>(max_line_width, n->x() + n->width() + p.right - line_start);
 		}
 
 		// Go over again and adjust position for VALIGN
 		for (RenderNode* n : nodes_in_line) {
 			uint16_t space = line_height - n->height();
-			if (!space || n->valign() == VALIGN_BOTTOM)
+			if (!space || n->valign() == UI::Align::Align_Bottom)
 				continue;
-			if (n->valign() == VALIGN_CENTER)
+			if (n->valign() == UI::Align::Align_Center)
 				space /= 2;
 			n->set_y(n->y() - space);
 		}
@@ -642,17 +657,19 @@
 		ns->font_style &= ~IFont::ITALIC;
 	}
 
-	FontDescr fd = {ns->font_face, ns->font_size};
+	uint16_t font_size = ns->font_size + ns->fontset->size_offset();
+
+	FontDescr fd = {ns->font_face, font_size};
 	FontMap::iterator i = m_fontmap.find(fd);
 	if (i != m_fontmap.end())
 		return *i->second;
 
 	std::unique_ptr<IFont> font;
 	try {
-		font.reset(load_font(ns->font_face, ns->font_size));
+		font.reset(load_font(ns->font_face, font_size));
 	} catch (FileNotFoundError& e) {
 		log("Font file not found. Falling back to serif: %s\n%s\n", ns->font_face.c_str(), e.what());
-		font.reset(load_font(ns->fontset->serif(), ns->font_size));
+		font.reset(load_font(ns->fontset->serif(), font_size));
 	}
 	assert(font != nullptr);
 
@@ -660,12 +677,15 @@
 }
 
 class TagHandler;
-TagHandler* create_taghandler(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache);
+TagHandler* create_taghandler(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache,
+										RendererStyle& renderer_style);
 
 class TagHandler {
 public:
-	TagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache) :
-		m_tag(tag), font_cache_(fc), m_ns(ns), image_cache_(image_cache) {}
+	TagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+				  RendererStyle& renderer_style_) :
+		m_tag(tag), font_cache_(fc), m_ns(ns), image_cache_(image_cache),
+		renderer_style(renderer_style_) {}
 	virtual ~TagHandler() {}
 
 	virtual void enter() {}
@@ -679,26 +699,72 @@
 	FontCache& font_cache_;
 	NodeStyle m_ns;
 	ImageCache* image_cache_;  // Not owned
+	RendererStyle& renderer_style; // Reference to global renderer style in the renderer
 };
 
 void TagHandler::m_make_text_nodes(const string& txt, vector<RenderNode*>& nodes, NodeStyle& ns) {
 	TextStream ts(txt);
-
-	while (ts.pos() < txt.size()) {
-		size_t cpos = ts.pos();
-		ts.skip_ws();
-		if (ts.pos() != cpos)
-			nodes.push_back(new WordSpacerNode(font_cache_.get_font(&ns), ns));
-		const string word = ts.till_any_or_end(" \t\n\r");
-		if (word.size())
-			nodes.push_back(new TextNode(font_cache_.get_font(&ns), ns, word));
+	std::string word;
+	std::vector<RenderNode*> text_nodes;
+
+	// Bidirectional text (Arabic etc.)
+	if (i18n::has_rtl_character(txt.c_str())) {
+		std::string previous_word;
+		std::vector<RenderNode*>::iterator it = text_nodes.begin();
+
+		// Collect the word nodes
+		while (ts.pos() < txt.size()) {
+			ts.skip_ws();
+			word = ts.till_any_or_end(" \t\n\r");
+			if (!word.empty()) {
+				bool word_is_bidi = i18n::has_rtl_character(word.c_str());
+				word = i18n::make_ligatures(word.c_str());
+				if (word_is_bidi || i18n::has_rtl_character(previous_word.c_str())) {
+					if (!previous_word.empty()) {
+						text_nodes.insert(text_nodes.begin(), new WordSpacerNode(font_cache_.get_font(&ns), ns));
+					}
+					if (word_is_bidi) {
+						word = i18n::line2bidi(word.c_str());
+					}
+					it = text_nodes.insert(text_nodes.begin(),
+												  new TextNode(font_cache_.get_font(&ns), ns, word.c_str()));
+				} else { // Sequences of Latin words go to the right from current position
+					if (it < text_nodes.end()) {
+						++it;
+					}
+					if (!previous_word.empty()) {
+						it = text_nodes.insert(it, new WordSpacerNode(font_cache_.get_font(&ns), ns));
+					}
+					it = text_nodes.insert(it, new TextNode(font_cache_.get_font(&ns), ns, word));
+				}
+			}
+			previous_word = word;
+		}
+		// Add the nodes to the end of the previously existing nodes.
+		for (RenderNode* node : text_nodes) {
+			nodes.push_back(node);
+		}
+
+	} else {  // LTR
+		while (ts.pos() < txt.size()) {
+			std::size_t cpos = ts.pos();
+			ts.skip_ws();
+			if (ts.pos() != cpos) {
+				nodes.push_back(new WordSpacerNode(font_cache_.get_font(&ns), ns));
+			}
+			word = ts.till_any_or_end(" \t\n\r");
+			if (!word.empty()) {
+				nodes.push_back(new TextNode(font_cache_.get_font(&ns), ns, i18n::make_ligatures(word.c_str())));
+			}
+		}
 	}
 }
 
 void TagHandler::emit(vector<RenderNode*>& nodes) {
 	for (Child* c : m_tag.childs()) {
 		if (c->tag) {
-			std::unique_ptr<TagHandler> th(create_taghandler(*c->tag, font_cache_, m_ns, image_cache_));
+			std::unique_ptr<TagHandler> th(create_taghandler(*c->tag, font_cache_, m_ns, image_cache_,
+																			 renderer_style));
 			th->enter();
 			th->emit(nodes);
 		} else
@@ -708,8 +774,9 @@
 
 class FontTagHandler : public TagHandler {
 public:
-	FontTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache)
-		: TagHandler(tag, fc, ns, image_cache) {}
+	FontTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+						RendererStyle& init_renderer_style)
+		: TagHandler(tag, fc, ns, image_cache, init_renderer_style) {}
 
 	void enter() override {
 		const AttrMap& a = m_tag.attrs();
@@ -726,35 +793,47 @@
 
 class PTagHandler : public TagHandler {
 public:
-	PTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache)
-		: TagHandler(tag, fc, ns, image_cache), m_indent(0) {
+	PTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+					RendererStyle& init_renderer_style)
+		: TagHandler(tag, fc, ns, image_cache, init_renderer_style), m_indent(0) {
 	}
 
 	void enter() override {
 		const AttrMap& a = m_tag.attrs();
 		if (a.has("indent")) m_indent = a["indent"].get_int();
 		if (a.has("align")) {
-			const string align = a["align"].get_string();
-			if (align == "left") m_ns.halign = HALIGN_LEFT;
-			else if (align == "right") m_ns.halign = HALIGN_RIGHT;
-			else if (align == "center" || align == "middle") m_ns.halign = HALIGN_CENTER;
+			const std::string align = a["align"].get_string();
+			if (align == "right") {
+				m_ns.halign = UI::Align::Align_Left;
+			} else if (align == "center" || align == "middle") {
+				m_ns.halign = UI::Align::Align_Center;
+			} else {
+				m_ns.halign = UI::Align::Align_Right;
+			}
 		}
+		m_ns.halign = mirror_alignment(m_ns.halign);
 		if (a.has("valign")) {
 			const string align = a["valign"].get_string();
-			if (align == "top") m_ns.valign = VALIGN_TOP;
-			else if (align == "bottom") m_ns.valign = VALIGN_BOTTOM;
-			else if (align == "center" || align == "middle") m_ns.valign = VALIGN_CENTER;
+			if (align == "bottom") {
+				m_ns.valign = UI::Align::Align_Bottom;
+			} else if (align == "center" || align == "middle") {
+				m_ns.valign = UI::Align::Align_Center;
+			} else {
+				m_ns.valign = UI::Align::Align_Top;
+			}
 		}
 		if (a.has("spacing"))
 			m_ns.spacing = a["spacing"].get_int();
 	}
 	void emit(vector<RenderNode*>& nodes) override {
+		// Put a newline if this is not the first paragraph
+		if (!nodes.empty()) {
+			nodes.push_back(new NewlineNode(m_ns));
+		}
 		if (m_indent) {
 			nodes.push_back(new SpaceNode(m_ns, m_indent));
 		}
 		TagHandler::emit(nodes);
-
-		nodes.push_back(new NewlineNode(m_ns));
 	}
 
 private:
@@ -763,8 +842,9 @@
 
 class ImgTagHandler : public TagHandler {
 public:
-	ImgTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache) :
-		TagHandler(tag, fc, ns, image_cache), m_rn(nullptr) {
+	ImgTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+					  RendererStyle& init_renderer_style) :
+		TagHandler(tag, fc, ns, image_cache, init_renderer_style), m_rn(nullptr) {
 	}
 
 	void enter() override {
@@ -781,8 +861,9 @@
 
 class VspaceTagHandler : public TagHandler {
 public:
-	VspaceTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache) :
-		TagHandler(tag, fc, ns, image_cache), m_space(0) {}
+	VspaceTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+						  RendererStyle& init_renderer_style) :
+		TagHandler(tag, fc, ns, image_cache, init_renderer_style), m_space(0) {}
 
 	void enter() override {
 		const AttrMap& a = m_tag.attrs();
@@ -800,8 +881,9 @@
 
 class HspaceTagHandler : public TagHandler {
 public:
-	HspaceTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache) :
-		TagHandler(tag, fc, ns, image_cache), m_bg(nullptr), m_space(0) {}
+	HspaceTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+						  RendererStyle& init_renderer_style) :
+		TagHandler(tag, fc, ns, image_cache, init_renderer_style), m_bg(nullptr), m_space(0) {}
 
 	void enter() override {
 		const AttrMap& a = m_tag.attrs();
@@ -851,8 +933,9 @@
 
 class BrTagHandler : public TagHandler {
 public:
-	BrTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache) :
-		TagHandler(tag, fc, ns, image_cache) {
+	BrTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+					 RendererStyle& init_renderer_style) :
+		TagHandler(tag, fc, ns, image_cache, init_renderer_style) {
 	}
 
 	void emit(vector<RenderNode*>& nodes) override {
@@ -865,9 +948,10 @@
 public:
 	SubTagHandler
 		(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
-		 uint16_t max_w = 0, bool shrink_to_fit = false)
+		 RendererStyle& init_renderer_style,
+		 uint16_t max_w = 0, bool shrink_to_fit = true)
 		:
-			TagHandler(tag, fc, ns, image_cache),
+			TagHandler(tag, fc, ns, image_cache, init_renderer_style),
 			shrink_to_fit_(shrink_to_fit),
 			m_w(max_w),
 			m_rn(new SubTagRenderNode(ns))
@@ -915,17 +999,34 @@
 		// Layout takes ownership of subnodes
 		Layout layout(subnodes);
 		vector<RenderNode*> nodes_to_render;
-		uint16_t max_line_width = layout.fit_nodes(nodes_to_render, m_w, padding);
-		if (shrink_to_fit_) {
-			m_w = min(m_w, max_line_width);
+		uint16_t max_line_width = layout.fit_nodes(nodes_to_render, m_w, padding, shrink_to_fit_);
+		uint16_t m_extra_width = 0;
+		if (m_w < INFINITE_WIDTH && m_w > max_line_width) {
+			m_extra_width = m_w - max_line_width;
 		}
 
 		// Collect all tags from children
 		for (RenderNode* rn : nodes_to_render) {
 			for (const Reference& r : rn->get_references()) {
-			m_rn->add_reference(rn->x() + r.dim.x, rn->y() + r.dim.y, r.dim.w, r.dim.h, r.ref);
-		}
-	}
+				m_rn->add_reference(rn->x() + r.dim.x, rn->y() + r.dim.y, r.dim.w, r.dim.h, r.ref);
+			}
+			if (shrink_to_fit_) {
+				if (rn->halign() == UI::Align::Align_Center) {
+					rn->set_x(rn->x() - m_extra_width / 2);
+				} else if (rn->halign() == UI::Align::Align_Right) {
+					rn->set_x(rn->x() - m_extra_width);
+				}
+			}
+		}
+		if (shrink_to_fit_ || m_w >= INFINITE_WIDTH) {
+			m_w = max_line_width;
+		}
+
+		if (renderer_style.remaining_width >= m_w) {
+			renderer_style.remaining_width -= m_w;
+		} else {
+			renderer_style.remaining_width = renderer_style.overall_width;
+		}
 
 		m_rn->set_dimensions(m_w, layout.height(), margin);
 		m_rn->set_nodes_to_render(nodes_to_render);
@@ -938,7 +1039,17 @@
 	virtual void handle_unique_attributes() {
 		const AttrMap& a = m_tag.attrs();
 		if (a.has("width")) {
-			m_w = a["width"].get_int();
+			std::string width_string = a["width"].get_string();
+			if (width_string == "*") {
+				m_w = renderer_style.remaining_width;
+			} else if (boost::algorithm::ends_with(width_string, "%")) {
+				width_string = width_string.substr(0, width_string.length() - 1);
+				uint8_t new_width_percent = strtol(width_string.c_str(), nullptr, 10);
+				m_w = floor(renderer_style.overall_width * new_width_percent / 100);
+				m_w = std::min(m_w, renderer_style.remaining_width);
+			} else {
+				m_w = a["width"].get_int();
+			}
 			shrink_to_fit_ = false;
 		}
 		if (a.has("float")) {
@@ -948,12 +1059,11 @@
 		}
 		if (a.has("valign")) {
 			const string align = a["valign"].get_string();
-			if (align == "top") m_rn->set_valign(VALIGN_TOP);
-			else if (align == "bottom") m_rn->set_valign(VALIGN_BOTTOM);
-			else if (align == "center" || align == "middle") m_rn->set_valign(VALIGN_CENTER);
+			if (align == "top") m_rn->set_valign(UI::Align::Align_Top);
+			else if (align == "bottom") m_rn->set_valign(UI::Align::Align_Bottom);
+			else if (align == "center" || align == "middle") m_rn->set_valign(UI::Align::Align_Center);
 		}
 	}
-
 private:
 	bool shrink_to_fit_;
 	uint16_t m_w;
@@ -962,8 +1072,9 @@
 
 class RTTagHandler : public SubTagHandler {
 public:
-	RTTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache, uint16_t w) :
-		SubTagHandler(tag, fc, ns, image_cache, w, true) {
+	RTTagHandler(Tag& tag, FontCache& fc, NodeStyle ns, ImageCache* image_cache,
+					 RendererStyle& init_renderer_style, uint16_t w) :
+		SubTagHandler(tag, fc, ns, image_cache, init_renderer_style, w, true) {
 	}
 
 	// Handle attributes that are in rt, but not in sub.
@@ -974,14 +1085,17 @@
 };
 
 template<typename T> TagHandler* create_taghandler
-	(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache)
+	(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache,
+	 RendererStyle& renderer_style)
 {
-	return new T(tag, fc, ns, image_cache);
+	return new T(tag, fc, ns, image_cache, renderer_style);
 }
 using TagHandlerMap = map<const string, TagHandler* (*)
-	(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache)>;
+	(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache,
+	 RendererStyle& renderer_style)>;
 
-TagHandler* create_taghandler(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache) {
+TagHandler* create_taghandler(Tag& tag, FontCache& fc, NodeStyle& ns, ImageCache* image_cache,
+										RendererStyle& renderer_style) {
 	static TagHandlerMap map;
 	if (map.empty()) {
 		map["br"] = &create_taghandler<BrTagHandler>;
@@ -997,12 +1111,15 @@
 		throw RenderError
 			((boost::format("No Tag handler for %s. This is a bug, please submit a report.")
 			  % tag.name()).str());
-	return i->second(tag, fc, ns, image_cache);
+	return i->second(tag, fc, ns, image_cache, renderer_style);
 }
 
 Renderer::Renderer(ImageCache* image_cache, TextureCache* texture_cache, UI::FontSet* fontset) :
 	font_cache_(new FontCache()), parser_(new Parser()),
-	image_cache_(image_cache), texture_cache_(texture_cache), fontset_(fontset) {
+	image_cache_(image_cache), texture_cache_(texture_cache), fontset_(fontset),
+	renderer_style_(fontset->serif(), 16, INFINITE_WIDTH, INFINITE_WIDTH) {
+	TextureCache* render
+		(const std::string&, uint16_t, const TagSet&);
 }
 
 Renderer::~Renderer() {
@@ -1011,16 +1128,22 @@
 RenderNode* Renderer::layout_(const string& text, uint16_t width, const TagSet& allowed_tags) {
 	std::unique_ptr<Tag> rt(parser_->parse(text, allowed_tags));
 
+	if (!width) {
+		width = INFINITE_WIDTH;
+	}
+
+	renderer_style_.remaining_width = width;
+	renderer_style_.overall_width = width;
+
 	NodeStyle default_style = {
-		fontset_, fontset_->serif(), 16,
-		RGBColor(0, 0, 0), IFont::DEFAULT, 0, HALIGN_LEFT, VALIGN_BOTTOM,
+		fontset_,
+		renderer_style_.font_face, renderer_style_.font_size,
+		RGBColor(255, 255, 0), IFont::DEFAULT, fontset_->is_rtl(), 0,
+		UI::Align::Align_Left, UI::Align::Align_Top,
 		""
 	};
 
-	if (!width)
-		width = INFINITE_WIDTH;
-
-	RTTagHandler rtrn(*rt, *font_cache_, default_style, image_cache_, width);
+	RTTagHandler rtrn(*rt, *font_cache_, default_style, image_cache_, renderer_style_, width);
 	vector<RenderNode*> nodes;
 	rtrn.enter();
 	rtrn.emit(nodes);

=== modified file 'src/graphic/text/rt_render.h'
--- src/graphic/text/rt_render.h	2014-12-11 12:25:59 +0000
+++ src/graphic/text/rt_render.h	2015-09-26 18:15:59 +0000
@@ -40,6 +40,18 @@
 class Parser;
 class RenderNode;
 
+struct RendererStyle {
+	RendererStyle(const std::string& font_face_, uint8_t font_size_,
+						  uint16_t remaining_width_, uint16_t overall_width_) :
+		font_face(font_face_), font_size(font_size_),
+		remaining_width(remaining_width_), overall_width(overall_width_) {}
+
+	std::string font_face;
+	uint8_t font_size;
+	uint16_t remaining_width;
+	uint16_t overall_width;
+};
+
 /**
  * Wrapper object around a font.
  *
@@ -104,6 +116,7 @@
 	ImageCache* const image_cache_;  // Not owned.
 	TextureCache* const texture_cache_;  // Not owned.
 	UI::FontSet* const fontset_;  // Not owned.
+	RendererStyle renderer_style_; // Properties that all render nodes need to know about
 };
 
 }

=== modified file 'src/graphic/text_layout.cc'
--- src/graphic/text_layout.cc	2015-05-30 12:19:57 +0000
+++ src/graphic/text_layout.cc	2015-09-26 18:15:59 +0000
@@ -26,6 +26,7 @@
 
 #include "base/utf8.h"
 #include "graphic/font_handler1.h"
+#include "graphic/text/bidi.h"
 #include "graphic/text/font_set.h"
 #include "graphic/text_constants.h"
 
@@ -99,6 +100,7 @@
 {
 	int w, h;
 	setup();
+
 	TTF_SizeUTF8(font->get_ttf_font(), text.c_str(), &w, &h);
 	return w;
 }

=== modified file 'src/graphic/text_parser.cc'
--- src/graphic/text_parser.cc	2014-12-06 12:22:35 +0000
+++ src/graphic/text_parser.cc	2015-09-26 18:15:59 +0000
@@ -26,6 +26,7 @@
 
 #include "base/log.h"
 #include "graphic/font_handler1.h"
+#include "graphic/text/bidi.h"
 #include "graphic/text/font_set.h"
 #include "helper.h"
 
@@ -120,6 +121,7 @@
 	//Handle user defined line breaks, and save them
 	for (const std::string& temp_words : unwrapped_words) {
 		for (std::string line = temp_words;;) {
+			line = i18n::make_ligatures(line.c_str());
 			std::string::size_type next_break = line.find("<br>");
 
 			// Replace &lt; with <

=== modified file 'src/graphic/wordwrap.cc'
--- src/graphic/wordwrap.cc	2014-06-01 18:00:48 +0000
+++ src/graphic/wordwrap.cc	2015-09-26 18:15:59 +0000
@@ -25,7 +25,9 @@
 
 #include "base/log.h"
 #include "graphic/font_handler.h"
+#include "graphic/font_handler1.h"
 #include "graphic/rendertarget.h"
+#include "graphic/text/bidi.h"
 
 namespace UI {
 
@@ -127,8 +129,11 @@
 		return;
 	}
 
+
 	// Optimism: perhaps the entire line fits?
-	if (m_style.calc_bare_width(text.substr(line_start, orig_end - line_start)) <= m_wrapwidth) {
+	// TODO(GunChleoc): Arabic Multiple calls of make_ligatures are inefficient.
+	if (m_style.calc_bare_width(i18n::make_ligatures(text.substr(line_start, orig_end - line_start).c_str()))
+		 <= m_wrapwidth) {
 		line_end = orig_end;
 		next_line_start = orig_end + 1;
 		return;
@@ -145,7 +150,8 @@
 	while (end_upper - end_lower > 4) {
 		std::string::size_type mid = end_lower + (end_upper - end_lower + 1) / 2;
 
-		if (m_style.calc_bare_width(text.substr(line_start, mid - line_start)) <= m_wrapwidth) {
+		if (m_style.calc_bare_width(i18n::make_ligatures(text.substr(line_start, mid - line_start).c_str()))
+			 <= m_wrapwidth) {
 			end_lower = mid;
 		} else {
 			end_upper = mid - 1;
@@ -165,7 +171,9 @@
 			break; // we already know that this cannot possibly fit
 
 		// check whether the next word still fits
-		if (m_style.calc_bare_width(text.substr(line_start, nextspace - line_start)) > m_wrapwidth)
+		if (m_style.calc_bare_width(
+				 i18n::make_ligatures(text.substr(line_start, nextspace - line_start).c_str()))
+			 > m_wrapwidth)
 			break;
 
 		space = nextspace;
@@ -182,10 +190,12 @@
 	while (end_upper > end_lower) {
 		std::string::size_type mid = end_lower + (end_upper - end_lower + 1) / 2;
 
-		if (m_style.calc_bare_width(text.substr(line_start, mid - line_start)) <= m_wrapwidth)
+		if (m_style.calc_bare_width(i18n::make_ligatures(text.substr(line_start, mid - line_start).c_str()))
+			 <= m_wrapwidth) {
 			end_lower = mid;
-		else
+		} else {
 			end_upper = mid - 1;
+		}
 	}
 
 	next_line_start = line_end = end_lower;
@@ -283,8 +293,17 @@
 		if (where.y >= dst.height() || int32_t(where.y + fontheight) <= 0)
 			continue;
 
+		// Right-align text for RTL languages
+		// NOCOM(GunChleoc) we have a ragged edge here for Arabic,
+		// just like in richtext.cc - bug in TTF_SizeUTF8?
+		Point drawpos(UI::g_fh1->fontset().is_rtl() ?
+							  where.x + m_wrapwidth
+							  - m_style.calc_bare_width(i18n::make_ligatures(m_lines[line].text.c_str())) - 2 :
+							  where.x,
+						  where.y);
+
 		g_fh->draw_text
-			(dst, m_style, where, m_lines[line].text, Align(align & Align_Horizontal),
+			(dst, m_style, drawpos, m_lines[line].text.c_str(), Align(align & Align_Horizontal),
 			 line == caretline ? caretpos : std::numeric_limits<uint32_t>::max());
 	}
 }

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2015-09-09 18:49:58 +0000
+++ src/ui_basic/button.cc	2015-09-26 18:15:59 +0000
@@ -33,7 +33,7 @@
 // Margin around image. The image will be scaled down to fit into this rectangle with preserving size.
 constexpr int kButtonImageMargin = 2;
 
-Button::Button //  for textual buttons
+Button::Button //  for textual buttons. If h = 0, h will resize according to the font's height.
 	(Panel * const parent,
 	 const std::string & name,
 	 int32_t const x, int32_t const y, uint32_t const w, uint32_t const h,
@@ -58,6 +58,11 @@
 	m_clr_down      (229, 161, 2),
 	m_draw_caret    (false)
 {
+	// Automatically resize for font height and give it a margin.
+	if (h < 1) {
+		int new_height = m_textstyle.font->height() + 4;
+		set_desired_size(w, new_height);
+	}
 	set_thinks(false);
 }
 

=== modified file 'src/ui_basic/editbox.cc'
--- src/ui_basic/editbox.cc	2014-11-27 16:43:37 +0000
+++ src/ui_basic/editbox.cc	2015-09-26 18:15:59 +0000
@@ -30,6 +30,8 @@
 #include "graphic/text_constants.h"
 #include "ui_basic/mouse_constants.h"
 
+// NOCOM Fix positioning for Arabic
+
 namespace UI {
 
 struct EditBoxImpl {

=== modified file 'src/ui_basic/listselect.cc'
--- src/ui_basic/listselect.cc	2014-12-06 12:22:35 +0000
+++ src/ui_basic/listselect.cc	2015-09-26 18:15:59 +0000
@@ -136,14 +136,11 @@
 	er->name    = name;
 	er->tooltip = tooltip_text;
 	er->font_face = fontname;
-	uint32_t entry_height = 0;
-	if (!pic) {
-		entry_height = g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
-	} else {
+	uint32_t entry_height = g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
+	if (pic) {
 		uint16_t w = pic->width();
 		uint16_t h = pic->height();
-		entry_height = (h >= g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize))
-			? h : g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
+		entry_height = (h >= entry_height) ? h : entry_height;
 		if (m_max_pic_width < w)
 			m_max_pic_width = w;
 	}
@@ -155,7 +152,7 @@
 
 	m_scrollbar.set_steps(m_entry_records.size() * get_lineheight() - get_h());
 
-	update(0, 0, get_eff_w(), get_h());
+	update(0, 0, get_w(), get_h());
 
 	if (sel)
 		select(m_entry_records.size() - 1);
@@ -181,14 +178,11 @@
 	er->tooltip = tooltip_text;
 	er->font_face = fontname;
 
-	uint32_t entry_height = 0;
-	if (!pic)
-		entry_height = g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
-	else {
+	uint32_t entry_height = g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
+	if (pic) {
 		uint16_t w = pic->width();
 		uint16_t h = pic->height();
-		entry_height = (h >= g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize))
-			? h : g_fh->get_fontheight(fontname.empty() ? m_fontname : fontname, m_fontsize);
+		entry_height = (h >= entry_height) ? h : entry_height;
 		if (m_max_pic_width < w)
 			m_max_pic_width = w;
 	}
@@ -200,7 +194,7 @@
 
 	m_scrollbar.set_steps(m_entry_records.size() * get_lineheight() - get_h());
 
-	update(0, 0, get_eff_w(), get_h());
+	update(0, 0, get_w(), get_h());
 
 	if (sel)
 		select(0);
@@ -261,7 +255,7 @@
 
 	m_scrollpos = i;
 
-	update(0, 0, get_eff_w(), get_h());
+	update(0, 0, get_w(), get_h());
 }
 
 
@@ -297,7 +291,7 @@
 	m_selection = i;
 
 	selected(m_selection);
-	update(0, 0, get_eff_w(), get_h());
+	update(0, 0, get_w(), get_h());
 }
 
 /**
@@ -345,7 +339,7 @@
 
 uint32_t BaseListselect::get_eff_w() const
 {
-	return get_w();
+	return m_scrollbar.is_enabled() ? get_w() - m_scrollbar.get_w() : get_w();
 }
 
 /**
@@ -388,29 +382,30 @@
 			}
 		}
 
+		Align draw_alignment = mirror_alignment(m_align);
 
 		int32_t const x =
-			m_align & Align_Right   ? get_eff_w() -      1 :
-			m_align & Align_HCenter ? get_eff_w() >>     1 :
+			draw_alignment & Align_Right   ? get_eff_w() -      1 :
+			draw_alignment & Align_HCenter ? get_eff_w() >>     1 :
 
 			// Pictures are always left aligned, leave some space here
 			m_max_pic_width         ? m_max_pic_width + 10 :
 			1;
 
+		std::string font_face = er.font_face.empty() ? m_fontname : er.font_face;
+
 		// Horizontal center the string
 		UI::g_fh->draw_text
 			(dst,
-			 TextStyle::makebold(Font::get(er.font_face.empty() ? m_fontname : er.font_face, m_fontsize),
-										er.use_clr ? er.clr : UI_FONT_CLR_FG),
+			 TextStyle::makebold(Font::get(font_face, m_fontsize), er.use_clr ? er.clr : UI_FONT_CLR_FG),
 			 Point
 			 	(x,
 			 	 y +
-				 (get_lineheight() - g_fh->get_fontheight(er.font_face.empty() ? m_fontname : er.font_face,
-																		m_fontsize))
+				 (get_lineheight() - g_fh->get_fontheight(font_face, m_fontsize))
 			 	 /
 			 	 2),
 			 er.name,
-			 m_align);
+			 draw_alignment);
 
 		// Now draw pictures
 		if (er.pic) {

=== modified file 'src/ui_basic/multilineeditbox.cc'
--- src/ui_basic/multilineeditbox.cc	2014-11-27 12:02:08 +0000
+++ src/ui_basic/multilineeditbox.cc	2015-09-26 18:15:59 +0000
@@ -28,6 +28,8 @@
 #include "graphic/wordwrap.h"
 #include "ui_basic/scrollbar.h"
 
+// NOCOM Fix positioning for Arabic
+
 namespace UI {
 
 static const int32_t ms_darken_value = -20;

=== modified file 'src/ui_basic/scrollbar.cc'
--- src/ui_basic/scrollbar.cc	2014-11-22 10:18:20 +0000
+++ src/ui_basic/scrollbar.cc	2015-09-26 18:15:59 +0000
@@ -83,6 +83,11 @@
 }
 
 
+bool Scrollbar::is_enabled() const {
+	return m_steps != 1 || m_force_draw;
+}
+
+
 /**
  * \return the number of steps
  */
@@ -309,8 +314,9 @@
 	uint32_t knobpos = get_knob_pos();
 	uint32_t knobsize = get_knob_size();
 
-	if (m_steps == 1 && !m_force_draw)
+	if (!is_enabled()) {
 		return; // don't draw a not doing scrollbar
+	}
 
 	if (m_horizontal) {
 		if ((2 * Size + knobsize) > static_cast<uint32_t>(get_w())) {

=== modified file 'src/ui_basic/scrollbar.h'
--- src/ui_basic/scrollbar.h	2014-10-27 08:37:54 +0000
+++ src/ui_basic/scrollbar.h	2015-09-26 18:15:59 +0000
@@ -57,6 +57,7 @@
 	void set_pagesize(int32_t pagesize);
 	void set_scrollpos(int32_t pos);
 
+	bool is_enabled() const;
 	uint32_t get_steps() const;
 	uint32_t get_singlestepsize() const {return m_singlestepsize;}
 	uint32_t get_pagesize() const {return m_pagesize;}

=== modified file 'src/ui_basic/table.cc'
--- src/ui_basic/table.cc	2014-12-06 12:22:35 +0000
+++ src/ui_basic/table.cc	2015-09-26 18:15:59 +0000
@@ -52,7 +52,7 @@
 	m_total_width     (0),
 	m_fontname        (UI::g_fh1->fontset().serif()),
 	m_fontsize        (UI_FONT_SIZE_SMALL),
-	m_headerheight    (UI_FONT_SIZE_SMALL * 8 / 5),
+	m_headerheight    (g_fh->get_fontheight(m_fontname, m_fontsize) + 4),
 	m_lineheight      (g_fh->get_fontheight(m_fontname, m_fontsize)),
 	m_scrollbar       (nullptr),
 	m_scrollpos       (0),
@@ -246,6 +246,18 @@
 	m_last_selection = no_selection_index();
 }
 
+
+void Table<void *>::fit_height(uint32_t entries) {
+	if (entries == 0) {
+		entries = size();
+	}
+	uint32_t tablewidth;
+	uint32_t tableheight;
+	get_desired_size(tablewidth, tableheight);
+	tableheight = m_headerheight + 2 + get_lineheight() * entries;
+	set_desired_size(tablewidth, tableheight);
+}
+
 /**
  * Redraw the table
 */
@@ -275,7 +287,7 @@
 		for (uint32_t i = 0, curx = 0; i < nr_columns; ++i) {
 			const Column & column    = m_columns[i];
 			uint32_t const curw      = column.width;
-			Align    const alignment = column.alignment;
+			Align alignment = mirror_alignment(column.alignment);
 
 			const Image* entry_picture = er.get_picture(i);
 			const std::string &       entry_string  = er.get_string (i);

=== modified file 'src/ui_basic/table.h'
--- src/ui_basic/table.h	2014-11-02 20:06:17 +0000
+++ src/ui_basic/table.h	2015-09-26 18:15:59 +0000
@@ -240,6 +240,10 @@
 	uint32_t get_lineheight() const {return m_lineheight + 2;}
 	uint32_t get_eff_w     () const {return get_w();}
 
+	/// Adjust the desired size to fit the height needed for the number of entries.
+	/// If entries == 0, the current entries are used.
+	void fit_height(uint32_t entries = 0);
+
 	// Drawing and event handling
 	void draw(RenderTarget &) override;
 	bool handle_mousepress  (uint8_t btn, int32_t x, int32_t y) override;

=== modified file 'src/ui_fsmenu/loadgame.cc'
--- src/ui_fsmenu/loadgame.cc	2015-09-04 11:03:41 +0000
+++ src/ui_fsmenu/loadgame.cc	2015-09-26 18:15:59 +0000
@@ -45,6 +45,7 @@
 #include "ui_basic/icon.h"
 #include "ui_basic/messagebox.h"
 
+// TODO(GunChleoc): Arabic line height broken for descriptions for Arabic.
 namespace {
 
 // This function concatenates the filename and localized map name for a savegame/replay.

=== modified file 'src/ui_fsmenu/mapselect.cc'
--- src/ui_fsmenu/mapselect.cc	2015-08-06 17:14:34 +0000
+++ src/ui_fsmenu/mapselect.cc	2015-09-26 18:15:59 +0000
@@ -34,6 +34,9 @@
 #include "map_io/widelands_map_loader.h"
 #include "ui_basic/box.h"
 
+// TODO(GunChleoc): Arabic line height broken for descriptions for Arabic.
+// Fix align for table headings & entries and for wordwrap.
+
 using Widelands::WidelandsMapLoader;
 
 FullscreenMenuMapSelect::FullscreenMenuMapSelect

=== modified file 'src/ui_fsmenu/options.cc'
--- src/ui_fsmenu/options.cc	2015-09-03 07:12:49 +0000
+++ src/ui_fsmenu/options.cc	2015-09-26 18:15:59 +0000
@@ -33,6 +33,7 @@
 #include "graphic/default_resolution.h"
 #include "graphic/font_handler1.h"
 #include "graphic/graphic.h"
+#include "graphic/text/bidi.h"
 #include "graphic/text/font_set.h"
 #include "graphic/text_constants.h"
 #include "helper.h"
@@ -91,6 +92,7 @@
 
 }  // namespace
 
+// TODO(GunChleoc): Arabic This doesn't fit the window in Arabic.
 FullscreenMenuOptions::FullscreenMenuOptions
 		(OptionsCtrl::OptionsStruct opt)
 	:
@@ -433,9 +435,10 @@
 				std::unique_ptr<LuaTable> table = all_locales->get_table(localename);
 				table->do_not_warn_about_unaccessed_keys();
 
-				const std::string name = table->get_string("name");
+				std::string name = i18n::make_ligatures(table->get_string("name").c_str());
 				const std::string sortname = table->get_string("sort_name");
 				std::unique_ptr<UI::FontSet> fontset(new UI::FontSet(localename));
+
 				entries.push_back(LanguageEntry(localename, name, sortname, fontset->serif()));
 
 				if (localename == current_locale) {

=== modified file 'src/wui/game_options_menu.cc'
--- src/wui/game_options_menu.cc	2015-08-06 17:14:34 +0000
+++ src/wui/game_options_menu.cc	2015-09-26 18:15:59 +0000
@@ -32,19 +32,25 @@
 #include "wui/game_options_sound_menu.h"
 #include "wui/unique_window_handler.h"
 
+#define width 200
+#define margin 10
+#define vspacing 5
+#define vgap 3
+
 class GameOptionsMenuExitConfirmBox : public UI::WLMessageBox {
 public:
+	// TODO(GunChleoc): Arabic Buttons need more height for Arabic
 	GameOptionsMenuExitConfirmBox(UI::Panel& parent, InteractiveGameBase& gb)
 		: UI::WLMessageBox(&parent,
 								 /** TRANSLATORS: Window label when "Exit game" has been pressed */
 								 _("Exit Game Confirmation"),
 								 _("Are you sure you wish to exit this game?"),
 								 MBoxType::kOkCancel),
-		  m_gb(gb) {
+		  igb_(gb) {
 	}
 
 	void clicked_ok() override {
-		m_gb.end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
+		igb_.end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
 	}
 
 	void clicked_back() override {
@@ -52,7 +58,7 @@
 	}
 
 private:
-	InteractiveGameBase& m_gb;
+	InteractiveGameBase& igb_;
 };
 
 GameOptionsMenu::GameOptionsMenu
@@ -60,94 +66,87 @@
 	 UI::UniqueWindow::Registry               & registry,
 	 InteractiveGameBase::GameMainMenuWindows & windows)
 :
-	UI::UniqueWindow
-		(&gb, "options", &registry,
-		 145,
-		 vmargin()
-		 + 4 * (20 + vspacing()) + 2 * vgap() +
-		 35 + vspacing() + 35 +
-		 vmargin(),
-		 _("Options")),
-	m_gb(gb),
-	m_windows(windows),
-	readme
-		(this, "readme",
-		 posx(0, 1),
-		 vmargin() + 0 * (20 + vspacing()) + 0 * vgap(),
-		 buttonw(1), 20,
+	UI::UniqueWindow(&gb, "options", &registry, 2 * margin + width, 0, _("Options")),
+	igb_(gb),
+	windows_(windows),
+	box_(this, margin, margin, UI::Box::Vertical,
+		  width, get_h() - 2 * margin, vspacing),
+	readme_
+		(&box_, "readme",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but4.png"),
 		 _("README"),
 		/** TRANSLATORS: Button tooltip */
 		_("Show general information about Widelands and keyboard shortcuts")),
-	license
-		(this, "license",
-		 posx(0, 1),
-		 vmargin() + 1 * (20 + vspacing()) + 0 * vgap(),
-		 buttonw(1), 20,
+	license_
+		(&box_, "license",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but4.png"),
 		 _("License"),
 		/** TRANSLATORS: Button tooltip */
 		_("Show the distribution licence document")),
-	authors
-		(this, "authors",
-		 posx(0, 1),
-		 vmargin() + 2 * (20 + vspacing()) + 0 * vgap(),
-		 buttonw(1), 20,
+	authors_
+		(&box_, "authors",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but4.png"),
 		 _("Authors"),
 		/** TRANSLATORS: Button tooltip */
 		_("Show information about the Widelands Development Team")),
-	sound
-		(this, "sound_options",
-		 posx(0, 1),
-		 vmargin() + 3 * (20 + vspacing()) + 1 * vgap(),
-		 buttonw(1), 20,
+	sound_
+		(&box_, "sound_options",
+		 0, 0, width, 0,
 		 g_gr->images().get("pics/but4.png"),
 		 _("Sound Options"),
 		/** TRANSLATORS: Button tooltip */
 		_("Set sound effect and music options")),
-	save_game
-		(this, "save_game",
-		 posx(0, 1),
-		 vmargin() + 4 * (20 + vspacing()) + 2 * vgap(),
-		 buttonw(1), 35,
+	save_game_
+		(&box_, "save_game",
+		 0, 0, width, 35,
 		 g_gr->images().get("pics/but4.png"),
 		 g_gr->images().get("pics/menu_save_game.png"),
 		 /** TRANSLATORS: Button tooltip */
 		 _("Save Game")),
-	exit_game
-		(this, "exit_game",
-		 posx(0, 1),
-		 vmargin() + 4 * (20 + vspacing()) + 2 * vgap() +
-		 35 + vspacing(),
-		 buttonw(1), 35,
+	exit_game_
+		(&box_, "exit_game",
+		 0, 0, width, 35,
 		 g_gr->images().get("pics/but4.png"),
 		 g_gr->images().get("pics/menu_exit_game.png"),
 		 /** TRANSLATORS: Button tooltip */
 		 _("Exit Game"))
 {
-	readme.sigclicked.connect
-		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(m_windows.readme)));
-	license.sigclicked.connect
-		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(m_windows.license)));
-	authors.sigclicked.connect
-		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(m_windows.authors)));
-	sound.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_sound, boost::ref(*this)));
-	save_game.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_save_game, boost::ref(*this)));
-	exit_game.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_exit_game, boost::ref(*this)));
-
-
-	m_windows.readme.open_window = boost::bind
-		(&fileview_window, boost::ref(m_gb),
-		 boost::ref(m_windows.readme),
+	box_.add(&readme_, UI::Box::AlignCenter);
+	box_.add(&license_, UI::Box::AlignCenter);
+	box_.add(&authors_, UI::Box::AlignCenter);
+	box_.add_space(vgap);
+	box_.add(&sound_, UI::Box::AlignCenter);
+	box_.add_space(vgap);
+	box_.add(&save_game_, UI::Box::AlignCenter);
+	box_.add(&exit_game_, UI::Box::AlignCenter);
+	box_.set_size(width, 4 * readme_.get_h() + 2 * save_game_.get_h() + 2 * vgap + 7 * vspacing);
+	set_inner_size(get_inner_w(), box_.get_h() + 2 * margin);
+
+	readme_.sigclicked.connect
+		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.readme)));
+	license_.sigclicked.connect
+		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.license)));
+	authors_.sigclicked.connect
+		(boost::bind(&UI::UniqueWindow::Registry::toggle, boost::ref(windows_.authors)));
+	sound_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_sound, boost::ref(*this)));
+	save_game_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_save_game, boost::ref(*this)));
+	exit_game_.sigclicked.connect(boost::bind(&GameOptionsMenu::clicked_exit_game, boost::ref(*this)));
+
+
+	windows_.readme.open_window = boost::bind
+		(&fileview_window, boost::ref(igb_),
+		 boost::ref(windows_.readme),
 		 "txts/README.lua");
-	m_windows.license.open_window = boost::bind
-		(&fileview_window, boost::ref(m_gb),
-		 boost::ref(m_windows.license),
+	windows_.license.open_window = boost::bind
+		(&fileview_window, boost::ref(igb_),
+		 boost::ref(windows_.license),
 		 "txts/LICENSE.lua");
-	m_windows.authors.open_window = boost::bind
-		(&fileview_window, boost::ref(m_gb),
-		 boost::ref(m_windows.license),
+	windows_.authors.open_window = boost::bind
+		(&fileview_window, boost::ref(igb_),
+		 boost::ref(windows_.license),
 		 "txts/AUTHORS.lua");
 
 #define INIT_BTN_HOOKS(registry, btn)                                        \
@@ -155,38 +154,34 @@
  registry.on_delete = std::bind(&UI::Button::set_perm_pressed, &btn, false); \
  if (registry.window) btn.set_perm_pressed(true);                            \
 
-	INIT_BTN_HOOKS(m_windows.readme, readme)
-	INIT_BTN_HOOKS(m_windows.license, license)
-	INIT_BTN_HOOKS(m_windows.authors, authors)
-	INIT_BTN_HOOKS(m_windows.sound_options, sound)
+	INIT_BTN_HOOKS(windows_.readme, readme_)
+	INIT_BTN_HOOKS(windows_.license, license_)
+	INIT_BTN_HOOKS(windows_.authors, authors_)
+	INIT_BTN_HOOKS(windows_.sound_options, sound_)
 
-	set_inner_size
-		(hmargin() + hmargin() +
-		 std::max<int32_t>(get_inner_w(), readme.get_w()),
-		 get_inner_h());
 	if (get_usedefaultpos())
 		center_to_parent();
 }
 
 
 void GameOptionsMenu::clicked_sound() {
-	if (m_windows.sound_options.window)
-		delete m_windows.sound_options.window;
+	if (windows_.sound_options.window)
+		delete windows_.sound_options.window;
 	else
-		new GameOptionsSoundMenu(m_gb, m_windows.sound_options);
+		new GameOptionsSoundMenu(igb_, windows_.sound_options);
 }
 
 void GameOptionsMenu::clicked_save_game() {
-	new GameMainMenuSaveGame(m_gb, m_windows.savegame);
+	new GameMainMenuSaveGame(igb_, windows_.savegame);
 	die();
 }
 
 void GameOptionsMenu::clicked_exit_game() {
 	if (get_key_state(SDL_SCANCODE_LCTRL) || get_key_state(SDL_SCANCODE_RCTRL)) {
-		m_gb.end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
+		igb_.end_modal<UI::Panel::Returncodes>(UI::Panel::Returncodes::kBack);
 	}
 	else {
-		new GameOptionsMenuExitConfirmBox(*get_parent(), m_gb);
+		new GameOptionsMenuExitConfirmBox(*get_parent(), igb_);
 		die();
 	}
 }

=== modified file 'src/wui/game_options_menu.h'
--- src/wui/game_options_menu.h	2014-10-13 19:32:08 +0000
+++ src/wui/game_options_menu.h	2015-09-26 18:15:59 +0000
@@ -21,6 +21,7 @@
 #define WL_WUI_GAME_OPTIONS_MENU_H
 
 #include "wui/interactive_gamebase.h"
+#include "ui_basic/box.h"
 #include "ui_basic/button.h"
 #include "ui_basic/messagebox.h"
 #include "ui_basic/textarea.h"
@@ -35,36 +36,15 @@
 		 InteractiveGameBase::GameMainMenuWindows &);
 
 private:
-	InteractiveGameBase                         & m_gb;
-	InteractiveGameBase::GameMainMenuWindows & m_windows;
-	UI::Button readme;
-	UI::Button license;
-	UI::Button authors;
-	UI::Button sound;
-	UI::Button save_game;
-	UI::Button exit_game;
-
-	/** Returns the horizontal/vertical spacing between buttons. */
-	uint32_t hspacing() const {return 5;}
-	uint32_t vspacing() const {return 5;}
-
-	/** Returns the horizontal/vertical margin between edge and buttons. */
-	uint32_t hmargin() const {return 2 * hspacing();}
-	uint32_t vmargin() const {return 2 * vspacing();}
-	uint32_t vgap()    const {return 8;}
-
-	/** Returns the width of a button in a row with nr_buttons buttons. */
-	uint32_t buttonw(const uint32_t nr_buttons) const {
-		return
-			static_cast<uint32_t>
-			((get_inner_w() * 1.45 - (nr_buttons + 3) * hspacing()) / nr_buttons);
-	}
-
-	/// Returns the x coordinate of the (left edge of) button number nr in a row
-	/// with nr_buttons buttons.
-	uint32_t posx(uint32_t const nr, uint32_t const nr_buttons) const {
-		return hmargin() + nr * (buttonw(nr_buttons) + hspacing());
-	}
+	InteractiveGameBase& igb_;
+	InteractiveGameBase::GameMainMenuWindows& windows_;
+	UI::Box box_;
+	UI::Button readme_;
+	UI::Button license_;
+	UI::Button authors_;
+	UI::Button sound_;
+	UI::Button save_game_;
+	UI::Button exit_game_;
 
 	void clicked_sound    ();
 	void clicked_save_game();

=== modified file 'src/wui/game_summary.cc'
--- src/wui/game_summary.cc	2015-09-04 06:16:58 +0000
+++ src/wui/game_summary.cc	2015-09-26 18:15:59 +0000
@@ -40,7 +40,7 @@
 
 GameSummaryScreen::GameSummaryScreen
 	(InteractiveGameBase * parent, UI::UniqueWindow::Registry * r)
-: UI::UniqueWindow(parent, "game_summary", r, 550, 260, _("Game over")),
+: UI::UniqueWindow(parent, "game_summary", r, 0, 0, _("Game over")),
 m_game(parent->game())
 {
 	// Init boxes
@@ -50,44 +50,55 @@
 	vbox->add_space(PADDING);
 
 	UI::Box * hbox1 = new UI::Box(this, 0, 0, UI::Box::Horizontal);
-	m_players_table = new UI::Table<uintptr_t const>(hbox1, 0, 0, 150 + 80 + 100 + 100, 200);
+	m_players_table = new UI::Table<uintptr_t const>(hbox1, 0, 0, 0, 0);
+	m_players_table->fit_height(m_game.player_manager()->get_players_end_status().size());
 	hbox1->add_space(PADDING);
 	hbox1->add(m_players_table, UI::Box::AlignTop);
 	hbox1->add_space(PADDING);
 
-	UI::Box * infoBox = new UI::Box(hbox1, 0, 0, UI::Box::Vertical, 0, 0);
-	m_gametime_label = new UI::Textarea(infoBox, _("Elapsed time:"));
-	infoBox->add(m_gametime_label, UI::Box::AlignLeft);
-	m_gametime_value = new UI::Textarea(infoBox);
-	infoBox->add(m_gametime_value, UI::Box::AlignLeft);
-	infoBox->add_space(2 * PADDING);
-	m_info_area_label = new UI::Textarea(infoBox, _("Player info:"));
-	infoBox->add(m_info_area_label, UI::Box::AlignLeft);
-	m_info_area = new UI::MultilineTextarea(infoBox, 0, 0, 130, 130, "");
-	infoBox->add(m_info_area, UI::Box::AlignLeft, true);
-	infoBox->add_space(PADDING);
-	hbox1->add(infoBox, UI::Box::AlignTop);
+	UI::Box * info_box = new UI::Box(hbox1, 0, 0, UI::Box::Vertical, 0, 0);
+	m_info_area_label = new UI::Textarea(info_box, _("Player info:"));
+	info_box->add(m_info_area_label, UI::Box::AlignLeft);
+	m_info_area = new UI::MultilineTextarea(
+						  info_box, 0, 0, 130,
+						  std::max(130, m_players_table->get_h() - m_info_area_label->get_h() - PADDING),
+						  "");
+	info_box->add(m_info_area, UI::Box::AlignLeft, true);
+	info_box->add_space(PADDING);
+	hbox1->add(info_box, UI::Box::AlignTop);
 	hbox1->add_space(PADDING);
 	vbox->add(hbox1, UI::Box::AlignLeft);
 
-	UI::Box * buttonBox = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+	UI::Box * bottom_box = new UI::Box(this, 0, 0, UI::Box::Horizontal);
+
+	bottom_box->add_space(PADDING);
+
+	m_gametime_label = new UI::Textarea(bottom_box, _("Elapsed time:"));
+	bottom_box->add(m_gametime_label, UI::Box::AlignCenter);
+	bottom_box->add_space(PADDING);
+	m_gametime_value = new UI::Textarea(bottom_box, gametimestring(m_game.get_gametime()));
+	bottom_box->add(m_gametime_value, UI::Box::AlignCenter);
+
+	bottom_box->add_inf_space();
+
 	m_continue_button = new UI::Button
-		(buttonBox, "continue_button",
+		(bottom_box, "continue_button",
 		 0, 0, 35, 35,
 		 g_gr->images().get("pics/but4.png"),
 		 g_gr->images().get("pics/continue.png"),
 		 _("Continue playing"));
-	buttonBox->add(m_continue_button, UI::Box::AlignRight);
-	buttonBox->add_space(PADDING);
+	bottom_box->add(m_continue_button, UI::Box::AlignCenter);
+	bottom_box->add_space(PADDING);
 	m_stop_button = new UI::Button
-		(buttonBox, "stop_button",
+		(bottom_box, "stop_button",
 		 0, 0, 35, 35,
 		 g_gr->images().get("pics/but4.png"),
 		 g_gr->images().get("pics/menu_exit_game.png"),
 		_("Exit Game"));
-	buttonBox->add(m_stop_button, UI::Box::AlignRight);
-	buttonBox->add_space(PADDING);
-	vbox->add(buttonBox, UI::Box::AlignBottom);
+	bottom_box->add(m_stop_button, UI::Box::AlignCenter);
+	bottom_box->add_space(PADDING);
+
+	vbox->add(bottom_box, UI::Box::AlignLeft, true);
 	vbox->add_space(PADDING);
 	set_center_panel(vbox);
 
@@ -210,7 +221,6 @@
 	if (!players_status.empty()) {
 		m_players_table->select(current_player_position);
 	}
-	m_gametime_value->set_text(gametimestring(m_game.get_gametime()));
 }
 
 void GameSummaryScreen::continue_clicked()

=== modified file 'src/wui/interactive_gamebase.cc'
--- src/wui/interactive_gamebase.cc	2015-02-14 22:11:44 +0000
+++ src/wui/interactive_gamebase.cc	2015-09-26 18:15:59 +0000
@@ -189,6 +189,7 @@
 
 void InteractiveGameBase::show_game_summary()
 {
+	game().game_controller()->set_desired_speed(0);
 	if (m_game_summary.window) {
 		m_game_summary.window->set_visible(true);
 		m_game_summary.window->think();

=== modified file 'src/wui/minimap.cc'
--- src/wui/minimap.cc	2015-09-09 18:49:58 +0000
+++ src/wui/minimap.cc	2015-09-26 18:15:59 +0000
@@ -30,7 +30,6 @@
 #include "wui/interactive_player.h"
 #include "wui/mapviewpixelconstants.h"
 
-
 MiniMap::View::View
 	(UI::Panel & parent, MiniMapLayer * flags,
 	 int32_t const x, int32_t const y, uint32_t const, uint32_t const,

=== modified file 'src/wui/productionsitewindow.cc'
--- src/wui/productionsitewindow.cc	2014-10-14 07:53:47 +0000
+++ src/wui/productionsitewindow.cc	2015-09-26 18:15:59 +0000
@@ -84,10 +84,10 @@
 		m_worker_table->add_column(60, _("Exp"));
 		m_worker_table->add_column(150, _("Next Level"));
 
-		for
-			(unsigned int i = 0;
-			 i < productionsite().descr().nr_working_positions(); ++i)
+		for (unsigned int i = 0; i < productionsite().descr().nr_working_positions(); ++i) {
 			m_worker_table->add(i);
+		}
+		m_worker_table->fit_height();
 
 		if (igbase().can_act(building().owner().player_number())) {
 			m_worker_caps->add_inf_space();
@@ -102,6 +102,7 @@
 		}
 
 		worker_box->add(m_worker_table, UI::Box::AlignLeft, true);
+		worker_box->add_space(4);
 		worker_box->add(m_worker_caps, UI::Box::AlignLeft, true);
 		get_tabs()->add
 			("workers", g_gr->images().get(pic_tab_workers),

=== modified file 'src/wui/soldierlist.cc'
--- src/wui/soldierlist.cc	2015-08-04 07:49:23 +0000
+++ src/wui/soldierlist.cc	2015-09-26 18:15:59 +0000
@@ -32,7 +32,6 @@
 #include "logic/soldiercontrol.h"
 #include "ui_basic/box.h"
 #include "ui_basic/button.h"
-#include "ui_basic/table.h"
 #include "wlapplication.h"
 #include "wui/interactive_gamebase.h"
 #include "wui/soldiercapacitycontrol.h"


Follow ups