Просмотр исходного кода

Add example to use libRmlUi with SDL2 SDL_Renderer / SDL_RenderGeometry (#252)

* Add example to use libRmlUi with SDL2 SDL_Renderer / SDL_RenderGeometry()

* - remove un-needed ifdef opengl.
- change window title
Sylvain Becker 4 лет назад
Родитель
Сommit
8577a0b87a

+ 171 - 0
Samples/basic/sdl2_sdlrenderer/src/RenderInterfaceSDL2.cpp

@@ -0,0 +1,171 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 Nuno Silva
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * 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 <RmlUi/Core.h>
+#include <SDL_image.h>
+
+#include "RenderInterfaceSDL2.h"
+
+RmlUiSDL2Renderer::RmlUiSDL2Renderer(SDL_Renderer* renderer, SDL_Window* screen)
+{
+    mRenderer = renderer;
+    mScreen = screen;
+
+    SDL_GetRendererOutputSize(renderer, &mRenderer_w, &mRenderer_h);
+
+    mRectScisor.x = 0;
+    mRectScisor.y = 0;
+    mRectScisor.w = mRenderer_w;
+    mRectScisor.h = mRenderer_h;
+}
+
+// Called by RmlUi when it wants to render geometry that it does not wish to optimise.
+void RmlUiSDL2Renderer::RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, const Rml::TextureHandle texture, const Rml::Vector2f& translation)
+{
+    SDL_Texture *sdl_texture = (SDL_Texture *) texture;
+
+    SDL_Rect r;
+    r.x = translation.x;
+    r.y = translation.y;
+    r.w = mRenderer_w - r.x;
+    r.h = mRenderer_h - r.y;
+    
+    SDL_RenderSetViewport(mRenderer, &r);
+
+    if (sdl_texture) {
+        SDL_SetTextureBlendMode(sdl_texture, SDL_BLENDMODE_BLEND);
+    }
+
+    int sz = sizeof(vertices[0]);
+    int off1 = offsetof(Rml::Vertex, position);
+    int off2 = offsetof(Rml::Vertex, colour);
+    int off3 = offsetof(Rml::Vertex, tex_coord);
+    SDL_RenderGeometryRaw(mRenderer, sdl_texture, 
+            (float *)((Uint8 *) vertices + off1), sz,
+            (int *)((Uint8 *) vertices + off2), sz,
+            (float *)((Uint8 *) vertices + off3), sz,
+            num_vertices, indices, num_indices, 4);
+
+}
+
+// Called by RmlUi when it wants to enable or disable scissoring to clip content.		
+void RmlUiSDL2Renderer::EnableScissorRegion(bool enable)
+{
+    if (enable) {
+        SDL_RenderSetClipRect(mRenderer, &mRectScisor);
+    } else {
+        SDL_RenderSetClipRect(mRenderer, NULL);
+    }
+}
+
+// Called by RmlUi when it wants to change the scissor region.		
+void RmlUiSDL2Renderer::SetScissorRegion(int x, int y, int width, int height)
+{
+    int w_width, w_height;
+    SDL_GetWindowSize(mScreen, &w_width, &w_height);
+    mRectScisor.x = x;
+    mRectScisor.y = w_height - (y + height);
+    mRectScisor.w = width;
+    mRectScisor.h = height;
+}
+
+// Called by RmlUi when a texture is required by the library.		
+bool RmlUiSDL2Renderer::LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source)
+{
+
+    Rml::FileInterface* file_interface = Rml::GetFileInterface();
+    Rml::FileHandle file_handle = file_interface->Open(source);
+    if (!file_handle)
+        return false;
+
+    file_interface->Seek(file_handle, 0, SEEK_END);
+    size_t buffer_size = file_interface->Tell(file_handle);
+    file_interface->Seek(file_handle, 0, SEEK_SET);
+
+    char* buffer = new char[buffer_size];
+    file_interface->Read(buffer, buffer_size, file_handle);
+    file_interface->Close(file_handle);
+
+    size_t i;
+    for(i = source.length() - 1; i > 0; i--)
+    {
+        if(source[i] == '.')
+            break;
+    }
+
+    Rml::String extension = source.substr(i+1, source.length()-i);
+
+    SDL_Surface* surface = IMG_LoadTyped_RW(SDL_RWFromMem(buffer, int(buffer_size)), 1, extension.c_str());
+
+    if (surface) {
+        SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer, surface);
+
+        if (texture) {
+            texture_handle = (Rml::TextureHandle) texture;
+            texture_dimensions = Rml::Vector2i(surface->w, surface->h);
+            SDL_FreeSurface(surface);
+        }
+        else
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+// Called by RmlUi when a texture is required to be built from an internally-generated sequence of pixels.
+bool RmlUiSDL2Renderer::GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions)
+{
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+        Uint32 rmask = 0xff000000;
+        Uint32 gmask = 0x00ff0000;
+        Uint32 bmask = 0x0000ff00;
+        Uint32 amask = 0x000000ff;
+    #else
+        Uint32 rmask = 0x000000ff;
+        Uint32 gmask = 0x0000ff00;
+        Uint32 bmask = 0x00ff0000;
+        Uint32 amask = 0xff000000;
+    #endif
+
+    SDL_Surface *surface = SDL_CreateRGBSurfaceFrom ((void*) source, source_dimensions.x, source_dimensions.y, 32, source_dimensions.x*4, rmask, gmask, bmask, amask);
+    SDL_Texture *texture = SDL_CreateTextureFromSurface(mRenderer, surface);
+    SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
+    SDL_FreeSurface(surface);
+    texture_handle = (Rml::TextureHandle) texture;
+    return true;
+}
+
+// Called by RmlUi when a loaded texture is no longer required.		
+void RmlUiSDL2Renderer::ReleaseTexture(Rml::TextureHandle texture_handle)
+{
+    SDL_DestroyTexture((SDL_Texture*) texture_handle);
+}

+ 68 - 0
Samples/basic/sdl2_sdlrenderer/src/RenderInterfaceSDL2.h

@@ -0,0 +1,68 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 Nuno Silva
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * 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 RENDERINTERFACESDL2_H
+#define RENDERINTERFACESDL2_H
+
+#include <RmlUi/Core/RenderInterface.h>
+
+#include <SDL.h>
+
+#if !(SDL_VIDEO_RENDER_OGL)
+    #error "Only the opengl sdl backend is supported."
+#endif
+
+
+class RmlUiSDL2Renderer : public Rml::RenderInterface
+{
+public:
+	RmlUiSDL2Renderer(SDL_Renderer* renderer, SDL_Window* screen);
+
+	/// Called by RmlUi when it wants to render geometry that it does not wish to optimise.
+	void RenderGeometry(Rml::Vertex* vertices, int num_vertices, int* indices, int num_indices, Rml::TextureHandle texture, const Rml::Vector2f& translation) override;
+
+	/// Called by RmlUi when it wants to enable or disable scissoring to clip content.
+	void EnableScissorRegion(bool enable) override;
+	/// Called by RmlUi when it wants to change the scissor region.
+	void SetScissorRegion(int x, int y, int width, int height) override;
+
+	/// Called by RmlUi when a texture is required by the library.
+	bool LoadTexture(Rml::TextureHandle& texture_handle, Rml::Vector2i& texture_dimensions, const Rml::String& source) override;
+	/// Called by RmlUi when a texture is required to be built from an internally-generated sequence of pixels.
+	bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override;
+	/// Called by RmlUi when a loaded texture is no longer required.
+	void ReleaseTexture(Rml::TextureHandle texture_handle) override;
+
+private:
+    SDL_Renderer* mRenderer;
+    int mRenderer_w;
+    int mRenderer_h;
+    SDL_Window* mScreen;
+    SDL_Rect mRectScisor;
+};
+
+#endif

+ 442 - 0
Samples/basic/sdl2_sdlrenderer/src/SystemInterfaceSDL2.cpp

@@ -0,0 +1,442 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 Nuno Silva
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * 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 <RmlUi/Core.h>
+#include "SystemInterfaceSDL2.h"
+
+Rml::Input::KeyIdentifier RmlUiSDL2SystemInterface::TranslateKey(SDL_Keycode sdlkey)
+{
+    using namespace Rml::Input;
+
+
+    switch(sdlkey) {
+        case SDLK_UNKNOWN:
+            return KI_UNKNOWN;
+            break;
+        case SDLK_SPACE:
+            return KI_SPACE;
+            break;
+        case SDLK_0:
+            return KI_0;
+            break;
+        case SDLK_1:
+            return KI_1;
+            break;
+        case SDLK_2:
+            return KI_2;
+            break;
+        case SDLK_3:
+            return KI_3;
+            break;
+        case SDLK_4:
+            return KI_4;
+            break;
+        case SDLK_5:
+            return KI_5;
+            break;
+        case SDLK_6:
+            return KI_6;
+            break;
+        case SDLK_7:
+            return KI_7;
+            break;
+        case SDLK_8:
+            return KI_8;
+            break;
+        case SDLK_9:
+            return KI_9;
+            break;
+        case SDLK_a:
+            return KI_A;
+            break;
+        case SDLK_b:
+            return KI_B;
+            break;
+        case SDLK_c:
+            return KI_C;
+            break;
+        case SDLK_d:
+            return KI_D;
+            break;
+        case SDLK_e:
+            return KI_E;
+            break;
+        case SDLK_f:
+            return KI_F;
+            break;
+        case SDLK_g:
+            return KI_G;
+            break;
+        case SDLK_h:
+            return KI_H;
+            break;
+        case SDLK_i:
+            return KI_I;
+            break;
+        case SDLK_j:
+            return KI_J;
+            break;
+        case SDLK_k:
+            return KI_K;
+            break;
+        case SDLK_l:
+            return KI_L;
+            break;
+        case SDLK_m:
+            return KI_M;
+            break;
+        case SDLK_n:
+            return KI_N;
+            break;
+        case SDLK_o:
+            return KI_O;
+            break;
+        case SDLK_p:
+            return KI_P;
+            break;
+        case SDLK_q:
+            return KI_Q;
+            break;
+        case SDLK_r:
+            return KI_R;
+            break;
+        case SDLK_s:
+            return KI_S;
+            break;
+        case SDLK_t:
+            return KI_T;
+            break;
+        case SDLK_u:
+            return KI_U;
+            break;
+        case SDLK_v:
+            return KI_V;
+            break;
+        case SDLK_w:
+            return KI_W;
+            break;
+        case SDLK_x:
+            return KI_X;
+            break;
+        case SDLK_y:
+            return KI_Y;
+            break;
+        case SDLK_z:
+            return KI_Z;
+            break;
+        case SDLK_SEMICOLON:
+            return KI_OEM_1;
+            break;
+        case SDLK_PLUS:
+            return KI_OEM_PLUS;
+            break;
+        case SDLK_COMMA:
+            return KI_OEM_COMMA;
+            break;
+        case SDLK_MINUS:
+            return KI_OEM_MINUS;
+            break;
+        case SDLK_PERIOD:
+            return KI_OEM_PERIOD;
+            break;
+        case SDLK_SLASH:
+            return KI_OEM_2;
+            break;
+        case SDLK_BACKQUOTE:
+            return KI_OEM_3;
+            break;
+        case SDLK_LEFTBRACKET:
+            return KI_OEM_4;
+            break;
+        case SDLK_BACKSLASH:
+            return KI_OEM_5;
+            break;
+        case SDLK_RIGHTBRACKET:
+            return KI_OEM_6;
+            break;
+        case SDLK_QUOTEDBL:
+            return KI_OEM_7;
+            break;
+        case SDLK_KP_0:
+            return KI_NUMPAD0;
+            break;
+        case SDLK_KP_1:
+            return KI_NUMPAD1;
+            break;
+        case SDLK_KP_2:
+            return KI_NUMPAD2;
+            break;
+        case SDLK_KP_3:
+            return KI_NUMPAD3;
+            break;
+        case SDLK_KP_4:
+            return KI_NUMPAD4;
+            break;
+        case SDLK_KP_5:
+            return KI_NUMPAD5;
+            break;
+        case SDLK_KP_6:
+            return KI_NUMPAD6;
+            break;
+        case SDLK_KP_7:
+            return KI_NUMPAD7;
+            break;
+        case SDLK_KP_8:
+            return KI_NUMPAD8;
+            break;
+        case SDLK_KP_9:
+            return KI_NUMPAD9;
+            break;
+        case SDLK_KP_ENTER:
+            return KI_NUMPADENTER;
+            break;
+        case SDLK_KP_MULTIPLY:
+            return KI_MULTIPLY;
+            break;
+        case SDLK_KP_PLUS:
+            return KI_ADD;
+            break;
+        case SDLK_KP_MINUS:
+            return KI_SUBTRACT;
+            break;
+        case SDLK_KP_PERIOD:
+            return KI_DECIMAL;
+            break;
+        case SDLK_KP_DIVIDE:
+            return KI_DIVIDE;
+            break;
+        case SDLK_KP_EQUALS:
+            return KI_OEM_NEC_EQUAL;
+            break;
+        case SDLK_BACKSPACE:
+            return KI_BACK;
+            break;
+        case SDLK_TAB:
+            return KI_TAB;
+            break;
+        case SDLK_CLEAR:
+            return KI_CLEAR;
+            break;
+        case SDLK_RETURN:
+            return KI_RETURN;
+            break;
+        case SDLK_PAUSE:
+            return KI_PAUSE;
+            break;
+        case SDLK_CAPSLOCK:
+            return KI_CAPITAL;
+            break;
+        case SDLK_PAGEUP:
+            return KI_PRIOR;
+            break;
+        case SDLK_PAGEDOWN:
+            return KI_NEXT;
+            break;
+        case SDLK_END:
+            return KI_END;
+            break;
+        case SDLK_HOME:
+            return KI_HOME;
+            break;
+        case SDLK_LEFT:
+            return KI_LEFT;
+            break;
+        case SDLK_UP:
+            return KI_UP;
+            break;
+        case SDLK_RIGHT:
+            return KI_RIGHT;
+            break;
+        case SDLK_DOWN:
+            return KI_DOWN;
+            break;
+        case SDLK_INSERT:
+            return KI_INSERT;
+            break;
+        case SDLK_DELETE:
+            return KI_DELETE;
+            break;
+        case SDLK_HELP:
+            return KI_HELP;
+            break;
+        case SDLK_F1:
+            return KI_F1;
+            break;
+        case SDLK_F2:
+            return KI_F2;
+            break;
+        case SDLK_F3:
+            return KI_F3;
+            break;
+        case SDLK_F4:
+            return KI_F4;
+            break;
+        case SDLK_F5:
+            return KI_F5;
+            break;
+        case SDLK_F6:
+            return KI_F6;
+            break;
+        case SDLK_F7:
+            return KI_F7;
+            break;
+        case SDLK_F8:
+            return KI_F8;
+            break;
+        case SDLK_F9:
+            return KI_F9;
+            break;
+        case SDLK_F10:
+            return KI_F10;
+            break;
+        case SDLK_F11:
+            return KI_F11;
+            break;
+        case SDLK_F12:
+            return KI_F12;
+            break;
+        case SDLK_F13:
+            return KI_F13;
+            break;
+        case SDLK_F14:
+            return KI_F14;
+            break;
+        case SDLK_F15:
+            return KI_F15;
+            break;
+        case SDLK_NUMLOCKCLEAR:
+            return KI_NUMLOCK;
+            break;
+        case SDLK_SCROLLLOCK:
+            return KI_SCROLL;
+            break;
+        case SDLK_LSHIFT:
+            return KI_LSHIFT;
+            break;
+        case SDLK_RSHIFT:
+            return KI_RSHIFT;
+            break;
+        case SDLK_LCTRL:
+            return KI_LCONTROL;
+            break;
+        case SDLK_RCTRL:
+            return KI_RCONTROL;
+            break;
+        case SDLK_LALT:
+            return KI_LMENU;
+            break;
+        case SDLK_RALT:
+            return KI_RMENU;
+            break;
+        case SDLK_LGUI:
+            return KI_LMETA;
+            break;
+        case SDLK_RGUI:
+            return KI_RMETA;
+            break;
+        /*case SDLK_LSUPER:
+            return KI_LWIN;
+            break;
+        case SDLK_RSUPER:
+            return KI_RWIN;
+            break;*/
+        default:
+            return KI_UNKNOWN;
+            break;
+    }
+}
+
+int RmlUiSDL2SystemInterface::TranslateMouseButton(Uint8 button)
+{
+    switch(button)
+    {
+        case SDL_BUTTON_LEFT:
+            return 0;
+        case SDL_BUTTON_RIGHT:
+            return 1;
+        case SDL_BUTTON_MIDDLE:
+            return 2;
+        default:
+            return 3;
+    }
+}
+
+int RmlUiSDL2SystemInterface::GetKeyModifiers()
+{
+    SDL_Keymod sdlMods = SDL_GetModState();
+
+    int retval = 0;
+
+    if(sdlMods & KMOD_CTRL)
+        retval |= Rml::Input::KM_CTRL;
+
+    if(sdlMods & KMOD_SHIFT)
+        retval |= Rml::Input::KM_SHIFT;
+
+    if(sdlMods & KMOD_ALT)
+        retval |= Rml::Input::KM_ALT;
+
+    return retval;
+}
+
+double RmlUiSDL2SystemInterface::GetElapsedTime()
+{
+	return double(SDL_GetTicks()) / 1000.0;
+}
+
+bool RmlUiSDL2SystemInterface::LogMessage(Rml::Log::Type type, const Rml::String& message)
+{
+	Rml::String Type;
+
+	switch(type)
+	{
+	case Rml::Log::LT_ALWAYS:
+		Type = "[Always]";
+		break;
+	case Rml::Log::LT_ERROR:
+		Type = "[Error]";
+		break;
+	case Rml::Log::LT_ASSERT:
+		Type = "[Assert]";
+		break;
+	case Rml::Log::LT_WARNING:
+		Type = "[Warning]";
+		break;
+	case Rml::Log::LT_INFO:
+		Type = "[Info]";
+		break;
+	case Rml::Log::LT_DEBUG:
+		Type = "[Debug]";
+		break;
+    case Rml::Log::LT_MAX:
+        break;
+	};
+
+	printf("%s - %s\n", Type.c_str(), message.c_str());
+
+	return true;
+}

+ 46 - 0
Samples/basic/sdl2_sdlrenderer/src/SystemInterfaceSDL2.h

@@ -0,0 +1,46 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 Nuno Silva
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * 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 SYSTEMINTEFACESDL2_H
+#define SYSTEMINTEFACESDL2_H
+
+#include <RmlUi/Core/SystemInterface.h>
+#include <RmlUi/Core/Input.h>
+
+#include <SDL.h>
+
+class RmlUiSDL2SystemInterface : public Rml::SystemInterface
+{
+public:
+    Rml::Input::KeyIdentifier TranslateKey(SDL_Keycode sdlkey);
+    int TranslateMouseButton(Uint8 button);
+	int GetKeyModifiers();
+	
+	double GetElapsedTime() override;
+    bool LogMessage(Rml::Log::Type type, const Rml::String& message) override;
+};
+#endif

+ 175 - 0
Samples/basic/sdl2_sdlrenderer/src/main.cpp

@@ -0,0 +1,175 @@
+/*
+ * This source file is part of RmlUi, the HTML/CSS Interface Middleware
+ *
+ * For the latest information, see http://github.com/mikke89/RmlUi
+ *
+ * Copyright (c) 2008-2010 Nuno Silva
+ * Copyright (c) 2019 The RmlUi Team, and contributors
+ *
+ * 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 <RmlUi/Core.h>
+#include <RmlUi/Core/Input.h>
+#include <RmlUi/Debugger/Debugger.h>
+#include <Shell.h>
+#include <ShellFileInterface.h>
+#include <string.h>
+
+#include "SystemInterfaceSDL2.h"
+#include "RenderInterfaceSDL2.h"
+
+#ifdef RMLUI_PLATFORM_WIN32
+#include <windows.h>
+#endif
+
+#include <SDL.h>
+
+int main(int /*argc*/, char** /*argv*/)
+{
+#ifdef RMLUI_PLATFORM_WIN32
+	AllocConsole();
+#endif
+
+    int window_width = 1024;
+    int window_height = 768;
+
+    SDL_Init( SDL_INIT_VIDEO );
+    SDL_Window * screen = SDL_CreateWindow("RmlUi SDL2 with SDL_Renderer test", 20, 20, window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
+
+    /*
+     * Force a specific back-end
+    SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");
+    SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
+    SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2");
+    */
+    
+    SDL_Renderer * renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+	
+	RmlUiSDL2Renderer Renderer(renderer, screen);
+	RmlUiSDL2SystemInterface SystemInterface;
+
+	Rml::String root = Shell::FindSamplesRoot();
+	ShellFileInterface FileInterface(root);
+
+	Rml::SetFileInterface(&FileInterface);
+	Rml::SetRenderInterface(&Renderer);
+	Rml::SetSystemInterface(&SystemInterface);
+
+	if (!Rml::Initialise())
+		return 1;
+
+	struct FontFace {
+		Rml::String filename;
+		bool fallback_face;
+	};
+	FontFace font_faces[] = {
+		{ "LatoLatin-Regular.ttf",    false },
+		{ "LatoLatin-Italic.ttf",     false },
+		{ "LatoLatin-Bold.ttf",       false },
+		{ "LatoLatin-BoldItalic.ttf", false },
+		{ "NotoEmoji-Regular.ttf",    true  },
+	};
+
+	for (const FontFace& face : font_faces)
+	{
+		Rml::LoadFontFace("assets/" + face.filename, face.fallback_face);
+	}
+
+	Rml::Context* Context = Rml::CreateContext("default",
+		Rml::Vector2i(window_width, window_height));
+
+	Rml::Debugger::Initialise(Context);
+
+	Rml::ElementDocument* Document = Context->LoadDocument("assets/demo.rml");
+
+	if (Document)
+	{
+		Document->Show();
+		fprintf(stdout, "\nDocument loaded");
+	}
+	else
+	{
+		fprintf(stdout, "\nDocument is nullptr");
+	}
+
+	bool done = false;
+
+	while (!done)
+	{
+		SDL_Event event;
+
+		SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
+		SDL_RenderClear(renderer);
+
+		Context->Render();
+		SDL_RenderPresent(renderer);
+
+		while (SDL_PollEvent(&event))
+		{
+			switch (event.type)
+			{
+			case SDL_QUIT:
+				done = true;
+				break;
+
+			case SDL_MOUSEMOTION:
+				Context->ProcessMouseMove(event.motion.x, event.motion.y, SystemInterface.GetKeyModifiers());
+				break;
+			case SDL_MOUSEBUTTONDOWN:
+				Context->ProcessMouseButtonDown(SystemInterface.TranslateMouseButton(event.button.button), SystemInterface.GetKeyModifiers());
+				break;
+
+			case SDL_MOUSEBUTTONUP:
+				Context->ProcessMouseButtonUp(SystemInterface.TranslateMouseButton(event.button.button), SystemInterface.GetKeyModifiers());
+				break;
+
+			case SDL_MOUSEWHEEL:
+				Context->ProcessMouseWheel(float(event.wheel.y), SystemInterface.GetKeyModifiers());
+				break;
+
+			case SDL_KEYDOWN:
+			{
+				// Intercept F8 key stroke to toggle RmlUi's visual debugger tool
+				if (event.key.keysym.sym == SDLK_F8)
+				{
+					Rml::Debugger::SetVisible(!Rml::Debugger::IsVisible());
+					break;
+				}
+
+				Context->ProcessKeyDown(SystemInterface.TranslateKey(event.key.keysym.sym), SystemInterface.GetKeyModifiers());
+				break;
+			}
+
+			default:
+				break;
+			}
+		}
+		Context->Update();
+	}
+
+	Rml::Shutdown();
+
+    SDL_DestroyRenderer(renderer);
+    SDL_DestroyWindow(screen);
+    SDL_Quit();
+
+	return 0;
+}