2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali-toolkit/internal/text/rendering/vector-based/vector-based-renderer.h>
22 #include <dali/devel-api/text-abstraction/font-client.h>
23 #include <dali/integration-api/debug.h>
24 #include <dali/public-api/rendering/geometry.h>
25 #include <dali/public-api/rendering/renderer.h>
28 #include <dali-toolkit/internal/text/glyph-run.h>
29 #include <dali-toolkit/internal/text/rendering/vector-based/glyphy-shader/glyphy-shader.h>
30 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas-share.h>
31 #include <dali-toolkit/internal/text/rendering/vector-based/vector-blob-atlas.h>
32 #include <dali-toolkit/internal/text/text-view.h>
35 using namespace Dali::Toolkit;
36 using namespace Dali::Toolkit::Text;
40 #if defined(DEBUG_ENABLED)
41 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::Concise, true, "LOG_TEXT_RENDERING");
44 const float DEFAULT_POINT_SIZE = 13.f;
55 void AddVertex(Vector<Vertex2D>& vertices, float x, float y, float u, float v, const Vector4& color)
62 meshVertex.color = color;
63 vertices.PushBack(meshVertex);
66 void AddTriangle(Vector<unsigned short>& indices, unsigned int v0, unsigned int v1, unsigned int v2)
73 bool CreateGeometry(const Vector<GlyphInfo>& glyphs,
74 unsigned int numberOfGlyphs,
75 const Vector<Vector2>& positions,
78 VectorBlobAtlas& atlas,
79 Dali::TextAbstraction::FontClient& fontClient,
80 Vector<Vertex2D>& vertices,
81 Vector<unsigned short>& indices,
82 const Vector4* const colorsBuffer,
83 const ColorIndex* const colorIndicesBuffer,
84 const Vector4& defaultColor)
86 // Whether the default color is used.
87 const bool useDefaultColor = (NULL == colorsBuffer);
89 bool atlasFull(false);
91 for(unsigned int i = 0, idx = 0; i < numberOfGlyphs && !atlasFull; ++i)
93 if(glyphs[i].width > 0 &&
98 BlobCoordinate blobCoords[4];
100 if(!atlas.FindGlyph(glyphs[i].fontId, glyphs[i].index, blobCoords))
103 VectorBlob* blob(NULL);
104 unsigned int blobLength(0);
105 unsigned int nominalWidth(0);
106 unsigned int nominalHeight(0);
107 fontClient.CreateVectorBlob(glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight);
111 bool glyphAdded = atlas.AddGlyph(glyphs[i].fontId, glyphs[i].index, blob, blobLength, nominalWidth, nominalHeight, blobCoords);
113 foundBlob = glyphAdded;
114 atlasFull = !glyphAdded;
124 // Get the color of the character.
125 const ColorIndex colorIndex = useDefaultColor ? 0u : *(colorIndicesBuffer + i);
126 const Vector4& color = (useDefaultColor || (0u == colorIndex)) ? defaultColor : *(colorsBuffer + colorIndex - 1u);
128 const float x1(xOffset + positions[i].x);
129 const float x2(xOffset + positions[i].x + glyphs[i].width);
130 const float y1(yOffset + positions[i].y);
131 const float y2(yOffset + positions[i].y + glyphs[i].height);
133 AddVertex(vertices, x1, y2, blobCoords[0].u, blobCoords[0].v, color);
134 AddVertex(vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color);
135 AddVertex(vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color);
136 AddTriangle(indices, idx, idx + 1, idx + 2);
139 AddVertex(vertices, x1, y1, blobCoords[1].u, blobCoords[1].v, color);
140 AddVertex(vertices, x2, y2, blobCoords[2].u, blobCoords[2].v, color);
141 AddVertex(vertices, x2, y1, blobCoords[3].u, blobCoords[3].v, color);
142 AddTriangle(indices, idx, idx + 1, idx + 2);
148 // If the atlas is still partially empty, all the glyphs were added
152 } // unnamed namespace
154 struct VectorBasedRenderer::Impl
158 mFontClient = TextAbstraction::FontClient::Get();
160 mQuadVertexFormat["aPosition"] = Property::VECTOR2;
161 mQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
162 mQuadVertexFormat["aColor"] = Property::VECTOR4;
165 Actor mActor; ///< The actor parent which renders the text
167 TextAbstraction::FontClient mFontClient; ///> The font client used to supply glyph information
169 Property::Map mQuadVertexFormat; ///> Describes the vertex format for text
171 Shader mShaderEffect;
173 IntrusivePtr<VectorBlobAtlas> mAtlas;
176 Text::RendererPtr VectorBasedRenderer::New()
178 DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Text::VectorBasedRenderer::New()\n");
180 return Text::RendererPtr(new VectorBasedRenderer());
183 Actor VectorBasedRenderer::Render(Text::ViewInterface& view,
185 Property::Index animatablePropertyIndex,
186 float& alignmentOffset,
189 UnparentAndReset(mImpl->mActor);
191 mImpl->mActor = Actor::New();
192 mImpl->mActor.SetProperty(Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER);
193 mImpl->mActor.SetProperty(Actor::Property::SIZE, Vector2(view.GetControlSize()));
194 mImpl->mActor.SetProperty(Actor::Property::COLOR, Color::WHITE);
195 #if defined(DEBUG_ENABLED)
196 mImpl->mActor.SetProperty(Dali::Actor::Property::NAME, "Text renderable actor");
199 Length numberOfGlyphs = view.GetNumberOfGlyphs();
201 if(numberOfGlyphs > 0u)
203 Vector<GlyphInfo> glyphs;
204 glyphs.Resize(numberOfGlyphs);
206 Vector<Vector2> positions;
207 positions.Resize(numberOfGlyphs);
209 numberOfGlyphs = view.GetGlyphs(glyphs.Begin(),
215 glyphs.Resize(numberOfGlyphs);
216 positions.Resize(numberOfGlyphs);
218 const Vector4* const colorsBuffer = view.GetColors();
219 const ColorIndex* const colorIndicesBuffer = view.GetColorIndices();
220 const Vector4& defaultColor = view.GetTextColor();
222 Vector<Vertex2D> vertices;
223 Vector<unsigned short> indices;
225 const Vector2& controlSize = view.GetControlSize();
226 float xOffset = -alignmentOffset + controlSize.width * -0.5f;
227 float yOffset = controlSize.height * -0.5f;
230 mImpl->mAtlas->IsFull())
232 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
233 mImpl->mAtlas = atlasShare.GetCurrentAtlas();
236 // First try adding the glyphs to the previous shared atlas
237 bool allGlyphsAdded = CreateGeometry(glyphs,
252 // The current atlas is full, abandon it and use a new one
253 mImpl->mAtlas.Reset();
257 VectorBlobAtlasShare atlasShare = VectorBlobAtlasShare::Get();
258 mImpl->mAtlas = atlasShare.GetNewAtlas();
260 CreateGeometry(glyphs,
272 // Return value ignored; using more than an entire new atlas is not supported
275 if(0 != vertices.Count())
277 VertexBuffer quadVertices = VertexBuffer::New(mImpl->mQuadVertexFormat);
279 quadVertices.SetData(&vertices[0], vertices.Size());
281 Geometry quadGeometry = Geometry::New();
282 quadGeometry.AddVertexBuffer(quadVertices);
283 quadGeometry.SetIndexBuffer(&indices[0], indices.Size());
285 TextureSet texture = mImpl->mAtlas->GetTextureSet();
287 const Vector4 atlasInfo = mImpl->mAtlas->GetInfo();
288 mImpl->mShaderEffect = GlyphyShader::New(atlasInfo);
290 Dali::Renderer renderer = Dali::Renderer::New(quadGeometry, mImpl->mShaderEffect);
291 renderer.SetTextures(texture);
292 mImpl->mActor.AddRenderer(renderer);
296 return mImpl->mActor;
299 VectorBasedRenderer::VectorBasedRenderer()
304 VectorBasedRenderer::~VectorBasedRenderer()