Browse Source

Merge branch 'master' into transform

# Conflicts:
#	Build/CMakeLists.txt
#	Include/Rocket/Core/Context.h
#	Include/Rocket/Core/Property.h
#	Include/Rocket/Core/StyleSheetKeywords.h
#	Source/Core/Context.cpp
#	Source/Core/ElementStyle.cpp
#	Source/Core/PropertyDefinition.cpp
#	Source/Core/PropertyParserNumber.cpp
#	Source/Core/StringCache.cpp
#	Source/Core/StringCache.h
#	Source/Core/StyleSheetSpecification.cpp
Michael 7 years ago
parent
commit
bf36355694
100 changed files with 4835 additions and 707 deletions
  1. 3 0
      .gitignore
  2. 122 54
      Build/CMakeLists.txt
  3. 25 2
      Build/cmake/FileList.cmake
  4. 165 0
      Build/cmake/FindSDL2.cmake
  5. 119 0
      Build/cmake/FindSDL2_image.cmake
  6. 4 7
      Build/cmake/Platform/iOS.cmake
  7. 7 0
      Build/cmake/SampleFileList.cmake
  8. 11 0
      Build/libRocketConfig.cmake.build.in
  9. 7 0
      Build/libRocketConfig.cmake.install.in
  10. 120 0
      Dependencies/osx-depends.sh
  11. 6 1
      Include/Rocket/Controls/Header.h
  12. 6 1
      Include/Rocket/Controls/Lua/Header.h
  13. 101 0
      Include/Rocket/Core/BitmapFont/FontProvider.h
  14. 10 0
      Include/Rocket/Core/Context.h
  15. 4 0
      Include/Rocket/Core/Element.h
  16. 3 0
      Include/Rocket/Core/ElementDocument.h
  17. 4 0
      Include/Rocket/Core/ElementUtilities.h
  18. 17 10
      Include/Rocket/Core/FontDatabase.h
  19. 6 9
      Include/Rocket/Core/FontFace.h
  20. 6 7
      Include/Rocket/Core/FontFamily.h
  21. 70 0
      Include/Rocket/Core/FontProvider.h
  22. 101 0
      Include/Rocket/Core/FreeType/FontProvider.h
  23. 6 1
      Include/Rocket/Core/Header.h
  24. 6 1
      Include/Rocket/Core/Lua/Header.h
  25. 1 1
      Include/Rocket/Core/Platform.h
  26. 10 10
      Include/Rocket/Core/Property.h
  27. 2 0
      Include/Rocket/Core/PropertySpecification.h
  28. 6 1
      Include/Rocket/Core/Python/Header.h
  29. 3 1
      Include/Rocket/Core/StyleSheetKeywords.h
  30. 6 1
      Include/Rocket/Debugger/Header.h
  31. 270 0
      Samples/assets/Arial.fnt
  32. BIN
      Samples/assets/Arial_0.tga
  33. 28 0
      Samples/assets/bitmapfont.rml
  34. 130 0
      Samples/basic/bitmapfont/src/main.cpp
  35. 1 1
      Samples/basic/customlog/src/main.cpp
  36. 1 1
      Samples/basic/drag/src/main.cpp
  37. 1 1
      Samples/basic/loaddocument/src/main.cpp
  38. 12 0
      Samples/basic/sdl2/src/main.cpp
  39. 1 1
      Samples/basic/sfml2/src/main.cpp
  40. 1 1
      Samples/basic/treeview/src/main.cpp
  41. 1 1
      Samples/luainvaders/src/LuaInterface.cpp
  42. 1 0
      Samples/pyinvaders/src/main.cpp
  43. 3 1
      Samples/shell/src/macosx/ShellRenderInterfaceExtensionsOpenGL_MacOSX.cpp
  44. 1 1
      Samples/tutorial/datagrid/src/main.cpp
  45. 1 1
      Samples/tutorial/datagrid_tree/src/main.cpp
  46. 1 1
      Samples/tutorial/template/src/main.cpp
  47. 1 1
      Samples/tutorial/tutorial_drag/src/main.cpp
  48. 1 1
      Source/Controls/ElementDataGridRow.cpp
  49. 6 6
      Source/Controls/Lua/DataSource.cpp
  50. 5 5
      Source/Controls/Lua/ElementFormControlInput.cpp
  51. 3 3
      Source/Controls/Lua/ElementFormControlSelect.cpp
  52. 3 3
      Source/Controls/Lua/ElementFormControlTextArea.cpp
  53. 3 3
      Source/Controls/Lua/ElementTabSet.cpp
  54. 1 1
      Source/Controls/Lua/LuaDataSource.cpp
  55. 1 1
      Source/Controls/Lua/SelectOptionsProxy.cpp
  56. 18 3
      Source/Controls/WidgetDropDown.cpp
  57. 54 32
      Source/Controls/WidgetSlider.cpp
  58. 147 0
      Source/Core/BitmapFont/BitmapFontDefinitions.h
  59. 130 0
      Source/Core/BitmapFont/FontFace.cpp
  60. 68 0
      Source/Core/BitmapFont/FontFace.h
  61. 428 0
      Source/Core/BitmapFont/FontFaceHandle.cpp
  62. 136 0
      Source/Core/BitmapFont/FontFaceHandle.h
  63. 127 0
      Source/Core/BitmapFont/FontFaceLayer.cpp
  64. 78 0
      Source/Core/BitmapFont/FontFaceLayer.h
  65. 55 0
      Source/Core/BitmapFont/FontFamily.cpp
  66. 66 0
      Source/Core/BitmapFont/FontFamily.h
  67. 114 0
      Source/Core/BitmapFont/FontParser.cpp
  68. 68 0
      Source/Core/BitmapFont/FontParser.h
  69. 208 0
      Source/Core/BitmapFont/FontProvider.cpp
  70. 40 1
      Source/Core/Context.cpp
  71. 9 1
      Source/Core/DecoratorTiled.cpp
  72. 25 9
      Source/Core/Element.cpp
  73. 6 0
      Source/Core/ElementBackground.cpp
  74. 7 0
      Source/Core/ElementBorder.cpp
  75. 7 1
      Source/Core/ElementDocument.cpp
  76. 18 2
      Source/Core/ElementImage.cpp
  77. 4 0
      Source/Core/ElementImage.h
  78. 40 0
      Source/Core/ElementStyle.cpp
  79. 6 0
      Source/Core/ElementStyle.h
  80. 53 1
      Source/Core/ElementStyleCache.cpp
  81. 8 0
      Source/Core/ElementStyleCache.h
  82. 20 2
      Source/Core/ElementUtilities.cpp
  83. 94 158
      Source/Core/FontDatabase.cpp
  84. 2 95
      Source/Core/FontFace.cpp
  85. 0 209
      Source/Core/FontFaceHandle.cpp
  86. 7 26
      Source/Core/FontFaceHandle.h
  87. 3 3
      Source/Core/FontFaceLayer.h
  88. 2 11
      Source/Core/FontFamily.cpp
  89. 45 0
      Source/Core/FontProvider.cpp
  90. 139 0
      Source/Core/FreeType/FontFace.cpp
  91. 68 0
      Source/Core/FreeType/FontFace.h
  92. 458 0
      Source/Core/FreeType/FontFaceHandle.cpp
  93. 117 0
      Source/Core/FreeType/FontFaceHandle.h
  94. 58 0
      Source/Core/FreeType/FontFamily.cpp
  95. 67 0
      Source/Core/FreeType/FontFamily.h
  96. 258 0
      Source/Core/FreeType/FontProvider.cpp
  97. 60 0
      Source/Core/LayoutBlockBox.cpp
  98. 3 0
      Source/Core/LayoutBlockBox.h
  99. 78 10
      Source/Core/LayoutEngine.cpp
  100. 2 2
      Source/Core/LayoutEngine.h

+ 3 - 0
.gitignore

@@ -7,6 +7,9 @@
 *.user
 *.opensdf
 bin/*
+bin64/*
+*.dir/
+Win32/
 
 /lib/
 RocketCore.dir/

+ 122 - 54
Build/CMakeLists.txt

@@ -2,12 +2,31 @@
 # Build script for libRocket =======
 #===================================
 
-# This has to be before most other options so CMake properly handles the 
-# compiler variables, it MUST bebefore the project() definition
 if(APPLE)
+	# This has to be before most other options so CMake properly handles the 
+	# compiler variables, it MUST bebefore the project() definition
 	if(IOS_PLATFORM)
 		set(CMAKE_TOOLCHAIN_FILE cmake/Platform/iOS.cmake)
 	endif(IOS_PLATFORM)
+
+	option(BUILD_UNIVERSAL_BINARIES "Build universal binaries for all architectures supported" ON)
+	if (NOT CMAKE_OSX_ARCHITECTURES AND BUILD_UNIVERSAL_BINARIES)
+		if(IOS)
+			# set the architecture for iOS 
+			if (${IOS_PLATFORM} STREQUAL "OS")
+				set (IOS_ARCH armv6 armv7 armv7s arm64)
+				set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for iOS")
+			else (${IOS_PLATFORM} STREQUAL "OS")
+				set (IOS_ARCH i386 x86_64)
+				set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for iOS Simulator")
+			endif (${IOS_PLATFORM} STREQUAL "OS")
+
+		else(IOS)
+			# set the architectures for OS X
+			set (OSXI_ARCH i386 x86_64)
+			set (CMAKE_OSX_ARCHITECTURES ${OSXI_ARCH} CACHE string  "Build architecture for OS X universal binaries")		
+		endif(IOS)
+	endif (NOT CMAKE_OSX_ARCHITECTURES AND BUILD_UNIVERSAL_BINARIES)
 endif(APPLE)
 
 # We use the new OSX_ARCHITECTURES property
@@ -18,6 +37,18 @@ if(COMMAND cmake_policy)
   cmake_policy(SET CMP0015 NEW)
 endif(COMMAND cmake_policy)
 
+# Enable the use of MACOSX_RPATH by default for CMake v3.0+; this effectively 
+# allows plug 'n' play functionality, so to speak -- the resulting shared 
+# library files can simply be copied over into the end-user's application 
+# bundle or framework bundle. No mucking around with install_name_tool.
+#
+# 	See also: 
+# cmake --help-policy cmp0042
+# http://www.kitware.com/blog/home/post/510
+if(POLICY CMP0042)
+  cmake_policy(SET CMP0042 NEW)
+endif(POLICY CMP0042)
+
 project(libRocket C CXX)
 
 # paths
@@ -55,20 +86,23 @@ if(NOT DEFINED ENV{FREETYPE_DIR})
 	set(ENV{FREETYPE_DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
 endif()
 
-if(NOT DEFINED ENV{Boost_DIR})
-	set(ENV{Boost_DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
+#if(NOT DEFINED ENV{Boost_DIR})
+#	set(ENV{Boost_DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
+#endif()
+if(NOT DEFINED ENV{BOOST_ROOT})
+	set(ENV{BOOST_ROOT} "${PROJECT_SOURCE_DIR}/../Dependencies/boost")
 endif()
 
 if(NOT DEFINED ENV{LUA_DIR})
 	set(ENV{LUA_DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
 endif()
 
-if(NOT DEFINED ENV{SDLDIR})
-	set(ENV{SDLDIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
+if(NOT DEFINED ENV{SDL2DIR})
+	set(ENV{SDL2DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
 endif()
 
-if(NOT DEFINED ENV{SDLIMAGEDIR})
-	set(ENV{SDLIMAGEDIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
+if(NOT DEFINED ENV{SDL2_IMAGE_DIR})
+	set(ENV{SDL2_IMAGE_DIR} "${PROJECT_SOURCE_DIR}/../Dependencies")
 endif()
 
 if(NOT DEFINED ENV{SFML_ROOT})
@@ -102,9 +136,11 @@ endif(NOT IOS)
 
 option(BUILD_PYTHON_BINDINGS "Build python bindings" OFF)
 option(BUILD_LUA_BINDINGS "Build Lua bindings" OFF)
+
 if(APPLE)
 	option(BUILD_FRAMEWORK "Build Framework bundle for OSX" OFF)
 endif()
+
 option(BUILD_SAMPLES "Build samples" OFF)
 if(WIN32)
 	option(SKIP_DIRECTX_SAMPLES "Skip build of all DirectX related samples.  Only applies if BUILD_SAMPLES is ON" OFF)
@@ -112,28 +148,29 @@ if(WIN32)
 	option(SKIP_DIRECTX10_SAMPLE "Skip build of DirectX 10 related sample.  Only applies if BUILD_SAMPLES is ON and SKIP_DIRECTX_SAMPLES is OFF" OFF)
 endif()
 
-if(IOS)
-	if(BUILD_SHARED_LIBS)
-		message(FATAL_ERROR "BUILD_SHARED_LIBS must be OFF for iOS builds.  iOS does not support shared libraries.")
-	endif(BUILD_SHARED_LIBS)
-endif(IOS)
+if(APPLE)
+	if(IOS)
+		if(BUILD_SHARED_LIBS)
+			message(FATAL_ERROR "BUILD_SHARED_LIBS must be OFF for iOS builds.  iOS does not support shared libraries.")
+		endif(BUILD_SHARED_LIBS)
+	endif(IOS)
 
-if(BUILD_FRAMEWORK)
-	if(APPLE)
+	if(BUILD_FRAMEWORK)
 		if(NOT "${CMAKE_GENERATOR}" STREQUAL "Xcode")
 			message(FATAL_ERROR "You should use Xcode generator with BUILD_FRAMEWORK enabled")
 		endif()
-		set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)")
 		if(NOT BUILD_SHARED_LIBS)
 			message(FATAL_ERROR "BUILD_SHARED_LIBS must be ON with BUILD_FRAMEWORK enabled")
 		endif()
-	else(APPLE)
+	endif()
+else(APPLE)
+	if(BUILD_FRAMEWORK)
 		message(FATAL_ERROR "BUILD_FRAMEWORK is only supported on Mac OS X with the Xcode generator")
-	endif(APPLE)
-endif()
+	endif()
+endif(APPLE)
 
 if(NOT BUILD_SHARED_LIBS)
-    add_definitions(-DSTATIC_LIB)
+	add_definitions(-DROCKET_STATIC_LIB)
 endif()
 
 #on windows, check for VC10 and fix the multiple compile target issue.
@@ -239,19 +276,14 @@ foreach(library ${LIBRARIES})
                            SOVERSION ${LIBROCKET_VERSION_MAJOR}
     )
     
-    if(APPLE)
-	if(NOT IOS)
-    		set_target_properties(${NAME} PROPERTIES
-    						OSX_ARCHITECTURES "i386;x86_64;"
-    		)
-	endif(NOT IOS)
-    endif(APPLE)
-
     install(TARGETS ${NAME}
+            EXPORT libRocketTargets
             LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
             ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
             RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
     )
+
+    set(ROCKET_EXPORTED_TARGETS ${ROCKET_EXPORTED_TARGETS} ${NAME})
 endforeach(library)
 else(NOT BUILD_FRAMEWORK)
 	#===================================
@@ -286,9 +318,6 @@ else(NOT BUILD_FRAMEWORK)
 		SOVERSION ${LIBROCKET_VERSION_MAJOR}
 	)
 
-	set_target_properties(${NAME} PROPERTIES
-		OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)"
-	)
 		set_property(SOURCE ${MASTER_PUB_HDR_FILES}
 			PROPERTY MACOSX_PACKAGE_LOCATION Headers
 		)
@@ -312,11 +341,14 @@ else(NOT BUILD_FRAMEWORK)
 		)
 
     install(TARGETS ${NAME}
+            EXPORT libRocketTargets
             LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
             ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
             RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
             FRAMEWORK DESTINATION Library/Frameworks
     )
+
+    set(ROCKET_EXPORTED_TARGETS ${ROCKET_EXPORTED_TARGETS} ${NAME})
 endif(NOT BUILD_FRAMEWORK)
 
 # Build python bindings
@@ -331,19 +363,13 @@ if(BUILD_PYTHON_BINDINGS)
                             ${Py${library}_PUB_HDR_FILES}
         )
 
-    if(APPLE)
-	if(NOT IOS)
-    		set_target_properties(${NAME} PROPERTIES
-    						OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)"
-    		)
-	endif(NOT IOS)
-    endif(APPLE)
-
         set_target_properties(${NAME} PROPERTIES PREFIX "")
 
         install(TARGETS ${NAME}
+                EXPORT libRocketTargets
                 LIBRARY DESTINATION ${PYTHON_INSTDIR}
         )
+ 
     endforeach(library)
 endif()
 
@@ -364,19 +390,14 @@ if(BUILD_LUA_BINDINGS)
                            SOVERSION ${LIBROCKET_VERSION_MAJOR}
         )
         
-    if(APPLE)
-	if(NOT IOS)
-    		set_target_properties(${NAME} PROPERTIES
-    						OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_64_BIT)"
-    		)
-	endif(NOT IOS)
-    endif(APPLE)
-
         install(TARGETS ${NAME}
+            EXPORT libRocketTargets
             LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
             ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
             RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
         )
+        
+        set(ROCKET_EXPORTED_TARGETS ${ROCKET_EXPORTED_TARGETS} ${NAME})
     endforeach(library)
 endif()
 
@@ -447,7 +468,7 @@ endmacro()
 if(BUILD_SAMPLES)
     include(SampleFileList)
 
-    set(samples treeview customlog drag loaddocument transform)
+    set(samples treeview customlog drag loaddocument transform bitmapfont)
     set(tutorials template datagrid datagrid_tree tutorial_drag)
     
 if(NOT BUILD_FRAMEWORK)
@@ -605,16 +626,16 @@ endif(NOT BUILD_FRAMEWORK)
 	endif()
 
     message("-- Can SDL2 sample be built")
-    find_package(SDL)
-    if(SDL_FOUND)
-	find_package(SDL_image)
-	if(SDL_IMAGE_FOUND)
+    find_package(SDL2)
+    if(SDL2_FOUND)
+	find_package(SDL2_image)
+	if(SDL2_IMAGE_FOUND)
 		find_package(GLEW)
 		if(GLEW_FOUND)
         		message("-- Can SDL2 sample be built - yes")
-			include_directories(${SDL_INCLUDE_DIR} ${GLEW_INCLUDE_DIR})
+			include_directories(${SDL2_INCLUDE_DIR} ${GLEW_INCLUDE_DIR})
 
-			bl_sample(sdl2 ${sample_LIBRARIES}  ${SDL_LIBRARY} ${SDL_IMAGE_LIBRARY} ${GLEW_LIBRARY})
+			bl_sample(sdl2 ${sample_LIBRARIES}  ${SDL2_LIBRARY} ${SDL2_IMAGE_LIBRARY} ${GLEW_LIBRARY})
 			# The samples always set this as their current working directory
 			install(DIRECTORY DESTINATION ${SAMPLES_DIR}/basic/sdl2)
 			install(TARGETS sdl2
@@ -790,3 +811,50 @@ if(BUILD_SAMPLES)
         )
     endif()
 endif()
+
+#===================================
+# Generate Config.cmake files ======
+#===================================
+
+# Try to include helper module
+include(CMakePackageConfigHelpers OPTIONAL
+  RESULT_VARIABLE PkgHelpers_AVAILABLE)
+# guard against older versions of cmake which do not provide it
+if(PkgHelpers_AVAILABLE)
+
+  set (INCLUDE_INSTALL_DIR "include")
+  set (LIB_INSTALL_DIR "lib")
+  set (INCLUDE_DIR "${PROJECT_SOURCE_DIR}/Include")
+
+  # generate configuration for install tree
+  configure_package_config_file(libRocketConfig.cmake.install.in
+    ${CMAKE_CURRENT_BINARY_DIR}/install/libRocketConfig.cmake
+    INSTALL_DESTINATION ${LIB_INSTALL_DIR}/libRocket/cmake
+    PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
+  write_basic_package_version_file(
+    ${CMAKE_CURRENT_BINARY_DIR}/install/libRocketConfigVersion.cmake
+    VERSION ${PROJECT_VERSION}
+    COMPATIBILITY SameMajorVersion )
+  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/install/libRocketConfig.cmake
+    ${CMAKE_CURRENT_BINARY_DIR}/install/libRocketConfigVersion.cmake
+    DESTINATION ${LIB_INSTALL_DIR}/libRocket/cmake )
+  install(EXPORT libRocketTargets
+    DESTINATION ${LIB_INSTALL_DIR}/libRocket/cmake)
+
+  # generate configuration for build tree
+  configure_package_config_file(libRocketConfig.cmake.build.in
+    ${CMAKE_CURRENT_BINARY_DIR}/libRocketConfig.cmake
+    INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
+    PATH_VARS INCLUDE_DIR CMAKE_CURRENT_BINARY_DIR)
+  export(TARGETS ${ROCKET_EXPORTED_TARGETS}
+    FILE "${CMAKE_CURRENT_BINARY_DIR}/libRocketTargets.cmake")
+  write_basic_package_version_file(
+    ${CMAKE_CURRENT_BINARY_DIR}/libRocketConfigVersion.cmake
+    VERSION ${PROJECT_VERSION}
+    COMPATIBILITY SameMajorVersion )
+  set(libRocket_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE PATH "The directory containing a CMake configuration file for libRocket.")
+else()
+  message("If you wish to use find_package(libRocket) in your own project to find libRocket library"
+    " please update cmake to version which provides CMakePackageConfighelpers module"
+    " or write generators for libRocketConfig.cmake by yourself.")
+endif()

+ 25 - 2
Build/cmake/FileList.cmake

@@ -36,10 +36,17 @@ set(Core_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectOutlineInstancer.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadow.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontEffectShadowInstancer.h
-    ${PROJECT_SOURCE_DIR}/Source/Core/FontFace.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.h
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.h
-    ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/BitmapFontDefinitions.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontParser.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFace.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceHandle.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceLayer.h
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFamily.h
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.h
     ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBox.h
     ${PROJECT_SOURCE_DIR}/Source/Core/LayoutBlockBoxSpace.h
@@ -129,7 +136,12 @@ set(Core_PUB_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontDatabase.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffect.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontEffectInstancer.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFace.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontFamily.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontGlyph.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FontProvider.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/FreeType/FontProvider.h
+    ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/BitmapFont/FontProvider.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Geometry.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/GeometryUtilities.h
     ${PROJECT_SOURCE_DIR}/Include/Rocket/Core/Header.h
@@ -244,6 +256,17 @@ set(Core_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceHandle.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFaceLayer.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FontProvider.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFace.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFaceHandle.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/FreeType/FontProvider.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontParser.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFace.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceHandle.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFaceLayer.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontFamily.cpp
+    ${PROJECT_SOURCE_DIR}/Source/Core/BitmapFont/FontProvider.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/Geometry.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryDatabase.cpp
     ${PROJECT_SOURCE_DIR}/Source/Core/GeometryUtilities.cpp

+ 165 - 0
Build/cmake/FindSDL2.cmake

@@ -0,0 +1,165 @@
+# Locate SDL2 library
+# This module defines
+# SDL2_LIBRARY, the name of the library to link against
+# SDL2_FOUND, if false, do not try to link to SDL2
+# SDL2_INCLUDE_DIR, where to find SDL.h
+#
+# Source: https://code.google.com/p/freerct/source/browse/trunk/CMake/FindSDL2.cmake
+#
+# This module responds to the the flag:
+# SDL2_BUILDING_LIBRARY
+# If this is defined, then no SDL2main will be linked in because
+# only applications need main().
+# Otherwise, it is assumed you are building an application and this
+# module will attempt to locate and set the the proper link flags
+# as part of the returned SDL2_LIBRARY variable.
+#
+# Don't forget to include SDLmain.h and SDLmain.m your project for the
+# OS X framework based version. (Other versions link to -lSDL2main which
+# this module will try to find on your behalf.) Also for OS X, this
+# module will automatically add the -framework Cocoa on your behalf.
+#
+#
+# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration
+# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library
+# (SDL2.dll, libsdl2.so, SDL2.framework, etc).
+# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again.
+# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value
+# as appropriate. These values are used to generate the final SDL2_LIBRARY
+# variable, but when these values are unset, SDL2_LIBRARY does not get created.
+#
+#
+# $SDL2DIR is an environment variable that would
+# correspond to the ./configure --prefix=$SDL2DIR
+# used in building SDL2.
+# l.e.galup  9-20-02
+#
+# Modified by Eric Wing.
+# Added code to assist with automated building by using environmental variables
+# and providing a more controlled/consistent search behavior.
+# Added new modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+# Also corrected the header search path to follow "proper" SDL guidelines.
+# Added a search for SDL2main which is needed by some platforms.
+# Added a search for threads which is needed by some platforms.
+# Added needed compile switches for MinGW.
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of
+# SDL2_LIBRARY to override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+#
+# Note that the header path has changed from SDL2/SDL.h to just SDL.h
+# This needed to change because "proper" SDL convention
+# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
+# reasons because not all systems place things in SDL2/ (see FreeBSD).
+
+#=============================================================================
+# Copyright 2003-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+SET(SDL2_SEARCH_PATHS
+  ~/Library/Frameworks
+  /Library/Frameworks
+  /usr/local
+  /usr
+  /sw # Fink
+  /opt/local # DarwinPorts
+  /opt/csw # Blastwave
+  /opt
+)
+
+FIND_PATH(SDL2_INCLUDE_DIR SDL.h
+  HINTS
+  $ENV{SDL2DIR}
+  PATH_SUFFIXES include/SDL2 include
+  PATHS ${SDL2_SEARCH_PATHS}
+)
+
+FIND_LIBRARY(SDL2_LIBRARY_TEMP
+  NAMES SDL2
+  HINTS
+  $ENV{SDL2DIR}
+  PATH_SUFFIXES lib64 lib
+  PATHS ${SDL2_SEARCH_PATHS}
+)
+
+IF(NOT SDL2_BUILDING_LIBRARY)
+  IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+    # Non-OS X framework versions expect you to also dynamically link to
+    # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms
+    # seem to provide SDL2main for compatibility even though they don't
+    # necessarily need it.
+    FIND_LIBRARY(SDL2MAIN_LIBRARY
+      NAMES SDL2main
+      HINTS
+      $ENV{SDL2DIR}
+      PATH_SUFFIXES lib64 lib
+      PATHS ${SDL2_SEARCH_PATHS}
+    )
+  ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework")
+ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+# SDL2 may require threads on your system.
+# The Apple build may not need an explicit flag because one of the
+# frameworks may already provide it.
+# But for non-OSX systems, I will use the CMake Threads package.
+IF(NOT APPLE)
+  FIND_PACKAGE(Threads)
+ENDIF(NOT APPLE)
+
+# MinGW needs an additional library, mwindows
+# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows
+# (Actually on second look, I think it only needs one of the m* libraries.)
+IF(MINGW)
+  SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
+ENDIF(MINGW)
+
+IF(SDL2_LIBRARY_TEMP)
+  # For SDL2main
+  IF(NOT SDL2_BUILDING_LIBRARY)
+    IF(SDL2MAIN_LIBRARY)
+      SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP})
+    ENDIF(SDL2MAIN_LIBRARY)
+  ENDIF(NOT SDL2_BUILDING_LIBRARY)
+
+  # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa.
+  # CMake doesn't display the -framework Cocoa string in the UI even
+  # though it actually is there if I modify a pre-used variable.
+  # I think it has something to do with the CACHE STRING.
+  # So I use a temporary variable until the end so I can set the
+  # "real" variable in one-shot.
+  IF(APPLE)
+    SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa")
+  ENDIF(APPLE)
+
+  # For threads, as mentioned Apple doesn't need this.
+  # In fact, there seems to be a problem if I used the Threads package
+  # and try using this line, so I'm just skipping it entirely for OS X.
+  IF(NOT APPLE)
+    SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
+  ENDIF(NOT APPLE)
+
+  # For MinGW library
+  IF(MINGW)
+    SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP})
+  ENDIF(MINGW)
+
+  # Set the final string here so the GUI reflects the final state.
+  SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found")
+  # Set the temp variable to INTERNAL so it is not seen in the CMake GUI
+  SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "")
+ENDIF(SDL2_LIBRARY_TEMP)
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR)

+ 119 - 0
Build/cmake/FindSDL2_image.cmake

@@ -0,0 +1,119 @@
+# Locate SDL2_image library
+# This module defines
+# SDL2_IMAGE_LIBRARY, the name of the library to link against
+# SDL2_IMAGE_FOUND, if false, do not try to link to SDL2_image
+# SDL2_IMAGE_INCLUDE_DIR, where to find SDL.h
+#
+# Source: https://code.google.com/p/freerct/source/browse/trunk/CMake/FindSDL2_ttf.cmake
+#
+# $SDL2_IMAGE_DIR is an environment variable that would
+# correspond to the ./configure --prefix=$SDL2_IMAGE_DIR
+# used in building SDL2_image.
+# l.e.galup  9-20-02
+#
+# Modified by Eric Wing.
+# Added code to assist with automated building by using environmental variables
+# and providing a more controlled/consistent search behavior.
+# Added new modifications to recognize OS X frameworks and
+# additional Unix paths (FreeBSD, etc).
+# Also corrected the header search path to follow "proper" SDL guidelines.
+# Added a search for SDL2main which is needed by some platforms.
+# Added a search for threads which is needed by some platforms.
+# Added needed compile switches for MinGW.
+#
+# On OSX, this will prefer the Framework version (if found) over others.
+# People will have to manually change the cache values of
+# SDL2_LIBRARY to override this selection or set the CMake environment
+# CMAKE_INCLUDE_PATH to modify the search paths.
+#
+# Note that the header path has changed from SDL2/SDL.h to just SDL.h
+# This needed to change because "proper" SDL convention
+# is #include "SDL.h", not <SDL2/SDL.h>. This is done for portability
+# reasons because not all systems place things in SDL2/ (see FreeBSD).
+
+#=============================================================================
+# Copyright 2003-2009 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+SET(SDL2_IMAGE_SEARCH_PATHS
+        ~/Library/Frameworks
+        /Library/Frameworks
+        /usr/local
+        /usr
+        /sw # Fink
+        /opt/local # DarwinPorts
+        /opt/csw # Blastwave
+        /opt
+)
+
+FIND_PATH(SDL2_IMAGE_INCLUDE_DIR SDL_image.h
+        HINTS
+        $ENV{SDL2_IMAGE_DIR}
+        PATH_SUFFIXES include/SDL2 include
+        PATHS ${SDL2_IMAGE_SEARCH_PATHS}
+)
+
+FIND_LIBRARY(SDL2_IMAGE_LIBRARY_TEMP
+        NAMES SDL2_image
+        HINTS
+        $ENV{SDL2_IMAGE_DIR}
+        PATH_SUFFIXES lib64 lib
+        PATHS ${SDL2_IMAGE_SEARCH_PATHS}
+)
+
+# SDL2_image may require threads on your system.
+# The Apple build may not need an explicit flag because one of the
+# frameworks may already provide it.
+# But for non-OSX systems, I will use the CMake Threads package.
+# IF(NOT APPLE)
+        # FIND_PACKAGE(Threads)
+# ENDIF(NOT APPLE)
+
+# MinGW needs an additional library, mwindows
+# It's total link flags should look like -lmingw32 -lSDL2_image -lmwindows
+# (Actually on second look, I think it only needs one of the m* libraries.)
+IF(MINGW)
+        SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW")
+ENDIF(MINGW)
+
+IF(SDL2_IMAGE_LIBRARY_TEMP)
+        # For OS X, SDL2_IMAGE uses Cocoa as a backend so it must link to Cocoa.
+        # CMake doesn't display the -framework Cocoa string in the UI even
+        # though it actually is there if I modify a pre-used variable.
+        # I think it has something to do with the CACHE STRING.
+        # So I use a temporary variable until the end so I can set the
+        # "real" variable in one-shot.
+        # IF(APPLE)
+                # SET(SDL2_IMAGE_LIBRARY_TEMP ${SDL2_IMAGE_LIBRARY_TEMP} "-framework Cocoa")
+        # ENDIF(APPLE)
+
+        # For threads, as mentioned Apple doesn't need this.
+        # In fact, there seems to be a problem if I used the Threads package
+        # and try using this line, so I'm just skipping it entirely for OS X.
+        # IF(NOT APPLE)
+                # SET(SDL2_IMAGE_LIBRARY_TEMP ${SDL2_IMAGE_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT})
+        # ENDIF(NOT APPLE)
+
+        # For MinGW library
+        # IF(MINGW)
+                # SET(SDL2_IMAGE_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_IMAGE_LIBRARY_TEMP})
+        # ENDIF(MINGW)
+
+        # Set the final string here so the GUI reflects the final state.
+        SET(SDL2_IMAGE_LIBRARY ${SDL2_IMAGE_LIBRARY_TEMP} CACHE STRING "Where the SDL2_IMAGE Library can be found")
+        # Set the temp variable to INTERNAL so it is not seen in the CMake GUI
+        SET(SDL2_IMAGE_LIBRARY_TEMP "${SDL2_IMAGE_LIBRARY_TEMP}" CACHE INTERNAL "")
+ENDIF(SDL2_IMAGE_LIBRARY_TEMP)
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2_image REQUIRED_VARS SDL2_IMAGE_LIBRARY SDL2_IMAGE_INCLUDE_DIR)

+ 4 - 7
Build/cmake/Platform/iOS.cmake

@@ -46,11 +46,6 @@ if (CMAKE_UNAME)
 	string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
 endif (CMAKE_UNAME)
 
-# Force the compilers to gcc for iOS
-include (CMakeForceCompiler)
-CMAKE_FORCE_C_COMPILER (gcc gcc)
-CMAKE_FORCE_CXX_COMPILER (g++ g++)
-
 # Skip the platform compiler checks for cross compiling
 set (CMAKE_CXX_COMPILER_WORKS TRUE)
 set (CMAKE_C_COMPILER_WORKS TRUE)
@@ -146,10 +141,12 @@ set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS su
 if (${IOS_PLATFORM} STREQUAL "OS")
 	set (IOS_ARCH armv6 armv7 armv7s arm64)
 else (${IOS_PLATFORM} STREQUAL "OS")
-	set (IOS_ARCH i386)
+	set (IOS_ARCH i386 x86_64)
 endif (${IOS_PLATFORM} STREQUAL "OS")
 
-set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for iOS")
+if (NOT DEFINED CMAKE_OSX_ARCHITECTURES)
+	set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string  "Build architecture for iOS")
+endif (NOT DEFINED CMAKE_OSX_ARCHITECTURES)
 
 # Set the find root to the iOS developer roots and to user defined paths
 set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string  "iOS find search path root")

+ 7 - 0
Build/cmake/SampleFileList.cmake

@@ -45,6 +45,13 @@ set(loaddocument_SRC_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/loaddocument/src/main.cpp
 )
 
+set(bitmapfont_HDR_FILES
+)
+
+set(bitmapfont_SRC_FILES
+    ${PROJECT_SOURCE_DIR}/Samples/basic/bitmapfont/src/main.cpp
+)
+
 set(ogre3d_HDR_FILES
     ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RenderInterfaceOgre3D.h
     ${PROJECT_SOURCE_DIR}/Samples/basic/ogre3d/src/RocketApplication.h

+ 11 - 0
Build/libRocketConfig.cmake.build.in

@@ -0,0 +1,11 @@
+@PACKAGE_INIT@
+
+set_and_check(libRocket_INCLUDE_DIRS "@PACKAGE_INCLUDE_DIR@")
+set(libRocket_LIBRARIES @ROCKET_EXPORTED_TARGETS@)
+list(GET libRocket_LIBRARIES 0 ROCKET_FIRST_TARGET)
+
+if(NOT (TARGET ${ROCKET_FIRST_TARGET}))
+  include("${CMAKE_CURRENT_LIST_DIR}/libRocketTargets.cmake")
+endif()
+
+check_required_components(libRocket)

+ 7 - 0
Build/libRocketConfig.cmake.install.in

@@ -0,0 +1,7 @@
+@PACKAGE_INIT@
+
+set_and_check(libRocket_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@")
+set(libRocket_LIBRARIES @ROCKET_EXPORTED_TARGETS@)
+include("${CMAKE_CURRENT_LIST_DIR}/libRocketTargets.cmake")
+
+check_required_components(libRocket)

+ 120 - 0
Dependencies/osx-depends.sh

@@ -0,0 +1,120 @@
+#!/usr/bin/env sh
+
+BUILD_FREETYPE2=YES
+BUILD_BOOST_PYTHON=YES
+BUILD_LUA=YES
+BUILD_PLATFORM=osx
+
+
+#Get depends root directory
+
+pushd `dirname $0` > /dev/null
+SCRIPT_PATH=`pwd`
+popd > /dev/null
+
+DEPS_DIR=${SCRIPT_PATH}
+
+BUILD_OUTPUTDIR=${DEPS_DIR}/${BUILD_PLATFORM}
+
+if [ ! -d "${BUILD_OUTPUTDIR}" ]; then
+	mkdir "${BUILD_OUTPUTDIR}"
+fi
+if [ ! -d "${BUILD_OUTPUTDIR}/lib" ]; then
+	mkdir "${BUILD_OUTPUTDIR}/lib"
+fi
+if [ ! -d "${BUILD_OUTPUTDIR}/include" ]; then
+	mkdir "${BUILD_OUTPUTDIR}/include"
+fi
+
+create_ios_outdir_lipo()
+{
+        for lib_i386 in `find $LOCAL_OUTDIR/i386 -name "lib*.a"`; do
+                lib_arm7=`echo $lib_i386 | sed "s/i386/arm7/g"`
+                lib_arm7s=`echo $lib_i386 | sed "s/i386/arm7s/g"`
+                lib=`echo $lib_i386 | sed "s/i386//g"`
+                xcrun -sdk iphoneos lipo -arch armv7s $lib_arm7s -arch armv7 $lib_arm7 -create -output $lib
+        done
+}
+
+build_freetype()
+{
+
+	cd "${DEPS_DIR}"
+	if [ ! -d "freetype2" ]; then
+		git clone --recursive git://git.sv.nongnu.org/freetype/freetype2.git freetype2
+	fi
+
+	cd freetype2
+
+	cmake CMakeLists.txt -DBUILD_SHARED_LIBS:BOOL=false
+	make
+
+	cmake CMakeLists.txt -DBUILD_SHARED_LIBS:BOOL=true
+	make
+
+	if [ ! -d "${BUILD_OUTPUTDIR}/include/freetype2" ]; then
+		mkdir "${BUILD_OUTPUTDIR}/include/freetype2"
+	fi
+	cp -Rp include/* "${BUILD_OUTPUTDIR}/include/freetype2/"
+	cp libfreetype.a "${BUILD_OUTPUTDIR}/lib/"
+	cp libfreetype.dylib "${BUILD_OUTPUTDIR}/lib/"
+
+	cd "${DEPS_DIR}"
+}
+
+build_boostpython()
+{
+	cd "${DEPS_DIR}"
+	if [ ! -d "boost" ]; then
+		git clone --recursive https://github.com/boostorg/boost.git boost
+	fi
+
+	cd boost
+
+	git submodule foreach 'git clean -fdx; git reset --hard'
+	git clean -fdx
+
+	./bootstrap.sh
+	./b2 architecture=x86 address-model=32_64 --with-python
+	##./b2 architecture=x86 address-model=32_64 link=shared --with-python
+	##./b2 architecture=x86 address-model=32_64 link=static --with-python
+
+
+	cp libs/python/include/boost/python.hpp boost/
+	cp libs/utility/include/boost/utility/value_init.hpp boost/utility/
+	cp libs/lexical_cast/include/boost/lexical_cast.hpp boost/
+cp -R libs/lexical_cast/include/boost/lexical_cast boost/
+	cp libs/lexical_cast/include/boost/detail/lcast_precision.hpp boost/detail/
+#	mkdir -p boost/math
+#	cp libs/math/include/boost/math/special_functions/sign.hpp boost/math/special_functions/
+#	cp libs/math/include/boost/math/special_functions/math_fwd.hpp boost/math/special_functions/
+#	cp libs/math/include/boost/math/special_functions/detail/round_fwd.hpp boost/math/special_functions/detail/
+#	cp libs/math/include/boost/math/special_functions/detail/fp_traits.hpp boost/math/special_functions/detail/
+	cp -R libs/math/include/boost/math boost/math
+
+#	mkdir -p boost/math/tools
+#	cp libs/math/include/boost/math/tools/config.hpp boost/math/tools/
+#	cp libs/math/include/boost/math/tools/user.hpp boost/math/tools/
+#	cp libs/math/include/boost/math/tools/promotion.hpp boost/math/tools/
+	mkdir -p boost/math/policies
+	cp libs/math/include/boost/math/policies/policy.hpp boost/math/policies/
+
+	cp libs/predef/include/boost/detail/endian.hpp boost/detail/
+
+	cp libs/math/include/boost/math/special_functions/fpclassify.hpp boost/math/special_functions/
+
+	cp libs/math/include/boost/math/tools/real_cast.hpp boost/math/tools/
+
+	cp libs/lexical_cast/include/boost/detail/basic_pointerbuf.hpp boost/detail/
+
+	cp libs/foreach/include/boost/foreach.hpp boost/
+
+	cp -R boost "${BUILD_OUTPUTDIR}/include/"
+	cp -R stage/lib/* "${BUILD_OUTPUTDIR}/lib/"
+	cd "${DEPS_DIR}"
+}
+
+
+
+build_freetype
+build_boostpython

+ 6 - 1
Include/Rocket/Controls/Header.h

@@ -30,7 +30,12 @@
 
 #include "../Core/Platform.h"
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 	#ifdef ROCKET_PLATFORM_WIN32
 		#ifdef RocketControls_EXPORTS
 			#define ROCKETCONTROLS_API __declspec(dllexport)

+ 6 - 1
Include/Rocket/Controls/Lua/Header.h

@@ -34,7 +34,12 @@
 #undef ROCKETLUA_API
 #endif
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 	#ifdef ROCKET_PLATFORM_WIN32
 		#if defined RocketCoreLua_EXPORTS 
 			#define ROCKETLUA_API __declspec(dllexport)

+ 101 - 0
Include/Rocket/Core/BitmapFont/FontProvider.h

@@ -0,0 +1,101 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREBITMAPFONTFONTPROVIDER_H
+#define ROCKETCOREBITMAPFONTFONTPROVIDER_H
+
+#include "../StringUtilities.h"
+#include "../Font.h"
+#include "../FontProvider.h"
+
+namespace Rocket {
+namespace Core {
+
+
+class FontEffect;
+class FontFaceHandle;
+class PropertyDictionary;
+
+namespace BitmapFont {
+
+class FontFamily;
+
+/**
+    The font database contains all font families currently in use by Rocket.
+    @author Peter Curry
+ */
+
+class ROCKETCORE_API FontProvider : public Rocket::Core::FontProvider
+{
+public:
+    static bool Initialise();
+    static void Shutdown();
+
+    /// Adds a new font face to the database. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name);
+    /// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight);
+    /// Adds a new font face to the database, loading from memory. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length);
+    /// Adds a new font face to the database, loading from memory.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
+
+private:
+    FontProvider(void);
+    ~FontProvider(void);
+
+    // Adds a loaded face to the appropriate font family.
+    bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream);
+    // Loads a FreeType face.
+    void* LoadFace(const String& file_name);
+    // Loads a FreeType face from memory.
+    void* LoadFace(const byte* data, int data_length, const String& source, bool local_data);
+
+    static FontProvider* instance;
+};
+
+}
+}
+}
+
+#endif

+ 10 - 0
Include/Rocket/Core/Context.h

@@ -81,9 +81,18 @@ public:
 	/// @return The current dimensions of the context.
 	const Vector2i& GetDimensions() const;
 
+
 	/// Returns the current state of the view.
 	const ViewState& GetViewState() const throw();
 
+	/// Changes the size ratio of 'dp' unit to 'px' unit
+	/// @param[in] dimensions The new density-independent pixel ratio of the context.
+	void SetDensityIndependentPixelRatio(float density_independent_pixel_ratio);
+	/// Returns the size ratio of 'dp' unit to 'px' unit
+	/// @return The current density-independent pixel ratio of the context.
+	float GetDensityIndependentPixelRatio() const;
+
+
 	/// Updates all elements in the context's documents.
 	bool Update();
 	/// Renders all visible elements in the context's documents.
@@ -242,6 +251,7 @@ protected:
 private:
 	String name;
 	Vector2i dimensions;
+	float density_independent_pixel_ratio;
 
 	ContextInstancer* instancer;
 

+ 4 - 0
Include/Rocket/Core/Element.h

@@ -233,6 +233,8 @@ public:
 	/// @return The value of this property for this element.
 	float ResolveProperty(const Property *property, float base_value);
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );
 	/// Returns 'border-width' properties from element's style or local cache.
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
@@ -254,6 +256,8 @@ public:
 	int GetDisplay();
 	/// Returns 'white-space' property value from element's style or local cache.
 	int GetWhitespace();
+	/// Returns 'pointer-events' property value from element's style or local cache.
+	int GetPointerEvents();
 
 	/// Returns 'line-height' property value from element's style or local cache.
 	const Property *GetLineHeightProperty();

+ 3 - 0
Include/Rocket/Core/ElementDocument.h

@@ -147,6 +147,9 @@ protected:
 	/// Returns true if the document has been marked as needing a re-layout.
 	virtual bool IsLayoutDirty();
 
+	/// Updates all sizes defined by the 'lp' unit.
+	virtual void DirtyDpProperties();
+
 	/// Processes the 'onpropertychange' event, checking for a change in position or size.
 	virtual void ProcessEvent(Event& event);
 

+ 4 - 0
Include/Rocket/Core/ElementUtilities.h

@@ -81,6 +81,10 @@ public:
 	/// @param[in] element The element to determine the font face for.
 	/// @return The element's font face. This will be NULL if no valid RCSS font styles have been set up for this element.
 	static FontFaceHandle* GetFontFaceHandle(Element* element);
+	/// Returns an element's density-independent pixel ratio, defined by it's context
+	/// @param[in] element The element to determine the density-independent pixel ratio for.
+	/// @return The density-independent pixel ratio of the context, or 1.0 if no context assigned.
+	static float GetDensityIndependentPixelRatio(Element* element);
 	/// Returns an element's font size, if it has a font defined.
 	/// @param[in] element The element to determine the font size for.
 	/// @return The font size as determined by the element's font, or 0 if it has no font specified.

+ 17 - 10
Include/Rocket/Core/FontDatabase.h

@@ -31,6 +31,7 @@
 #include "StringUtilities.h"
 #include "Header.h"
 #include "Font.h"
+#include "FontProvider.h"
 
 namespace Rocket {
 namespace Core {
@@ -49,6 +50,13 @@ class PropertyDictionary;
 class ROCKETCORE_API FontDatabase
 {
 public:
+
+    enum FontProviderType
+    {
+        FreeType = 0,
+        BitmapFont
+    };
+
 	static bool Initialise();
 	static void Shutdown();
 
@@ -67,7 +75,7 @@ public:
 	/// @param[in] data The font data.
 	/// @param[in] data_length Length of the data.
 	/// @return True if the face was loaded successfully, false otherwise.
-	static bool LoadFontFace(const byte* data, int data_length);
+    static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length);
 	/// Adds a new font face to the database, loading from memory.
 	/// @param[in] data The font data.
 	/// @param[in] data_length Length of the data.
@@ -75,7 +83,7 @@ public:
 	/// @param[in] style The style of the face (normal or italic).
 	/// @param[in] weight The weight of the face (normal or bold).
 	/// @return True if the face was loaded successfully, false otherwise.
-	static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
+    static bool LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
 
 	/// Returns a handle to a font face that can be used to position and render text. This will return the closest match
 	/// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a
@@ -99,20 +107,19 @@ public:
 	/// @param[in] The effect to release.
 	static void ReleaseFontEffect(const FontEffect* effect);
 
+    static void AddFontProvider(FontProvider * provider);
+
+    static void RemoveFontProvider(FontProvider * provider);
+
 private:
 	FontDatabase(void);
 	~FontDatabase(void);
 
-	// Adds a loaded face to the appropriate font family.
-	bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream);
-	// Loads a FreeType face.
-	void* LoadFace(const String& file_name);
-	// Loads a FreeType face from memory.
-	void* LoadFace(const byte* data, int data_length, const String& source, bool local_data);
+    static FontProviderType GetFontProviderType(const String& file_name);
 
-	typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
-	FontFamilyMap font_families;
+    typedef std::vector< FontProvider *> FontProviderTable;
 
+    static FontProviderTable font_provider_table;
 	static FontDatabase* instance;
 };
 

+ 6 - 9
Source/Core/FontFace.h → Include/Rocket/Core/FontFace.h

@@ -28,9 +28,7 @@
 #ifndef ROCKETCOREFONTFACE_H
 #define ROCKETCOREFONTFACE_H
 
-#include "../../Include/Rocket/Core/Font.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include "Font.h"
 
 namespace Rocket {
 namespace Core {
@@ -44,8 +42,8 @@ class FontFaceHandle;
 class FontFace
 {
 public:
-	FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream);
-	~FontFace();
+    FontFace(Font::Style style, Font::Weight weight, bool release_stream);
+    virtual ~FontFace();
 
 	/// Returns the style of the font face.
 	/// @return The font face's style.
@@ -58,14 +56,13 @@ public:
 	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
 	/// @param[in] size The size of the desired handle, in points.
 	/// @return The shared font handle.
-	FontFaceHandle* GetHandle(const String& charset, int size);
+    virtual FontFaceHandle* GetHandle(const String& charset, int size) = 0;
 
 	/// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed,
 	/// but existing ones can still be fetched.
-	void ReleaseFace();
+    virtual void ReleaseFace() = 0;
 
-private:
-	FT_Face face;
+protected:
 	Font::Style style;
 	Font::Weight weight;
 

+ 6 - 7
Source/Core/FontFamily.h → Include/Rocket/Core/FontFamily.h

@@ -28,9 +28,8 @@
 #ifndef ROCKETCOREFONTFAMILY_H
 #define ROCKETCOREFONTFAMILY_H
 
-#include "../../Include/Rocket/Core/Font.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <Rocket/Core/StringUtilities.h>
+#include "Font.h"
 
 namespace Rocket {
 namespace Core {
@@ -46,7 +45,7 @@ class FontFamily
 {
 public:
 	FontFamily(const String& name);
-	~FontFamily();
+    virtual ~FontFamily();
 
 	/// Adds a new face to the family.
 	/// @param[in] ft_face The previously loaded FreeType face.
@@ -54,7 +53,7 @@ public:
 	/// @param[in] weight The weight of the new face.
 	/// @param[in] release_stream True if the application must free the face's memory stream.
 	/// @return True if the face was loaded successfully, false otherwise.
-	bool AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream);
+    virtual bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream) = 0;
 
 	/// Returns a handle to the most appropriate font in the family, at the correct size.
 	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
@@ -62,9 +61,9 @@ public:
 	/// @param[in] weight The weight of the desired handle.
 	/// @param[in] size The size of desired handle, in points.
 	/// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise.
-	FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size);
+    FontFaceHandle* GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size);
 
-private:
+protected:
 	String name;
 
 	typedef std::vector< FontFace* > FontFaceList;

+ 70 - 0
Include/Rocket/Core/FontProvider.h

@@ -0,0 +1,70 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFONTPROVIDER_H
+#define ROCKETCOREFONTPROVIDER_H
+
+#include <Rocket/Core/StringUtilities.h>
+#include <Rocket/Core/Font.h>
+#include <Rocket/Core/Header.h>
+
+namespace Rocket {
+namespace Core {
+
+class FontFaceHandle;
+class FontFamily;
+
+/**
+    The font database contains all font families currently in use by Rocket.
+    @author Peter Curry
+ */
+
+class ROCKETCORE_API FontProvider
+{
+public:
+
+    /// Returns a handle to a font face that can be used to position and render text. This will return the closest match
+    /// it can find, but in the event a font family is requested that does not exist, NULL will be returned instead of a
+    /// valid handle.
+    /// @param[in] family The family of the desired font handle.
+    /// @param[in] charset The set of characters required in the font face, as a comma-separated list of unicode ranges.
+    /// @param[in] style The style of the desired font handle.
+    /// @param[in] weight The weight of the desired font handle.
+    /// @param[in] size The size of desired handle, in points.
+    /// @return A valid handle if a matching (or closely matching) font face was found, NULL otherwise.
+    FontFaceHandle* GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size);
+
+protected:
+
+    typedef std::map< String, FontFamily*, StringUtilities::StringComparei > FontFamilyMap;
+    FontFamilyMap font_families;
+};
+
+}
+}
+
+#endif

+ 101 - 0
Include/Rocket/Core/FreeType/FontProvider.h

@@ -0,0 +1,101 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTPROVIDER_H
+#define ROCKETCOREFREETYPEFONTPROVIDER_H
+
+#include "../StringUtilities.h"
+#include "../Font.h"
+#include "../FontProvider.h"
+
+namespace Rocket {
+namespace Core {
+
+
+class FontEffect;
+class FontFaceHandle;
+class PropertyDictionary;
+
+namespace FreeType {
+
+class FontFamily;
+
+/**
+    The font database contains all font families currently in use by Rocket.
+    @author Peter Curry
+ */
+
+class ROCKETCORE_API FontProvider : public Rocket::Core::FontProvider
+{
+public:
+    static bool Initialise();
+    static void Shutdown();
+
+    /// Adds a new font face to the database. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name);
+    /// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+    /// @param[in] file_name The file to load the face from.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight);
+    /// Adds a new font face to the database, loading from memory. The face's family, style and weight will be determined from the face itself.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length);
+    /// Adds a new font face to the database, loading from memory.
+    /// @param[in] data The font data.
+    /// @param[in] data_length Length of the data.
+    /// @param[in] family The family to add the face to.
+    /// @param[in] style The style of the face (normal or italic).
+    /// @param[in] weight The weight of the face (normal or bold).
+    /// @return True if the face was loaded successfully, false otherwise.
+    static bool LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight);
+
+private:
+    FontProvider(void);
+    ~FontProvider(void);
+
+    // Adds a loaded face to the appropriate font family.
+    bool AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream);
+    // Loads a FreeType face.
+    void* LoadFace(const String& file_name);
+    // Loads a FreeType face from memory.
+    void* LoadFace(const byte* data, int data_length, const String& source, bool local_data);
+
+    static FontProvider* instance;
+};
+
+}
+}
+}
+
+#endif

+ 6 - 1
Include/Rocket/Core/Header.h

@@ -33,7 +33,12 @@
 // Note: Changing a ROCKETCORE_API_INLINE method
 // breaks ABI compatibility!!
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 	#if defined ROCKET_PLATFORM_WIN32
 		#if defined RocketCore_EXPORTS
 			#define ROCKETCORE_API __declspec(dllexport)

+ 6 - 1
Include/Rocket/Core/Lua/Header.h

@@ -34,7 +34,12 @@
 #undef ROCKETLUA_API
 #endif
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 	#ifdef ROCKET_PLATFORM_WIN32
 		#if defined RocketCoreLua_EXPORTS 
 			#define ROCKETLUA_API __declspec(dllexport)

+ 1 - 1
Include/Rocket/Core/Platform.h

@@ -48,7 +48,7 @@
 	#define ROCKET_DEBUG
 #endif
 
-#if defined __LP64__ || defined _M_X64 || defined __MING64__ || defined _LP64
+#if defined __LP64__ || defined _M_X64 || defined __MINGW64__ || defined _LP64
     #define ROCKET_ARCH_64
 #else
     #define ROCKET_ARCH_32

+ 10 - 10
Include/Rocket/Core/Property.h

@@ -60,21 +60,21 @@ public:
 		ABSOLUTE_UNIT = NUMBER | PX | DEG | RAD | COLOUR,
 
 		// Relative values.
-		PERCENT = 1 << 8,			// number suffixed by '%'; fetch as < float >
-		EM = 1 << 9,				// number suffixed by 'em'; fetch as < float >
+		EM = 1 << 8,				// number suffixed by 'em'; fetch as < float >
+		PERCENT = 1 << 9,			// number suffixed by '%'; fetch as < float >
 		REM = 1 << 10,				// number suffixed by 'rem'; fetch as < float >
-		RELATIVE_UNIT = EM | REM | PERCENT,
+		DP = 1 << 11,				// density-independent pixel; number suffixed by 'dp'; fetch as < float >
+		RELATIVE_UNIT = EM | REM | PERCENT | DP,
 
 		// Values based on pixels-per-inch.
-		INCH = 1 << 11,				// number suffixed by 'in'; fetch as < float >
-		CM = 1 << 12,				// number suffixed by 'cm'; fetch as < float >
-		MM = 1 << 13,				// number suffixed by 'mm'; fetch as < float >
-		PT = 1 << 14,				// number suffixed by 'pt'; fetch as < float >
-		PC = 1 << 15,				// number suffixed by 'pc'; fetch as < float >
+		INCH = 1 << 12,				// number suffixed by 'in'; fetch as < float >
+		CM = 1 << 13,				// number suffixed by 'cm'; fetch as < float >
+		MM = 1 << 14,				// number suffixed by 'mm'; fetch as < float >
+		PT = 1 << 15,				// number suffixed by 'pt'; fetch as < float >
+		PC = 1 << 16,				// number suffixed by 'pc'; fetch as < float >
 		PPI_UNIT = INCH | CM | MM | PT | PC,
 
-
-		TRANSFORM = 1 << 16			// transform; fetch as < TransformRef >
+		TRANSFORM = 1 << 17			// transform; fetch as < TransformRef >
 	};
 
 	Property();

+ 2 - 0
Include/Rocket/Core/PropertySpecification.h

@@ -56,6 +56,8 @@ public:
 		REPLICATE,
 		// For 'padding', 'margin', etc; up four properties are expected.
 		BOX,
+		// Recursively resolves the full value string on each property, whether it is a normal property or another shorthand.
+		RECURSIVE,
 		// BOX if four properties are shorthanded and they end in '-top', '-right', etc, otherwise FALL_THROUGH.
 		AUTO
 	};

+ 6 - 1
Include/Rocket/Core/Python/Header.h

@@ -30,7 +30,12 @@
 
 #include "../Platform.h"
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 #if defined ROCKET_PLATFORM_WIN32
 	#if defined RocketCorePython_EXPORTS
 		#define ROCKETCOREPYTHON_API __declspec(dllexport)

+ 3 - 1
Include/Rocket/Core/StyleSheetKeywords.h

@@ -113,6 +113,9 @@ const int TAB_INDEX_AUTO = 1;
 const int FOCUS_NONE = 0;
 const int FOCUS_AUTO = 1;
 
+const int POINTER_EVENTS_AUTO = 0;
+const int POINTER_EVENTS_NONE = 1;
+
 const int PERSPECTIVE_NONE = 0;
 
 const int PERSPECTIVE_ORIGIN_X_LEFT = 0;
@@ -132,7 +135,6 @@ const int TRANSFORM_ORIGIN_X_RIGHT = 2;
 const int TRANSFORM_ORIGIN_Y_TOP = 0;
 const int TRANSFORM_ORIGIN_Y_CENTER = 1;
 const int TRANSFORM_ORIGIN_Y_BOTTOM = 2;
-
 }
 }
 

+ 6 - 1
Include/Rocket/Debugger/Header.h

@@ -30,7 +30,12 @@
 
 #include "../Core/Platform.h"
 
-#if !defined STATIC_LIB
+#ifdef STATIC_LIB
+	#define ROCKET_STATIC_LIB
+	#pragma message("DEPRECATED: STATIC_LIB macro has been deprecated in favor of ROCKET_STATIC_LIB and support will be removed in a future release")
+#endif
+
+#if !defined ROCKET_STATIC_LIB
 	#ifdef ROCKET_PLATFORM_WIN32
 		#ifdef RocketDebugger_EXPORTS
 			#define ROCKETDEBUGGER_API __declspec(dllexport)

+ 270 - 0
Samples/assets/Arial.fnt

@@ -0,0 +1,270 @@
+<?xml version="1.0"?>
+<font>
+  <info face="Arial" size="26" bold="0" italic="0" src="Arial_0.tga"/>
+  <common lineHeight="26" base="26" scaleW="1024" scaleH="1024" />
+  <chars count="191">
+    <char id="32" x="170" y="40" width="1" height="1" xoffset="0" yoffset="21" xadvance="6" />
+    <char id="33" x="643" y="19" width="2" height="17" xoffset="3" yoffset="4" xadvance="8" />
+    <char id="34" x="63" y="41" width="6" height="6" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="35" x="84" y="23" width="13" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="36" x="511" y="0" width="11" height="20" xoffset="1" yoffset="3" xadvance="13" />
+    <char id="37" x="724" y="0" width="18" height="17" xoffset="1" yoffset="4" xadvance="20" />
+    <char id="38" x="56" y="23" width="13" height="17" xoffset="1" yoffset="4" xadvance="15" />
+    <char id="39" x="77" y="41" width="2" height="6" xoffset="1" yoffset="4" xadvance="4" />
+    <char id="40" x="91" y="0" width="5" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="41" x="97" y="0" width="5" height="22" xoffset="2" yoffset="4" xadvance="8" />
+    <char id="42" x="54" y="41" width="8" height="7" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="43" x="916" y="18" width="12" height="12" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="44" x="80" y="41" width="2" height="5" xoffset="2" yoffset="19" xadvance="6" />
+    <char id="45" x="149" y="40" width="7" height="2" xoffset="0" yoffset="14" xadvance="8" />
+    <char id="46" x="167" y="40" width="2" height="2" xoffset="2" yoffset="19" xadvance="6" />
+    <char id="47" x="604" y="19" width="7" height="17" xoffset="0" yoffset="4" xadvance="6" />
+    <char id="48" x="273" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="49" x="620" y="19" width="6" height="17" xoffset="3" yoffset="4" xadvance="13" />
+    <char id="50" x="285" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="51" x="345" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="52" x="441" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="53" x="453" y="21" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="54" x="189" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="55" x="261" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="56" x="201" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="57" x="213" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="58" x="913" y="18" width="2" height="13" xoffset="2" yoffset="8" xadvance="6" />
+    <char id="59" x="717" y="18" width="2" height="16" xoffset="2" yoffset="8" xadvance="6" />
+    <char id="60" x="941" y="18" width="10" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="61" x="32" y="41" width="10" height="7" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="62" x="952" y="18" width="10" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="63" x="225" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="64" x="0" y="0" width="21" height="22" xoffset="1" yoffset="4" xadvance="23" />
+    <char id="65" x="816" y="0" width="17" height="17" xoffset="-1" yoffset="4" xadvance="15" />
+    <char id="66" x="124" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="67" x="919" y="0" width="15" height="17" xoffset="1" yoffset="4" xadvance="17" />
+    <char id="68" x="951" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="69" x="163" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="70" x="237" y="22" width="11" height="17" xoffset="2" yoffset="4" xadvance="14" />
+    <char id="71" x="869" y="0" width="16" height="17" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="72" x="42" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="73" x="640" y="19" width="2" height="17" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="74" x="576" y="19" width="9" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="75" x="996" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="76" x="543" y="19" width="10" height="17" xoffset="2" yoffset="4" xadvance="13" />
+    <char id="77" x="935" y="0" width="15" height="17" xoffset="2" yoffset="4" xadvance="19" />
+    <char id="78" x="70" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="79" x="852" y="0" width="16" height="17" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="80" x="98" y="23" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="81" x="560" y="0" width="16" height="18" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="82" x="981" y="0" width="14" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="83" x="28" y="23" width="13" height="17" xoffset="1" yoffset="4" xadvance="15" />
+    <char id="84" x="1011" y="0" width="12" height="17" xoffset="1" yoffset="4" xadvance="14" />
+    <char id="85" x="14" y="23" width="13" height="17" xoffset="2" yoffset="4" xadvance="17" />
+    <char id="86" x="798" y="0" width="17" height="17" xoffset="-1" yoffset="4" xadvance="15" />
+    <char id="87" x="657" y="0" width="23" height="17" xoffset="0" yoffset="4" xadvance="23" />
+    <char id="88" x="903" y="0" width="15" height="17" xoffset="0" yoffset="4" xadvance="15" />
+    <char id="89" x="966" y="0" width="14" height="17" xoffset="0" yoffset="4" xadvance="14" />
+    <char id="90" x="0" y="23" width="13" height="17" xoffset="0" yoffset="4" xadvance="14" />
+    <char id="91" x="108" y="0" width="4" height="22" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="92" x="612" y="19" width="7" height="17" xoffset="0" yoffset="4" xadvance="6" />
+    <char id="93" x="103" y="0" width="4" height="22" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="94" x="983" y="18" width="10" height="9" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="95" x="111" y="41" width="14" height="2" xoffset="-1" yoffset="24" xadvance="13" />
+    <char id="96" x="106" y="41" width="4" height="3" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="97" x="814" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="98" x="477" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="99" x="850" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="100" x="565" y="19" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="101" x="826" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="102" x="595" y="19" width="8" height="17" xoffset="0" yoffset="4" xadvance="7" />
+    <char id="103" x="614" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="104" x="554" y="19" width="10" height="17" xoffset="1" yoffset="4" xadvance="12" />
+    <char id="105" x="637" y="19" width="2" height="17" xoffset="1" yoffset="4" xadvance="5" />
+    <char id="106" x="85" y="0" width="5" height="22" xoffset="-2" yoffset="4" xadvance="4" />
+    <char id="107" x="249" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="11" />
+    <char id="108" x="646" y="19" width="2" height="17" xoffset="1" yoffset="4" xadvance="4" />
+    <char id="109" x="771" y="18" width="16" height="13" xoffset="1" yoffset="8" xadvance="18" />
+    <char id="110" x="894" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="111" x="802" y="18" width="11" height="13" xoffset="1" yoffset="8" xadvance="13" />
+    <char id="112" x="636" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="113" x="591" y="0" width="11" height="18" xoffset="0" yoffset="8" xadvance="12" />
+    <char id="114" x="905" y="18" width="7" height="13" xoffset="1" yoffset="8" xadvance="8" />
+    <char id="115" x="883" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="116" x="647" y="0" width="6" height="18" xoffset="0" yoffset="3" xadvance="6" />
+    <char id="117" x="861" y="18" width="10" height="13" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="118" x="788" y="18" width="13" height="13" xoffset="-1" yoffset="8" xadvance="11" />
+    <char id="119" x="753" y="18" width="17" height="13" xoffset="-1" yoffset="8" xadvance="15" />
+    <char id="120" x="838" y="18" width="11" height="13" xoffset="0" yoffset="8" xadvance="11" />
+    <char id="121" x="577" y="0" width="13" height="18" xoffset="-1" yoffset="8" xadvance="11" />
+    <char id="122" x="872" y="18" width="10" height="13" xoffset="0" yoffset="8" xadvance="11" />
+    <char id="123" x="71" y="0" width="6" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="124" x="113" y="0" width="2" height="22" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="125" x="78" y="0" width="6" height="22" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="126" x="83" y="41" width="11" height="4" xoffset="1" yoffset="11" xadvance="13" />
+    <char id="160" x="172" y="40" width="1" height="1" xoffset="0" yoffset="21" xadvance="6" />
+    <char id="161" x="654" y="0" width="2" height="18" xoffset="3" yoffset="8" xadvance="8" />
+    <char id="162" x="60" y="0" width="10" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="163" x="111" y="23" width="12" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="164" x="929" y="18" width="11" height="11" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="165" x="176" y="22" width="12" height="17" xoffset="0" yoffset="4" xadvance="13" />
+    <char id="166" x="116" y="0" width="2" height="22" xoffset="2" yoffset="4" xadvance="6" />
+    <char id="167" x="48" y="0" width="11" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="168" x="157" y="40" width="6" height="2" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="169" x="762" y="0" width="17" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="170" x="8" y="41" width="7" height="8" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="171" x="973" y="18" width="9" height="10" xoffset="1" yoffset="10" xadvance="13" />
+    <char id="172" x="43" y="41" width="10" height="7" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="173" x="141" y="40" width="7" height="2" xoffset="0" yoffset="14" xadvance="8" />
+    <char id="174" x="834" y="0" width="17" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="175" x="126" y="40" width="14" height="2" xoffset="-1" yoffset="1" xadvance="13" />
+    <char id="176" x="70" y="41" width="6" height="6" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="177" x="720" y="18" width="12" height="14" xoffset="1" yoffset="7" xadvance="13" />
+    <char id="178" x="16" y="41" width="7" height="8" xoffset="0" yoffset="4" xadvance="8" />
+    <char id="179" x="0" y="41" width="7" height="8" xoffset="0" yoffset="4" xadvance="8" />
+    <char id="180" x="101" y="41" width="4" height="3" xoffset="3" yoffset="4" xadvance="8" />
+    <char id="181" x="603" y="0" width="10" height="18" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="182" x="378" y="0" width="12" height="21" xoffset="0" yoffset="4" xadvance="12" />
+    <char id="183" x="164" y="40" width="2" height="2" xoffset="3" yoffset="12" xadvance="8" />
+    <char id="184" x="95" y="41" width="5" height="4" xoffset="1" yoffset="21" xadvance="8" />
+    <char id="185" x="1017" y="18" width="5" height="8" xoffset="1" yoffset="4" xadvance="8" />
+    <char id="186" x="24" y="41" width="7" height="8" xoffset="1" yoffset="4" xadvance="9" />
+    <char id="187" x="963" y="18" width="9" height="10" xoffset="3" yoffset="10" xadvance="13" />
+    <char id="188" x="705" y="0" width="18" height="17" xoffset="1" yoffset="4" xadvance="19" />
+    <char id="189" x="780" y="0" width="17" height="17" xoffset="1" yoffset="4" xadvance="19" />
+    <char id="190" x="743" y="0" width="18" height="17" xoffset="0" yoffset="4" xadvance="19" />
+    <char id="191" x="625" y="0" width="10" height="18" xoffset="2" yoffset="8" xadvance="14" />
+    <char id="192" x="137" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="193" x="173" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="194" x="191" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="195" x="155" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="196" x="449" y="0" width="17" height="20" xoffset="-1" yoffset="1" xadvance="15" />
+    <char id="197" x="119" y="0" width="17" height="21" xoffset="-1" yoffset="0" xadvance="15" />
+    <char id="198" x="681" y="0" width="23" height="17" xoffset="-1" yoffset="4" xadvance="23" />
+    <char id="199" x="277" y="0" width="15" height="21" xoffset="1" yoffset="4" xadvance="17" />
+    <char id="200" x="404" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="201" x="391" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="202" x="417" y="0" width="12" height="21" xoffset="2" yoffset="0" xadvance="15" />
+    <char id="203" x="498" y="0" width="12" height="20" xoffset="2" yoffset="1" xadvance="15" />
+    <char id="204" x="444" y="0" width="4" height="21" xoffset="1" yoffset="0" xadvance="6" />
+    <char id="205" x="439" y="0" width="4" height="21" xoffset="1" yoffset="0" xadvance="6" />
+    <char id="206" x="430" y="0" width="8" height="21" xoffset="-1" yoffset="0" xadvance="6" />
+    <char id="207" x="523" y="0" width="6" height="20" xoffset="0" yoffset="1" xadvance="6" />
+    <char id="208" x="886" y="0" width="16" height="17" xoffset="0" yoffset="4" xadvance="17" />
+    <char id="209" x="364" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="210" x="209" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="211" x="260" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="212" x="243" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="213" x="226" y="0" width="16" height="21" xoffset="1" yoffset="0" xadvance="18" />
+    <char id="214" x="467" y="0" width="16" height="20" xoffset="1" yoffset="1" xadvance="18" />
+    <char id="215" x="994" y="18" width="9" height="9" xoffset="2" yoffset="8" xadvance="13" />
+    <char id="216" x="542" y="0" width="17" height="18" xoffset="1" yoffset="4" xadvance="18" />
+    <char id="217" x="350" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="218" x="336" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="219" x="322" y="0" width="13" height="21" xoffset="2" yoffset="0" xadvance="17" />
+    <char id="220" x="484" y="0" width="13" height="20" xoffset="2" yoffset="1" xadvance="17" />
+    <char id="221" x="293" y="0" width="14" height="21" xoffset="0" yoffset="0" xadvance="15" />
+    <char id="222" x="137" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="15" />
+    <char id="223" x="150" y="22" width="12" height="17" xoffset="2" yoffset="4" xadvance="14" />
+    <char id="224" x="297" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="225" x="309" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="226" x="321" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="227" x="333" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="228" x="675" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="229" x="530" y="0" width="11" height="19" xoffset="1" yoffset="2" xadvance="13" />
+    <char id="230" x="733" y="18" width="19" height="13" xoffset="1" yoffset="8" xadvance="20" />
+    <char id="231" x="488" y="21" width="10" height="17" xoffset="1" yoffset="8" xadvance="12" />
+    <char id="232" x="465" y="21" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="233" x="357" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="234" x="369" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="235" x="663" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="236" x="627" y="19" width="4" height="17" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="237" x="632" y="19" width="4" height="17" xoffset="1" yoffset="4" xadvance="6" />
+    <char id="238" x="586" y="19" width="8" height="17" xoffset="-1" yoffset="4" xadvance="6" />
+    <char id="239" x="710" y="18" width="6" height="16" xoffset="0" yoffset="5" xadvance="6" />
+    <char id="240" x="381" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="241" x="510" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="242" x="393" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="243" x="405" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="244" x="417" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="245" x="429" y="22" width="11" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="246" x="687" y="18" width="11" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="247" x="1004" y="18" width="12" height="8" xoffset="1" yoffset="9" xadvance="13" />
+    <char id="248" x="649" y="19" width="13" height="16" xoffset="0" yoffset="6" xadvance="13" />
+    <char id="249" x="532" y="20" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="250" x="521" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="251" x="499" y="21" width="10" height="17" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="252" x="699" y="18" width="10" height="16" xoffset="1" yoffset="5" xadvance="13" />
+    <char id="253" x="22" y="0" width="13" height="22" xoffset="-1" yoffset="4" xadvance="12" />
+    <char id="254" x="36" y="0" width="11" height="22" xoffset="1" yoffset="4" xadvance="13" />
+    <char id="255" x="308" y="0" width="13" height="21" xoffset="-1" yoffset="5" xadvance="12" />
+  </chars>
+  <kernings count="70">
+    <kerning first="32" second="65" amount="-1" />
+    <kerning first="49" second="49" amount="-2" />
+    <kerning first="65" second="32" amount="-1" />
+    <kerning first="65" second="84" amount="-2" />
+    <kerning first="65" second="86" amount="-2" />
+    <kerning first="65" second="87" amount="-1" />
+    <kerning first="65" second="89" amount="-2" />
+    <kerning first="70" second="44" amount="-3" />
+    <kerning first="70" second="46" amount="-3" />
+    <kerning first="70" second="65" amount="-1" />
+    <kerning first="76" second="32" amount="-1" />
+    <kerning first="76" second="84" amount="-2" />
+    <kerning first="76" second="86" amount="-2" />
+    <kerning first="76" second="87" amount="-2" />
+    <kerning first="76" second="89" amount="-2" />
+    <kerning first="76" second="121" amount="-1" />
+    <kerning first="80" second="44" amount="-3" />
+    <kerning first="80" second="46" amount="-3" />
+    <kerning first="80" second="65" amount="-2" />
+    <kerning first="84" second="44" amount="-3" />
+    <kerning first="84" second="45" amount="-1" />
+    <kerning first="84" second="46" amount="-3" />
+    <kerning first="84" second="58" amount="-3" />
+    <kerning first="84" second="65" amount="-2" />
+    <kerning first="84" second="97" amount="-3" />
+    <kerning first="84" second="99" amount="-3" />
+    <kerning first="84" second="101" amount="-3" />
+    <kerning first="84" second="105" amount="-1" />
+    <kerning first="84" second="111" amount="-3" />
+    <kerning first="84" second="114" amount="-1" />
+    <kerning first="84" second="115" amount="-3" />
+    <kerning first="84" second="117" amount="-1" />
+    <kerning first="84" second="119" amount="-1" />
+    <kerning first="84" second="121" amount="-1" />
+    <kerning first="86" second="44" amount="-2" />
+    <kerning first="86" second="45" amount="-1" />
+    <kerning first="86" second="46" amount="-2" />
+    <kerning first="86" second="58" amount="-1" />
+    <kerning first="86" second="65" amount="-2" />
+    <kerning first="86" second="97" amount="-2" />
+    <kerning first="86" second="101" amount="-1" />
+    <kerning first="86" second="111" amount="-1" />
+    <kerning first="86" second="114" amount="-1" />
+    <kerning first="86" second="117" amount="-1" />
+    <kerning first="86" second="121" amount="-1" />
+    <kerning first="87" second="44" amount="-1" />
+    <kerning first="87" second="46" amount="-1" />
+    <kerning first="87" second="65" amount="-1" />
+    <kerning first="87" second="97" amount="-1" />
+    <kerning first="89" second="44" amount="-3" />
+    <kerning first="89" second="45" amount="-2" />
+    <kerning first="89" second="46" amount="-3" />
+    <kerning first="89" second="58" amount="-1" />
+    <kerning first="89" second="65" amount="-2" />
+    <kerning first="89" second="97" amount="-2" />
+    <kerning first="89" second="101" amount="-2" />
+    <kerning first="89" second="105" amount="-1" />
+    <kerning first="89" second="111" amount="-2" />
+    <kerning first="89" second="112" amount="-2" />
+    <kerning first="89" second="113" amount="-2" />
+    <kerning first="89" second="117" amount="-1" />
+    <kerning first="89" second="118" amount="-1" />
+    <kerning first="114" second="44" amount="-1" />
+    <kerning first="114" second="46" amount="-1" />
+    <kerning first="118" second="44" amount="-2" />
+    <kerning first="118" second="46" amount="-2" />
+    <kerning first="119" second="44" amount="-1" />
+    <kerning first="119" second="46" amount="-1" />
+    <kerning first="121" second="44" amount="-2" />
+    <kerning first="121" second="46" amount="-2" />
+  </kernings>
+</font>

BIN
Samples/assets/Arial_0.tga


+ 28 - 0
Samples/assets/bitmapfont.rml

@@ -0,0 +1,28 @@
+<rml>
+	<head>
+		<title>Demo</title>
+		<link type="text/template" href="window.rml" />
+		<style>
+			body
+			{
+				width: 300px;
+				height: 225px;
+				font-family: Arial;
+				margin: auto;
+			}
+			
+			div#title_bar div#icon
+			{
+				display: none;
+			}
+			
+			div#content
+			{
+				text-align: left;
+			}
+		</style>
+	</head>
+	<body template="window">
+		This is a bitmap font<br/>sample.
+	</body>
+</rml>

+ 130 - 0
Samples/basic/bitmapfont/src/main.cpp

@@ -0,0 +1,130 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <Rocket/Core.h>
+#include <Rocket/Debugger.h>
+#include <Input.h>
+#include <Shell.h>
+
+Rocket::Core::Context* context = NULL;
+
+ShellRenderInterfaceExtensions *shell_renderer;
+
+void GameLoop()
+{
+	context->Update();
+
+	shell_renderer->PrepareRenderBuffer();
+	context->Render();
+	shell_renderer->PresentRenderBuffer();
+}
+
+#if defined ROCKET_PLATFORM_WIN32
+#include <windows.h>
+int APIENTRY WinMain(HINSTANCE ROCKET_UNUSED_PARAMETER(instance_handle), HINSTANCE ROCKET_UNUSED_PARAMETER(previous_instance_handle), char* ROCKET_UNUSED_PARAMETER(command_line), int ROCKET_UNUSED_PARAMETER(command_show))
+#else
+int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv))
+#endif
+{
+#ifdef ROCKET_PLATFORM_WIN32
+	ROCKET_UNUSED(instance_handle);
+	ROCKET_UNUSED(previous_instance_handle);
+	ROCKET_UNUSED(command_line);
+	ROCKET_UNUSED(command_show);
+#else
+	ROCKET_UNUSED(argc);
+	ROCKET_UNUSED(argv);
+#endif
+
+#ifdef ROCKET_PLATFORM_LINUX
+#define APP_PATH "../Samples/basic/loaddocument/"
+#else
+#define APP_PATH "../../Samples/basic/loaddocument/"
+#endif
+
+#ifdef ROCKET_PLATFORM_WIN32
+        AllocConsole();
+#endif
+
+        int window_width = 1024;
+        int window_height = 768;
+
+	ShellRenderInterfaceOpenGL opengl_renderer;
+	shell_renderer = &opengl_renderer;
+
+	// Generic OS initialisation, creates a window and attaches OpenGL.
+	if (!Shell::Initialise(APP_PATH) ||
+		!Shell::OpenWindow("Load Document Sample", shell_renderer, window_width, window_height, true))
+	{
+		Shell::Shutdown();
+		return -1;
+	}
+
+	// Rocket initialisation.
+	Rocket::Core::SetRenderInterface(&opengl_renderer);
+	shell_renderer->SetViewport(window_width, window_height);
+
+	ShellSystemInterface system_interface;
+	Rocket::Core::SetSystemInterface(&system_interface);
+
+	Rocket::Core::Initialise();
+
+	// Create the main Rocket context and set it on the shell's input layer.
+	context = Rocket::Core::CreateContext("main", Rocket::Core::Vector2i(window_width, window_height));
+	if (context == NULL)
+	{
+		Rocket::Core::Shutdown();
+		Shell::Shutdown();
+		return -1;
+	}
+
+	Rocket::Debugger::Initialise(context);
+	Input::SetContext(context);
+	shell_renderer->SetContext(context);
+
+    // Load bitmap font
+    Rocket::Core::FontDatabase::LoadFontFace("../../assets/Arial.fnt");
+	
+    // Load and show the demo document.
+	Rocket::Core::ElementDocument* document = context->LoadDocument("../../assets/bitmapfont.rml");
+	if (document != NULL)
+	{
+		document->Show();
+		document->RemoveReference();
+	}
+
+	Shell::EventLoop(GameLoop);
+
+	// Shutdown Rocket.
+	context->RemoveReference();
+	Rocket::Core::Shutdown();
+
+	Shell::CloseWindow();
+	Shell::Shutdown();
+
+	return 0;
+}

+ 1 - 1
Samples/basic/customlog/src/main.cpp

@@ -68,7 +68,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
 	int window_width = 1024;

+ 1 - 1
Samples/basic/drag/src/main.cpp

@@ -68,7 +68,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
         int window_width = 1024;

+ 1 - 1
Samples/basic/loaddocument/src/main.cpp

@@ -67,7 +67,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
         int window_width = 1024;

+ 12 - 0
Samples/basic/sdl2/src/main.cpp

@@ -154,8 +154,20 @@ int main(int argc, char **argv)
                     break;
 
                 case SDL_KEYDOWN:
+                {
+                    // Intercept SHIFT + ~ key stroke to toggle libRocket's 
+                    // visual debugger tool
+                    if( event.key.keysym.sym == SDLK_BACKQUOTE && 
+                        event.key.keysym.mod == KMOD_LSHIFT )
+                    {
+                        Rocket::Debugger::SetVisible( ! Rocket::Debugger::IsVisible() );
+                        break;
+                    }
+                    
                     Context->ProcessKeyDown(SystemInterface.TranslateKey(event.key.keysym.sym), SystemInterface.GetKeyModifiers());
                     break;
+                }
+                
                 default:
                     break;
             }

+ 1 - 1
Samples/basic/sfml2/src/main.cpp

@@ -46,7 +46,7 @@
 int main(int argc, char **argv)
 {
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
         int window_width = 1024;

+ 1 - 1
Samples/basic/treeview/src/main.cpp

@@ -70,7 +70,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
         int window_width = 1024;

+ 1 - 1
Samples/luainvaders/src/LuaInterface.cpp

@@ -84,7 +84,7 @@ int GameSetPaused(lua_State* L)
 
 int GameSetDifficulty(lua_State* L)
 {
-    int difficulty = luaL_checkint(L,1);
+    int difficulty = luaL_checkinteger(L,1);
     GameDetails::SetDifficulty((GameDetails::Difficulty)difficulty);
     return 0;
 }

+ 1 - 0
Samples/pyinvaders/src/main.cpp

@@ -74,6 +74,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 // @TODO Make these lookup at runtime rather than using hard coded paths
 #ifdef ROCKET_PLATFORM_LINUX
 #define APP_PATH "../Samples/pyinvaders/"
+#define ROCKET_PATH ""
 #else
 #define APP_PATH "../../Samples/pyinvaders/"
 #define ROCKET_PATH "."

+ 3 - 1
Samples/shell/src/macosx/ShellRenderInterfaceExtensionsOpenGL_MacOSX.cpp

@@ -105,7 +105,9 @@ bool ShellRenderInterfaceOpenGL::AttachToNative(void *nativeWindow)
 	
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
-	glOrtho(0, 1024, 768, 0, -1, 1);
+	Rect crect;
+	GetWindowBounds(window, kWindowContentRgn, &crect);
+	glOrtho(0, (crect.right - crect.left), (crect.bottom - crect.top), 0, -1, 1);
 	
 	glMatrixMode(GL_MODELVIEW);
 	glLoadIdentity();

+ 1 - 1
Samples/tutorial/datagrid/src/main.cpp

@@ -54,7 +54,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
 	ShellRenderInterfaceOpenGL opengl_renderer;

+ 1 - 1
Samples/tutorial/datagrid_tree/src/main.cpp

@@ -55,7 +55,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
 	int window_width = 1024;

+ 1 - 1
Samples/tutorial/template/src/main.cpp

@@ -51,7 +51,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
 	int window_width = 1024;

+ 1 - 1
Samples/tutorial/tutorial_drag/src/main.cpp

@@ -52,7 +52,7 @@ int main(int ROCKET_UNUSED_PARAMETER(argc), char** ROCKET_UNUSED_PARAMETER(argv)
 #endif
 
 #ifdef ROCKET_PLATFORM_WIN32
-        DoAllocConsole();
+        AllocConsole();
 #endif
 
 	int window_width = 1024;

+ 1 - 1
Source/Controls/ElementDataGridRow.cpp

@@ -249,7 +249,7 @@ ElementDataGrid* ElementDataGridRow::GetParentGrid()
 	return parent_grid;
 }
 
-void ElementDataGridRow::OnDataSourceDestroy(DataSource* data_source)
+void ElementDataGridRow::OnDataSourceDestroy(DataSource* ROCKET_UNUSED_PARAMETER(_data_source))
 {
 	if(data_source != NULL)
 	{

+ 6 - 6
Source/Controls/Lua/DataSource.cpp

@@ -48,8 +48,8 @@ int DataSourceNotifyRowAdd(lua_State* L, DataSource* obj)
 {
     LUACHECKOBJ(obj);
     const char* table_name = luaL_checkstring(L,1);
-    int first_row_added = luaL_checkint(L,2);
-    int num_rows_added = luaL_checkint(L,3);
+    int first_row_added = luaL_checkinteger(L,2);
+    int num_rows_added = luaL_checkinteger(L,3);
     obj->NotifyRowAdd(table_name,first_row_added,num_rows_added);
     return 0;
 }
@@ -58,8 +58,8 @@ int DataSourceNotifyRowRemove(lua_State* L, DataSource* obj)
 {
     LUACHECKOBJ(obj);
     const char* table_name = luaL_checkstring(L,1);
-    int first_row_removed = luaL_checkint(L,2);
-    int num_rows_removed = luaL_checkint(L,3);
+    int first_row_removed = luaL_checkinteger(L,2);
+    int num_rows_removed = luaL_checkinteger(L,3);
     obj->NotifyRowRemove(table_name,first_row_removed,num_rows_removed);
     return 0;
 }
@@ -74,8 +74,8 @@ int DataSourceNotifyRowChange(lua_State* L, DataSource* obj)
     }
     else
     {
-        int first_row_changed = luaL_checkint(L,2);
-        int num_rows_changed = luaL_checkint(L,3);
+        int first_row_changed = luaL_checkinteger(L,2);
+        int num_rows_changed = luaL_checkinteger(L,3);
         obj->NotifyRowChange(table_name,first_row_changed,num_rows_changed);
     }
     return 0;

+ 5 - 5
Source/Controls/Lua/ElementFormControlInput.cpp

@@ -103,7 +103,7 @@ int ElementFormControlInputSetAttrmaxlength(lua_State* L)
 {
     ElementFormControlInput* obj = LuaType<ElementFormControlInput>::check(L,1);
     LUACHECKOBJ(obj);
-    int maxlength = luaL_checkint(L,2);
+    int maxlength = luaL_checkinteger(L,2);
     obj->SetAttribute("maxlength",maxlength);
     return 0;
 }
@@ -112,7 +112,7 @@ int ElementFormControlInputSetAttrsize(lua_State* L)
 {
     ElementFormControlInput* obj = LuaType<ElementFormControlInput>::check(L,1);
     LUACHECKOBJ(obj);
-    int size = luaL_checkint(L,2);
+    int size = luaL_checkinteger(L,2);
     obj->SetAttribute("size",size);
     return 0;
 }
@@ -121,7 +121,7 @@ int ElementFormControlInputSetAttrmax(lua_State* L)
 {
     ElementFormControlInput* obj = LuaType<ElementFormControlInput>::check(L,1);
     LUACHECKOBJ(obj);
-    int max = luaL_checkint(L,2);
+    int max = luaL_checkinteger(L,2);
     obj->SetAttribute("max",max);
     return 0;
 }
@@ -130,7 +130,7 @@ int ElementFormControlInputSetAttrmin(lua_State* L)
 {
     ElementFormControlInput* obj = LuaType<ElementFormControlInput>::check(L,1);
     LUACHECKOBJ(obj);
-    int min = luaL_checkint(L,2);
+    int min = luaL_checkinteger(L,2);
     obj->SetAttribute("min",min);
     return 0;
 }
@@ -139,7 +139,7 @@ int ElementFormControlInputSetAttrstep(lua_State* L)
 {
     ElementFormControlInput* obj = LuaType<ElementFormControlInput>::check(L,1);
     LUACHECKOBJ(obj);
-    int step = luaL_checkint(L,2);
+    int step = luaL_checkinteger(L,2);
     obj->SetAttribute("step",step);
     return 0;
 }

+ 3 - 3
Source/Controls/Lua/ElementFormControlSelect.cpp

@@ -46,7 +46,7 @@ int ElementFormControlSelectAdd(lua_State* L, ElementFormControlSelect* obj)
     const char* value = luaL_checkstring(L,2);
     int before = -1; //default
     if(lua_gettop(L) >= 3)
-        before = luaL_checkint(L,3);
+        before = luaL_checkinteger(L,3);
 
     int index = obj->Add(rml,value,before);
     lua_pushinteger(L,index);
@@ -55,7 +55,7 @@ int ElementFormControlSelectAdd(lua_State* L, ElementFormControlSelect* obj)
 
 int ElementFormControlSelectRemove(lua_State* L, ElementFormControlSelect* obj)
 {
-    int index = luaL_checkint(L,1);
+    int index = luaL_checkinteger(L,1);
     obj->Remove(index);
     return 0;
 }
@@ -86,7 +86,7 @@ int ElementFormControlSelectSetAttrselection(lua_State* L)
 {
     ElementFormControlSelect* obj = LuaType<ElementFormControlSelect>::check(L,1);
     LUACHECKOBJ(obj);
-    int selection = luaL_checkint(L,2);
+    int selection = luaL_checkinteger(L,2);
     obj->SetSelection(selection);
     return 0;
 }

+ 3 - 3
Source/Controls/Lua/ElementFormControlTextArea.cpp

@@ -74,7 +74,7 @@ int ElementFormControlTextAreaSetAttrcols(lua_State* L)
 {
     ElementFormControlTextArea* obj = LuaType<ElementFormControlTextArea>::check(L,1);
     LUACHECKOBJ(obj);
-    int cols = luaL_checkint(L,2);
+    int cols = luaL_checkinteger(L,2);
     obj->SetNumColumns(cols);
     return 0;
 }
@@ -83,7 +83,7 @@ int ElementFormControlTextAreaSetAttrmaxlength(lua_State* L)
 {
     ElementFormControlTextArea* obj = LuaType<ElementFormControlTextArea>::check(L,1);
     LUACHECKOBJ(obj);
-    int ml = luaL_checkint(L,2);
+    int ml = luaL_checkinteger(L,2);
     obj->SetMaxLength(ml);
     return 0;
 }
@@ -92,7 +92,7 @@ int ElementFormControlTextAreaSetAttrrows(lua_State* L)
 {
     ElementFormControlTextArea* obj = LuaType<ElementFormControlTextArea>::check(L,1);
     LUACHECKOBJ(obj);
-    int rows = luaL_checkint(L,2);
+    int rows = luaL_checkinteger(L,2);
     obj->SetNumRows(rows);
     return 0;
 }

+ 3 - 3
Source/Controls/Lua/ElementTabSet.cpp

@@ -39,7 +39,7 @@ namespace Lua {
 int ElementTabSetSetPanel(lua_State* L, ElementTabSet* obj)
 {
     LUACHECKOBJ(obj);
-    int index = luaL_checkint(L,1);
+    int index = luaL_checkinteger(L,1);
     const char* rml = luaL_checkstring(L,2);
 
     obj->SetPanel(index,rml);
@@ -49,7 +49,7 @@ int ElementTabSetSetPanel(lua_State* L, ElementTabSet* obj)
 int ElementTabSetSetTab(lua_State* L, ElementTabSet* obj)
 {
     LUACHECKOBJ(obj);
-    int index = luaL_checkint(L,1);
+    int index = luaL_checkinteger(L,1);
     const char* rml = luaL_checkstring(L,2);
 
     obj->SetTab(index,rml);
@@ -82,7 +82,7 @@ int ElementTabSetSetAttractive_tab(lua_State* L)
 {
     ElementTabSet* obj = LuaType<ElementTabSet>::check(L,1);
     LUACHECKOBJ(obj);
-    int tab = luaL_checkint(L,2);
+    int tab = luaL_checkinteger(L,2);
     obj->SetActiveTab(tab);
     return 0;
 }

+ 1 - 1
Source/Controls/Lua/LuaDataSource.cpp

@@ -98,7 +98,7 @@ int LuaDataSource::GetNumRows(const Rocket::Core::String& table)
     int res = lua_gettop(L);
     if(lua_type(L,res) == LUA_TNUMBER)
     {
-        return luaL_checkint(L,res);
+        return luaL_checkinteger(L,res);
     }
     else
     {

+ 1 - 1
Source/Controls/Lua/SelectOptionsProxy.cpp

@@ -43,7 +43,7 @@ int SelectOptionsProxy__index(lua_State* L)
     {
         SelectOptionsProxy* proxy = LuaType<SelectOptionsProxy>::check(L,1);
         LUACHECKOBJ(proxy);
-        int index = luaL_checkint(L,2);
+        int index = luaL_checkinteger(L,2);
         Rocket::Controls::SelectOption* opt = proxy->owner->GetOption(index);
         LUACHECKOBJ(opt);
         lua_newtable(L);

+ 18 - 3
Source/Controls/WidgetDropDown.cpp

@@ -71,7 +71,11 @@ WidgetDropDown::WidgetDropDown(ElementFormControl* element)
 
 WidgetDropDown::~WidgetDropDown()
 {
-	ClearOptions();
+	// We shouldn't clear the options ourselves, as removing the element will automatically clear children.
+	//   Not always a problem, but sometimes it invalidates the layout lock in Element::RemoveChild, which results in a permanently corrupted document.
+	//   However, we do need to remove events of children.
+	for(auto& option : options)
+		option.GetElement()->RemoveEventListener("click", this);
 
 	parent_element->RemoveEventListener("click", this, true);
 	parent_element->RemoveEventListener("blur", this);
@@ -146,6 +150,9 @@ void WidgetDropDown::SetValue(const Rocket::Core::String& _value)
 		}
 	}
 
+	if (selected_option >= 0 && selected_option < (int)options.size())
+		options[selected_option].GetElement()->SetPseudoClass("checked", false);
+
 	value = _value;
 	value_element->SetInnerRML(value);
 	value_layout_dirty = true;
@@ -178,12 +185,20 @@ void WidgetDropDown::SetSelection(int selection, bool force)
 		selection != selected_option ||
 		value != new_value)
 	{
+		if (selected_option >= 0 && selected_option < (int)options.size())
+			options[selected_option].GetElement()->SetPseudoClass("checked", false);
+		
 		selected_option = selection;
 		value = new_value;
 
 		Rocket::Core::String value_rml;
-		if (selected_option >= 0)
-			options[selected_option].GetElement()->GetInnerRML(value_rml);
+		if (selected_option >= 0) 
+		{
+			auto* el = options[selected_option].GetElement();
+			el->GetInnerRML(value_rml);
+			el->SetPseudoClass("checked", true);
+		}
+
 
 		value_element->SetInnerRML(value_rml);
 		value_layout_dirty = true;

+ 54 - 32
Source/Controls/WidgetSlider.cpp

@@ -58,21 +58,24 @@ WidgetSlider::~WidgetSlider()
 {
 	if (bar != NULL)
 	{
-		bar->RemoveEventListener("drag", this);
-		bar->RemoveEventListener("dragstart", this);
 		parent->RemoveChild(bar);
 	}
 
-	parent->RemoveEventListener("blur", this);
-	parent->RemoveEventListener("focus", this);
-	parent->RemoveEventListener("keydown", this, true);
-
 	if (track != NULL)
 	{
-		track->RemoveEventListener("click", this);
+		track->RemoveEventListener("mousedown", this);
 		parent->RemoveChild(track);
 	}
 
+	parent->RemoveEventListener("blur", this);
+	parent->RemoveEventListener("focus", this);
+	parent->RemoveEventListener("keydown", this, true);
+	parent->RemoveEventListener("mousedown", this);
+
+	parent->RemoveEventListener("drag", this);
+	parent->RemoveEventListener("dragstart", this);
+	parent->RemoveEventListener("dragend", this);
+
 	for (int i = 0; i < 2; i++)
 	{
 		if (arrows[i] != NULL)
@@ -88,14 +91,17 @@ WidgetSlider::~WidgetSlider()
 // Initialises the slider to a given orientation.
 bool WidgetSlider::Initialise()
 {
+	parent->SetProperty("drag", "drag");
+
 	// Create all of our child elements as standard elements, and abort if we can't create them.
 	track = Core::Factory::InstanceElement(parent, "*", "slidertrack", Rocket::Core::XMLAttributes());
 
 	bar = Core::Factory::InstanceElement(parent, "*", "sliderbar", Rocket::Core::XMLAttributes());
-	bar->SetProperty("drag", "drag");
 
 	arrows[0] = Core::Factory::InstanceElement(parent, "*", "sliderarrowdec", Rocket::Core::XMLAttributes());
 	arrows[1] = Core::Factory::InstanceElement(parent, "*", "sliderarrowinc", Rocket::Core::XMLAttributes());
+	arrows[0]->SetProperty("drag", "drag");
+	arrows[1]->SetProperty("drag", "drag");
 
 	if (track == NULL ||
 		bar == NULL ||
@@ -130,13 +136,16 @@ bool WidgetSlider::Initialise()
 	arrows[1]->RemoveReference();
 
 	// Attach the listeners as appropriate.
-	bar->AddEventListener("drag", this);
-	bar->AddEventListener("dragstart", this);
+	track->AddEventListener("mousedown", this);
 
 	parent->AddEventListener("blur", this);
 	parent->AddEventListener("focus", this);
 	parent->AddEventListener("keydown", this, true);
-	track->AddEventListener("click", this);
+	parent->AddEventListener("mousedown", this);
+
+	parent->AddEventListener("drag", this);
+	parent->AddEventListener("dragstart", this);
+	parent->AddEventListener("dragend", this);
 
 	for (int i = 0; i < 2; i++)
 	{
@@ -383,7 +392,40 @@ void WidgetSlider::ProcessEvent(Core::Event& event)
 	if (parent->IsDisabled())
 		return;
 
-	if (event.GetTargetElement() == bar)
+	if (event == "mousedown")
+	{
+		if(event.GetTargetElement() == parent || event.GetTargetElement() == track) 
+		{
+			if (orientation == HORIZONTAL)
+			{
+				float mouse_position = event.GetParameter< float >("mouse_x", 0);
+				float click_position = (mouse_position - track->GetAbsoluteOffset().x) / track->GetBox().GetSize().x;
+
+				SetBarPosition(click_position <= bar_position ? OnPageDecrement(click_position) : OnPageIncrement(click_position));
+			}
+			else
+			{
+				float mouse_position = event.GetParameter< float >("mouse_y", 0);
+				float click_position = (mouse_position - track->GetAbsoluteOffset().y) / track->GetBox().GetSize().y;
+
+				SetBarPosition(click_position <= bar_position ? OnPageDecrement(click_position) : OnPageIncrement(click_position));
+			}
+		}
+	}
+
+	if (event.GetTargetElement() == parent)
+	{
+		if (event == "dragstart")
+		{
+			bar->SetPseudoClass("active", true);
+		}
+		else if (event == "dragend")
+		{
+			bar->SetPseudoClass("active", false);
+		}
+	}
+
+	if (event.GetTargetElement() == parent)
 	{
 		if (event == "drag")
 		{
@@ -420,26 +462,6 @@ void WidgetSlider::ProcessEvent(Core::Event& event)
 				bar_drag_anchor = event.GetParameter< int >("mouse_y", 0) - Rocket::Core::Math::RealToInteger(bar->GetAbsoluteOffset().y);
 		}
 	}
-	else if (event.GetTargetElement() == track)
-	{
-		if (event == "click")
-		{
-			if (orientation == HORIZONTAL)
-			{
-				float mouse_position = event.GetParameter< float >("mouse_x", 0);
-				float click_position = (mouse_position - track->GetAbsoluteOffset().x) / track->GetBox().GetSize().x;
-
-				SetBarPosition(click_position <= bar_position ? OnPageDecrement(click_position) : OnPageIncrement(click_position));
-			}
-			else
-			{
-				float mouse_position = event.GetParameter< float >("mouse_y", 0);
-				float click_position = (mouse_position - track->GetAbsoluteOffset().y) / track->GetBox().GetSize().y;
-
-				SetBarPosition(click_position <= bar_position ? OnPageDecrement(click_position) : OnPageIncrement(click_position));
-			}
-		}
-	}
 
 	if (event == "mousedown")
 	{

+ 147 - 0
Source/Core/BitmapFont/BitmapFontDefinitions.h

@@ -0,0 +1,147 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef BITMAPFONTDEFINITIONS_H
+#define BITMAPFONTDEFINITIONS_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/Types.h>
+#include <Rocket/Core/Dictionary.h>
+#include <set>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+	struct FontInfo
+	{
+		String FamilyName;
+		String Source;
+		String BitmapSource;
+		int Size;
+		Font::Style Style;
+		Font::Weight Weight;
+	};
+
+	struct CharacterCommonInfo
+	{
+		int LineHeight;
+		int BaseLine;
+		int ScaleWidth;
+		int ScaleHeight;
+		int CharacterCount;
+		int KerningCount;
+	};
+
+	struct CharacterInfo
+	{
+		int Id;
+		int X;
+		int Y;
+		int Width;
+		int Height;
+		int XOffset;
+		int YOffset;
+		int Advance;
+	};
+
+	struct KerningInfo
+	{
+		int FirstCharacterId;
+		int SecondCharacterId;
+		int KerningAmount;
+	};
+
+	class BitmapFontDefinitions
+	{
+	public:
+		FontInfo Face;
+		CharacterCommonInfo CommonCharactersInfo;
+		CharacterInfo *CharactersInfo;
+		KerningInfo *KerningsInfo;
+
+		int BM_Helper_GetCharacterTableIndex( int unicode_code )
+		{
+			return BinarySearch( unicode_code, 0, CommonCharactersInfo.CharacterCount );
+		}
+
+		int BM_Helper_GetXKerning( int left_uni_id, int right_uni_id )
+		{
+			for ( int i = 0; i < this->CommonCharactersInfo.KerningCount; i++ )
+			{
+				if ( this->KerningsInfo[i].FirstCharacterId == left_uni_id && this->KerningsInfo[i].SecondCharacterId == right_uni_id )
+				{
+					return this->KerningsInfo[i].KerningAmount;
+				}
+			}
+
+			return 0;
+		}
+
+	private:
+
+		int BinarySearch( int unicode_code, int min_index, int max_index )
+		{
+			if ( abs( max_index - min_index ) <= 1 )
+			{
+				if ( this->CharactersInfo[ min_index ].Id == unicode_code )
+				{
+					return min_index;
+				}
+				else if ( this->CharactersInfo[ max_index ].Id == unicode_code )
+				{
+					return max_index;
+				}
+				else
+				{
+					return -1;
+				}
+			}
+			else
+			{
+				int mid_index = ( min_index + max_index ) / 2;
+
+				if ( this->CharactersInfo[ mid_index ].Id == unicode_code )
+				{
+					return mid_index;
+				}
+				else if ( this->CharactersInfo[ mid_index ].Id > unicode_code )
+				{
+					return BinarySearch( unicode_code, min_index, mid_index );
+				}
+				else
+				{
+					return BinarySearch( unicode_code, mid_index, max_index );
+				}
+			}
+		}
+	};
+
+}
+}
+}
+#endif

+ 130 - 0
Source/Core/BitmapFont/FontFace.cpp

@@ -0,0 +1,130 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFace.h"
+#include "FontFaceHandle.h"
+#include <Rocket/Core/Log.h>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontFace::FontFace(BitmapFontDefinitions *_face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream)
+{
+	face = _face;
+}
+
+FontFace::~FontFace()
+{
+	ReleaseFace();
+}
+
+// Returns a handle for positioning and rendering this face at the given size.
+Rocket::Core::FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
+{
+	UnicodeRangeList charset;
+
+	HandleMap::iterator iterator = handles.find(size);
+	if (iterator != handles.end())
+	{
+		const HandleList& handles = (*iterator).second;
+
+		// Check all the handles if their charsets match the requested one exactly (ie, were specified by the same
+		// string).
+		String raw_charset(_raw_charset);
+		for (size_t i = 0; i < handles.size(); ++i)
+		{
+			if (handles[i]->GetRawCharset() == _raw_charset)
+			{
+				handles[i]->AddReference();
+				return (FontFaceHandle*)handles[i];
+			}
+		}
+
+		// Check all the handles if their charsets contain the requested charset.
+		if (!UnicodeRange::BuildList(charset, raw_charset))
+		{
+			Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString());
+			return NULL;
+		}
+
+		for (size_t i = 0; i < handles.size(); ++i)
+		{
+			bool range_contained = true;
+
+			const UnicodeRangeList& handle_charset = handles[i]->GetCharset();
+			for (size_t j = 0; j < charset.size() && range_contained; ++j)
+			{
+				if (!charset[j].IsContained(handle_charset))
+					range_contained = false;
+			}
+
+			if (range_contained)
+			{
+				handles[i]->AddReference();
+				return (FontFaceHandle*)handles[i];
+			}
+		}
+	}
+
+	// See if this face has been released.
+	if (face == NULL)
+	{
+		Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle.");
+		return NULL;
+	}
+
+	// Construct and initialise the new handle.
+	FontFaceHandle* handle = new FontFaceHandle();
+	if (!handle->Initialise(face, _raw_charset, size))
+	{
+		handle->RemoveReference();
+		return NULL;
+	}
+
+	// Save the handle, and add a reference for the callee. The initial reference will be removed when the font face
+	// releases it.
+	if (iterator != handles.end())
+		(*iterator).second.push_back(handle);
+	else
+		handles[size] = HandleList(1, handle);
+
+	handle->AddReference();
+
+	return handle;
+}
+
+// Releases the face's structure.
+void FontFace::ReleaseFace()
+{
+	delete face;
+}
+
+}
+}
+}

+ 68 - 0
Source/Core/BitmapFont/FontFace.h

@@ -0,0 +1,68 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREBITMAPFONTFACE_H
+#define ROCKETCOREBITMAPFONTFACE_H
+
+#include "../../../Include/Rocket/Core/FontFace.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+class FontFaceHandle;
+
+/**
+	@author Peter Curry
+ */
+
+class FontFace : public Rocket::Core::FontFace
+{
+public:
+	FontFace(BitmapFontDefinitions *_face, Font::Style style, Font::Weight weight, bool release_stream);
+	~FontFace();
+
+	/// Returns a handle for positioning and rendering this face at the given size.
+	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
+	/// @param[in] size The size of the desired handle, in points.
+	/// @return The shared font handle.
+	Rocket::Core::FontFaceHandle* GetHandle(const String& charset, int size);
+
+	/// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed,
+	/// but existing ones can still be fetched.
+	void ReleaseFace();
+
+private:
+	BitmapFontDefinitions *face;
+};
+
+}
+}
+}
+
+#endif

+ 428 - 0
Source/Core/BitmapFont/FontFaceHandle.cpp

@@ -0,0 +1,428 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFaceHandle.h"
+#include "FontFaceLayer.h"
+#include <algorithm>
+#include "../TextureLayout.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+class FontEffectSort
+{
+public:
+	bool operator()(const Rocket::Core::FontEffect* lhs, const Rocket::Core::FontEffect* rhs)
+	{
+		return lhs->GetZIndex() < rhs->GetZIndex();
+	}
+};
+
+FontFaceHandle::FontFaceHandle()
+{
+	size = 0;
+	average_advance = 0;
+	x_height = 0;
+	line_height = 0;
+	baseline = 0;
+
+	underline_position = 0;
+	underline_thickness = 0;
+
+	base_layer = NULL;
+}
+
+FontFaceHandle::~FontFaceHandle()
+{
+}
+
+// Initialises the handle so it is able to render text.
+bool FontFaceHandle::Initialise(BitmapFontDefinitions *bm_face, const String& _charset, int _size)
+{
+	this->bm_face = bm_face;
+	size = _size;
+	line_height = _size;
+	texture_width = bm_face->CommonCharactersInfo.ScaleWidth;
+	texture_height = bm_face->CommonCharactersInfo.ScaleHeight;
+	raw_charset = _charset;
+
+	// Construct proper path to texture
+	URL fnt_source = bm_face->Face.Source;
+	URL bitmap_source = bm_face->Face.BitmapSource;
+	if(bitmap_source.GetPath().Empty())
+	{
+		texture_source = fnt_source.GetPath() + bitmap_source.GetFileName();
+		if(!bitmap_source.GetExtension().Empty())
+		{
+			texture_source += "." + bitmap_source.GetExtension();
+		}
+	}
+	else
+	{
+		texture_source = bitmap_source.GetPathedFileName();
+	}
+
+	if (!UnicodeRange::BuildList(charset, raw_charset))
+	{
+		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
+		return false;
+	}
+
+	// Construct the list of the characters specified by the charset.
+	for (size_t i = 0; i < charset.size(); ++i)
+		BuildGlyphMap(bm_face, charset[i]);
+
+	// Generate the metrics for the handle.
+	GenerateMetrics(bm_face);
+
+	// Generate the default layer and layer configuration.
+	base_layer = GenerateLayer(NULL);
+	layer_configurations.push_back(LayerConfiguration());
+	layer_configurations.back().push_back(base_layer);
+
+	return true;
+}
+
+// Returns the width a string will take up if rendered with this handle.
+int FontFaceHandle::GetStringWidth(const WString& string, word prior_character) const
+{
+	int width = 0;
+
+	for (size_t i = 0; i < string.Length(); i++)
+	{
+		word character_code = string[i];
+
+		if (character_code >= glyphs.size())
+			continue;
+		const FontGlyph &glyph = glyphs[character_code];
+
+		// Adjust the cursor for the kerning between this character and the previous one.
+		if (prior_character != 0)
+			width += GetKerning(prior_character, string[i]);
+		// Adjust the cursor for this character's advance.
+		width += glyph.advance;
+
+		prior_character = character_code;
+	}
+
+	return width;
+}
+
+// Generates, if required, the layer configuration for a given array of font effects.
+int FontFaceHandle::GenerateLayerConfiguration(FontEffectMap& font_effects)
+{
+	if (font_effects.empty())
+		return 0;
+
+	// Prepare a list of effects, sorted by z-index.
+	FontEffectList sorted_effects;
+	for (FontEffectMap::const_iterator i = font_effects.begin(); i != font_effects.end(); ++i)
+		sorted_effects.push_back(i->second);
+
+	std::sort(sorted_effects.begin(), sorted_effects.end(), FontEffectSort());
+
+	// Check each existing configuration for a match with this arrangement of effects.
+	int configuration_index = 1;
+	for (; configuration_index < (int) layer_configurations.size(); ++configuration_index)
+	{
+		const LayerConfiguration& configuration = layer_configurations[configuration_index];
+
+		// Check the size is correct. For a math, there should be one layer in the configuration
+		// plus an extra for the base layer.
+		if (configuration.size() != sorted_effects.size() + 1)
+			continue;
+
+		// Check through each layer, checking it was created by the same effect as the one we're
+		// checking.
+		size_t effect_index = 0;
+		for (size_t i = 0; i < configuration.size(); ++i)
+		{
+			// Skip the base layer ...
+			if (configuration[i]->GetFontEffect() == NULL)
+				continue;
+
+			// If the ith layer's effect doesn't match the equivalent effect, then this
+			// configuration can't match.
+			if (configuration[i]->GetFontEffect() != sorted_effects[effect_index])
+				break;
+
+			// Check the next one ...
+			++effect_index;
+		}
+
+		if (effect_index == sorted_effects.size())
+			return configuration_index;
+	}
+
+	// No match, so we have to generate a new layer configuration.
+	layer_configurations.push_back(LayerConfiguration());
+	LayerConfiguration& layer_configuration = layer_configurations.back();
+
+	bool added_base_layer = false;
+
+	for (size_t i = 0; i < sorted_effects.size(); ++i)
+	{
+		if (!added_base_layer &&
+			sorted_effects[i]->GetZIndex() >= 0)
+		{
+			layer_configuration.push_back(base_layer);
+			added_base_layer = true;
+		}
+
+		layer_configuration.push_back(GenerateLayer(sorted_effects[i]));
+	}
+
+	// Add the base layer now if we still haven't added it.
+	if (!added_base_layer)
+		layer_configuration.push_back(base_layer);
+
+	return (int) (layer_configurations.size() - 1);
+}
+
+// Generates the texture data for a layer (for the texture database).
+bool FontFaceHandle::GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, Rocket::Core::FontEffect* layer_id, int texture_id)
+{
+	FontLayerMap::iterator layer_iterator = layers.find(layer_id);
+	if (layer_iterator == layers.end())
+		return false;
+
+	return layer_iterator->second->GenerateTexture(texture_data, texture_dimensions, texture_id);
+}
+
+// Generates the geometry required to render a single line of text.
+int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration_index) const
+{
+	int geometry_index = 0;
+	int line_width = 0;
+
+	ROCKET_ASSERT(layer_configuration_index >= 0);
+	ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size());
+
+	// Fetch the requested configuration and generate the geometry for each one.
+	const LayerConfiguration& layer_configuration = layer_configurations[layer_configuration_index];
+	for (size_t i = 0; i < layer_configuration.size(); ++i)
+	{
+		Rocket::Core::FontFaceLayer* layer = layer_configuration[i];
+
+		Colourb layer_colour;
+		if (layer == base_layer)
+			layer_colour = colour;
+		else
+			layer_colour = layer->GetColour();
+
+		// Resize the geometry list if required.
+		if ((int) geometry.size() < geometry_index + layer->GetNumTextures())
+			geometry.resize(geometry_index + layer->GetNumTextures());
+
+		// Bind the textures to the geometries.
+		for (int i = 0; i < layer->GetNumTextures(); ++i)
+			geometry[geometry_index + i].SetTexture(layer->GetTexture(i));
+
+		line_width = 0;
+		word prior_character = 0;
+
+		const word* string_iterator = string.CString();
+		const word* string_end = string.CString() + string.Length();
+
+		for (; string_iterator != string_end; string_iterator++)
+		{
+			if (*string_iterator >= glyphs.size())
+				continue;
+			const FontGlyph &glyph = glyphs[*string_iterator];
+
+			// Adjust the cursor for the kerning between this character and the previous one.
+			if (prior_character != 0)
+				line_width += GetKerning(prior_character, *string_iterator);
+
+			layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
+
+			line_width += glyph.advance;
+			prior_character = *string_iterator;
+		}
+
+		geometry_index += layer->GetNumTextures();
+	}
+
+	// Cull any excess geometry from a previous generation.
+	geometry.resize(geometry_index);
+
+	return line_width;
+}
+
+// Generates the geometry required to render a line above, below or through a line of text.
+void FontFaceHandle::GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const
+{
+	std::vector< Vertex >& line_vertices = geometry->GetVertices();
+	std::vector< int >& line_indices = geometry->GetIndices();
+
+	float offset;
+	switch (height)
+	{
+		case Font::UNDERLINE:			offset = -underline_position; break;
+		case Font::OVERLINE:			// where to place? offset = -line_height - underline_position; break;
+		case Font::STRIKE_THROUGH:		// where to place? offset = -line_height * 0.5f; break;
+		default:						return;
+	}
+
+	line_vertices.resize(line_vertices.size() + 4);
+	line_indices.resize(line_indices.size() + 6);
+	GeometryUtilities::GenerateQuad(&line_vertices[0] + (line_vertices.size() - 4), &line_indices[0] + (line_indices.size() - 6), Vector2f(position.x, position.y + offset), Vector2f((float) width, underline_thickness), colour, line_vertices.size() - 4);
+}
+
+// Destroys the handle.
+void FontFaceHandle::OnReferenceDeactivate()
+{
+	delete this;
+}
+
+void FontFaceHandle::GenerateMetrics(BitmapFontDefinitions *bm_face)
+{
+	line_height = bm_face->CommonCharactersInfo.LineHeight;
+	baseline = bm_face->CommonCharactersInfo.BaseLine;
+
+	underline_position = (float)line_height - bm_face->CommonCharactersInfo.BaseLine;
+	baseline += int( underline_position / 1.6f );
+	underline_thickness = 1.0f;
+
+	average_advance = 0;
+	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+		average_advance += i->advance;
+
+	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
+	average_advance = Math::RealToInteger((float) average_advance / (glyphs.size() * 0.9f));
+
+	// Determine the x-height of this font face.
+	word x = (word) 'x';
+	int index = bm_face->BM_Helper_GetCharacterTableIndex( x );// FT_Get_Char_Index(ft_face, x);
+
+	if ( index >= 0)
+		x_height = bm_face->CharactersInfo[ index ].Height;
+	else
+		x_height = 0;
+}
+
+void FontFaceHandle::BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range)
+{
+	glyphs.resize(unicode_range.max_codepoint + 1);
+
+	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
+	{
+		int index = bm_face->BM_Helper_GetCharacterTableIndex( character_code );
+
+		if ( index < 0 )
+		{
+			continue;
+		}
+
+		FontGlyph glyph;
+		glyph.character = character_code;
+		BuildGlyph(glyph, &bm_face->CharactersInfo[ index ] );
+		glyphs[character_code] = glyph;
+	}
+}
+
+void Rocket::Core::BitmapFont::FontFaceHandle::BuildGlyph(FontGlyph& glyph, CharacterInfo *bm_glyph)
+{
+	// Set the glyph's dimensions.
+	glyph.dimensions.x = bm_glyph->Width;
+	glyph.dimensions.y = bm_glyph->Height;
+
+	// Set the glyph's bearing.
+	glyph.bearing.x = bm_glyph->XOffset;
+	glyph.bearing.y = bm_glyph->YOffset;
+
+	// Set the glyph's advance.
+	glyph.advance = bm_glyph->Advance;
+
+	// Set the glyph's bitmap position.
+	glyph.bitmap_dimensions.x = bm_glyph->X;
+	glyph.bitmap_dimensions.y = bm_glyph->Y;
+
+	glyph.bitmap_data = NULL;
+}
+
+int Rocket::Core::BitmapFont::FontFaceHandle::GetKerning(word lhs, word rhs) const
+{
+	if( bm_face != NULL)
+	{
+		return bm_face->BM_Helper_GetXKerning(lhs, rhs);
+	}
+
+	return 0;
+}
+
+// Generates (or shares) a layer derived from a font effect.
+Rocket::Core::FontFaceLayer* FontFaceHandle::GenerateLayer( FontEffect* font_effect)
+{
+	// See if this effect has been instanced before, as part of a different configuration.
+	FontLayerMap::iterator i = layers.find(font_effect);
+	if (i != layers.end())
+		return i->second;
+
+	Rocket::Core::FontFaceLayer* layer = new Rocket::Core::BitmapFont::FontFaceLayer();
+	layers[font_effect] = layer;
+
+	if (font_effect == NULL)
+	{
+		layer->Initialise(this);
+	}
+	else
+	{
+		// Determine which, if any, layer the new layer should copy its geometry and textures from.
+		Rocket::Core::FontFaceLayer* clone = NULL;
+		bool deep_clone = true;
+		String generation_key;
+
+		if (!font_effect->HasUniqueTexture())
+		{
+			clone = base_layer;
+			deep_clone = false;
+		}
+		else
+		{
+			generation_key = font_effect->GetName() + ";" + font_effect->GetGenerationKey();
+			FontLayerCache::iterator cache_iterator = layer_cache.find(generation_key);
+			if (cache_iterator != layer_cache.end())
+				clone = cache_iterator->second;
+		}
+
+		// Create a new layer.
+		layer->Initialise(this, font_effect, clone, deep_clone);
+
+		// Cache the layer in the layer cache if it generated its own textures (ie, didn't clone).
+		if (clone == NULL)
+			layer_cache[generation_key] = (Rocket::Core::FontFaceLayer*) layer;
+	}
+
+	return (Rocket::Core::FontFaceLayer*)layer;
+}
+
+}
+}
+}

+ 136 - 0
Source/Core/BitmapFont/FontFaceHandle.h

@@ -0,0 +1,136 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREBITMAPFONTFONTFACEHANDLE_H
+#define ROCKETCOREBITMAPFONTFONTFACEHANDLE_H
+
+#include "../UnicodeRange.h"
+#include "../../../Include/Rocket/Core/Font.h"
+#include "../../../Include/Rocket/Core/FontEffect.h"
+#include "../../../Include/Rocket/Core/FontGlyph.h"
+#include "../../../Include/Rocket/Core/Geometry.h"
+#include "../../../Include/Rocket/Core/String.h"
+#include "../../../Include/Rocket/Core/Texture.h"
+#include "../FontFaceHandle.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle : public Rocket::Core::FontFaceHandle
+{
+public:
+	FontFaceHandle();
+	virtual ~FontFaceHandle();
+
+	/// Initialises the handle so it is able to render text.
+	/// @param[in] ft_face The FreeType face that this handle is rendering.
+	/// @param[in] charset The comma-separated list of unicode ranges this handle must support.
+	/// @param[in] size The size, in points, of the face this handle should render at.
+	/// @return True if the handle initialised successfully and is ready for rendering, false if an error occured.
+	bool Initialise(BitmapFontDefinitions *bm_face, const String& charset, int size);
+
+	/// Returns the width a string will take up if rendered with this handle.
+	/// @param[in] string The string to measure.
+	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
+	/// @return The width, in pixels, this string will occupy if rendered with this handle.
+	int GetStringWidth(const WString& string, word prior_character = 0) const;
+
+	/// Generates, if required, the layer configuration for a given array of font effects.
+	/// @param[in] font_effects The list of font effects to generate the configuration for.
+	/// @return The index to use when generating geometry using this configuration.
+	int GenerateLayerConfiguration(Rocket::Core::FontEffectMap& font_effects);
+
+	/// Generates the texture data for a layer (for the texture database).
+	/// @param[out] texture_data The pointer to be set to the generated texture data.
+	/// @param[out] texture_dimensions The dimensions of the texture.
+	/// @param[in] layer_id The id of the layer to request the texture data from.
+	/// @param[in] texture_id The index of the texture within the layer to generate.
+	bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id);
+
+	/// Generates the geometry required to render a single line of text.
+	/// @param[out] geometry An array of geometries to generate the geometry into.
+	/// @param[in] string The string to render.
+	/// @param[in] position The position of the baseline of the first character to render.
+	/// @param[in] colour The colour to render the text.
+	/// @return The width, in pixels, of the string geometry.
+	int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const;
+
+	/// Generates the geometry required to render a line above, below or through a line of text.
+	/// @param[out] geometry The geometry to append the newly created geometry into.
+	/// @param[in] position The position of the baseline of the lined text.
+	/// @param[in] width The width of the string to line.
+	/// @param[in] height The height to render the line at.
+	/// @param[in] colour The colour to draw the line in.
+	void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const;
+
+	const String & GetTextureSource() const
+	{
+		return texture_source;
+	}
+
+	unsigned int GetTextureWidth() const
+	{
+		return texture_width;
+	}
+
+	unsigned int GetTextureHeight() const
+	{
+		return texture_height;
+	}
+
+protected:
+	/// Destroys the handle.
+	virtual void OnReferenceDeactivate();
+
+private:
+	void GenerateMetrics(BitmapFontDefinitions *bm_face);
+
+	void BuildGlyphMap(BitmapFontDefinitions *bm_face, const UnicodeRange& unicode_range);
+	void BuildGlyph(FontGlyph& glyph, CharacterInfo *ft_glyph);
+	int GetKerning(word lhs, word rhs) const;
+
+	// Generates (or shares) a layer derived from a font effect.
+	virtual FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+
+	BitmapFontDefinitions * bm_face;
+	String texture_source;
+	String texture_directory;
+	unsigned int texture_width;
+	unsigned int texture_height;
+};
+
+}
+}
+}
+
+#endif

+ 127 - 0
Source/Core/BitmapFont/FontFaceLayer.cpp

@@ -0,0 +1,127 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFaceLayer.h"
+#include "FontFaceHandle.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontFaceLayer::FontFaceLayer() : Rocket::Core::FontFaceLayer()
+{
+	handle = NULL;
+	effect = NULL;
+}
+
+FontFaceLayer::~FontFaceLayer()
+{
+}
+
+// Generates the character and texture data for the layer.
+bool FontFaceLayer::Initialise(const Rocket::Core::FontFaceHandle* _handle, FontEffect* _effect, const Rocket::Core::FontFaceLayer* clone, bool deep_clone)
+{
+	(void)(_effect);
+
+	Rocket::Core::BitmapFont::FontFaceHandle
+		* bm_font_face_handle;
+
+	handle = _handle;
+
+	bm_font_face_handle = ( Rocket::Core::BitmapFont::FontFaceHandle * ) handle;
+
+	const FontGlyphList& glyphs = handle->GetGlyphs();
+
+	// Clone the geometry and textures from the clone layer.
+	if (clone != NULL)
+	{
+		// Copy the cloned layer's characters.
+		characters = clone->characters;
+
+		// Copy (and reference) the cloned layer's textures.
+		for (size_t i = 0; i < clone->textures.size(); ++i)
+			textures.push_back(clone->textures[i]);
+	}
+	else
+	{
+		// Load texture from file
+		Texture texture;
+		if (!texture.Load( bm_font_face_handle->GetTextureSource() ))
+			return false;
+
+		textures.push_back(texture);
+
+		// Initialise the texture layout for the glyphs.
+		characters.resize(glyphs.size(), Character());
+		for (FontGlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+		{
+			const FontGlyph& glyph = *i;
+
+			if(glyph.dimensions.x <= 0 || glyph.dimensions.y <= 0)
+				continue;
+
+			Vector2i glyph_origin( glyph.bitmap_dimensions.x, glyph.bitmap_dimensions.y ); // position in texture
+			Vector2i glyph_dimensions = glyph.dimensions; // size of char
+
+			Character character;
+			character.origin = Vector2f((float) (glyph.bearing.x), (float) (glyph.bearing.y) - handle->GetBaseline()*3 );
+			character.dimensions = Vector2f((float) glyph.dimensions.x, (float) glyph.dimensions.y);
+
+			// Set the character's texture index.
+			character.texture_index = 0;
+
+			// Generate the character's texture coordinates.
+			character.texcoords[0].x = float(glyph_origin.x) / float(bm_font_face_handle->GetTextureWidth());
+			character.texcoords[0].y = float(glyph_origin.y) / float(bm_font_face_handle->GetTextureHeight());
+			character.texcoords[1].x = float(glyph_origin.x + character.dimensions.x) / float(bm_font_face_handle->GetTextureWidth());
+			character.texcoords[1].y = float(glyph_origin.y + character.dimensions.y) / float(bm_font_face_handle->GetTextureHeight());
+
+			characters[glyph.character] = character;
+
+			// Add the character's dimensions into the texture layout engine.
+			texture_layout.AddRectangle(glyph.character, glyph_dimensions);
+		}
+
+		// Generate the texture layout; this will position the glyph rectangles efficiently and
+		// allocate the texture data ready for writing.
+		if (!texture_layout.GenerateLayout(512))
+			return false;
+
+	}
+	return true;
+}
+
+// Generates the texture data for a layer (for the texture database).
+bool FontFaceLayer::GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id)
+{
+	return true;
+}
+
+}
+}
+}

+ 78 - 0
Source/Core/BitmapFont/FontFaceLayer.h

@@ -0,0 +1,78 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREBITMAPFONTFACELAYER_H
+#define ROCKETCOREBITMAPFONTFACELAYER_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/FontGlyph.h>
+#include <Rocket/Core/Geometry.h>
+#include <Rocket/Core/GeometryUtilities.h>
+#include <Rocket/Core/String.h>
+#include "../FontFaceLayer.h"
+
+namespace Rocket {
+namespace Core {
+
+	class TextureLayout;
+
+namespace BitmapFont {
+
+/**
+	A textured layer stored as part of a font face handle. Each handle will have at least a base
+	layer for the standard font. Further layers can be added to allow to rendering of text effects.
+	@author Peter Curry
+ */
+
+class FontFaceLayer : public Rocket::Core::FontFaceLayer
+{
+public:
+	FontFaceLayer();
+	virtual ~FontFaceLayer();
+
+	/// Generates the character and texture data for the layer.
+	/// @param[in] handle The handle generating this layer.
+	/// @param[in] effect The effect to initialise the layer with.
+	/// @param[in] clone The layer to optionally clone geometry and texture data from.
+	/// @param[in] deep_clone If true, the clones geometry will be completely cloned and the effect will have no option to affect even the glyph origins.
+	/// @return True if the layer was generated successfully, false if not.
+	virtual bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const Rocket::Core::FontFaceLayer* clone = NULL, bool deep_clone = false);
+
+	/// Generates the texture data for a layer (for the texture database).
+	/// @param[out] texture_data The pointer to be set to the generated texture data.
+	/// @param[out] texture_dimensions The dimensions of the texture.
+	/// @param[in] glyphs The glyphs required by the font face handle.
+	/// @param[in] texture_id The index of the texture within the layer to generate.
+	virtual bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id);
+
+};
+
+}
+}
+}
+
+#endif

+ 55 - 0
Source/Core/BitmapFont/FontFamily.cpp

@@ -0,0 +1,55 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFamily.h"
+#include "FontFace.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontFamily::FontFamily(const String& name) : Rocket::Core::FontFamily(name)
+{
+}
+
+FontFamily::~FontFamily()
+{
+}
+
+// Adds a new face to the family.
+bool FontFamily::AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	Rocket::Core::FontFace* face = new FontFace((BitmapFontDefinitions*)bm_face, style, weight, release_stream);
+	font_faces.push_back(face);
+
+	return true;
+}
+
+}
+}
+}

+ 66 - 0
Source/Core/BitmapFont/FontFamily.h

@@ -0,0 +1,66 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREBITMAPFONTFAMILY_H
+#define ROCKETCOREBITMAPFONTFAMILY_H
+
+#include "../../../Include/Rocket/Core/Font.h"
+#include "../../../Include/Rocket/Core/FontFamily.h"
+#include "BitmapFontDefinitions.h"
+
+namespace Rocket {
+namespace Core {
+
+class FontFace;
+class FontFaceHandle;
+
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+class FontFamily : public Rocket::Core::FontFamily
+{
+public:
+	FontFamily(const String& name);
+	~FontFamily();
+
+	/// Adds a new face to the family.
+	/// @param[in] ft_face The previously loaded FreeType face.
+	/// @param[in] style The style of the new face.
+	/// @param[in] weight The weight of the new face.
+	/// @param[in] release_stream True if the application must free the face's memory stream.
+	/// @return True if the face was loaded successfully, false otherwise.
+	bool AddFace( void *bm_face, Font::Style style, Font::Weight weight, bool release_stream);
+};
+
+}
+}
+}
+
+#endif

+ 114 - 0
Source/Core/BitmapFont/FontParser.cpp

@@ -0,0 +1,114 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontParser.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+FontParser::FontParser( BitmapFontDefinitions *face )
+	: BaseXMLParser()
+{
+	bm_face = face;
+	char_id = 0;
+	kern_id = 0;
+}
+
+FontParser::~FontParser()
+{
+}
+
+// Called when the parser finds the beginning of an element tag.
+void FontParser::HandleElementStart(const String& name, const XMLAttributes& attributes)
+{
+	if ( name == "info" )
+	{
+		bm_face->Face.FamilyName = attributes.Get( "face" )->Get< String >();
+		bm_face->Face.Size = attributes.Get( "size" )->Get< int >();
+		bm_face->Face.Weight = attributes.Get( "bold" )->Get< bool >() ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+		bm_face->Face.Style = attributes.Get( "italic" )->Get< bool >() ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+		bm_face->Face.BitmapSource = attributes.Get( "src" )->Get< String >();
+	}
+	else if ( name == "common" )
+	{
+		bm_face->CommonCharactersInfo.LineHeight = attributes.Get( "lineHeight" )->Get< int >();
+		bm_face->CommonCharactersInfo.BaseLine = attributes.Get( "base" )->Get< int >() * -1;
+		bm_face->CommonCharactersInfo.ScaleWidth = attributes.Get( "scaleW" )->Get< int >();
+		bm_face->CommonCharactersInfo.ScaleHeight = attributes.Get( "scaleH" )->Get< int >();
+		bm_face->CommonCharactersInfo.CharacterCount = 0;
+		bm_face->CommonCharactersInfo.KerningCount = 0;
+	}
+	else if ( name == "chars" )
+	{
+		bm_face->CommonCharactersInfo.CharacterCount = attributes.Get( "count" )->Get< int >();
+		bm_face->CharactersInfo = new CharacterInfo[ attributes.Get( "count" )->Get< int >() ];
+	}
+	else if ( name == "char" )
+	{
+		bm_face->CharactersInfo[ char_id ].Id = attributes.Get( "id" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].X = attributes.Get( "x" )->Get< int >(); //The left position of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Y = attributes.Get( "y" )->Get< int >(); //The top position of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Width = attributes.Get( "width" )->Get< int >(); //The width of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].Height = attributes.Get( "height" )->Get< int >(); //The height of the character image in the texture.
+		bm_face->CharactersInfo[ char_id ].XOffset = attributes.Get( "xoffset" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].YOffset = attributes.Get( "yoffset" )->Get< int >();
+		bm_face->CharactersInfo[ char_id ].Advance = attributes.Get( "xadvance" )->Get< int >();
+
+		char_id++;
+	}
+	else if ( name == "kernings" )
+	{
+		bm_face->CommonCharactersInfo.KerningCount = attributes.Get( "count" )->Get< int >();
+		bm_face->KerningsInfo = new KerningInfo[ attributes.Get( "count" )->Get< int >() ];
+	}
+	else if ( name == "kerning" )
+	{
+		bm_face->KerningsInfo[ kern_id ].FirstCharacterId = attributes.Get( "first" )->Get< int >();
+		bm_face->KerningsInfo[ kern_id ].SecondCharacterId = attributes.Get( "second" )->Get< int >();
+		bm_face->KerningsInfo[ kern_id ].KerningAmount = attributes.Get( "amount" )->Get< int >();
+
+		kern_id++;
+	}
+}
+
+// Called when the parser finds the end of an element tag.
+void FontParser::HandleElementEnd(const String& ROCKET_UNUSED_PARAMETER(name))
+{
+	ROCKET_UNUSED(name);
+}
+
+// Called when the parser encounters data.
+void FontParser::HandleData(const String& ROCKET_UNUSED_PARAMETER(data))
+{
+	ROCKET_UNUSED(data);
+}
+
+}
+}
+}

+ 68 - 0
Source/Core/BitmapFont/FontParser.h

@@ -0,0 +1,68 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef BITMAPFONTPARSER_H
+#define BITMAPFONTPARSER_H
+
+#include <Rocket/Core/Header.h>
+#include <Rocket/Core/Types.h>
+#include <Rocket/Core/Dictionary.h>
+#include "BitmapFontDefinitions.h"
+#include <set>
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+/**
+	@author Peter Curry
+ */
+
+class FontParser : public BaseXMLParser
+{
+	public:
+		FontParser( BitmapFontDefinitions *face );
+		virtual ~FontParser();
+
+		/// Called when the parser finds the beginning of an element tag.
+		virtual void HandleElementStart(const String& name, const XMLAttributes& attributes);
+		/// Called when the parser finds the end of an element tag.
+		virtual void HandleElementEnd(const String& name);
+		/// Called when the parser encounters data.
+		virtual void HandleData(const String& data);
+
+	private:
+		FontParser();
+		BitmapFontDefinitions *bm_face;
+		int char_id;
+		int kern_id;
+};
+
+}
+}
+}
+#endif

+ 208 - 0
Source/Core/BitmapFont/FontProvider.cpp

@@ -0,0 +1,208 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include <Rocket/Core/BitmapFont/FontProvider.h>
+#include "../FontFaceHandle.h"
+#include <Rocket/Core/FontDatabase.h>
+#include <Rocket/Core/StreamMemory.h>
+#include "FontFamily.h"
+#include <Rocket/Core.h>
+#include "BitmapFontDefinitions.h"
+#include "FontParser.h"
+
+namespace Rocket {
+namespace Core {
+namespace BitmapFont {
+
+
+FontProvider* FontProvider::instance = NULL;
+
+FontProvider::FontProvider()
+{
+	ROCKET_ASSERT(instance == NULL);
+	instance = this;
+}
+
+FontProvider::~FontProvider()
+{
+	ROCKET_ASSERT(instance == this);
+	instance = NULL;
+}
+
+bool FontProvider::Initialise()
+{
+	if (instance == NULL)
+	{
+		new FontProvider();
+
+		FontDatabase::AddFontProvider(instance);
+	}
+
+	return true;
+}
+
+void FontProvider::Shutdown()
+{
+	if (instance != NULL)
+	{
+		FontDatabase::RemoveFontProvider(instance);
+		delete instance;
+		instance = NULL;
+	}
+}
+
+// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+bool FontProvider::LoadFontFace(const String& file_name)
+{
+	BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name);
+
+	if (bm_font == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	Font::Style style = bm_font->Face.Style;
+	Font::Weight weight = bm_font->Face.Weight;
+
+	if (instance->AddFace(bm_font, bm_font->Face.FamilyName, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return false;
+	}
+
+	return true;
+}
+
+// Loads a new font face.
+bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
+{
+	BitmapFontDefinitions *bm_font = (BitmapFontDefinitions*) instance->LoadFace(file_name);
+	if (bm_font == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	if (instance->AddFace(bm_font, family, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s (from %s).", bm_font->Face.FamilyName.CString(), file_name.CString());
+		return false;
+	}
+
+	return true;
+}
+
+bool FontProvider::LoadFontFace(const byte* data, int data_length)
+{
+	// TODO: Loading from memory
+	return false;
+}
+
+// Adds a new font face to the database, loading from memory.
+bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+{
+	// TODO Loading from memory
+	return false;
+}
+
+// Adds a loaded face to the appropriate font family.
+bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	Rocket::Core::FontFamily* font_family = NULL;
+	FontFamilyMap::iterator iterator = instance->font_families.find(family);
+	if (iterator != instance->font_families.end())
+		font_family = (*iterator).second;
+	else
+	{
+		font_family = new FontFamily(family);
+		instance->font_families[family] = font_family;
+	}
+
+	return font_family->AddFace((BitmapFontDefinitions *) face, style, weight, release_stream);
+	return true;
+}
+
+// Loads a FreeType face.
+void* FontProvider::LoadFace(const String& file_name)
+{
+	BitmapFontDefinitions *bm_face = new BitmapFontDefinitions();
+	FontParser parser( bm_face );
+
+	FileInterface* file_interface = GetFileInterface();
+	FileHandle handle = file_interface->Open(file_name);
+
+	if (!handle)
+	{
+		return NULL;
+	}
+
+	size_t length = file_interface->Length(handle);
+
+	byte* buffer = new byte[length];
+	file_interface->Read(buffer, length, handle);
+	file_interface->Close(handle);
+
+	StreamMemory* stream = new StreamMemory( buffer, length );
+	stream->SetSourceURL( file_name );
+
+	parser.Parse( stream );
+
+	bm_face->Face.Source = file_name;
+	return bm_face;
+}
+
+// Loads a FreeType face from memory.
+void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
+{
+	URL file_url = source + ".fnt";
+
+	BitmapFontDefinitions *bm_face = new BitmapFontDefinitions();
+	FontParser parser( bm_face );
+	StreamMemory* stream = new StreamMemory( data, data_length );
+	stream->SetSourceURL( file_url );
+
+	parser.Parse( stream );
+
+	bm_face->Face.Source = file_url.GetPathedFileName();
+	return bm_face;
+}
+
+}
+}
+}

+ 40 - 1
Source/Core/Context.cpp

@@ -40,7 +40,7 @@ namespace Core {
 
 const float DOUBLE_CLICK_TIME = 0.5f;
 
-Context::Context(const String& name) : name(name), dimensions(0, 0), mouse_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1), view_state()
+Context::Context(const String& name) : name(name), dimensions(0, 0), mouse_position(0, 0), clip_origin(-1, -1), clip_dimensions(-1, -1), density_independent_pixel_ratio(1.0f), view_state()
 {
 	instancer = NULL;
 
@@ -139,15 +139,49 @@ const Vector2i& Context::GetDimensions() const
 	return dimensions;
 }
 
+
 // Returns the current state of the view.
 const ViewState& Context::GetViewState() const throw()
 {
 	return view_state;
 }
 
+void Context::SetDensityIndependentPixelRatio(float _density_independent_pixel_ratio)
+{
+	if (density_independent_pixel_ratio != _density_independent_pixel_ratio)
+	{
+		density_independent_pixel_ratio = _density_independent_pixel_ratio;
+
+		for (int i = 0; i < root->GetNumChildren(); ++i)
+		{
+			ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
+			if (document != NULL)
+			{
+				document->DirtyDpProperties();
+			}
+		}
+	}
+}
+
+float Context::GetDensityIndependentPixelRatio() const
+{
+	return density_independent_pixel_ratio;
+}
+
 // Updates all elements in the element tree.
 bool Context::Update()
 {
+	// Reset all document layout locks (work-around due to leak, possibly in select element?)
+	for (int i = 0; i < root->GetNumChildren(); ++i)
+	{
+		ElementDocument* document = root->GetChild(i)->GetOwnerDocument();
+		if (document != NULL && document->lock_layout != 0)
+		{
+			Log::Message(Log::LT_WARNING, "Layout lock leak. Document '%s' had lock layout value: %d", document->title.CString(), document->lock_layout);
+			document->lock_layout = 0;
+		}
+	}
+
 	root->Update();
 
 	// Release any documents that were unloaded during the update.
@@ -1092,6 +1126,7 @@ Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore
 		}
 	}
 
+
 	// Check any elements within our stacking context. We want to return the lowest-down element
 	// that is under the cursor.
 	if (element->local_stacking_context)
@@ -1122,6 +1157,10 @@ Element* Context::GetElementAtPoint(const Vector2f& point, const Element* ignore
 		}
 	}
 
+	// Ignore elements whose pointer events are disabled
+	if (element->GetPointerEvents() == POINTER_EVENTS_NONE)
+		return NULL;
+
 	Vector2f projected_point = element->Project(point);
 
 	// Check if the point is actually within this element.

+ 9 - 1
Source/Core/DecoratorTiled.cpp

@@ -25,6 +25,7 @@
  *
  */
 
+
 #include "precompiled.h"
 #include "DecoratorTiled.h"
 #include "../../Include/Rocket/Core.h"
@@ -108,6 +109,13 @@ Vector2f DecoratorTiled::Tile::GetDimensions(Element* element)
 void DecoratorTiled::Tile::GenerateGeometry(std::vector< Vertex >& vertices, std::vector< int >& indices, Element* element, const Vector2f& surface_origin, const Vector2f& surface_dimensions, const Vector2f& tile_dimensions) const
 {
 	RenderInterface* render_interface = element->GetRenderInterface();
+    float opacity = element->GetProperty<float>(OPACITY);
+
+    Colourb quad_colour = element->GetProperty<Colourb>(IMAGE_COLOR);
+
+    // Apply opacity
+    quad_colour.alpha = (byte)(opacity * (float)quad_colour.alpha);
+	
 	TileDataMap::iterator data_iterator = data.find(render_interface);
 	if (data_iterator == data.end())
 		return;
@@ -244,7 +252,7 @@ void DecoratorTiled::Tile::GenerateGeometry(std::vector< Vertex >& vertices, std
 			tile_position.x = surface_origin.x + (float) tile_dimensions.x * x;
 			tile_size.x = (float) (x < num_tiles[0] - 1 ? tile_dimensions.x : final_tile_dimensions.x);
 
-			GeometryUtilities::GenerateQuad(new_vertices, new_indices, tile_position, tile_size, Colourb(255, 255, 255), tile_texcoords[0], tile_texcoords[1], index_offset);
+			GeometryUtilities::GenerateQuad(new_vertices, new_indices, tile_position, tile_size, quad_colour, tile_texcoords[0], tile_texcoords[1], index_offset);
 			new_vertices += 4;
 			new_indices += 6;
 			index_offset += 4;

+ 25 - 9
Source/Core/Element.cpp

@@ -25,6 +25,7 @@
  *
  */
 
+  
 #include "precompiled.h"
 #include "../../Include/Rocket/Core/Element.h"
 #include "../../Include/Rocket/Core/Dictionary.h"
@@ -54,7 +55,7 @@ namespace Core {
 class ElementSortZOrder
 {
 public:
-	bool operator()(const std::pair< Element*, float >& lhs, const std::pair< Element*, float >& rhs)
+	bool operator()(const std::pair< Element*, float >& lhs, const std::pair< Element*, float >& rhs) const
 	{
 		return lhs.second < rhs.second;
 	}
@@ -67,7 +68,7 @@ public:
 class ElementSortZIndex
 {
 public:
-	bool operator()(const Element* lhs, const Element* rhs)
+	bool operator()(const Element* lhs, const Element* rhs) const
 	{
 		// Check the z-index.
 		return lhs->GetZIndex() < rhs->GetZIndex();
@@ -548,6 +549,11 @@ float Element::ResolveProperty(const Property *property, float base_value)
 	return style->ResolveProperty(property, base_value);
 }
 
+void Element::GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right )
+{
+	style->GetOffsetProperties(top, bottom, left, right);
+}
+
 void Element::GetBorderWidthProperties(const Property **border_top, const Property **border_bottom, const Property **border_left, const Property **bottom_right)
 {
 	style->GetBorderWidthProperties(border_top, border_bottom, border_left, bottom_right);
@@ -598,6 +604,11 @@ int Element::GetWhitespace()
 	return style->GetWhitespace();
 }
 
+int Element::GetPointerEvents()
+{
+	return style->GetPointerEvents();
+}
+
 const Property *Element::GetLineHeightProperty()
 {
 	return style->GetLineHeightProperty();
@@ -1801,9 +1812,13 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 	}
 
 	// Dirty the background if it's changed.
-	if (all_dirty ||
-		changed_properties.find(BACKGROUND_COLOR) != changed_properties.end())
-		background->DirtyBackground();
+    if (all_dirty ||
+        changed_properties.find(BACKGROUND_COLOR) != changed_properties.end() ||
+		changed_properties.find(OPACITY) != changed_properties.end() ||
+		changed_properties.find(IMAGE_COLOR) != changed_properties.end()) {
+        background->DirtyBackground();
+        decoration->ReloadDecorators();
+    }
 
 	// Dirty the border if it's changed.
 	if (all_dirty || 
@@ -1814,7 +1829,8 @@ void Element::OnPropertyChange(const PropertyNameList& changed_properties)
 		changed_properties.find(BORDER_TOP_COLOR) != changed_properties.end() ||
 		changed_properties.find(BORDER_RIGHT_COLOR) != changed_properties.end() ||
 		changed_properties.find(BORDER_BOTTOM_COLOR) != changed_properties.end() ||
-		changed_properties.find(BORDER_LEFT_COLOR) != changed_properties.end())
+		changed_properties.find(BORDER_LEFT_COLOR) != changed_properties.end() ||
+		changed_properties.find(OPACITY) != changed_properties.end())
 		border->DirtyBorder();
 
 	// Fetch a new font face if it has been changed.
@@ -1970,7 +1986,7 @@ void Element::ProcessEvent(Event& event)
 			if (overflow_property == OVERFLOW_AUTO ||
 				overflow_property == OVERFLOW_SCROLL)
 			{
-				SetScrollTop(GetScrollTop() + wheel_delta * ElementUtilities::GetLineHeight(this));
+				SetScrollTop(GetScrollTop() + wheel_delta * (GetFontFaceHandle() ? ElementUtilities::GetLineHeight(this) : (GetProperty(SCROLL_DEFAULT_STEP_SIZE) ? GetProperty< int >(SCROLL_DEFAULT_STEP_SIZE) : 0 )));
 				event.StopPropagation();
 			}
 		}
@@ -2098,7 +2114,7 @@ void Element::UpdateOffset()
 			// If the element is anchored right, then the position is set first so the element's right-most edge
 			// (including margins) will render up against the containing box's right-most content edge, and then
 			// offset by the resolved value.
-			if (right != NULL && right->unit != Property::KEYWORD)
+			else if (right != NULL && right->unit != Property::KEYWORD)
 				relative_offset_base.x = containing_block.x + parent_box.GetEdge(Box::BORDER, Box::LEFT) - (ResolveProperty(RIGHT, containing_block.x) + GetBox().GetSize(Box::BORDER).x + GetBox().GetEdge(Box::MARGIN, Box::RIGHT));
 
 			const Property *top = GetLocalProperty(TOP);
@@ -2359,7 +2375,7 @@ void Element::UpdateTransformState()
 
 		bool have_transform = false;
 		Matrix4f transform_value = Matrix4f::Identity();
-		Vector3f transform_origin(pos.x + size.x * 0.5, pos.y + size.y * 0.5, 0);
+		Vector3f transform_origin(pos.x + size.x * 0.5f, pos.y + size.y * 0.5f, 0);
 
 		const Property *transform = GetTransform();
 		if (transform && (transform->unit != Property::KEYWORD || transform->value.Get< int >() != TRANSFORM_NONE))

+ 6 - 0
Source/Core/ElementBackground.cpp

@@ -25,6 +25,7 @@
  *
  */
 
+
 #include "precompiled.h"
 #include "ElementBackground.h"
 #include "../../Include/Rocket/Core/Element.h"
@@ -67,6 +68,11 @@ void ElementBackground::GenerateBackground()
 {
 	// Fetch the new colour for the background. If the colour is transparent, then we don't render any background.
 	Colourb colour = element->GetProperty(BACKGROUND_COLOR)->value.Get< Colourb >();
+	float opacity = element->GetProperty<float>(OPACITY);
+
+	// Apply opacity
+	colour.alpha = (byte)(opacity * (float)colour.alpha);
+
 	if (colour.alpha <= 0)
 	{
 		geometry.GetVertices().clear();

+ 7 - 0
Source/Core/ElementBorder.cpp

@@ -25,6 +25,7 @@
  *
  */
 
+ 
 #include "precompiled.h"
 #include "ElementBorder.h"
 #include "../../Include/Rocket/Core/Element.h"
@@ -94,6 +95,12 @@ void ElementBorder::GenerateBorder()
 		border_colours[2] = element->GetProperty(BORDER_BOTTOM_COLOR)->value.Get< Colourb >();
 		border_colours[3] = element->GetProperty(BORDER_LEFT_COLOR)->value.Get< Colourb >();
 
+		// Apply opacity to the border
+		float opacity = element->GetProperty<float>(OPACITY);
+		for(int i = 0; i < 4; ++i) {
+			border_colours[i].alpha = (byte)(opacity * (float)border_colours[i].alpha);
+		}
+
 		for (int i = 0; i < element->GetNumBoxes(); ++i)
 			GenerateBorder(raw_vertices, raw_indices, index_offset, element->GetBox(i), border_colours);
 	}

+ 7 - 1
Source/Core/ElementDocument.cpp

@@ -283,7 +283,7 @@ ElementText* ElementDocument::CreateTextNode(const String& text)
 // Is the current document modal
 bool ElementDocument::IsModal() const
 {
-	return modal;
+	return modal && IsVisible();
 }
 
 // Default load script implementation
@@ -361,6 +361,11 @@ bool ElementDocument::IsLayoutDirty()
 	return layout_dirty;
 }
 
+void ElementDocument::DirtyDpProperties()
+{
+	GetStyle()->DirtyDpProperties();
+}
+
 // Refreshes the document layout if required.
 void ElementDocument::OnUpdate()
 {
@@ -492,6 +497,7 @@ bool ElementDocument::SearchFocusSubtree(Element* element, bool forward)
 	if (element->GetProperty<int>(TAB_INDEX) == TAB_INDEX_AUTO)
 	{
 		element->Focus();
+		element->ScrollIntoView(false);
 		return true;
 	}
 

+ 18 - 2
Source/Core/ElementImage.cpp

@@ -156,6 +156,16 @@ void ElementImage::OnAttributeChange(const Rocket::Core::AttributeNameList& chan
 		DirtyLayout();
 }
 
+void ElementImage::OnPropertyChange(const PropertyNameList& changed_properties)
+{
+    Element::OnPropertyChange(changed_properties);
+
+    if (changed_properties.find(IMAGE_COLOR) != changed_properties.end() ||
+        changed_properties.find(OPACITY) != changed_properties.end()) {
+        GenerateGeometry();
+    }
+}
+
 // Regenerates the element's geometry.
 void ElementImage::ProcessEvent(Rocket::Core::Event& event)
 {
@@ -201,11 +211,17 @@ void ElementImage::GenerateGeometry()
 		texcoords[1] = Vector2f(1, 1);
 	}
 
+    float opacity = GetProperty<float>(OPACITY);
+	Colourb quad_colour = GetProperty<Colourb>(IMAGE_COLOR);
+
+    // Apply opacity
+    quad_colour.alpha = (byte)(opacity * (float)quad_colour.alpha);
+
 	Rocket::Core::GeometryUtilities::GenerateQuad(&vertices[0],									// vertices to write to
 												  &indices[0],									// indices to write to
-												  Vector2f(0, 0),					// origin of the quad
+												  Vector2f(0, 0),					            // origin of the quad
 												  GetBox().GetSize(Rocket::Core::Box::CONTENT),	// size of the quad
-												  Colourb(255, 255, 255, 255),		// colour of the vertices
+												  quad_colour,		                            // colour of the vertices
 												  texcoords[0],									// top-left texture coordinate
 												  texcoords[1]);								// top-right texture coordinate
 

+ 4 - 0
Source/Core/ElementImage.h

@@ -84,6 +84,10 @@ protected:
 	/// @param[in] changed_attributes A list of attributes changed on the element.
 	virtual void OnAttributeChange(const AttributeNameList& changed_attributes);
 
+	/// Called when properties on the element are changed.
+	/// @param[in] changed_properties The properties changed on the element.
+	virtual void OnPropertyChange(const PropertyNameList& changed_properties);
+
 	/// Regenerates the element's geometry on a resize event.
 	/// @param[in] event The event to process.
 	virtual void ProcessEvent(Event& event);

+ 40 - 0
Source/Core/ElementStyle.cpp

@@ -366,6 +366,8 @@ float ElementStyle::ResolveProperty(const Property* property, float base_value)
 			return property->value.Get< float >() * ElementUtilities::GetFontSize(element);
 		case Property::REM:
 			return property->value.Get< float >() * ElementUtilities::GetFontSize(element->GetOwnerDocument());
+		case Property::DP:
+			return property->value.Get< float >() * ElementUtilities::GetDensityIndependentPixelRatio(element);
 
 		case Property::RAD:
 			return Math::RadiansToDegrees(property->value.Get< float >());
@@ -405,6 +407,11 @@ float ElementStyle::ResolveProperty(const String& name, float base_value)
 		return 0.0f;
 	}
 
+	if (property->unit & Property::DP)
+	{
+		return property->value.Get< float >() * ElementUtilities::GetDensityIndependentPixelRatio(element);
+	}
+
 	// The calculated value of the font-size property is inherited, so we need to check if this
 	// is an inherited property. If so, then we return our parent's font size instead.
 	if (name == FONT_SIZE && property->unit & Property::RELATIVE_UNIT)
@@ -604,6 +611,27 @@ void ElementStyle::DirtyRemProperties()
 		element->GetChild(i)->GetStyle()->DirtyRemProperties();
 }
 
+void ElementStyle::DirtyDpProperties()
+{
+	const PropertyNameList &properties = StyleSheetSpecification::GetRegisteredProperties();
+	PropertyNameList dp_properties;
+
+	// Dirty all the properties of this element that use the dp unit.
+	for (PropertyNameList::const_iterator list_iterator = properties.begin(); list_iterator != properties.end(); ++list_iterator)
+	{
+		if (element->GetProperty(*list_iterator)->unit == Property::DP)
+			dp_properties.insert(*list_iterator);
+	}
+
+	if (!dp_properties.empty())
+		DirtyProperties(dp_properties, false);
+
+	// Now dirty all of our descendant's properties that use the dp unit.
+	int num_children = element->GetNumChildren(true);
+	for (int i = 0; i < num_children; ++i)
+		element->GetChild(i)->GetStyle()->DirtyDpProperties();
+}
+
 // Sets a single property as dirty.
 void ElementStyle::DirtyProperty(const String& property)
 {
@@ -631,6 +659,7 @@ void ElementStyle::DirtyProperties(const PropertyNameList& properties, bool clea
 
 		// Clear all cached properties.
 		cache->Clear();
+		cache->ClearInherited();
 	}
 	else
 	{
@@ -654,6 +683,7 @@ void ElementStyle::DirtyProperties(const PropertyNameList& properties, bool clea
 
 		// Clear cached properties.
 		cache->Clear();
+		cache->ClearInherited();
 	}
 
 	// clear the list of EM-properties, we will refill it in DirtyEmProperties
@@ -705,6 +735,11 @@ void ElementStyle::DirtyInheritedProperties(const PropertyNameList& properties)
 	element->OnPropertyChange(properties);
 }
 
+void ElementStyle::GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right )
+{
+	cache->GetOffsetProperties(top, bottom, left, right);
+}
+
 void ElementStyle::GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **bottom_right_width)
 {
 	cache->GetBorderWidthProperties(border_top_width, border_bottom_width, border_left_width, bottom_right_width);
@@ -755,6 +790,11 @@ int ElementStyle::GetWhitespace()
 	return cache->GetWhitespace();
 }
 
+int ElementStyle::GetPointerEvents()
+{
+	return cache->GetPointerEvents();
+}
+
 const Property *ElementStyle::GetLineHeightProperty()
 {
 	return cache->GetLineHeightProperty();

+ 6 - 0
Source/Core/ElementStyle.h

@@ -144,7 +144,11 @@ public:
 	void DirtyInheritedEmProperties();
 	// Dirties rem properties.
 	void DirtyRemProperties();
+	// Dirties dp properties.
+	void DirtyDpProperties();
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );	
 	/// Returns 'border-width' properties from element's style or local cache.
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
@@ -166,6 +170,8 @@ public:
 	int GetDisplay();
 	/// Returns 'white-space' property value from element's style or local cache.
 	int GetWhitespace();
+	/// Returns 'pointer-events' property value from element's style or local cache.
+	int GetPointerEvents();
 
 	/// Returns 'line-height' property value from element's style or local cache.
 	const Property *GetLineHeightProperty();

+ 53 - 1
Source/Core/ElementStyleCache.cpp

@@ -33,6 +33,7 @@ namespace Rocket {
 namespace Core {
 
 ElementStyleCache::ElementStyleCache(ElementStyle *style) : style(style), 
+	top(NULL), bottom(NULL), left(NULL), right(NULL),
 	border_top_width(NULL), border_bottom_width(NULL), border_left_width(NULL), border_right_width(NULL),
 	margin_top(NULL), margin_bottom(NULL), margin_left(NULL), margin_right(NULL),
 	padding_top(NULL), padding_bottom(NULL), padding_left(NULL), padding_right(NULL),
@@ -40,12 +41,14 @@ ElementStyleCache::ElementStyleCache(ElementStyle *style) : style(style),
 	local_width(NULL), local_height(NULL), have_local_width(false), have_local_height(false),
 	overflow_x(-1), overflow_y(-1),
 	position(-1), float_(-1), display(-1), whitespace(-1),
-	line_height(NULL), text_align(-1), text_transform(-1), vertical_align(NULL)
+	line_height(NULL), text_align(-1), text_transform(-1), vertical_align(NULL),
+	pointer_events(-1)
 {
 }
 
 void ElementStyleCache::Clear()
 {
+	ClearOffset();
 	ClearBorder();
 	ClearMargin();
 	ClearPadding();
@@ -63,6 +66,12 @@ void ElementStyleCache::ClearInherited()
 	ClearTextAlign();
 	ClearTextTransform();
 	ClearVerticalAlign();
+	ClearPointerEvents();
+}
+
+void ElementStyleCache::ClearOffset()
+{
+	top = bottom = left = right = NULL;
 }
 
 void ElementStyleCache::ClearBorder()
@@ -131,6 +140,42 @@ void ElementStyleCache::ClearVerticalAlign()
 	vertical_align = NULL;
 }
 
+void ElementStyleCache::ClearPointerEvents()
+{
+	pointer_events = -1;
+}
+
+void ElementStyleCache::GetOffsetProperties(const Property **o_top, const Property **o_bottom, const Property **o_left, const Property **o_right )
+{
+	if (o_top)
+	{
+		if (!top)
+			top = style->GetProperty(TOP);
+		*o_top = top;
+	}
+
+	if (o_bottom)
+	{
+		if (!bottom)
+			bottom = style->GetProperty(BOTTOM);
+		*o_bottom = bottom;
+	}
+
+	if (o_left)
+	{
+		if (!left)
+			left = style->GetProperty(LEFT);
+		*o_left = left;
+	}
+
+	if (o_right)
+	{
+		if (!right)
+			right = style->GetProperty(RIGHT);
+		*o_right = right;
+	}
+}
+
 void ElementStyleCache::GetBorderWidthProperties(const Property **o_border_top_width, const Property **o_border_bottom_width, const Property **o_border_left_width, const Property **o_border_right_width)
 {
 	if (o_border_top_width)
@@ -309,6 +354,13 @@ int ElementStyleCache::GetWhitespace()
 	return whitespace;
 }
 
+int ElementStyleCache::GetPointerEvents()
+{
+	if (pointer_events < 0)
+		pointer_events = style->GetProperty(POINTER_EVENTS)->Get< int >();
+	return pointer_events;
+}
+
 const Property *ElementStyleCache::GetLineHeightProperty()
 {
 	if (!line_height)

+ 8 - 0
Source/Core/ElementStyleCache.h

@@ -55,6 +55,7 @@ public:
 	void ClearInherited();
 
 	/// Invalidation functions for individual and grouped non-inherited properties
+	void ClearOffset();
 	void ClearBorder();
 	void ClearMargin();
 	void ClearPadding();
@@ -70,7 +71,10 @@ public:
 	void ClearTextAlign();
 	void ClearTextTransform();
 	void ClearVerticalAlign();
+	void ClearPointerEvents();
 
+	/// Returns 'top', 'bottom', 'left' and 'right' properties from element's style or local cache.
+	void GetOffsetProperties(const Property **top, const Property **bottom, const Property **left, const Property **right );
 	/// Returns 'border-width' properties from element's style or local cache.
 	void GetBorderWidthProperties(const Property **border_top_width, const Property **border_bottom_width, const Property **border_left_width, const Property **border_right_width);
 	/// Returns 'margin' properties from element's style or local cache.
@@ -92,6 +96,8 @@ public:
 	int GetDisplay();
 	/// Returns 'white-space' property value from element's style or local cache.
 	int GetWhitespace();
+	/// Returns 'pointer-events' property value from element's style or local cache.
+	int GetPointerEvents();
 
 	/// Returns 'line-height' property value from element's style or local cache.
 	const Property *GetLineHeightProperty();
@@ -107,6 +113,7 @@ private:
 	ElementStyle *style;
 
 	/// Cached properties.
+	const Property *top, *bottom, *left, *right;
 	const Property *border_top_width, *border_bottom_width, *border_left_width, *border_right_width;
 	const Property *margin_top, *margin_bottom, *margin_left, *margin_right;
 	const Property *padding_top, *padding_bottom, *padding_left, *padding_right;
@@ -122,6 +129,7 @@ private:
 	int text_align;
 	int text_transform;
 	const Property *vertical_align;
+	int pointer_events;
 };
 
 }

+ 20 - 2
Source/Core/ElementUtilities.cpp

@@ -125,6 +125,15 @@ FontFaceHandle* ElementUtilities::GetFontFaceHandle(Element* element)
 	return font;
 }
 
+float ElementUtilities::GetDensityIndependentPixelRatio(Element * element)
+{
+	Context* context = element->GetContext();
+	if (context == NULL)
+		return 1.0f;
+
+	return context->GetDensityIndependentPixelRatio();
+}
+
 // Returns an element's font size, if it has a font defined.
 int ElementUtilities::GetFontSize(Element* element)
 {
@@ -138,13 +147,18 @@ int ElementUtilities::GetFontSize(Element* element)
 // Returns an element's line height, if it has a font defined.
 int ElementUtilities::GetLineHeight(Element* element)
 {
-	FontFaceHandle* font_face_handle = element->GetFontFaceHandle();
+	const Property* line_height_property = element->GetLineHeightProperty();
+
+	Element* font_element = element;
+	if (line_height_property->unit == Property::REM)
+		font_element = element->GetOwnerDocument();
+
+	FontFaceHandle* font_face_handle = font_element->GetFontFaceHandle();
 	if (font_face_handle == NULL)
 		return 0;
 
 	int line_height = font_face_handle->GetLineHeight();
 	float inch = element->GetRenderInterface()->GetPixelsPerInch();
-	const Property* line_height_property = element->GetLineHeightProperty();
 
 	switch (line_height_property->unit)
 	{
@@ -157,6 +171,7 @@ int ElementUtilities::GetLineHeight(Element* element)
 	ROCKET_UNUSED_SWITCH_ENUM(Property::RELATIVE_UNIT);
 	case Property::NUMBER:
 	case Property::EM:
+	case Property::REM:
 		// If the property is a straight number or an em measurement, then it scales the line height.
 		return Math::Round(line_height_property->value.Get< float >() * line_height);
 	case Property::PERCENT:
@@ -165,6 +180,9 @@ int ElementUtilities::GetLineHeight(Element* element)
 	case Property::PX:
 		// A px measurement.
 		return Math::Round(line_height_property->value.Get< float >());
+	case Property::DP:
+		// A density-independent pixel measurement.
+		return Math::Round(line_height_property->value.Get< float >() * ElementUtilities::GetDensityIndependentPixelRatio(element));
 	case Property::INCH:
 		// Values based on pixels-per-inch.
 		return Math::Round(line_height_property->value.Get< float >() * inch);

+ 94 - 158
Source/Core/FontDatabase.cpp

@@ -26,22 +26,21 @@
  */
 
 #include "precompiled.h"
-#include "../../Include/Rocket/Core/FontDatabase.h"
-#include "FontFamily.h"
-#include "../../Include/Rocket/Core.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#include <Rocket/Core/FontDatabase.h>
+#include <Rocket/Core/FontFamily.h>
+#include <Rocket/Core.h>
+#include <Rocket/Core/FreeType/FontProvider.h>
+#include <Rocket/Core/BitmapFont/FontProvider.h>
 
 namespace Rocket {
 namespace Core {
 
 FontDatabase* FontDatabase::instance = NULL;
+FontDatabase::FontProviderTable FontDatabase::font_provider_table;
 
 typedef std::map< String, FontEffect* > FontEffectCache;
 FontEffectCache font_effect_cache;
 
-static FT_Library ft_library = NULL;
-
 FontDatabase::FontDatabase()
 {
 	ROCKET_ASSERT(instance == NULL);
@@ -60,13 +59,11 @@ bool FontDatabase::Initialise()
 	{
 		new FontDatabase();
 
-		FT_Error result = FT_Init_FreeType(&ft_library);
-		if (result != 0)
-		{
-			Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result);
-			Shutdown();
-			return false;
-		}
+        if(!FreeType::FontProvider::Initialise())
+            return false;
+
+        if(!BitmapFont::FontProvider::Initialise())
+            return false;
 	}
 
 	return true;
@@ -76,14 +73,8 @@ void FontDatabase::Shutdown()
 {
 	if (instance != NULL)
 	{
-		for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i)
-			delete (*i).second;
-
-		if (ft_library != NULL)
-		{
-			FT_Done_FreeType(ft_library);
-			ft_library = NULL;
-		}
+        FreeType::FontProvider::Shutdown();
+        BitmapFont::FontProvider::Shutdown();
 
 		delete instance;
 	}
@@ -92,105 +83,101 @@ void FontDatabase::Shutdown()
 // Loads a new font face.
 bool FontDatabase::LoadFontFace(const String& file_name)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
-		return false;
-	}
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
 
-	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
-	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(file_name);
 
-	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return false;
-	}
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(file_name);
+
+        default:
+            return false;
+    }
 }
 
 // Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
 bool FontDatabase::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
-		return false;
-	}
+    FontProviderType font_provider_type = GetFontProviderType(file_name);
 
-	if (instance->AddFace(ft_face, family, style, weight, true))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
-		return false;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(file_name, family, style, weight);
+
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(file_name, family, style, weight);
+
+        default:
+            return false;
+    }
 }
 
 // Adds a new font face to the database, loading from memory.
-bool FontDatabase::LoadFontFace(const byte* data, int data_length)
+bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
-		return false;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length);
 
-	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
-	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(data, data_length);
 
-	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return false;
-	}
+        default:
+            return false;
+    }
 }
 
 // Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself.
-bool FontDatabase::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+bool FontDatabase::LoadFontFace(FontProviderType font_provider_type, const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
 {
-	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
-	if (ft_face == NULL)
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
-		return false;
-	}
+    switch(font_provider_type)
+    {
+        case FreeType:
+            return FreeType::FontProvider::LoadFontFace(data, data_length, family, style, weight);
 
-	if (instance->AddFace(ft_face, family, style, weight, false))
-	{
-		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return true;
-	}
-	else
-	{
-		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
-		return false;
-	}
+        case BitmapFont:
+            return BitmapFont::FontProvider::LoadFontFace(data, data_length, family, style, weight);
+
+        default:
+            return false;
+    }
+}
+
+FontDatabase::FontProviderType FontDatabase::GetFontProviderType(const String& file_name)
+{
+    if(file_name.Find(".fnt") != String::npos)
+    {
+        return BitmapFont;
+    }
+    else
+    {
+        return FreeType;
+    }
 }
 
 // Returns a handle to a font face that can be used to position and render text.
 FontFaceHandle* FontDatabase::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size)
 {
-	FontFamilyMap::iterator iterator = instance->font_families.find(family);
-	if (iterator == instance->font_families.end())
-		return NULL;
+    size_t provider_index, provider_count;
+
+    provider_count = font_provider_table.size();
+
+    for(provider_index = 0; provider_index < provider_count; ++provider_index)
+    {
+        FontFaceHandle * face_handle = font_provider_table[ provider_index ]->GetFontFaceHandle(family, charset, style, weight, size);
+
+        if(face_handle)
+        {
+            return face_handle;
+        }
+    }
 
-	return (*iterator).second->GetFaceHandle(charset, style, weight, size);
+    return NULL;
 }
 
 // Returns a font effect, either a newly-instanced effect from the factory or an identical shared
@@ -255,72 +242,21 @@ void FontDatabase::ReleaseFontEffect(const FontEffect* effect)
 	}
 }
 
-// Adds a loaded face to the appropriate font family.
-bool FontDatabase::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream)
+void FontDatabase::AddFontProvider(FontProvider * provider)
 {
-	FontFamily* font_family = NULL;
-	FontFamilyMap::iterator iterator = instance->font_families.find(family);
-	if (iterator != instance->font_families.end())
-		font_family = (*iterator).second;
-	else
-	{
-		font_family = new FontFamily(family);
-		instance->font_families[family] = font_family;
-	}
-
-	return font_family->AddFace((FT_Face) face, style, weight, release_stream);
+    instance->font_provider_table.push_back(provider);
 }
 
-// Loads a FreeType face.
-void* FontDatabase::LoadFace(const String& file_name)
+void FontDatabase::RemoveFontProvider(FontProvider * provider)
 {
-	FileInterface* file_interface = GetFileInterface();
-	FileHandle handle = file_interface->Open(file_name);
-
-	if (!handle)
-	{
-		return NULL;
-	}
-
-	size_t length = file_interface->Length(handle);
-
-	FT_Byte* buffer = new FT_Byte[length];
-	file_interface->Read(buffer, length, handle);
-	file_interface->Close(handle);
-
-	return LoadFace(buffer, (int)length, file_name, true);
-}
-
-// Loads a FreeType face from memory.
-void* FontDatabase::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
-{
-	FT_Face face = NULL;
-	int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face);
-	if (error != 0)
-	{
-		Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString());
-		if (local_data)
-			delete[] data;
-
-		return NULL;
-	}
-
-	// Initialise the character mapping on the face.
-	if (face->charmap == NULL)
-	{
-		FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
-		if (face->charmap == NULL)
-		{
-			Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString());
-			FT_Done_Face(face);
-			if (local_data)
-				delete[] data;
-
-			return NULL;
-		}
-	}
-
-	return face;
+    for(FontProviderTable::iterator i = instance->font_provider_table.begin(); i != instance->font_provider_table.end(); ++i)
+    {
+        if(*i == provider)
+        {
+            instance->font_provider_table.erase(i);
+            return;
+        }
+    }
 }
 
 }

+ 2 - 95
Source/Core/FontFace.cpp

@@ -26,16 +26,15 @@
  */
 
 #include "precompiled.h"
-#include "FontFace.h"
+#include "../../Include/Rocket/Core/FontFace.h"
 #include "FontFaceHandle.h"
 #include "../../Include/Rocket/Core/Log.h"
 
 namespace Rocket {
 namespace Core {
 
-FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream)
+FontFace::FontFace(Font::Style _style, Font::Weight _weight, bool _release_stream)
 {
-	face = _face;
 	style = _style;
 	weight = _weight;
 
@@ -50,8 +49,6 @@ FontFace::~FontFace()
 		for (size_t i = 0; i < handle_list.size(); ++i)
 			handle_list[i]->RemoveReference();
 	}
-
-	ReleaseFace();
 }
 
 // Returns the style of the font face.
@@ -66,95 +63,5 @@ Font::Weight FontFace::GetWeight() const
 	return weight;
 }
 
-// Returns a handle for positioning and rendering this face at the given size.
-FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
-{
-	UnicodeRangeList charset;
-
-	HandleMap::iterator iterator = handles.find(size);
-	if (iterator != handles.end())
-	{
-		const HandleList& handles = (*iterator).second;
-
-		// Check all the handles if their charsets match the requested one exactly (ie, were specified by the same
-		// string).
-		String raw_charset(_raw_charset);
-		for (size_t i = 0; i < handles.size(); ++i)
-		{
-			if (handles[i]->GetRawCharset() == _raw_charset)
-			{
-				handles[i]->AddReference();
-				return handles[i];
-			}
-		}
-
-		// Check all the handles if their charsets contain the requested charset.
-		if (!UnicodeRange::BuildList(charset, raw_charset))
-		{
-			Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString());
-			return NULL;
-		}
-
-		for (size_t i = 0; i < handles.size(); ++i)
-		{
-			bool range_contained = true;
-
-			const UnicodeRangeList& handle_charset = handles[i]->GetCharset();
-			for (size_t j = 0; j < charset.size() && range_contained; ++j)
-			{
-				if (!charset[j].IsContained(handle_charset))
-					range_contained = false;
-			}
-
-			if (range_contained)
-			{
-				handles[i]->AddReference();
-				return handles[i];
-			}
-		}
-	}
-
-	// See if this face has been released.
-	if (face == NULL)
-	{
-		Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle.");
-		return NULL;
-	}
-
-	// Construct and initialise the new handle.
-	FontFaceHandle* handle = new FontFaceHandle();
-	if (!handle->Initialise(face, _raw_charset, size))
-	{
-		handle->RemoveReference();
-		return NULL;
-	}
-
-	// Save the handle, and add a reference for the callee. The initial reference will be removed when the font face
-	// releases it.
-	if (iterator != handles.end())
-		(*iterator).second.push_back(handle);
-	else
-		handles[size] = HandleList(1, handle);
-
-	handle->AddReference();
-
-	return handle;
-}
-
-// Releases the face's FreeType face structure.
-void FontFace::ReleaseFace()
-{
-	if (face != NULL)
-	{
-		FT_Byte* face_memory = face->stream->base;
-		FT_Done_Face(face);
-
-		if (release_stream)
-			delete[] face_memory;
-
-		face = NULL;
-	}
-}
-
 }
 }

+ 0 - 209
Source/Core/FontFaceHandle.cpp

@@ -55,8 +55,6 @@ FontFaceHandle::FontFaceHandle()
 	underline_position = 0;
 	underline_thickness = 0;
 
-	ft_face = NULL;
-
 	base_layer = NULL;
 }
 
@@ -69,50 +67,6 @@ FontFaceHandle::~FontFaceHandle()
 		delete i->second;
 }
 
-// Initialises the handle so it is able to render text.
-bool FontFaceHandle::Initialise(FT_Face ft_face, const String& _charset, int _size)
-{
-	size = _size;
-
-	raw_charset = _charset;
-	if (!UnicodeRange::BuildList(charset, raw_charset))
-	{
-		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
-		return false;
-	}
-
-	// Set the character size on the font face.
-	FT_Error error = FT_Set_Char_Size(ft_face, 0, size << 6, 0, 0);
-	if (error != 0)
-	{
-		Log::Message(Log::LT_ERROR, "Unable to set the character size '%d' on the font face '%s %s'.", size, ft_face->family_name, ft_face->style_name);
-		return false;
-	}
-
-	this->ft_face = ft_face;
-
-	// find the maximum character we are interested in
-	max_codepoint = 0;
-	for (size_t i = 0; i < charset.size(); ++i)
-		max_codepoint = Math::Max(max_codepoint, charset[i].max_codepoint);
-
-	// Construct the list of the characters specified by the charset.
-	glyphs.resize(max_codepoint+1, FontGlyph());
-	for (size_t i = 0; i < charset.size(); ++i)
-		BuildGlyphMap(charset[i]);
-
-	// Generate the metrics for the handle.
-	GenerateMetrics();
-
-	// Generate the default layer and layer configuration.
-	base_layer = GenerateLayer(NULL);
-	layer_configurations.push_back(LayerConfiguration());
-	layer_configurations.back().push_back(base_layer);
-
-
-	return true;
-}
-
 // Returns the point size of this font face.
 int FontFaceHandle::GetSize() const
 {
@@ -353,169 +307,6 @@ void FontFaceHandle::OnReferenceDeactivate()
 	delete this;
 }
 
-void FontFaceHandle::GenerateMetrics()
-{
-	line_height = ft_face->size->metrics.height >> 6;
-	baseline = line_height - (ft_face->size->metrics.ascender >> 6);
-
-	underline_position = FT_MulFix(ft_face->underline_position, ft_face->size->metrics.y_scale) / float(1 << 6);
-	underline_thickness = FT_MulFix(ft_face->underline_thickness, ft_face->size->metrics.y_scale) / float(1 << 6);
-	underline_thickness = Math::Max(underline_thickness, 1.0f);
-
-	average_advance = 0;
-	unsigned int num_visible_glyphs = 0;
-	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
-	{
-		if (i->advance)
-		{
-			average_advance += i->advance;
-			num_visible_glyphs++;
-		}
-	}
-
-	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
-	if (num_visible_glyphs)
-		average_advance = Math::RealToInteger((float) average_advance / (num_visible_glyphs * 0.9f));
-
-	// Determine the x-height of this font face.
-	word x = (word) 'x';
-	int index = FT_Get_Char_Index(ft_face, x);
-	if (FT_Load_Glyph(ft_face, index, 0) == 0)
-		x_height = ft_face->glyph->metrics.height >> 6;
-	else
-		x_height = 0;
-}
-
-void FontFaceHandle::BuildGlyphMap(const UnicodeRange& unicode_range)
-{
-	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
-	{
-		int index = FT_Get_Char_Index(ft_face, character_code);
-		if (index != 0)
-		{
-			FT_Error error = FT_Load_Glyph(ft_face, index, 0);
-			if (error != 0)
-			{
-				Log::Message(Log::LT_WARNING, "Unable to load glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
-				continue;
-			}
-
-			error = FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_NORMAL);
-			if (error != 0)
-			{
-				Log::Message(Log::LT_WARNING, "Unable to render glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
-				continue;
-			}
-
-			FontGlyph glyph;
-			glyph.character = character_code;
-			BuildGlyph(glyph, ft_face->glyph);
-			glyphs[character_code] = glyph;
-		}
-	}
-}
-
-void FontFaceHandle::BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph)
-{
-	// Set the glyph's dimensions.
-	glyph.dimensions.x = ft_glyph->metrics.width >> 6;
-	glyph.dimensions.y = ft_glyph->metrics.height >> 6;
-
-	// Set the glyph's bearing.
-	glyph.bearing.x = ft_glyph->metrics.horiBearingX >> 6;
-	glyph.bearing.y = ft_glyph->metrics.horiBearingY >> 6;
-
-	// Set the glyph's advance.
-	glyph.advance = ft_glyph->metrics.horiAdvance >> 6;
-
-	// Set the glyph's bitmap dimensions.
-	glyph.bitmap_dimensions.x = ft_glyph->bitmap.width;
-	glyph.bitmap_dimensions.y = ft_glyph->bitmap.rows;
-
-	// Copy the glyph's bitmap data from the FreeType glyph handle to our glyph handle.
-	if (glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y != 0)
-	{
-		// Check the pixel mode is supported.
-		if (ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
-			ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
-		{
-			glyph.bitmap_data = NULL;
-			Log::Message(Log::LT_WARNING, "Unable to render glyph on the font face '%s %s'; unsupported pixel mode (%d).", ft_glyph->face->family_name, ft_glyph->face->style_name, ft_glyph->bitmap.pixel_mode);
-		}
-		else
-		{
-			glyph.bitmap_data = new byte[glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y];
-
-			byte* source_bitmap = ft_glyph->bitmap.buffer;
-			byte* destination_bitmap = glyph.bitmap_data;
-
-			// Copy the bitmap data into the newly-allocated space on our glyph.
-			switch (ft_glyph->bitmap.pixel_mode)
-			{
-				// Unpack 1-bit data into 8-bit.
-				case FT_PIXEL_MODE_MONO:
-				{
-					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
-					{
-						int mask = 0x80;
-						byte* source_byte = source_bitmap;
-						for (int j = 0; j < glyph.bitmap_dimensions.x; ++j)
-						{
-							if ((*source_byte & mask) == mask)
-								destination_bitmap[j] = 255;
-							else
-								destination_bitmap[j] = 0;
-
-							mask >>= 1;
-							if (mask <= 0)
-							{
-								mask = 0x80;
-								++source_byte;
-							}
-						}
-
-						destination_bitmap += glyph.bitmap_dimensions.x;
-						source_bitmap += ft_glyph->bitmap.pitch;
-					}
-				}
-				break;
-
-				// Directly copy 8-bit data.
-				case FT_PIXEL_MODE_GRAY:
-				{
-					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
-					{
-						memcpy(destination_bitmap, source_bitmap, glyph.bitmap_dimensions.x);
-						destination_bitmap += glyph.bitmap_dimensions.x;
-						source_bitmap += ft_glyph->bitmap.pitch;
-					}
-				}
-				break;
-			}
-		}
-	}
-	else
-		glyph.bitmap_data = NULL;
-}
-
-int FontFaceHandle::GetKerning(word lhs, word rhs) const
-{
-	if (!FT_HAS_KERNING(ft_face))
-		return 0;
-
-	FT_Vector ft_kerning;
-
-	FT_Error ft_error = FT_Get_Kerning(ft_face, 
-		FT_Get_Char_Index(ft_face, lhs), FT_Get_Char_Index(ft_face, rhs),
-		FT_KERNING_DEFAULT, &ft_kerning);
-
-	if (ft_error != 0)
-		return 0;
-
-	int kerning = ft_kerning.x >> 6;
-	return kerning;
-}
-
 // Generates (or shares) a layer derived from a font effect.
 FontFaceLayer* FontFaceHandle::GenerateLayer(FontEffect* font_effect)
 {

+ 7 - 26
Source/Core/FontFaceHandle.h

@@ -36,8 +36,6 @@
 #include "../../Include/Rocket/Core/Geometry.h"
 #include "../../Include/Rocket/Core/String.h"
 #include "../../Include/Rocket/Core/Texture.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
 
 namespace Rocket {
 namespace Core {
@@ -54,13 +52,6 @@ public:
 	FontFaceHandle();
 	virtual ~FontFaceHandle();
 
-	/// Initialises the handle so it is able to render text.
-	/// @param[in] ft_face The FreeType face that this handle is rendering.
-	/// @param[in] charset The comma-separated list of unicode ranges this handle must support.
-	/// @param[in] size The size, in points, of the face this handle should render at.
-	/// @return True if the handle initialised successfully and is ready for rendering, false if an error occured.
-	bool Initialise(FT_Face ft_face, const String& charset, int size);
-
 	/// Returns the average advance of all glyphs in this font face.
 	/// @return An approximate width of the characters in this font face.
 	int GetCharacterWidth() const;
@@ -87,18 +78,18 @@ public:
 	/// @param[in] string The string to measure.
 	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
 	/// @return The width, in pixels, this string will occupy if rendered with this handle.
-	int GetStringWidth(const WString& string, word prior_character = 0) const;
+	virtual int GetStringWidth(const WString& string, word prior_character = 0) const = 0;
 
 	/// Generates, if required, the layer configuration for a given array of font effects.
 	/// @param[in] font_effects The list of font effects to generate the configuration for.
 	/// @return The index to use when generating geometry using this configuration.
-	int GenerateLayerConfiguration(FontEffectMap& font_effects);
+	virtual int GenerateLayerConfiguration(FontEffectMap& font_effects) = 0;
 	/// Generates the texture data for a layer (for the texture database).
 	/// @param[out] texture_data The pointer to be set to the generated texture data.
 	/// @param[out] texture_dimensions The dimensions of the texture.
 	/// @param[in] layer_id The id of the layer to request the texture data from.
 	/// @param[in] texture_id The index of the texture within the layer to generate.
-	bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id);
+	virtual bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id) = 0;
 
 	/// Generates the geometry required to render a single line of text.
 	/// @param[out] geometry An array of geometries to generate the geometry into.
@@ -106,14 +97,14 @@ public:
 	/// @param[in] position The position of the baseline of the first character to render.
 	/// @param[in] colour The colour to render the text.
 	/// @return The width, in pixels, of the string geometry.
-	int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const;
+	virtual int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const = 0;
 	/// Generates the geometry required to render a line above, below or through a line of text.
 	/// @param[out] geometry The geometry to append the newly created geometry into.
 	/// @param[in] position The position of the baseline of the lined text.
 	/// @param[in] width The width of the string to line.
 	/// @param[in] height The height to render the line at.
 	/// @param[in] colour The colour to draw the line in.
-	void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const;
+	virtual void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const = 0;
 
 	/// Returns the font face's raw charset (the charset range as a string).
 	/// @return The font face's charset.
@@ -125,24 +116,14 @@ public:
 protected:
 	/// Destroys the handle.
 	virtual void OnReferenceDeactivate();
-
-private:
-	void GenerateMetrics(void);
-
-	void BuildGlyphMap(const UnicodeRange& unicode_range);
-	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
-
-	int GetKerning(word lhs, word rhs) const;
-
-	// Generates (or shares) a layer derived from a font effect.
 	FontFaceLayer* GenerateLayer(FontEffect* font_effect);
+	virtual int GetKerning(word lhs, word rhs) const = 0;
 
 	typedef std::vector< int > GlyphKerningList;
 	typedef std::vector< GlyphKerningList > FontKerningList;
 
-	FT_Face ft_face;
-
 	FontGlyphList glyphs;
+	FontKerningList kerning;
 
 	typedef std::map< const FontEffect*, FontFaceLayer* > FontLayerMap;
 	typedef std::map< String, FontFaceLayer* > FontLayerCache;

+ 3 - 3
Source/Core/FontFaceLayer.h

@@ -60,14 +60,14 @@ public:
 	/// @param[in] clone The layer to optionally clone geometry and texture data from.
 	/// @param[in] deep_clone If true, the clones geometry will be completely cloned and the effect will have no option to affect even the glyph origins.
 	/// @return True if the layer was generated successfully, false if not.
-	bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const FontFaceLayer* clone = NULL, bool deep_clone = false);
+	virtual bool Initialise(const FontFaceHandle* handle, FontEffect* effect = NULL, const FontFaceLayer* clone = NULL, bool deep_clone = false);
 
 	/// Generates the texture data for a layer (for the texture database).
 	/// @param[out] texture_data The pointer to be set to the generated texture data.
 	/// @param[out] texture_dimensions The dimensions of the texture.
 	/// @param[in] glyphs The glyphs required by the font face handle.
 	/// @param[in] texture_id The index of the texture within the layer to generate.
-	bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id);
+	virtual bool GenerateTexture(const byte*& texture_data, Vector2i& texture_dimensions, int texture_id);
 	/// Generates the geometry required to render a single character.
 	/// @param[out] geometry An array of geometries this layer will write to. It must be at least as big as the number of textures in this layer.
 	/// @param[in] character_code The character to generate geometry for.
@@ -107,7 +107,7 @@ public:
 	/// @return The layer's colour.
 	const Colourb& GetColour() const;
 
-private:
+// protected:
 	struct Character
 	{
 		Character() : texture_index(-1) { }

+ 2 - 11
Source/Core/FontFamily.cpp

@@ -26,8 +26,8 @@
  */
 
 #include "precompiled.h"
-#include "FontFamily.h"
-#include "FontFace.h"
+#include "../../Include/Rocket/Core/FontFamily.h"
+#include "../../Include/Rocket/Core/FontFace.h"
 
 namespace Rocket {
 namespace Core {
@@ -42,15 +42,6 @@ FontFamily::~FontFamily()
 		delete font_faces[i];
 }
 
-// Adds a new face to the family.
-bool FontFamily::AddFace(FT_Face ft_face, Font::Style style, Font::Weight weight, bool release_stream)
-{
-	FontFace* face = new FontFace(ft_face, style, weight, release_stream);
-	font_faces.push_back(face);
-
-	return true;
-}
-
 // Returns a handle to the most appropriate font in the family, at the correct size.
 FontFaceHandle* FontFamily::GetFaceHandle(const String& charset, Font::Style style, Font::Weight weight, int size)
 {

+ 45 - 0
Source/Core/FontProvider.cpp

@@ -0,0 +1,45 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include <Rocket/Core/FontProvider.h>
+#include <Rocket/Core/FontFamily.h>
+
+namespace Rocket {
+namespace Core {
+
+// Returns a handle to a font face that can be used to position and render text.
+Rocket::Core::FontFaceHandle* FontProvider::GetFontFaceHandle(const String& family, const String& charset, Font::Style style, Font::Weight weight, int size)
+{
+	FontFamilyMap::iterator iterator = font_families.find(family);
+	if (iterator == font_families.end())
+		return NULL;
+
+	return (*iterator).second->GetFaceHandle(charset, style, weight, size);
+}
+
+}
+}

+ 139 - 0
Source/Core/FreeType/FontFace.cpp

@@ -0,0 +1,139 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFace.h"
+#include "FontFaceHandle.h"
+#include "../../../Include/Rocket/Core/Log.h"
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+
+FontFace::FontFace(FT_Face _face, Font::Style _style, Font::Weight _weight, bool _release_stream) : Rocket::Core::FontFace(_style, _weight, _release_stream)
+{
+	face = _face;
+}
+
+FontFace::~FontFace()
+{
+	ReleaseFace();
+}
+
+// Returns a handle for positioning and rendering this face at the given size.
+Rocket::Core::FontFaceHandle* FontFace::GetHandle(const String& _raw_charset, int size)
+{
+	UnicodeRangeList charset;
+
+	HandleMap::iterator iterator = handles.find(size);
+	if (iterator != handles.end())
+	{
+		const HandleList& handles = (*iterator).second;
+
+		// Check all the handles if their charsets match the requested one exactly (ie, were specified by the same
+		// string).
+		String raw_charset(_raw_charset);
+		for (size_t i = 0; i < handles.size(); ++i)
+		{
+			if (handles[i]->GetRawCharset() == _raw_charset)
+			{
+				handles[i]->AddReference();
+				return (Rocket::Core::FreeType::FontFaceHandle*)handles[i];
+			}
+		}
+
+		// Check all the handles if their charsets contain the requested charset.
+		if (!UnicodeRange::BuildList(charset, raw_charset))
+		{
+			Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", _raw_charset.CString());
+			return NULL;
+		}
+
+		for (size_t i = 0; i < handles.size(); ++i)
+		{
+			bool range_contained = true;
+
+			const UnicodeRangeList& handle_charset = handles[i]->GetCharset();
+			for (size_t j = 0; j < charset.size() && range_contained; ++j)
+			{
+				if (!charset[j].IsContained(handle_charset))
+					range_contained = false;
+			}
+
+			if (range_contained)
+			{
+				handles[i]->AddReference();
+				return (Rocket::Core::FreeType::FontFaceHandle*)handles[i];
+			}
+		}
+	}
+
+	// See if this face has been released.
+	if (face == NULL)
+	{
+		Log::Message(Log::LT_WARNING, "Font face has been released, unable to generate new handle.");
+		return NULL;
+	}
+
+	// Construct and initialise the new handle.
+	FontFaceHandle* handle = new FontFaceHandle();
+	if (!handle->Initialise(face, _raw_charset, size))
+	{
+		handle->RemoveReference();
+		return NULL;
+	}
+
+	// Save the handle, and add a reference for the callee. The initial reference will be removed when the font face
+	// releases it.
+	if (iterator != handles.end())
+		(*iterator).second.push_back(handle);
+	else
+		handles[size] = HandleList(1, handle);
+
+	handle->AddReference();
+
+	return handle;
+}
+
+// Releases the face's FreeType face structure.
+void FontFace::ReleaseFace()
+{
+	if (face != NULL)
+	{
+		FT_Byte* face_memory = face->stream->base;
+		FT_Done_Face(face);
+
+		if (release_stream)
+			delete[] face_memory;
+
+		face = NULL;
+	}
+}
+
+}
+}
+}

+ 68 - 0
Source/Core/FreeType/FontFace.h

@@ -0,0 +1,68 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTFACE_H
+#define ROCKETCOREFREETYPEFONTFACE_H
+
+#include "../../../Include/Rocket/Core/FontFace.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle;
+
+class FontFace : public Rocket::Core::FontFace
+{
+public:
+	FontFace(FT_Face face, Font::Style style, Font::Weight weight, bool release_stream);
+	~FontFace();
+
+	/// Returns a handle for positioning and rendering this face at the given size.
+	/// @param[in] charset The set of characters in the handle, as a comma-separated list of unicode ranges.
+	/// @param[in] size The size of the desired handle, in points.
+	/// @return The shared font handle.
+	Rocket::Core::FontFaceHandle* GetHandle(const String& charset, int size);
+
+	/// Releases the face's FreeType face structure. This will mean handles for new sizes cannot be constructed,
+	/// but existing ones can still be fetched.
+	void ReleaseFace();
+
+private:
+	FT_Face face;
+};
+
+}
+}
+}
+
+#endif

+ 458 - 0
Source/Core/FreeType/FontFaceHandle.cpp

@@ -0,0 +1,458 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFaceHandle.h"
+#include <algorithm>
+#include "../../../Include/Rocket/Core.h"
+#include "../FontFaceLayer.h"
+#include "../TextureLayout.h"
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+
+class FontEffectSort
+{
+public:
+	bool operator()(const FontEffect* lhs, const FontEffect* rhs)
+	{
+		return lhs->GetZIndex() < rhs->GetZIndex();
+	}
+};
+
+FontFaceHandle::FontFaceHandle()
+{
+	ft_face = NULL;
+}
+
+FontFaceHandle::~FontFaceHandle()
+{
+}
+
+// Initialises the handle so it is able to render text.
+bool FontFaceHandle::Initialise(FT_Face ft_face, const String& _charset, int _size)
+{
+	size = _size;
+
+	raw_charset = _charset;
+	if (!UnicodeRange::BuildList(charset, raw_charset))
+	{
+		Log::Message(Log::LT_ERROR, "Invalid font charset '%s'.", raw_charset.CString());
+		return false;
+	}
+
+	// Set the character size on the font face.
+	FT_Error error = FT_Set_Char_Size(ft_face, 0, size << 6, 0, 0);
+	if (error != 0)
+	{
+		Log::Message(Log::LT_ERROR, "Unable to set the character size '%d' on the font face '%s %s'.", size, ft_face->family_name, ft_face->style_name);
+		return false;
+	}
+
+	this->ft_face = ft_face;
+
+	// find the maximum character we are interested in
+	max_codepoint = 0;
+	for (size_t i = 0; i < charset.size(); ++i)
+		max_codepoint = Math::Max(max_codepoint, charset[i].max_codepoint);
+
+	// Construct the list of the characters specified by the charset.
+	glyphs.resize(max_codepoint+1, FontGlyph());
+	for (size_t i = 0; i < charset.size(); ++i)
+		BuildGlyphMap(charset[i]);
+
+	// Generate the metrics for the handle.
+	GenerateMetrics();
+
+	// Generate the default layer and layer configuration.
+	base_layer = GenerateLayer(NULL);
+	layer_configurations.push_back(LayerConfiguration());
+	layer_configurations.back().push_back(base_layer);
+
+
+	return true;
+}
+
+// Returns the width a string will take up if rendered with this handle.
+int FontFaceHandle::GetStringWidth(const WString& string, word prior_character) const
+{
+	int width = 0;
+
+	for (size_t i = 0; i < string.Length(); i++)
+	{
+		word character_code = string[i];
+
+		if (character_code >= glyphs.size())
+			continue;
+		const FontGlyph &glyph = glyphs[character_code];
+
+		// Adjust the cursor for the kerning between this character and the previous one.
+		if (prior_character != 0)
+			width += GetKerning(prior_character, string[i]);
+		// Adjust the cursor for this character's advance.
+		width += glyph.advance;
+
+		prior_character = character_code;
+	}
+
+	return width;
+}
+
+// Generates, if required, the layer configuration for a given array of font effects.
+int FontFaceHandle::GenerateLayerConfiguration(FontEffectMap& font_effects)
+{
+	if (font_effects.empty())
+		return 0;
+
+	// Prepare a list of effects, sorted by z-index.
+	FontEffectList sorted_effects;
+	for (FontEffectMap::const_iterator i = font_effects.begin(); i != font_effects.end(); ++i)
+		sorted_effects.push_back(i->second);
+
+	std::sort(sorted_effects.begin(), sorted_effects.end(), FontEffectSort());
+
+	// Check each existing configuration for a match with this arrangement of effects.
+	int configuration_index = 1;
+	for (; configuration_index < (int) layer_configurations.size(); ++configuration_index)
+	{
+		const LayerConfiguration& configuration = layer_configurations[configuration_index];
+
+		// Check the size is correct. For a math, there should be one layer in the configuration
+		// plus an extra for the base layer.
+		if (configuration.size() != sorted_effects.size() + 1)
+			continue;
+
+		// Check through each layer, checking it was created by the same effect as the one we're
+		// checking.
+		size_t effect_index = 0;
+		for (size_t i = 0; i < configuration.size(); ++i)
+		{
+			// Skip the base layer ...
+			if (configuration[i]->GetFontEffect() == NULL)
+				continue;
+
+			// If the ith layer's effect doesn't match the equivalent effect, then this
+			// configuration can't match.
+			if (configuration[i]->GetFontEffect() != sorted_effects[effect_index])
+				break;
+
+			// Check the next one ...
+			++effect_index;
+		}
+
+		if (effect_index == sorted_effects.size())
+			return configuration_index;
+	}
+
+	// No match, so we have to generate a new layer configuration.
+	layer_configurations.push_back(LayerConfiguration());
+	LayerConfiguration& layer_configuration = layer_configurations.back();
+
+	bool added_base_layer = false;
+
+	for (size_t i = 0; i < sorted_effects.size(); ++i)
+	{
+		if (!added_base_layer &&
+			sorted_effects[i]->GetZIndex() >= 0)
+		{
+			layer_configuration.push_back(base_layer);
+			added_base_layer = true;
+		}
+
+		layer_configuration.push_back(GenerateLayer(sorted_effects[i]));
+	}
+
+	// Add the base layer now if we still haven't added it.
+	if (!added_base_layer)
+		layer_configuration.push_back(base_layer);
+
+	return (int) (layer_configurations.size() - 1);
+}
+
+// Generates the texture data for a layer (for the texture database).
+bool FontFaceHandle::GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id)
+{
+	FontLayerMap::iterator layer_iterator = layers.find(layer_id);
+	if (layer_iterator == layers.end())
+		return false;
+
+	return layer_iterator->second->GenerateTexture(texture_data, texture_dimensions, texture_id);
+}
+
+// Generates the geometry required to render a single line of text.
+int FontFaceHandle::GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration_index) const
+{
+	int geometry_index = 0;
+	int line_width = 0;
+
+	ROCKET_ASSERT(layer_configuration_index >= 0);
+	ROCKET_ASSERT(layer_configuration_index < (int) layer_configurations.size());
+
+	// Fetch the requested configuration and generate the geometry for each one.
+	const LayerConfiguration& layer_configuration = layer_configurations[layer_configuration_index];
+	for (size_t i = 0; i < layer_configuration.size(); ++i)
+	{
+		FontFaceLayer* layer = layer_configuration[i];
+
+		Colourb layer_colour;
+		if (layer == base_layer)
+			layer_colour = colour;
+		else
+			layer_colour = layer->GetColour();
+
+		// Resize the geometry list if required.
+		if ((int) geometry.size() < geometry_index + layer->GetNumTextures())
+			geometry.resize(geometry_index + layer->GetNumTextures());
+
+		// Bind the textures to the geometries.
+		for (int i = 0; i < layer->GetNumTextures(); ++i)
+			geometry[geometry_index + i].SetTexture(layer->GetTexture(i));
+
+		line_width = 0;
+		word prior_character = 0;
+
+		const word* string_iterator = string.CString();
+		const word* string_end = string.CString() + string.Length();
+
+		for (; string_iterator != string_end; string_iterator++)
+		{
+			if (*string_iterator >= glyphs.size())
+				continue;
+			const FontGlyph &glyph = glyphs[*string_iterator];
+
+			// Adjust the cursor for the kerning between this character and the previous one.
+			if (prior_character != 0)
+				line_width += GetKerning(prior_character, *string_iterator);
+
+			layer->GenerateGeometry(&geometry[geometry_index], *string_iterator, Vector2f(position.x + line_width, position.y), layer_colour);
+
+			line_width += glyph.advance;
+			prior_character = *string_iterator;
+		}
+
+		geometry_index += layer->GetNumTextures();
+	}
+
+	// Cull any excess geometry from a previous generation.
+	geometry.resize(geometry_index);
+
+	return line_width;
+}
+
+// Generates the geometry required to render a line above, below or through a line of text.
+void FontFaceHandle::GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const
+{
+	std::vector< Vertex >& line_vertices = geometry->GetVertices();
+	std::vector< int >& line_indices = geometry->GetIndices();
+
+	float offset;
+	switch (height)
+	{
+		case Font::UNDERLINE:			offset = -underline_position; break;
+		case Font::OVERLINE:			// where to place? offset = -line_height - underline_position; break;
+		case Font::STRIKE_THROUGH:		// where to place? offset = -line_height * 0.5f; break;
+		default:						return;
+	}
+
+	line_vertices.resize(line_vertices.size() + 4);
+	line_indices.resize(line_indices.size() + 6);
+	GeometryUtilities::GenerateQuad(&line_vertices[0] + (line_vertices.size() - 4), &line_indices[0] + (line_indices.size() - 6), Vector2f(position.x, position.y + offset), Vector2f((float) width, underline_thickness), colour, (int)line_vertices.size() - 4);
+}
+
+// Destroys the handle.
+void FontFaceHandle::OnReferenceDeactivate()
+{
+	delete this;
+}
+
+void FontFaceHandle::GenerateMetrics()
+{
+	line_height = ft_face->size->metrics.height >> 6;
+	baseline = line_height - (ft_face->size->metrics.ascender >> 6);
+
+	underline_position = FT_MulFix(ft_face->underline_position, ft_face->size->metrics.y_scale) / float(1 << 6);
+	underline_thickness = FT_MulFix(ft_face->underline_thickness, ft_face->size->metrics.y_scale) / float(1 << 6);
+	underline_thickness = Math::Max(underline_thickness, 1.0f);
+
+	average_advance = 0;
+	unsigned int num_visible_glyphs = 0;
+	for (FontGlyphList::iterator i = glyphs.begin(); i != glyphs.end(); ++i)
+	{
+		if (i->advance)
+		{
+			average_advance += i->advance;
+			num_visible_glyphs++;
+		}
+	}
+
+	// Bring the total advance down to the average advance, but scaled up 10%, just to be on the safe side.
+	if (num_visible_glyphs)
+		average_advance = Math::RealToInteger((float) average_advance / (num_visible_glyphs * 0.9f));
+
+	// Determine the x-height of this font face.
+	word x = (word) 'x';
+	int index = FT_Get_Char_Index(ft_face, x);
+	if (FT_Load_Glyph(ft_face, index, 0) == 0)
+		x_height = ft_face->glyph->metrics.height >> 6;
+	else
+		x_height = 0;
+}
+
+void FontFaceHandle::BuildGlyphMap(const UnicodeRange& unicode_range)
+{
+	for (word character_code = (word) (Math::Max< unsigned int >(unicode_range.min_codepoint, 32)); character_code <= unicode_range.max_codepoint; ++character_code)
+	{
+		int index = FT_Get_Char_Index(ft_face, character_code);
+		if (index != 0)
+		{
+			FT_Error error = FT_Load_Glyph(ft_face, index, 0);
+			if (error != 0)
+			{
+				Log::Message(Log::LT_WARNING, "Unable to load glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
+				continue;
+			}
+
+			error = FT_Render_Glyph(ft_face->glyph, FT_RENDER_MODE_NORMAL);
+			if (error != 0)
+			{
+				Log::Message(Log::LT_WARNING, "Unable to render glyph for character '%u' on the font face '%s %s'; error code: %d.", character_code, ft_face->family_name, ft_face->style_name, error);
+				continue;
+			}
+
+			FontGlyph glyph;
+			glyph.character = character_code;
+			BuildGlyph(glyph, ft_face->glyph);
+			glyphs[character_code] = glyph;
+		}
+	}
+}
+
+void FontFaceHandle::BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph)
+{
+	// Set the glyph's dimensions.
+	glyph.dimensions.x = ft_glyph->metrics.width >> 6;
+	glyph.dimensions.y = ft_glyph->metrics.height >> 6;
+
+	// Set the glyph's bearing.
+	glyph.bearing.x = ft_glyph->metrics.horiBearingX >> 6;
+	glyph.bearing.y = ft_glyph->metrics.horiBearingY >> 6;
+
+	// Set the glyph's advance.
+	glyph.advance = ft_glyph->metrics.horiAdvance >> 6;
+
+	// Set the glyph's bitmap dimensions.
+	glyph.bitmap_dimensions.x = ft_glyph->bitmap.width;
+	glyph.bitmap_dimensions.y = ft_glyph->bitmap.rows;
+
+	// Copy the glyph's bitmap data from the FreeType glyph handle to our glyph handle.
+	if (glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y != 0)
+	{
+		// Check the pixel mode is supported.
+		if (ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_MONO &&
+			ft_glyph->bitmap.pixel_mode != FT_PIXEL_MODE_GRAY)
+		{
+			glyph.bitmap_data = NULL;
+			Log::Message(Log::LT_WARNING, "Unable to render glyph on the font face '%s %s'; unsupported pixel mode (%d).", ft_glyph->face->family_name, ft_glyph->face->style_name, ft_glyph->bitmap.pixel_mode);
+		}
+		else
+		{
+			glyph.bitmap_data = new byte[glyph.bitmap_dimensions.x * glyph.bitmap_dimensions.y];
+
+			byte* source_bitmap = ft_glyph->bitmap.buffer;
+			byte* destination_bitmap = glyph.bitmap_data;
+
+			// Copy the bitmap data into the newly-allocated space on our glyph.
+			switch (ft_glyph->bitmap.pixel_mode)
+			{
+				// Unpack 1-bit data into 8-bit.
+				case FT_PIXEL_MODE_MONO:
+				{
+					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
+					{
+						int mask = 0x80;
+						byte* source_byte = source_bitmap;
+						for (int j = 0; j < glyph.bitmap_dimensions.x; ++j)
+						{
+							if ((*source_byte & mask) == mask)
+								destination_bitmap[j] = 255;
+							else
+								destination_bitmap[j] = 0;
+
+							mask >>= 1;
+							if (mask <= 0)
+							{
+								mask = 0x80;
+								++source_byte;
+							}
+						}
+
+						destination_bitmap += glyph.bitmap_dimensions.x;
+						source_bitmap += ft_glyph->bitmap.pitch;
+					}
+				}
+				break;
+
+				// Directly copy 8-bit data.
+				case FT_PIXEL_MODE_GRAY:
+				{
+					for (int i = 0; i < glyph.bitmap_dimensions.y; ++i)
+					{
+						memcpy(destination_bitmap, source_bitmap, glyph.bitmap_dimensions.x);
+						destination_bitmap += glyph.bitmap_dimensions.x;
+						source_bitmap += ft_glyph->bitmap.pitch;
+					}
+				}
+				break;
+			}
+		}
+	}
+	else
+		glyph.bitmap_data = NULL;
+}
+
+int FontFaceHandle::GetKerning(word lhs, word rhs) const
+{
+	if (!FT_HAS_KERNING(ft_face))
+		return 0;
+
+	FT_Vector ft_kerning;
+
+	FT_Error ft_error = FT_Get_Kerning(ft_face,
+		FT_Get_Char_Index(ft_face, lhs), FT_Get_Char_Index(ft_face, rhs),
+		FT_KERNING_DEFAULT, &ft_kerning);
+
+	if (ft_error != 0)
+		return 0;
+
+	int kerning = ft_kerning.x >> 6;
+	return kerning;
+}
+
+}
+}
+}

+ 117 - 0
Source/Core/FreeType/FontFaceHandle.h

@@ -0,0 +1,117 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTFACEHANDLE_H
+#define ROCKETCOREFREETYPEFONTFACEHANDLE_H
+
+#include "../../../Include/Rocket/Core/ReferenceCountable.h"
+#include "../UnicodeRange.h"
+#include "../FontFaceHandle.h"
+#include "../../../Include/Rocket/Core/FontEffect.h"
+#include "../../../Include/Rocket/Core/FontGlyph.h"
+#include "../../../Include/Rocket/Core/Geometry.h"
+#include "../../../Include/Rocket/Core/String.h"
+#include "../../../Include/Rocket/Core/Texture.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+
+class FontFaceLayer;
+
+namespace FreeType {
+
+/**
+	@author Peter Curry
+ */
+
+class FontFaceHandle : public Rocket::Core::FontFaceHandle
+{
+public:
+	FontFaceHandle();
+	virtual ~FontFaceHandle();
+
+	/// Initialises the handle so it is able to render text.
+	/// @param[in] ft_face The FreeType face that this handle is rendering.
+	/// @param[in] charset The comma-separated list of unicode ranges this handle must support.
+	/// @param[in] size The size, in points, of the face this handle should render at.
+	/// @return True if the handle initialised successfully and is ready for rendering, false if an error occured.
+	bool Initialise(FT_Face ft_face, const String& charset, int size);
+
+	/// Returns the width a string will take up if rendered with this handle.
+	/// @param[in] string The string to measure.
+	/// @param[in] prior_character The optionally-specified character that immediately precedes the string. This may have an impact on the string width due to kerning.
+	/// @return The width, in pixels, this string will occupy if rendered with this handle.
+	int GetStringWidth(const WString& string, word prior_character = 0) const;
+
+	/// Generates, if required, the layer configuration for a given array of font effects.
+	/// @param[in] font_effects The list of font effects to generate the configuration for.
+	/// @return The index to use when generating geometry using this configuration.
+	int GenerateLayerConfiguration(FontEffectMap& font_effects);
+	/// Generates the texture data for a layer (for the texture database).
+	/// @param[out] texture_data The pointer to be set to the generated texture data.
+	/// @param[out] texture_dimensions The dimensions of the texture.
+	/// @param[in] layer_id The id of the layer to request the texture data from.
+	/// @param[in] texture_id The index of the texture within the layer to generate.
+	bool GenerateLayerTexture(const byte*& texture_data, Vector2i& texture_dimensions, FontEffect* layer_id, int texture_id);
+
+	/// Generates the geometry required to render a single line of text.
+	/// @param[out] geometry An array of geometries to generate the geometry into.
+	/// @param[in] string The string to render.
+	/// @param[in] position The position of the baseline of the first character to render.
+	/// @param[in] colour The colour to render the text.
+	/// @return The width, in pixels, of the string geometry.
+	int GenerateString(GeometryList& geometry, const WString& string, const Vector2f& position, const Colourb& colour, int layer_configuration = 0) const;
+	/// Generates the geometry required to render a line above, below or through a line of text.
+	/// @param[out] geometry The geometry to append the newly created geometry into.
+	/// @param[in] position The position of the baseline of the lined text.
+	/// @param[in] width The width of the string to line.
+	/// @param[in] height The height to render the line at.
+	/// @param[in] colour The colour to draw the line in.
+	void GenerateLine(Geometry* geometry, const Vector2f& position, int width, Font::Line height, const Colourb& colour) const;
+
+protected:
+	/// Destroys the handle.
+	virtual void OnReferenceDeactivate();
+
+	int GetKerning(word lhs, word rhs) const;
+
+private:
+	void GenerateMetrics(void);
+
+	void BuildGlyphMap(const UnicodeRange& unicode_range);
+	void BuildGlyph(FontGlyph& glyph, FT_GlyphSlot ft_glyph);
+
+	FT_Face ft_face;
+};
+
+}
+}
+}
+
+#endif

+ 58 - 0
Source/Core/FreeType/FontFamily.cpp

@@ -0,0 +1,58 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include "FontFamily.h"
+#include "FontFace.h"
+
+namespace Rocket {
+namespace Core {
+namespace FreeType
+{
+
+FontFamily::FontFamily(const String& name) : Rocket::Core::FontFamily(name)
+{
+
+}
+
+FontFamily::~FontFamily()
+{
+
+}
+
+// Adds a new face to the family.
+bool FontFamily::AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	FontFace* face = new FontFace((FT_Face)ft_face, style, weight, release_stream);
+	font_faces.push_back(face);
+
+	return true;
+}
+
+}
+}
+}

+ 67 - 0
Source/Core/FreeType/FontFamily.h

@@ -0,0 +1,67 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef ROCKETCOREFREETYPEFONTFAMILY_H
+#define ROCKETCOREFREETYPEFONTFAMILY_H
+
+#include <Rocket/Core/Font.h>
+#include <Rocket/Core/FontFamily.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+
+class FontFace;
+class FontFaceHandle;
+
+/**
+	@author Peter Curry
+ */
+
+namespace FreeType {
+
+class FontFamily : public Rocket::Core::FontFamily
+{
+public:
+	FontFamily(const String& name);
+	~FontFamily();
+
+	/// Adds a new face to the family.
+	/// @param[in] ft_face The previously loaded FreeType face.
+	/// @param[in] style The style of the new face.
+	/// @param[in] weight The weight of the new face.
+	/// @param[in] release_stream True if the application must free the face's memory stream.
+	/// @return True if the face was loaded successfully, false otherwise.
+	bool AddFace(void* ft_face, Font::Style style, Font::Weight weight, bool release_stream);
+};
+
+}
+}
+}
+
+#endif

+ 258 - 0
Source/Core/FreeType/FontProvider.cpp

@@ -0,0 +1,258 @@
+/*
+ * This source file is part of libRocket, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://www.librocket.com
+ *
+ * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "../precompiled.h"
+#include <Rocket/Core/FreeType/FontProvider.h>
+#include "FontFaceHandle.h"
+#include <Rocket/Core/FontDatabase.h>
+#include "FontFamily.h"
+#include <Rocket/Core.h>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+namespace Rocket {
+namespace Core {
+namespace FreeType {
+
+FontProvider* FontProvider::instance = NULL;
+
+static FT_Library ft_library = NULL;
+
+FontProvider::FontProvider()
+{
+	ROCKET_ASSERT(instance == NULL);
+	instance = this;
+}
+
+FontProvider::~FontProvider()
+{
+	ROCKET_ASSERT(instance == this);
+	instance = NULL;
+}
+
+bool FontProvider::Initialise()
+{
+	if (instance == NULL)
+	{
+		new FontProvider();
+
+		FontDatabase::AddFontProvider(instance);
+
+		FT_Error result = FT_Init_FreeType(&ft_library);
+		if (result != 0)
+		{
+			Log::Message(Log::LT_ERROR, "Failed to initialise FreeType, error %d.", result);
+			Shutdown();
+			return false;
+		}
+	}
+
+	return true;
+}
+
+void FontProvider::Shutdown()
+{
+	if (instance != NULL)
+	{
+		for (FontFamilyMap::iterator i = instance->font_families.begin(); i != instance->font_families.end(); ++i)
+			delete (*i).second;
+
+		if (ft_library != NULL)
+		{
+			FT_Done_FreeType(ft_library);
+			ft_library = NULL;
+		}
+
+		delete instance;
+	}
+}
+
+// Loads a new font face.
+bool FontProvider::LoadFontFace(const String& file_name)
+{
+	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
+	if (ft_face == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+
+	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+		return false;
+	}
+}
+
+// Adds a new font face to the database, ignoring any family, style and weight information stored in the face itself.
+bool FontProvider::LoadFontFace(const String& file_name, const String& family, Font::Style style, Font::Weight weight)
+{
+	FT_Face ft_face = (FT_Face) instance->LoadFace(file_name);
+	if (ft_face == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from %s.", file_name.CString());
+		return false;
+	}
+
+	if (instance->AddFace(ft_face, family, style, weight, true))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from %s).", ft_face->family_name, ft_face->style_name, file_name.CString());
+		return false;
+	}
+}
+
+// Adds a new font face to the database, loading from memory.
+bool FontProvider::LoadFontFace(const byte* data, int data_length)
+{
+	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
+	if (ft_face == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+		return false;
+	}
+
+	Font::Style style = ft_face->style_flags & FT_STYLE_FLAG_ITALIC ? Font::STYLE_ITALIC : Font::STYLE_NORMAL;
+	Font::Weight weight = ft_face->style_flags & FT_STYLE_FLAG_BOLD ? Font::WEIGHT_BOLD : Font::WEIGHT_NORMAL;
+
+	if (instance->AddFace(ft_face, ft_face->family_name, style, weight, false))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+		return false;
+	}
+}
+
+// Adds a new font face to the database, loading from memory, ignoring any family, style and weight information stored in the face itself.
+bool FontProvider::LoadFontFace(const byte* data, int data_length, const String& family, Font::Style style, Font::Weight weight)
+{
+	FT_Face ft_face = (FT_Face) instance->LoadFace(data, data_length, "memory", false);
+	if (ft_face == NULL)
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face from byte stream.");
+		return false;
+	}
+
+	if (instance->AddFace(ft_face, family, style, weight, false))
+	{
+		Log::Message(Log::LT_INFO, "Loaded font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+		return true;
+	}
+	else
+	{
+		Log::Message(Log::LT_ERROR, "Failed to load font face %s %s (from byte stream).", ft_face->family_name, ft_face->style_name);
+		return false;
+	}
+}
+
+// Adds a loaded face to the appropriate font family.
+bool FontProvider::AddFace(void* face, const String& family, Font::Style style, Font::Weight weight, bool release_stream)
+{
+	FontFamily* font_family = NULL;
+	FontFamilyMap::iterator iterator = font_families.find(family);
+	if (iterator != font_families.end())
+		font_family = (FontFamily*)(*iterator).second;
+	else
+	{
+		font_family = new FontFamily(family);
+		font_families[family] = font_family;
+	}
+
+	return font_family->AddFace((FT_Face) face, style, weight, release_stream);
+}
+
+// Loads a FreeType face.
+void* FontProvider::LoadFace(const String& file_name)
+{
+	FileInterface* file_interface = GetFileInterface();
+	FileHandle handle = file_interface->Open(file_name);
+
+	if (!handle)
+	{
+		return NULL;
+	}
+
+	size_t length = file_interface->Length(handle);
+
+	FT_Byte* buffer = new FT_Byte[length];
+	file_interface->Read(buffer, length, handle);
+	file_interface->Close(handle);
+
+	return LoadFace(buffer, (int)length, file_name, true);
+}
+
+// Loads a FreeType face from memory.
+void* FontProvider::LoadFace(const byte* data, int data_length, const String& source, bool local_data)
+{
+	FT_Face face = NULL;
+	int error = FT_New_Memory_Face(ft_library, (const FT_Byte*) data, data_length, 0, &face);
+	if (error != 0)
+	{
+		Log::Message(Log::LT_ERROR, "FreeType error %d while loading face from %s.", error, source.CString());
+		if (local_data)
+			delete[] data;
+
+		return NULL;
+	}
+
+	// Initialise the character mapping on the face.
+	if (face->charmap == NULL)
+	{
+		FT_Select_Charmap(face, FT_ENCODING_APPLE_ROMAN);
+		if (face->charmap == NULL)
+		{
+			Log::Message(Log::LT_ERROR, "Font face (from %s) does not contain a Unicode or Apple Roman character map.", source.CString());
+			FT_Done_Face(face);
+			if (local_data)
+				delete[] data;
+
+			return NULL;
+		}
+	}
+
+	return face;
+}
+
+}
+}
+}

+ 60 - 0
Source/Core/LayoutBlockBox.cpp

@@ -527,6 +527,66 @@ void LayoutBlockBox::PositionLineBox(Vector2f& box_position, float& box_width, b
 	_wrap_content = wrap_content;
 }
 
+
+// Calculate the dimensions of the box's internal width; i.e. the size of the largest line, plus this element's padding.
+float LayoutBlockBox::InternalContentWidth() const
+{
+	float content_width = 0.0f;
+
+	if (context == BLOCK)
+	{
+
+		for (size_t i = 0; i < block_boxes.size(); i++)
+		{
+			content_width = Math::Max(content_width, block_boxes[i]->InternalContentWidth());
+		}
+
+		// Work-around for supporting 'width' specification of 'display:block' elements inside 'display:inline-block'.
+		//  Alternative solution: Add some 'intrinsic_width' property to  every 'LayoutBlockBox' and have that propagate up to the nearest 'inline-block'.
+		if (element)
+		{
+			const Property* width = nullptr;
+			const Property* min_width = element->GetLocalProperty("min-width");
+			const Property* max_width = element->GetLocalProperty("max-width");
+			element->GetLocalDimensionProperties(&width, nullptr);
+			if(width)
+			{
+				float w_value = element->ResolveProperty(width, box.GetSize(Box::CONTENT).x);
+				content_width = Math::Max(content_width, w_value);
+			}
+			float block_width = box.GetSize(Box::CONTENT).x;
+			if (min_width)
+			{
+				float value = element->ResolveProperty(min_width, block_width);
+				content_width = Math::Max(content_width, value);
+			}
+			if (max_width)
+			{
+				float value = element->ResolveProperty(max_width, block_width);
+				content_width = Math::Min(content_width, value);
+			}
+		}
+
+		content_width += (box.GetEdge(Box::PADDING, Box::LEFT) + box.GetEdge(Box::PADDING, Box::RIGHT));
+		content_width += (box.GetEdge(Box::MARGIN, Box::LEFT) + box.GetEdge(Box::MARGIN, Box::RIGHT));
+	}
+	else
+	{
+		// Find the largest line in this layout block
+		for (size_t i = 0; i < line_boxes.size(); i++)
+		{
+			// Perhaps a more robust solution is to modify how we set the line box dimension on 'line_box->close()'
+			// and use that, or add another value in the line_box ... but seems to work for now.
+			LayoutLineBox* line_box = line_boxes[i];
+			content_width = Math::Max(content_width, line_box->GetBoxCursor());
+		}
+		content_width = Math::Min(content_width, box.GetSize(Box::CONTENT).x);
+	}
+
+	return content_width;
+}
+
+
 // Returns the block box's element.
 Element* LayoutBlockBox::GetElement() const
 {

+ 3 - 0
Source/Core/LayoutBlockBox.h

@@ -129,6 +129,8 @@ public:
 	/// @param dimensions[in] The minimum dimensions of the line.
 	void PositionLineBox(Vector2f& box_position, float& box_width, bool& wrap_content, const Vector2f& dimensions) const;
 
+	float InternalContentWidth() const;
+
 	/// Returns the block box's element.
 	/// @return The block box's element.
 	Element* GetElement() const;
@@ -148,6 +150,7 @@ public:
 	/// @return This box's offset root.
 	LayoutBlockBox* GetOffsetRoot() const;
 
+
 	/// Returns the block box's dimension box.
 	/// @return The block box's dimension box.
 	Box& GetBox();

+ 78 - 10
Source/Core/LayoutEngine.cpp

@@ -68,7 +68,7 @@ LayoutEngine::~LayoutEngine()
 }
 
 // Formats the contents for a root-level element (usually a document or floating element).
-bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_block)
+bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_block, bool shrink_to_fit)
 {
 	block_box = new LayoutBlockBox(this, NULL, NULL);
 	block_box->GetBox().SetContent(containing_block);
@@ -81,6 +81,30 @@ bool LayoutEngine::FormatElement(Element* element, const Vector2f& containing_bl
 			i = -1;
 	}
 
+	if (shrink_to_fit)
+	{
+		// For inline blocks, we want to shrink the box back to its inner content width, recreating the LayoutBlockBox.
+		// There is an issue where resize events are not propagated correctly, which affects e.g. DataGridCells.
+		float content_width = block_box->InternalContentWidth();
+
+		if (content_width < containing_block.x)
+		{
+			Vector2f shrinked_block_size(content_width, containing_block.y);
+			
+			delete block_box;
+			block_box = new LayoutBlockBox(this, NULL, NULL);
+			block_box->GetBox().SetContent(shrinked_block_size);
+
+			block_context_box = block_box->AddBlockElement(element);
+
+			for (int i = 0; i < element->GetNumChildren(); i++)
+			{
+				if (!FormatElement(element->GetChild(i)))
+					i = -1;
+			}
+		}
+	}
+
 	block_context_box->Close();
 	block_context_box->CloseAbsoluteElements();
 
@@ -181,7 +205,7 @@ void LayoutEngine::BuildBox(Box& box, const Vector2f& containing_block, Element*
 		if (replaced_element)
 		{
 			content_area.x = ClampWidth(content_area.x, element, containing_block.x);
-			content_area.y = ClampWidth(content_area.y, element, containing_block.y);
+			content_area.y = ClampHeight(content_area.y, element, containing_block.y);
 		}
 
 		// If the element was not replaced, then we leave its dimension as unsized (-1, -1) and ignore the width and
@@ -343,7 +367,7 @@ bool LayoutEngine::FormatElement(Element* element)
 	{
 		case DISPLAY_BLOCK:			return FormatElementBlock(element); break;
 		case DISPLAY_INLINE:		return FormatElementInline(element); break;
-		case DISPLAY_INLINE_BLOCK:	FormatElementReplaced(element); break;
+		case DISPLAY_INLINE_BLOCK:	return FormatElementReplaced(element); break;
 		default:					ROCKET_ERROR;
 	}
 
@@ -422,13 +446,17 @@ bool LayoutEngine::FormatElementInline(Element* element)
 }
 
 // Positions an element as a sized inline element, formatting its internal hierarchy as a block element.
-void LayoutEngine::FormatElementReplaced(Element* element)
+bool LayoutEngine::FormatElementReplaced(Element* element)
 {
 	// Format the element separately as a block element, then position it inside our own layout as an inline element.
+	Vector2f containing_block_size = GetContainingBlock(block_context_box);
+
 	LayoutEngine layout_engine;
-	layout_engine.FormatElement(element, GetContainingBlock(block_context_box));
+	layout_engine.FormatElement(element, containing_block_size, true);
 
 	block_context_box->AddInlineElement(element, element->GetBox())->Close();
+
+	return true;
 }
 
 // Executes any special formatting for special elements.
@@ -522,17 +550,33 @@ void LayoutEngine::BuildBoxWidth(Box& box, Element* element, float containing_bl
 		}
 	}
 
-	// If the width is set to auto, then any margins also set to auto are resolved to 0 and the width is set to the
-	// whatever if left of the containing block.
+	// If the width is set to auto, we need to calculate the width
 	if (width_auto)
 	{
+		float left = 0.0f, right = 0.0f;
+		// If we are dealing with an absolutely positioned element we need to
+		// consider if the left and right properties are set, since the width can be affected.
+		if (element->GetPosition() == POSITION_ABSOLUTE || 
+			element->GetPosition() == POSITION_FIXED)
+		{
+			Property const *left_property, *right_property;
+			element->GetOffsetProperties( NULL, NULL, &left_property, &right_property );
+			if (left_property->unit != Property::KEYWORD) 
+				left = element->ResolveProperty(left_property, containing_block_width );
+			if (right_property->unit != Property::KEYWORD) 
+				right = element->ResolveProperty(right_property, containing_block_width );
+		}
+
+		// We resolve any auto margins to 0 and the width is set to whatever is left of the containing block.
 		if (margins_auto[0])
 			box.SetEdge(Box::MARGIN, Box::LEFT, 0);
 		if (margins_auto[1])
 			box.SetEdge(Box::MARGIN, Box::RIGHT, 0);
 
-		content_area.x = containing_block_width - (box.GetCumulativeEdge(Box::CONTENT, Box::LEFT) +
-												   box.GetCumulativeEdge(Box::CONTENT, Box::RIGHT));
+		content_area.x = containing_block_width - (left +
+		                                           box.GetCumulativeEdge(Box::CONTENT, Box::LEFT) +
+		                                           box.GetCumulativeEdge(Box::CONTENT, Box::RIGHT) +
+		                                           right);
 		content_area.x = Math::Max(0.0f, content_area.x);
 	}
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
@@ -622,15 +666,39 @@ void LayoutEngine::BuildBoxHeight(Box& box, Element* element, float containing_b
 		}
 	}
 
-	// If the height is set to auto, then any margins also set to auto are resolved to 0 and the height is set to -1.
+	// If the height is set to auto, we need to calculate the height
 	if (height_auto)
 	{
+		// We resolve any auto margins to 0
 		if (margins_auto[0])
 			box.SetEdge(Box::MARGIN, Box::TOP, 0);
 		if (margins_auto[1])
 			box.SetEdge(Box::MARGIN, Box::BOTTOM, 0);
 
+		// If the height is set to auto for a box in normal flow, the height is set to -1.
 		content_area.y = -1;
+
+		// But if we are dealing with an absolutely positioned element we need to
+		// consider if the top and bottom properties are set, since the height can be affected.
+		if (element->GetPosition() == POSITION_ABSOLUTE || 
+			element->GetPosition() == POSITION_FIXED)
+		{
+			float top = 0.0f, bottom = 0.0f;
+			Property const *top_property, *bottom_property;
+			element->GetOffsetProperties( &top_property, &bottom_property, NULL, NULL );
+			if (top_property->unit != Property::KEYWORD && bottom_property->unit != Property::KEYWORD ) 
+			{
+				top = element->ResolveProperty(top_property, containing_block_height );
+				bottom = element->ResolveProperty(bottom_property, containing_block_height );
+
+				// The height gets resolved to whatever is left of the containing block
+				content_area.y = containing_block_height - (top +
+				                                            box.GetCumulativeEdge(Box::CONTENT, Box::TOP) +
+				                                            box.GetCumulativeEdge(Box::CONTENT, Box::BOTTOM) +
+				                                            bottom);
+				content_area.y = Math::Max(0.0f, content_area.y);
+			}
+		}
 	}
 	// Otherwise, the margins that are set to auto will pick up the remaining width of the containing block.
 	else if (num_auto_margins > 0)

+ 2 - 2
Source/Core/LayoutEngine.h

@@ -49,7 +49,7 @@ public:
 	/// Formats the contents for a root-level element (usually a document, floating or replaced element).
 	/// @param element[in] The element to lay out.
 	/// @param containing_block[in] The size of the containing block.
-	bool FormatElement(Element* element, const Vector2f& containing_block);
+	bool FormatElement(Element* element, const Vector2f& containing_block, bool shrink_to_fit = false);
 
 	/// Generates the box for an element.
 	/// @param[out] box The box to be built.
@@ -104,7 +104,7 @@ private:
 	bool FormatElementInline(Element* element);
 	/// Positions an element as a sized inline element, formatting its internal hierarchy as a block element.
 	/// @param[in] element The replaced element.
-	void FormatElementReplaced(Element* element);
+	bool FormatElementReplaced(Element* element);
 	/// Executes any special formatting for special elements.
 	/// @param[in] element The element to parse.
 	/// @return True if the element was parsed as a special element, false otherwise.

Some files were not shown because too many files changed in this diff