From c529f8b7c836cb78d445bc2de7c46ea8fc5f80f5 Mon Sep 17 00:00:00 2001
From: Paul Wisbey
Date: Fri, 6 Feb 2015 09:52:16 +0000
Subject: [PATCH] Basic text rendering back-end (reference implemenation)
Change-Id: I85ea6478519fecbb48d37ed57b474921a1a3ff91
---
.../public-api/controls/text-controls/text-label.h | 2 +-
base/dali-toolkit/public-api/file.list | 14 +-
.../text/rendering/basic/text-basic-renderer.cpp | 317 +++++++++++++++++++++
.../text/rendering/basic/text-basic-renderer.h | 90 ++++++
.../text/rendering/shaders/text-basic-shader.cpp | 64 +++++
.../text/rendering/shaders/text-basic-shader.h | 53 ++++
.../text/{ => rendering}/text-renderer.cpp | 2 +-
.../text/{ => rendering}/text-renderer.h | 0
build/tizen/dali-toolkit/Makefile.am | 6 +
optional/dali-toolkit/dali-toolkit.h | 4 +-
10 files changed, 547 insertions(+), 5 deletions(-)
create mode 100644 base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp
create mode 100644 base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.h
create mode 100644 base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.cpp
create mode 100644 base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.h
rename base/dali-toolkit/public-api/text/{ => rendering}/text-renderer.cpp (92%)
rename base/dali-toolkit/public-api/text/{ => rendering}/text-renderer.h (100%)
diff --git a/base/dali-toolkit/public-api/controls/text-controls/text-label.h b/base/dali-toolkit/public-api/controls/text-controls/text-label.h
index bf44949..04ec993 100644
--- a/base/dali-toolkit/public-api/controls/text-controls/text-label.h
+++ b/base/dali-toolkit/public-api/controls/text-controls/text-label.h
@@ -20,7 +20,7 @@
// INTERNAL INCLUDES
#include
-#include
+#include
namespace Dali
{
diff --git a/base/dali-toolkit/public-api/file.list b/base/dali-toolkit/public-api/file.list
index 93780bc..0d49c4f 100755
--- a/base/dali-toolkit/public-api/file.list
+++ b/base/dali-toolkit/public-api/file.list
@@ -43,10 +43,12 @@ public_api_base_src_files = \
$(public_api_base_src_dir)/text/character-set-conversion.cpp \
$(public_api_base_src_dir)/text/logical-model.cpp \
$(public_api_base_src_dir)/text/text-controller.cpp \
- $(public_api_base_src_dir)/text/text-renderer.cpp \
$(public_api_base_src_dir)/text/text-view.cpp \
$(public_api_base_src_dir)/text/text-view-interface.cpp \
$(public_api_base_src_dir)/text/visual-model.cpp \
+ $(public_api_base_src_dir)/text/rendering/text-renderer.cpp \
+ $(public_api_base_src_dir)/text/rendering/basic/text-basic-renderer.cpp \
+ $(public_api_base_src_dir)/text/rendering/shaders/text-basic-shader.cpp \
$(public_api_base_src_dir)/focus-manager/focus-manager.cpp \
$(public_api_base_src_dir)/focus-manager/keyboard-focus-manager.cpp \
$(public_api_base_src_dir)/focus-manager/keyinput-focus-manager.cpp \
@@ -128,11 +130,19 @@ public_api_base_text_header_files = \
$(public_api_base_src_dir)/text/logical-model.h \
$(public_api_base_src_dir)/text/text-controller.h \
$(public_api_base_src_dir)/text/text-definitions.h \
- $(public_api_base_src_dir)/text/text-renderer.h \
$(public_api_base_src_dir)/text/text-view.h \
$(public_api_base_src_dir)/text/text-view-interface.h \
$(public_api_base_src_dir)/text/visual-model.h
+public_api_base_text_rendering_header_files = \
+ $(public_api_base_src_dir)/text/rendering/text-renderer.h
+
+public_api_base_text_rendering_basic_header_files = \
+ $(public_api_base_src_dir)/text/rendering/basic/text-basic-renderer.h
+
+public_api_base_text_rendering_shaders_header_files = \
+ $(public_api_base_src_dir)/text/rendering/shaders/text-basic-shader.h
+
public_api_base_focus_manager_header_files = \
$(public_api_base_src_dir)/focus-manager/keyinput-focus-manager.h \
$(public_api_base_src_dir)/focus-manager/focus-manager.h \
diff --git a/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp b/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp
new file mode 100644
index 0000000..bde47cf
--- /dev/null
+++ b/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.cpp
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include
+
+// EXTERNAL INCLUDES
+#include
+
+// INTERNAL INCLUDES
+#include
+
+using namespace Dali;
+using namespace Dali::Toolkit;
+using namespace Dali::Toolkit::Text;
+
+namespace
+{
+
+const std::size_t PADDING = 2; //< To avoid GL filtering artefacts
+
+struct TextureCoordinates
+{
+ TextureCoordinates()
+ : topLeft( 0.0f, 0.0f ),
+ topRight( 1.0f, 0.0f ),
+ bottomLeft( 0.0f, 1.0f ),
+ bottomRight( 1.0f, 1.0f )
+ {
+ }
+
+ Vector2 topLeft;
+ Vector2 topRight;
+ Vector2 bottomLeft;
+ Vector2 bottomRight;
+};
+
+struct AtlasHelperGlyph
+{
+ AtlasHelperGlyph()
+ : fontId( 0 ),
+ index( 0 ),
+ xOffset( 0 ),
+ width( 0 ),
+ height( 0 )
+ {
+ }
+
+ AtlasHelperGlyph( FontId id,
+ GlyphIndex glyphIndex,
+ std::size_t offset,
+ std::size_t widthPixels,
+ std::size_t heightPixels )
+ : fontId( id ),
+ index( glyphIndex ),
+ xOffset( offset ),
+ width( widthPixels ),
+ height( heightPixels )
+ {
+ }
+
+ FontId fontId;
+ GlyphIndex index;
+ std::size_t xOffset;
+ std::size_t width;
+ std::size_t height;
+ TextureCoordinates coords;
+};
+
+struct AtlasHelper
+{
+ AtlasHelper()
+ : mWidth( 0.0f ),
+ mHeight( 0.0f )
+ {
+ mFontClient = TextAbstraction::FontClient::Get();
+ }
+
+ void Reset()
+ {
+ mWidth = 0.0f;
+ mHeight = 0.0f;
+ mGlyphs.clear();
+ }
+
+ void Reserve( std::size_t size )
+ {
+ mGlyphs.reserve( size );
+ }
+
+ bool GlyphFound( FontId fontId, GlyphIndex index ) const
+ {
+ for( unsigned int i=0; i(glyph.xOffset) / static_cast(mWidth);
+ coords.topLeft.y = 0.0f;
+ coords.topRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth);
+ coords.topRight.y = 0.0f;
+ coords.bottomLeft.x = static_cast(glyph.xOffset) / static_cast(mWidth);
+ coords.bottomLeft.y = static_cast(glyph.height) / static_cast(mHeight);
+ coords.bottomRight.x = static_cast(glyph.xOffset + glyph.width) / static_cast(mWidth);
+ coords.bottomRight.y = static_cast(glyph.height) / static_cast(mHeight);
+ }
+
+ return atlas;
+ }
+
+ void GetTextureCoordinates( FontId fontId, GlyphIndex index, TextureCoordinates& coords )
+ {
+ for( unsigned int i=0; i mGlyphs;
+
+ TextAbstraction::FontClient mFontClient;
+};
+
+} // unnamed namespace
+
+struct BasicRenderer::Impl
+{
+ /**
+ * @brief Ccreate an Atlas, uploading the necessary glyph bitmaps
+ *
+ * @param[in] glyphs The glyphs to upload.
+ */
+ Atlas CreateAtlas( const Vector& glyphs )
+ {
+ AtlasHelper& helper = mAtlasHelper;
+
+ // Clear previous atlas
+ helper.Reset();
+ helper.Reserve( glyphs.Count() );
+
+ for( unsigned int i=0; i 0 &&
+ height > 0 ) // skip whitespace
+ {
+ if( !helper.GlyphFound( glyphs[i].fontId, glyphs[i].index ) )
+ {
+ helper.AddGlyph( glyphs[i] );
+ }
+ }
+ }
+
+ // Uploads the bitmaps to Dali
+ return helper.CreateAtlas();
+ }
+
+ /**
+ * @brief Helper method to create a mesh with one quad per glyph.
+ *
+ * @param[in] glyphs The glyphs to display.
+ * @param[in] positions The 2D positions of the glyphs.
+ * @param[in] image The material uses this as a diffuse texture.
+ */
+ Mesh CreateMesh( const Vector& glyphs, const std::vector& positions, Image image )
+ {
+ MeshData::VertexContainer vertices( 4 * glyphs.Count() ); // 1 quad per glyph
+
+ MeshData::FaceIndices faces;
+ faces.reserve( 6 * glyphs.Count() ); // 2 triangles per quad
+
+ for( unsigned int i=0; i 0 &&
+ height > 0 ) // skip whitespace
+ {
+ const Vector2& position = positions[i];
+
+ TextureCoordinates coords;
+ mAtlasHelper.GetTextureCoordinates( glyphs[i].fontId, glyphs[i].index, coords );
+
+ vertices[ i*4 + 0 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 0.0f*height, 0.0f ), coords.topLeft, Vector3( 1.0f, 0.0f, 0.0f ) );
+ vertices[ i*4 + 1 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 0.0f*height, 0.0f ), coords.topRight, Vector3( 1.0f, 1.0f, 0.0f ) );
+ vertices[ i*4 + 2 ] = MeshData::Vertex( Vector3( position.x + 0.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomLeft, Vector3( 0.0f, 1.0f, 0.0f ) );
+ vertices[ i*4 + 3 ] = MeshData::Vertex( Vector3( position.x + 1.0f*width, position.y + 1.0f*height, 0.0f ), coords.bottomRight, Vector3( 0.0f, 0.0f, 1.0f ) );
+
+ faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 3 ); faces.push_back( i*4 + 1 );
+ faces.push_back( i*4 + 0 ); faces.push_back( i*4 + 2 ); faces.push_back( i*4 + 3 );
+ }
+ }
+
+ Material material = Material::New( "Material" );
+ material.SetDiffuseTexture( image );
+
+ // Create the mesh data from the vertices and faces
+ MeshData meshData;
+ meshData.SetHasColor( false );
+ meshData.SetMaterial( material );
+ meshData.SetVertices( vertices );
+ meshData.SetFaceIndices( faces );
+
+ // Create a mesh from the data
+ Dali::Mesh mesh = Mesh::New( meshData );
+ return mesh;
+ }
+
+ RenderableActor mActor; ///< The actor which renders the text
+
+ AtlasHelper mAtlasHelper; ///< A helper class for storing atlas positions etc.
+};
+
+Text::RendererPtr BasicRenderer::New()
+{
+ return Text::RendererPtr( new BasicRenderer() );
+}
+
+RenderableActor BasicRenderer::Render( Text::ViewInterface& view )
+{
+ Text::Length numberOfGlyphs = view.GetNumberOfGlyphs();
+
+ if( numberOfGlyphs > 0 )
+ {
+ Vector glyphs;
+ glyphs.Resize( numberOfGlyphs );
+
+ view.GetGlyphs( 0, &glyphs[0], numberOfGlyphs );
+
+ std::vector positions;
+ positions.resize( numberOfGlyphs );
+ view.GetGlyphPositions( 0, &positions[0], numberOfGlyphs );
+
+ Atlas atlas = mImpl->CreateAtlas( glyphs );
+
+ MeshActor actor = MeshActor::New( mImpl->CreateMesh( glyphs, positions, atlas ) );
+ actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+ actor.SetAffectedByLighting( false );
+
+ ShaderEffect shader = BasicShader::New();
+ actor.SetShaderEffect( shader );
+
+ mImpl->mActor = actor;
+ }
+
+ return mImpl->mActor;
+}
+
+BasicRenderer::BasicRenderer()
+{
+ mImpl = new Impl();
+}
+
+BasicRenderer::~BasicRenderer()
+{
+ delete mImpl;
+}
diff --git a/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.h b/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.h
new file mode 100644
index 0000000..3133c6d
--- /dev/null
+++ b/base/dali-toolkit/public-api/text/rendering/basic/text-basic-renderer.h
@@ -0,0 +1,90 @@
+#ifndef __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__
+#define __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include
+#include
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A reference implementation of Text::Renderer.
+ *
+ * This is intended for testing & performance comparisons with more complex solutions.
+ * Each basic renderer creates its own texture atlas, and uses a simple packing algorithm,
+ * in which glyphs are stored in a single row.
+ */
+class BasicRenderer : public Renderer
+{
+public:
+
+ /**
+ * @brief Create the renderer.
+ */
+ static RendererPtr New();
+
+ /**
+ * @brief Render the glyphs from a ViewInterface.
+ *
+ * @param[in] view The interface to a view.
+ * @return The Renderable actor used to position the text.
+ */
+ virtual RenderableActor Render( ViewInterface& view );
+
+protected:
+
+ /**
+ * @brief Constructor.
+ */
+ BasicRenderer();
+
+ /**
+ * @brief A reference counted object may only be deleted by calling Unreference().
+ */
+ virtual ~BasicRenderer();
+
+private:
+
+ // Undefined
+ BasicRenderer( const BasicRenderer& handle );
+
+ // Undefined
+ BasicRenderer& operator=( const BasicRenderer& handle );
+
+private:
+
+ struct Impl;
+ Impl* mImpl;
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_BASIC_RENDERER_H__
diff --git a/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.cpp b/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.cpp
new file mode 100644
index 0000000..f3a9004
--- /dev/null
+++ b/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+namespace BasicShader
+{
+
+Dali::ShaderEffect New()
+{
+ std::string vertexShader = DALI_COMPOSE_SHADER(
+ uniform mediump vec4 uTextureRect;\n
+ void main()\n
+ {\n
+ gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n
+ vTexCoord = aTexCoord.xy;\n
+ }\n
+ );
+
+ std::string fragmentShader = DALI_COMPOSE_SHADER(
+ void main()\n
+ {\n
+ mediump vec4 color = texture2D( sTexture, vTexCoord );
+ gl_FragColor = vec4(uColor.rgb, uColor.a*color.r);
+ }\n
+ );
+
+ Dali::ShaderEffect shaderEffect = Dali::ShaderEffect::New( vertexShader, fragmentShader,
+ Dali::GeometryType( Dali::GEOMETRY_TYPE_TEXTURED_MESH ),
+ Dali::ShaderEffect::GeometryHints( Dali::ShaderEffect::HINT_NONE ) );
+ return shaderEffect;
+}
+
+} // namespace BasicShader
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
diff --git a/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.h b/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.h
new file mode 100644
index 0000000..cc97d1b
--- /dev/null
+++ b/base/dali-toolkit/public-api/text/rendering/shaders/text-basic-shader.h
@@ -0,0 +1,53 @@
+#ifndef __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__
+#define __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief A basic shader for rendering glyphs in Pixel::L8 format.
+ */
+namespace BasicShader
+{
+
+/**
+ * Create a basic text shader.
+ * @return A handle to a newly allocated ShaderEffect
+ */
+Dali::ShaderEffect New();
+
+} // namespace BasicShader
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_BASIC_SHADER_H__
diff --git a/base/dali-toolkit/public-api/text/text-renderer.cpp b/base/dali-toolkit/public-api/text/rendering/text-renderer.cpp
similarity index 92%
rename from base/dali-toolkit/public-api/text/text-renderer.cpp
rename to base/dali-toolkit/public-api/text/rendering/text-renderer.cpp
index f10968d..fb7c7cb 100644
--- a/base/dali-toolkit/public-api/text/text-renderer.cpp
+++ b/base/dali-toolkit/public-api/text/rendering/text-renderer.cpp
@@ -16,7 +16,7 @@
*/
// CLASS HEADER
-#include
+#include
namespace Dali
{
diff --git a/base/dali-toolkit/public-api/text/text-renderer.h b/base/dali-toolkit/public-api/text/rendering/text-renderer.h
similarity index 100%
rename from base/dali-toolkit/public-api/text/text-renderer.h
rename to base/dali-toolkit/public-api/text/rendering/text-renderer.h
diff --git a/build/tizen/dali-toolkit/Makefile.am b/build/tizen/dali-toolkit/Makefile.am
index 60e340f..94deea2 100644
--- a/build/tizen/dali-toolkit/Makefile.am
+++ b/build/tizen/dali-toolkit/Makefile.am
@@ -116,6 +116,9 @@ publicapibasescrollviewdir = $(publicapibasedir)/controls/scrollable/scroll-view
publicapibasetableviewdir = $(publicapibasedir)/controls/table-view
publicapibasetextcontrolsdir = $(publicapibasedir)/controls/text-controls
publicapibasetextdir = $(publicapibasedir)/text
+publicapibasetextrenderingdir = $(publicapibasedir)/text/rendering
+publicapibasetextrenderingbasicdir = $(publicapibasedir)/text/rendering/basic
+publicapibasetextrenderingshadersdir = $(publicapibasedir)/text/rendering/shaders
publicapibasefactorydir = $(publicapibasedir)/factory
publicapibasefocusmanagerdir = $(publicapibasedir)/focus-manager
publicapibasemarkupprocessordir = $(publicapibasedir)/markup-processor
@@ -137,6 +140,9 @@ publicapibasescrollview_HEADERS = $(public_api_base_scroll_view_header_files)
publicapibasetableview_HEADERS = $(public_api_base_table_view_header_files)
publicapibasetextcontrols_HEADERS = $(public_api_base_text_controls_header_files)
publicapibasetext_HEADERS = $(public_api_base_text_header_files)
+publicapibasetextrendering_HEADERS = $(public_api_base_text_rendering_header_files)
+publicapibasetextrenderingbasic_HEADERS = $(public_api_base_text_rendering_basic_header_files)
+publicapibasetextrenderingshaders_HEADERS = $(public_api_base_text_rendering_shaders_header_files)
publicapibasefocusmanager_HEADERS = $(public_api_base_focus_manager_header_files)
publicapibasemarkupprocessor_HEADERS = $(public_api_base_markup_processor_header_files)
publicapibaseshadereffects_HEADERS = $(public_api_base_shader_effects_header_files)
diff --git a/optional/dali-toolkit/dali-toolkit.h b/optional/dali-toolkit/dali-toolkit.h
index 267e176..3cee3df 100644
--- a/optional/dali-toolkit/dali-toolkit.h
+++ b/optional/dali-toolkit/dali-toolkit.h
@@ -64,10 +64,12 @@
#include
#include
#include
-#include
#include
#include
#include
+#include
+#include
+#include
// INTERNAL INCLUDES
--
2.7.4