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