From: Paul Wisbey
Date: Mon, 14 Mar 2016 13:11:26 +0000 (-0700)
Subject: Merge "Added Emscripten guide" into devel/master
X-Git-Tag: dali_1.1.26~2
X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=commitdiff_plain;h=5b4982566aba41b5e21c3b8ce3e01a7e86db8f28;hp=469f5a14469849a28463710288da51a34a40e9da
Merge "Added Emscripten guide" into devel/master
---
diff --git a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt
index 7e21216..0852234 100644
--- a/automated-tests/src/dali-toolkit-internal/CMakeLists.txt
+++ b/automated-tests/src/dali-toolkit-internal/CMakeLists.txt
@@ -13,6 +13,8 @@ SET(TC_SOURCES
utc-Dali-Text-MultiLanguage.cpp
utc-Dali-LogicalModel.cpp
utc-Dali-BidirectionalSupport.cpp
+ utc-Dali-Text-Shaping.cpp
+ utc-Dali-VisualModel.cpp
)
# Append list of test harness files (Won't get parsed for test cases)
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
new file mode 100644
index 0000000..0dd3144
--- /dev/null
+++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-Text-Shaping.cpp
@@ -0,0 +1,528 @@
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following function.
+// void ShapeText( const Vector& text,
+// const Vector& lineBreakInfo,
+// const Vector& scripts,
+// const Vector& fonts,
+// CharacterIndex startCharacterIndex,
+// GlyphIndex startGlyphIndex,
+// Length numberOfCharacters,
+// Vector& glyphs,
+// Vector& glyphToCharacterMap,
+// Vector& charactersPerGlyph,
+// Vector& newParagraphGlyphs );
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct GlyphInfoData
+{
+ FontId fontId; ///< Identifies the font containing the glyph
+ GlyphIndex index; ///< Uniquely identifies a glyph for a given FontId
+ float width; ///< The width of the glyph
+ float height; ///< The height of the glyph
+ float xBearing; ///< The distance from the cursor position to the leftmost border of the glyph
+ float yBearing; ///< The distance from the baseline to the topmost border of the glyph
+ float advance; ///< The distance to move the cursor for this glyph
+ float scaleFactor; ///< The scaling applied (fixed-size fonts only)
+};
+
+bool IsEqualGlyph ( const GlyphInfoData& glyphData, const GlyphInfo& glyph )
+{
+ if( glyphData.fontId != glyph.fontId )
+ {
+ return false;
+ }
+ if( glyphData.index != glyph.index )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.width - glyph.width ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.height - glyph.height ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.xBearing - glyph.xBearing ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.yBearing - glyph.yBearing ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.advance - glyph.advance ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+ if( fabsf( glyphData.scaleFactor - glyph.scaleFactor ) > Math::MACHINE_EPSILON_1000 )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+struct ShapeInfoData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< input text.
+ uint32_t index; ///< The index from where to start to query the break info.
+ uint32_t numberOfCharacters; ///< The requested number of characters.
+ uint32_t expectedNumberOfGlyphs; ///< The expected number of glyphs.
+ GlyphInfoData* glyphs; ///< The glyphs.
+ CharacterIndex* characterIndices; ///< The character index for each glyph.
+ Length* charactersPerGlyph; ///< The characters per glyph.
+ uint32_t expectedNumberOfNewParagraphGlyphs; ///< The expected number of glyphs.
+ GlyphIndex* newParagraphGlyphs; ///< Indices to the new paragraphs glyphs.
+};
+
+bool ShapeInfoTest( const ShapeInfoData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the model.
+
+ Vector& glyphs = visualModel->mGlyphs;
+ Vector& glyphToCharacter = visualModel->mGlyphsToCharacters;
+ Vector& charactersPerGlyph = visualModel->mCharactersPerGlyph;
+ Vector& charactersToGlyph = visualModel->mCharactersToGlyph;
+ Vector& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+
+ // Get the glyph index.
+ GlyphIndex glyphIndex = 0u;
+ if( 0u != visualModel->mCharactersToGlyph.Count() )
+ {
+ glyphIndex = *( visualModel->mCharactersToGlyph.Begin() + data.index );
+
+ const CharacterIndex lastCharacterIndex = data.index + data.numberOfCharacters - 1u;
+ const Length numberOfGlyphs = *( visualModel->mCharactersToGlyph.Begin() + lastCharacterIndex ) + *( visualModel->mGlyphsPerCharacter.Begin() + lastCharacterIndex ) - glyphIndex;
+
+ // Erase the glyph info from the text model.
+ // Got from the ShapeText() function.
+ glyphs.Erase( glyphs.Begin() + glyphIndex, glyphs.Begin() + glyphIndex + numberOfGlyphs );
+ glyphToCharacter.Erase( glyphToCharacter.Begin() + glyphIndex, glyphToCharacter.Begin() + glyphIndex + numberOfGlyphs );
+ charactersPerGlyph.Erase( charactersPerGlyph.Begin() + glyphIndex, charactersPerGlyph.Begin() + glyphIndex + numberOfGlyphs );
+
+ // Got from the VisualModel::CreateCharacterToGlyphTable() and the VisualModel::CreateGlyphsPerCharacterTable() methods.
+ charactersToGlyph.Erase( charactersToGlyph.Begin() + data.index,
+ charactersToGlyph.Begin() + data.index + data.numberOfCharacters );
+ glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.index,
+ glyphsPerCharacter.Begin() + data.index + data.numberOfCharacters );
+
+ // Update the glyph to character indices.
+ for( Vector::Iterator it = glyphToCharacter.Begin() + glyphIndex,
+ endIt = glyphToCharacter.End();
+ it != endIt;
+ ++it )
+ {
+ CharacterIndex& index = *it;
+ index -= data.numberOfCharacters;
+ }
+
+ }
+
+ // Reset the metrics got from the model as the ShapeText() function doesn't retrieve them.
+ for( Vector::Iterator it = glyphs.Begin(),
+ endIt = glyphs.End();
+ it != endIt;
+ ++it )
+ {
+ GlyphInfo& info = *it;
+ info.width = 0.f;
+ info.height = 0.f;
+ info.xBearing = 0.f;
+ info.yBearing = 0.f;
+ info.scaleFactor = 0.f;
+ }
+
+ // 3) Call the ShapeText() function.
+
+ Vector newParagraphGlyphs;
+
+ ShapeText( logicalModel->mText,
+ logicalModel->mLineBreakInfo,
+ logicalModel->mScriptRuns,
+ logicalModel->mFontRuns,
+ data.index,
+ glyphIndex,
+ data.numberOfCharacters,
+ glyphs,
+ glyphToCharacter,
+ charactersPerGlyph,
+ newParagraphGlyphs );
+
+ // Clear the advance of the new paragraph glyphs.
+ for( Vector::Iterator it = newParagraphGlyphs.Begin(),
+ endIt = newParagraphGlyphs.End();
+ it != endIt;
+ ++it )
+ {
+ GlyphInfo& info = *( glyphs.Begin() + *it );
+ info.advance = 0.f;
+ }
+
+ // 4) Compare the results.
+
+ if( data.expectedNumberOfGlyphs != glyphs.Count() )
+ {
+ std::cout << " Different number of glyphs : " << glyphs.Count() << ", expected : " << data.expectedNumberOfGlyphs << std::endl;
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
+ {
+ if( !IsEqualGlyph( data.glyphs[index], glyphs[index] ) )
+ {
+ std::cout << " different glyph info, index : " << index << std::endl;
+ return false;
+ }
+ }
+
+ for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
+ {
+ if( data.characterIndices[index] != glyphToCharacter[index] )
+ {
+ std::cout << " different character index, index : " << index << std::endl;
+ return false;
+ }
+ }
+
+ for( unsigned int index = 0u; index < data.expectedNumberOfGlyphs; ++index )
+ {
+ if( data.charactersPerGlyph[index] != charactersPerGlyph[index] )
+ {
+ std::cout << " different character per glyph, index : " << index << std::endl;
+ return false;
+ }
+ }
+
+ if( data.expectedNumberOfNewParagraphGlyphs != newParagraphGlyphs.Count() )
+ {
+ std::cout << " Different number of new paragraph glyphs : " << newParagraphGlyphs.Count() << ", expected : " << data.expectedNumberOfNewParagraphGlyphs << std::endl;
+ return false;
+ }
+
+ for( unsigned int index = 0u; index < data.expectedNumberOfNewParagraphGlyphs; ++index )
+ {
+ if( data.newParagraphGlyphs[index] != newParagraphGlyphs[index] )
+ {
+ std::cout << " different new paragraph glyph, index : " << index << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliTextShape(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliTextShape");
+
+ struct GlyphInfoData glyphs02[] =
+ {
+ { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ };
+
+ CharacterIndex characterIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
+ Length charactersPerGlyph02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
+
+ struct GlyphInfoData glyphs03[] =
+ {
+ { 1u, 43u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 90u, 0.f, 0.f, 0.f, 0.f, 13.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
+ };
+
+ CharacterIndex characterIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u };
+ Length charactersPerGlyph03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
+ CharacterIndex newParagraphGlyphs03[] = { 11u, 16u };
+
+ struct GlyphInfoData glyphs04[] =
+ {
+ { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 123u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 150u, 0.f, 0.f, 0.f, 0.f, 14.f, 0.f },
+ { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 151u, 0.f, 0.f, 0.f, 0.f, 12.f, 0.f },
+ { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 160u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 2u, 147u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 2u, 153u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ };
+
+ CharacterIndex characterIndices04[] = { 0u, 0u, 0u, 2u, 2u, 2u, 4u, 4u, 4u, 6u, 6u, 6u };
+ Length charactersPerGlyph04[] = { 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u, 0u, 0u, 2u };
+
+ struct GlyphInfoData glyphs05[] =
+ {
+ { 1u, 47u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 79u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 87u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 84u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 5034u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 69u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
+ { 1u, 83u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 82u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 86u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 85u, 0.f, 0.f, 0.f, 0.f, 6.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 71u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 76u, 0.f, 0.f, 0.f, 0.f, 4.f, 0.f },
+ { 1u, 68u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 81u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 72u, 0.f, 0.f, 0.f, 0.f, 9.f, 0.f },
+ { 1u, 3u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 70u, 0.f, 0.f, 0.f, 0.f, 8.f, 0.f },
+ { 1u, 88u, 0.f, 0.f, 0.f, 0.f, 10.f, 0.f },
+ { 1u, 80u, 0.f, 0.f, 0.f, 0.f, 15.f, 0.f },
+ { 1u, 17u, 0.f, 0.f, 0.f, 0.f, 5.f, 0.f },
+ { 1u, 0u, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f },
+ };
+
+ CharacterIndex characterIndices05[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u,
+ 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
+ 20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u, 28u, 29u,
+ 30u, 31u, 32u, 33u, 34u, 35u, 37u, 38u, 39u, 40u,
+ 41u, 42u, 43u, 44u, 45u, 46u, 47u, 48u, 49u, 50u,
+ 51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u, 59u, 60u,
+ 61u, 62u, 63u, 64u, 65u, 66u, 67u, 68u, 69u, 70u,
+ 71u, 72u, 73u, 74u };
+ Length charactersPerGlyph05[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 2u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u };
+ CharacterIndex newParagraphGlyphs05[] = { 26u };
+ CharacterIndex newParagraphGlyphs06[] = { 49u };
+ CharacterIndex newParagraphGlyphs07[] = { 73u };
+
+ struct ShapeInfoData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ NULL,
+ NULL,
+ NULL,
+ 0u,
+ NULL
+ },
+ {
+ "Latin script",
+ "Hello world",
+ 0u,
+ 11u,
+ 11u,
+ glyphs02,
+ characterIndices02,
+ charactersPerGlyph02,
+ 0u,
+ NULL
+ },
+ {
+ "Latin script. Some paragraphs.",
+ "Hello world\ndemo\n",
+ 0u,
+ 17u,
+ 17u,
+ glyphs03,
+ characterIndices03,
+ charactersPerGlyph03,
+ 2u,
+ newParagraphGlyphs03
+ },
+ {
+ "Malayalam script. More glyphs than characters.",
+ "à´àµà´¸àµà´¹àµà´µàµ",
+ 0u,
+ 8u,
+ 12u,
+ glyphs04,
+ characterIndices04,
+ charactersPerGlyph04,
+ 0u,
+ NULL
+ },
+ {
+ "Latin script with some paragraphs. Update initial paragraph.",
+ "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
+ 0u,
+ 27u,
+ 74u,
+ glyphs05,
+ characterIndices05,
+ charactersPerGlyph05,
+ 1u,
+ newParagraphGlyphs05
+ },
+ {
+ "Latin script with some paragraphs. Update mid paragraph.",
+ "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
+ 27u,
+ 24u,
+ 74u,
+ glyphs05,
+ characterIndices05,
+ charactersPerGlyph05,
+ 1u,
+ newParagraphGlyphs06
+ },
+ {
+ "Latin script with some paragraphs. Update final paragraph.",
+ "Lorem ipsum dolor sit amet\naeque definiebas ea mei\nposse iracundia ne cum.\n",
+ 51u,
+ 24u,
+ 74u,
+ glyphs05,
+ characterIndices05,
+ charactersPerGlyph05,
+ 1u,
+ newParagraphGlyphs07
+ },
+ };
+ const unsigned int numberOfTests = 7u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !ShapeInfoTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
new file mode 100644
index 0000000..18faa9e
--- /dev/null
+++ b/automated-tests/src/dali-toolkit-internal/utc-Dali-VisualModel.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2016 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.
+ *
+ */
+
+#include
+
+#include
+
+#include
+#include
+#include
+
+
+using namespace Dali;
+using namespace Toolkit;
+using namespace Text;
+
+// Tests the following functions.
+//
+// void CreateCharacterToGlyphTable( CharacterIndex startIndex,
+// Length numberOfCharacters )
+//
+// void CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+// Length numberOfCharacters )
+
+
+//////////////////////////////////////////////////////////
+
+namespace
+{
+
+struct SetGlyphsPerCharacterData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The start index from where the glyphs per character table is set.
+ unsigned int numberOfCharacters; ///< The number of characters to set.
+ unsigned int totalNumberOfCharacters; ///< The total number of characters.
+ unsigned int* glyphsPerCharacter; ///< The number of glyphs per character.
+};
+
+struct SetCharacterToGlyphData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ unsigned int startIndex; ///< The start index from where the character to glyph table is set.
+ unsigned int numberOfCharacters; ///< The number of characters to set.
+ unsigned int totalNumberOfCharacters; ///< The total number of characters.
+ unsigned int* glyphsIndices; ///< The glyph indices.
+};
+
+bool SetGlyphsPerCharacterTest( const SetGlyphsPerCharacterData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the model.
+ Vector& charactersToGlyph = visualModel->mCharactersToGlyph;
+ Vector& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+
+ if( 0u != charactersToGlyph.Count() )
+ {
+ // The number of glyphs to be removed.
+ const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
+
+ charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
+ charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
+ glyphsPerCharacter.Erase( glyphsPerCharacter.Begin() + data.startIndex,
+ glyphsPerCharacter.Begin() + data.startIndex + data.numberOfCharacters );
+
+ // Update the character to glyph indices.
+ for( Vector::Iterator it = charactersToGlyph.Begin() + data.startIndex,
+ endIt = charactersToGlyph.End();
+ it != endIt;
+ ++it )
+ {
+ *it -= numberOfGlyphs;
+ }
+ }
+
+ // 3) Call the CreateGlyphsPerCharacterTable() function
+ visualModel->CreateGlyphsPerCharacterTable( data.startIndex,
+ data.numberOfCharacters );
+
+ // 4) Compare the results.
+ if( data.totalNumberOfCharacters != glyphsPerCharacter.Count() )
+ {
+ std::cout << " Different number of characters : " << glyphsPerCharacter.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
+ return false;
+ }
+
+ for( unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i )
+ {
+ if( data.glyphsPerCharacter[i] != glyphsPerCharacter[i] )
+ {
+ std::cout << " Different number of glyphs for index " << i << std::endl;
+ for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
+ {
+ std::cout << glyphsPerCharacter[j] << " ";
+ }
+ std::cout << std::endl;
+ std::cout << " expected" << std::endl;
+ for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
+ {
+ std::cout << data.glyphsPerCharacter[j] << " ";
+ }
+ std::cout << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool SetCharacterToGlyphTest( const SetCharacterToGlyphData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ CreateTextModel( data.text,
+ textArea,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the model.
+ Vector& charactersToGlyph = visualModel->mCharactersToGlyph;
+ Vector& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+
+ if( 0u != charactersToGlyph.Count() )
+ {
+ // The number of glyphs to be removed.
+ const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
+
+ charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
+ charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
+
+ // Update the character to glyph indices.
+ for( Vector::Iterator it = charactersToGlyph.Begin() + data.startIndex,
+ endIt = charactersToGlyph.End();
+ it != endIt;
+ ++it )
+ {
+ *it -= numberOfGlyphs;
+ }
+ }
+
+ // 3) Call the CreateCharacterToGlyphTable() function
+ visualModel->CreateCharacterToGlyphTable( data.startIndex,
+ data.numberOfCharacters );
+
+ // 4) Compare the results.
+ if( data.totalNumberOfCharacters != charactersToGlyph.Count() )
+ {
+ std::cout << " Different number of character : " << charactersToGlyph.Count() << ", expected : " << data.totalNumberOfCharacters << std::endl;
+ return false;
+ }
+
+ for( unsigned int i = 0u; i < data.totalNumberOfCharacters; ++i )
+ {
+ if( data.glyphsIndices[i] != charactersToGlyph[i] )
+ {
+ std::cout << " Different number of character to glyph index " << i << std::endl;
+ for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
+ {
+ std::cout << charactersToGlyph[j] << " ";
+ }
+ std::cout << std::endl;
+ std::cout << " expected" << std::endl;
+ for( unsigned int j = 0; j < data.totalNumberOfCharacters; ++j )
+ {
+ std::cout << data.glyphsIndices[j] << " ";
+ }
+ std::cout << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace
+
+//////////////////////////////////////////////////////////
+
+int UtcDaliSetGlyphsPerCharacter(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliSetGlyphsPerCharacter");
+
+ Length glyphsPerCharacter02[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
+ Length glyphsPerCharacter03[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u };
+ Length glyphsPerCharacter04[] = { 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 1u,
+ 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
+ 1u, 1u, 1u, 1u, 0u, 1u, 0u, 2u, 1u, 0u,
+ 2u, 0u, 2u, 0u, 2u, 1u, 1u, 0u, 0u, 0u,
+ 2u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 2u, 1u,
+ 0u, 2u, 1u, 1u };
+
+ struct SetGlyphsPerCharacterData data[] =
+ {
+ {
+ "Zero characters text",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ NULL
+ },
+ {
+ "Simple 1 to 1 text",
+ "Hello world",
+ 0u,
+ 11u,
+ 11u,
+ glyphsPerCharacter02,
+ },
+ {
+ "Text with different number of glyphs and characters.",
+ "Hello different world",
+ 0u,
+ 21u,
+ 21u,
+ glyphsPerCharacter03,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 0u,
+ 22u,
+ 54u,
+ glyphsPerCharacter04,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 22u,
+ 14u,
+ 54u,
+ glyphsPerCharacter04,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 36u,
+ 18u,
+ 54u,
+ glyphsPerCharacter04,
+ },
+ };
+ const unsigned int numberOfTests = 6u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !SetGlyphsPerCharacterTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliSetCharacterToGlyph(void)
+{
+ ToolkitTestApplication application;
+ tet_infoline(" UtcDaliSetGlyphsPerCharacter");
+
+ GlyphIndex glyphIndices02[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u };
+ GlyphIndex glyphIndices03[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u };
+ GlyphIndex glyphIndices04[] = { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u, 20u,
+ 21u, 22u, 23u, 23u, 24u, 24u, 26u, 27u, 27u, 29u, 29u, 31u, 31u, 33u,
+ 34u, 35u, 35u, 35u, 35u, 37u, 38u, 39u, 40u, 41u, 42u, 42u, 42u, 44u, 45u, 45u, 47u, 48u };
+
+ struct SetCharacterToGlyphData data[] =
+ {
+ {
+ "Zero characters text",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ NULL
+ },
+ {
+ "Simple 1 to 1 text",
+ "Hello world",
+ 0u,
+ 11u,
+ 11u,
+ glyphIndices02,
+ },
+ {
+ "Text with different number of glyphs and characters.",
+ "Hello different world",
+ 0u,
+ 21u,
+ 21u,
+ glyphIndices03,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update initial paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 0u,
+ 22u,
+ 54u,
+ glyphIndices04,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update mid paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 22u,
+ 14u,
+ 54u,
+ glyphIndices04,
+ },
+ {
+ "Text paragraphs with different number of glyphs and characters. Update final paragraphs.",
+ "Hello different world\nनमसà¥à¤¤à¥ दà¥à¤¨à¤¿à¤¯à¤¾\náááºá¹ááá¬áá«ááá¹áá¬áá±á¬á",
+ 36u,
+ 18u,
+ 54u,
+ glyphIndices04,
+ },
+ };
+
+ const unsigned int numberOfTests = 6u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ if( !SetCharacterToGlyphTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
diff --git a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
index 10f910c..6786bc5 100644
--- a/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
+++ b/automated-tests/src/dali-toolkit/dali-toolkit-test-utils/toolkit-text-model.cpp
@@ -214,30 +214,30 @@ void CreateTextModel( const std::string& text,
Vector& charactersPerGlyph = visualModel->mCharactersPerGlyph;
Vector newParagraphGlyphs;
- const Length currentNumberOfGlyphs = glyphs.Count();
const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
ShapeText( textToShape,
lineBreakInfo,
scripts,
validFonts,
+ 0u,
+ 0u,
+ numberOfCharacters,
glyphs,
glyphsToCharactersMap,
charactersPerGlyph,
newParagraphGlyphs );
// Create the 'number of glyphs' per character and the glyph to character conversion tables.
- visualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
- visualModel->CreateCharacterToGlyphTable( numberOfCharacters );
+ visualModel->CreateGlyphsPerCharacterTable( 0u, numberOfCharacters );
+ visualModel->CreateCharacterToGlyphTable( 0u, numberOfCharacters );
- const Length numberOfGlyphs = glyphs.Count() - currentNumberOfGlyphs;
+ const Length numberOfGlyphs = glyphs.Count();
// 8) Get the glyph metrics
MetricsPtr metrics = Metrics::New( fontClient );
- const GlyphIndex glyphIndex = currentNumberOfGlyphs;
-
- GlyphInfo* glyphsBuffer = glyphs.Begin() + glyphIndex;
+ GlyphInfo* glyphsBuffer = glyphs.Begin();
metrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
// Update the width and advance of all new paragraph characters.
@@ -247,7 +247,7 @@ void CreateTextModel( const std::string& text,
++it )
{
const GlyphIndex index = *it;
- GlyphInfo& glyph = *( glyphsBuffer + ( index - glyphIndex ) );
+ GlyphInfo& glyph = *( glyphsBuffer + index );
glyph.xBearing = 0.f;
glyph.width = 0.f;
diff --git a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp
index 2d30cd8..dd7012d 100644
--- a/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp
+++ b/automated-tests/src/dali-toolkit/utc-Dali-RendererFactory.cpp
@@ -531,9 +531,16 @@ int UtcDaliRendererFactoryGetImageRenderer1(void)
Actor actor = Actor::New();
// For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
// Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+ const int width=512;
+ const int height=513;
+
+ Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+ bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, width, height,width, height );
+
TestControlRendererRender( application, actor, controlRenderer, 1u,
- ImageDimensions(512, 513),
- Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)));
+ ImageDimensions(width, height),
+ Integration::ResourcePointer( bitmap ) );
TestGlAbstraction& gl = application.GetGlAbstraction();
int textureUnit = -1;
@@ -560,9 +567,16 @@ int UtcDaliRendererFactoryGetImageRenderer2(void)
Actor actor = Actor::New();
// For tesing the LoadResourceFunc is called, a big image size should be set, so the atlasing is not applied.
// Image with a size smaller than 512*512 will be uploaded as a part of the atlas.
+
+ const int width=512;
+ const int height=513;
+
+ Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+ bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, width, height,width, height );
+
TestControlRendererRender( application, actor, controlRenderer, 1u,
- ImageDimensions(512, 513),
- Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)) );
+ ImageDimensions(width, height),
+ Integration::ResourcePointer(bitmap) );
TestGlAbstraction& gl = application.GetGlAbstraction();
int textureUnit = -1;
@@ -775,10 +789,13 @@ int UtcDaliRendererFactoryGetNPatchRendererN1(void)
DALI_TEST_CHECK( controlRenderer );
Actor actor = Actor::New();
+
//The testkit still has to load a bitmap for the broken renderer image
+ Integration::Bitmap* bitmap = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD);
+ bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 100, 100, 100, 100 );
TestControlRendererRender( application, actor, controlRenderer, 1u,
ImageDimensions(),
- Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)) );
+ Integration::ResourcePointer(bitmap) );
TestGlAbstraction& gl = application.GetGlAbstraction();
int textureUnit = -1;
@@ -806,10 +823,13 @@ int UtcDaliRendererFactoryGetNPatchRendererN2(void)
DALI_TEST_CHECK( controlRenderer );
Actor actor = Actor::New();
+
//The testkit still has to load a bitmap for the broken renderer image
+ Integration::Bitmap* bitmap = Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD);
+ bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 100, 100, 100, 100 );
TestControlRendererRender( application, actor, controlRenderer, 1u,
ImageDimensions(),
- Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)) );
+ Integration::ResourcePointer(bitmap) );
TestGlAbstraction& gl = application.GetGlAbstraction();
int textureUnit = -1;
diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp
index 5061193..5313d0c 100644
--- a/dali-toolkit/internal/text/shaper.cpp
+++ b/dali-toolkit/internal/text/shaper.cpp
@@ -40,13 +40,14 @@ void ShapeText( const Vector& text,
const Vector& lineBreakInfo,
const Vector& scripts,
const Vector& fonts,
+ CharacterIndex startCharacterIndex,
+ GlyphIndex startGlyphIndex,
+ Length numberOfCharacters,
Vector& glyphs,
Vector& glyphToCharacterMap,
Vector& charactersPerGlyph,
Vector& newParagraphGlyphs )
{
- const Length numberOfCharacters = text.Count();
-
if( 0u == numberOfCharacters )
{
// Nothing to do if there are no characters.
@@ -56,14 +57,15 @@ void ShapeText( const Vector& text,
#ifdef DEBUG_ENABLED
const Length numberOfFontRuns = fonts.Count();
const Length numberOfScriptRuns = scripts.Count();
+ const Length totalNumberOfCharacters = text.Count();
#endif
DALI_ASSERT_DEBUG( ( 0u != numberOfFontRuns ) &&
- ( numberOfCharacters == fonts[numberOfFontRuns - 1u].characterRun.characterIndex + fonts[numberOfFontRuns - 1u].characterRun.numberOfCharacters ) &&
+ ( totalNumberOfCharacters == fonts[numberOfFontRuns - 1u].characterRun.characterIndex + fonts[numberOfFontRuns - 1u].characterRun.numberOfCharacters ) &&
"Toolkit::Text::ShapeText. All characters must have a font set." );
DALI_ASSERT_DEBUG( ( 0u != numberOfScriptRuns ) &&
- ( numberOfCharacters == scripts[numberOfScriptRuns - 1u].characterRun.characterIndex + scripts[numberOfScriptRuns - 1u].characterRun.numberOfCharacters ) &&
+ ( totalNumberOfCharacters == scripts[numberOfScriptRuns - 1u].characterRun.characterIndex + scripts[numberOfScriptRuns - 1u].characterRun.numberOfCharacters ) &&
"Toolkit::Text::ShapeText. All characters must have a script set." );
// The text needs to be split in chunks of consecutive characters.
@@ -73,8 +75,30 @@ void ShapeText( const Vector& text,
TextAbstraction::Shaping shaping = TextAbstraction::Shaping::Get();
// To shape the text a font and an script is needed.
+
+ // Get the font run containing the startCharacterIndex character.
Vector::ConstIterator fontRunIt = fonts.Begin();
+ for( Vector::ConstIterator endIt = fonts.End(); fontRunIt < endIt; ++fontRunIt )
+ {
+ const FontRun& run = *fontRunIt;
+ if( startCharacterIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Found.
+ break;
+ }
+ }
+
+ // Get the script run containing the startCharacterIndex character.
Vector::ConstIterator scriptRunIt = scripts.Begin();
+ for( Vector::ConstIterator endIt = scripts.End(); scriptRunIt < endIt; ++scriptRunIt )
+ {
+ const ScriptRun& run = *scriptRunIt;
+ if( startCharacterIndex < run.characterRun.characterIndex + run.characterRun.numberOfCharacters )
+ {
+ // Found.
+ break;
+ }
+ }
// Index to the the next one to be shaped. Is pointing the character after the last one it was shaped.
CharacterIndex previousIndex = 0u;
@@ -87,20 +111,25 @@ void ShapeText( const Vector& text,
// There is no way to know the number of glyphs before shaping the text.
// To avoid reallocations it's reserved space for a slightly biger number of glyphs than the number of characters.
- Length numberOfGlyphsReserved = static_cast( numberOfCharacters * 1.3f );
- glyphs.Resize( numberOfGlyphsReserved );
- glyphToCharacterMap.Resize( numberOfGlyphsReserved );
+ const Length currentNumberOfGlyphs = glyphs.Count();
+ const Length numberOfGlyphsReserved = static_cast( numberOfCharacters * 1.3f );
+ glyphs.Resize( currentNumberOfGlyphs + numberOfGlyphsReserved );
+ glyphToCharacterMap.Resize( currentNumberOfGlyphs + numberOfGlyphsReserved );
// The actual number of glyphs.
- Length totalNumberOfGlyphs = 0u;
+ Length totalNumberOfGlyphs = currentNumberOfGlyphs;
+ // The number of new glyphs.
+ Length numberOfNewGlyphs = 0u;
const Character* const textBuffer = text.Begin();
const LineBreakInfo* const lineBreakInfoBuffer = lineBreakInfo.Begin();
- GlyphInfo* glyphsBuffer = glyphs.Begin();
CharacterIndex* glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+ Length glyphIndex = startGlyphIndex;
+
// Traverse the characters and shape the text.
- for( previousIndex = 0; previousIndex < numberOfCharacters; )
+ const CharacterIndex lastCharacter = startCharacterIndex + numberOfCharacters;
+ for( previousIndex = startCharacterIndex; previousIndex < lastCharacter; )
{
// Get the font id and the script.
const FontRun& fontRun = *fontRunIt;
@@ -138,40 +167,41 @@ void ShapeText( const Vector& text,
currentFontId,
currentScript );
- const Length glyphIndex = totalNumberOfGlyphs;
- totalNumberOfGlyphs += numberOfGlyphs;
-
- if( totalNumberOfGlyphs > numberOfGlyphsReserved )
+ // Retrieve the glyphs and the glyph to character conversion map.
+ Vector tmpGlyphs;
+ Vector tmpGlyphToCharacterMap;
+ tmpGlyphs.Resize( numberOfGlyphs );
+ tmpGlyphToCharacterMap.Resize( numberOfGlyphs );
+ shaping.GetGlyphs( tmpGlyphs.Begin(),
+ tmpGlyphToCharacterMap.Begin() );
+
+ // Update the indices.
+ if( 0u != totalNumberOfGlyphs )
{
- // Resize the vectors to get enough space.
- numberOfGlyphsReserved = static_cast( totalNumberOfGlyphs * 1.3f );
- glyphs.Resize( numberOfGlyphsReserved );
- glyphToCharacterMap.Resize( numberOfGlyphsReserved );
-
- // Iterators are not valid anymore, set them again.
- glyphsBuffer = glyphs.Begin();
- glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
+ for( Vector::Iterator it = tmpGlyphToCharacterMap.Begin(),
+ endIt = tmpGlyphToCharacterMap.End();
+ it != endIt;
+ ++it )
+ {
+ *it += previousIndex;
+ }
}
- // Retrieve the glyphs and the glyph to character conversion map.
- shaping.GetGlyphs( glyphsBuffer + glyphIndex,
- glyphToCharacterMapBuffer + glyphIndex );
+ totalNumberOfGlyphs += numberOfGlyphs;
+ numberOfNewGlyphs += numberOfGlyphs;
+
+ glyphs.Insert( glyphs.Begin() + glyphIndex, tmpGlyphs.Begin(), tmpGlyphs.End() );
+ glyphToCharacterMap.Insert( glyphToCharacterMap.Begin() + glyphIndex, tmpGlyphToCharacterMap.Begin(), tmpGlyphToCharacterMap.End() );
+ glyphIndex += numberOfGlyphs;
+
+ // Set the buffer pointers again.
+ glyphToCharacterMapBuffer = glyphToCharacterMap.Begin();
if( isNewParagraph )
{
// Add the index of the new paragraph glyph to a vector.
// Their metrics will be updated in a following step.
- newParagraphGlyphs.PushBack( totalNumberOfGlyphs - 1u );
- }
-
- // Update indices.
- if( 0u != glyphIndex )
- {
- for( Length index = glyphIndex; index < glyphIndex + numberOfGlyphs; ++index )
- {
- CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index );
- characterIndex += previousIndex;
- }
+ newParagraphGlyphs.PushBack( glyphIndex - 1u );
}
// Update the iterators to get the next font or script run.
@@ -188,19 +218,28 @@ void ShapeText( const Vector& text,
previousIndex = currentIndex;
}
+ // Update indices.
+ for( Length index = startGlyphIndex + numberOfNewGlyphs; index < totalNumberOfGlyphs; ++index )
+ {
+ CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index );
+ characterIndex += numberOfCharacters;
+ }
+
// Add the number of characters per glyph.
charactersPerGlyph.Reserve( totalNumberOfGlyphs );
- previousIndex = 0u;
- for( Length index = 1u; index < totalNumberOfGlyphs; ++index )
+ Length* charactersPerGlyphBuffer = charactersPerGlyph.Begin();
+
+ const GlyphIndex lastGlyph = startGlyphIndex + numberOfNewGlyphs;
+ previousIndex = startCharacterIndex;
+ for( Length index = startGlyphIndex + 1u; index < lastGlyph; ++index )
{
const CharacterIndex characterIndex = *( glyphToCharacterMapBuffer + index );
- charactersPerGlyph.PushBack( characterIndex - previousIndex );
+ charactersPerGlyph.Insert( charactersPerGlyphBuffer + index - 1u, characterIndex - previousIndex );
previousIndex = characterIndex;
}
-
- charactersPerGlyph.PushBack( numberOfCharacters - previousIndex );
+ charactersPerGlyph.Insert( charactersPerGlyphBuffer + lastGlyph - 1u, numberOfCharacters + startCharacterIndex - previousIndex );
// Resize the vectors to set the right number of items.
glyphs.Resize( totalNumberOfGlyphs );
diff --git a/dali-toolkit/internal/text/shaper.h b/dali-toolkit/internal/text/shaper.h
index 70e2e58..2cd47cb 100644
--- a/dali-toolkit/internal/text/shaper.h
+++ b/dali-toolkit/internal/text/shaper.h
@@ -44,6 +44,9 @@ class VisualModel;
* @param[in] lineBreakInfo The line break info.
* @param[in] scripts Vector containing the script runs for the whole text.
* @param[in] fonts Vector with validated fonts.
+ * @param[in] startCharacterIndex The character from where the text is shaped.
+ * @param[in] startGlyphIndex The glyph from where the text is shaped.
+ * @param[in] numberOfCharacters The number of characters to be shaped.
* @param[out] glyphs Vector of glyphs in the visual order.
* @param[out] glyphToCharacterMap Vector containing the first character in the logical model that each glyph relates to.
* @param[out] charactersPerGlyph Vector containing the number of characters per glyph.
@@ -53,6 +56,9 @@ void ShapeText( const Vector& text,
const Vector& lineBreakInfo,
const Vector& scripts,
const Vector& fonts,
+ CharacterIndex startCharacterIndex,
+ GlyphIndex startGlyphIndex,
+ Length numberOfCharacters,
Vector& glyphs,
Vector& glyphToCharacterMap,
Vector& charactersPerGlyph,
diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp
index 9458933..c2c2fa8 100644
--- a/dali-toolkit/internal/text/text-controller-impl.cpp
+++ b/dali-toolkit/internal/text/text-controller-impl.cpp
@@ -453,6 +453,7 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
Vector newParagraphGlyphs;
newParagraphGlyphs.Reserve( numberOfParagraphs );
+ GlyphIndex startGlyphIndex = 0u;
if( SHAPE_TEXT & operations )
{
const Vector& textToShape = textMirrored ? mirroredUtf32Characters : utf32Characters;
@@ -461,21 +462,24 @@ void Controller::Impl::UpdateModel( OperationsMask operationsRequired )
lineBreakInfo,
scripts,
validFonts,
+ startIndex,
+ startGlyphIndex,
+ requestedNumberOfCharacters,
glyphs,
glyphsToCharactersMap,
charactersPerGlyph,
newParagraphGlyphs );
// Create the 'number of glyphs' per character and the glyph to character conversion tables.
- mVisualModel->CreateGlyphsPerCharacterTable( numberOfCharacters );
- mVisualModel->CreateCharacterToGlyphTable( numberOfCharacters );
+ mVisualModel->CreateGlyphsPerCharacterTable( startIndex, numberOfCharacters );
+ mVisualModel->CreateCharacterToGlyphTable( startIndex, numberOfCharacters );
}
const Length numberOfGlyphs = glyphs.Count();
if( GET_GLYPH_METRICS & operations )
{
- GlyphInfo* glyphsBuffer = glyphs.Begin();
+ GlyphInfo* glyphsBuffer = glyphs.Begin() + startGlyphIndex;
mMetrics->GetGlyphMetrics( glyphsBuffer, numberOfGlyphs );
// Update the width and advance of all new paragraph characters.
diff --git a/dali-toolkit/internal/text/visual-model-impl.cpp b/dali-toolkit/internal/text/visual-model-impl.cpp
index 561beee..3e9c123 100644
--- a/dali-toolkit/internal/text/visual-model-impl.cpp
+++ b/dali-toolkit/internal/text/visual-model-impl.cpp
@@ -35,29 +35,50 @@ VisualModelPtr VisualModel::New()
return VisualModelPtr( new VisualModel() );
}
-void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
+void VisualModel::CreateCharacterToGlyphTable( CharacterIndex startIndex,
+ Length numberOfCharacters )
{
- // 1) Reserve some space for the characters to avoid reallocations.
if( 0u == numberOfCharacters )
{
- // If no number of characters is given, just set something sensible to avoid reallocations.
- numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f );
+ // Nothing to do.
+ return;
}
- mCharactersToGlyph.Reserve( numberOfCharacters );
- DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u ||
- ( 0u == numberOfCharacters ) );
+ DALI_ASSERT_DEBUG( mGlyphsPerCharacter.Count() != 0u );
+
+ // Get the total number of characters.
+ const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
+
+ // Whether the current buffer is being updated or is set from scratch.
+ const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+ Vector newCharactersToGlyph;
+ GlyphIndex* charactersToGlyphBuffer = NULL;
+
+ // 1) Reserve some space for the glyph indices to avoid reallocations.
+ if( updateCurrentBuffer )
+ {
+ newCharactersToGlyph.Resize( numberOfCharacters );
+ charactersToGlyphBuffer = newCharactersToGlyph.Begin();
+ }
+ else
+ {
+ mCharactersToGlyph.Resize( numberOfCharacters );
+ charactersToGlyphBuffer = mCharactersToGlyph.Begin() + startIndex;
+ }
const Length* const glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin();
// 2) Traverse the glyphs and set the glyph indices per character.
// Index to the glyph.
- GlyphIndex glyphIndex = 0u;
- CharacterIndex characterIndex = 0u;
- for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(),
+ const GlyphIndex startGlyphIndex = updateCurrentBuffer ? *( mCharactersToGlyph.Begin() + startIndex ) : 0u;
+ GlyphIndex glyphIndex = startGlyphIndex;
+ CharacterIndex characterIndex = startIndex;
+ const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+ for( Vector::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex,
endIt = mCharactersPerGlyph.End();
- it != endIt;
+ ( it != endIt ) && ( characterIndex < lastCharacterIndexPlusOne );
++it )
{
const Length numberOfCharactersPerGlyph = *it;
@@ -66,34 +87,79 @@ void VisualModel::CreateCharacterToGlyphTable( Length numberOfCharacters )
// Set the glyph indices.
for( Length index = 0u; index < numberOfCharactersPerGlyph; ++index, ++characterIndex )
{
- mCharactersToGlyph.PushBack( glyphIndex );
+ *charactersToGlyphBuffer = glyphIndex;
numberOfGlyphs += *( glyphsPerCharacterBuffer + characterIndex );
+ ++charactersToGlyphBuffer;
}
glyphIndex += numberOfGlyphs;
}
+
+ // If the character to glyph buffer is updated, it needs to be inserted in the model.
+ if( updateCurrentBuffer )
+ {
+ // Update the indices.
+ const Length numberOfGlyphs = glyphIndex - startGlyphIndex;
+ for( Vector::Iterator it = mCharactersToGlyph.Begin() + startIndex,
+ endIt = mCharactersToGlyph.End();
+ it != endIt;
+ ++it )
+ {
+ *it += numberOfGlyphs;
+ }
+
+ mCharactersToGlyph.Insert( mCharactersToGlyph.Begin() + startIndex,
+ newCharactersToGlyph.Begin(),
+ newCharactersToGlyph.End() );
+
+ }
}
-void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
+void VisualModel::CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+ Length numberOfCharacters )
{
- // 1) Reserve some space for the characters to avoid reallocations.
if( 0u == numberOfCharacters )
{
- // If no number of characters is given, just set something sensible to avoid reallocations.
- numberOfCharacters = static_cast ( static_cast( mGlyphs.Count() ) * 1.3f );
+ // Nothing to do.
+ return;
+ }
+
+ // Get the total number of characters.
+ const Length totalNumberOfCharacters = ( 0u == mGlyphsToCharacters.Count() ) ? 0u : *( mGlyphsToCharacters.End() - 1u ) + *( mCharactersPerGlyph.End() - 1u ); // Index to the first character + the number of characters that form the last glyph.
+
+ // Whether the current buffer is being updated or is set from scratch.
+ const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+ Vector newGlyphsPerCharacter;
+ Length* glyphsPerCharacterBuffer = NULL;
+
+ // 1) Reserve some space for the glyphs per character to avoid reallocations.
+ if( updateCurrentBuffer )
+ {
+ newGlyphsPerCharacter.Resize( numberOfCharacters );
+ glyphsPerCharacterBuffer = newGlyphsPerCharacter.Begin();
+ }
+ else
+ {
+ mGlyphsPerCharacter.Resize( numberOfCharacters );
+ glyphsPerCharacterBuffer = mGlyphsPerCharacter.Begin() + startIndex;
}
- mGlyphsPerCharacter.Reserve( numberOfCharacters );
// 2) Traverse the glyphs and set the number of glyphs per character.
+ // The glyph index.
+ const GlyphIndex glyphIndex = updateCurrentBuffer ? *( mCharactersToGlyph.Begin() + startIndex ) : 0u;
+ Length traversedCharacters = 0;
+
// The number of 'characters per glyph' equal to zero.
Length zeroCharactersPerGlyph = 0u;
- for( Vector::ConstIterator it = mCharactersPerGlyph.Begin(),
+ for( Vector::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex,
endIt = mCharactersPerGlyph.End();
- it != endIt;
+ ( it != endIt ) && ( traversedCharacters < numberOfCharacters );
++it )
{
const Length numberOfCharactersPerGlyph = *it;
+ traversedCharacters += numberOfCharactersPerGlyph;
// Set the glyphs per character.
if( 0u == numberOfCharactersPerGlyph )
@@ -103,16 +169,30 @@ void VisualModel::CreateGlyphsPerCharacterTable( Length numberOfCharacters )
else
{
const Length numberOfZeroGlyphsPerCharacter = ( numberOfCharactersPerGlyph - 1u );
- for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter ; ++zeroIndex )
+ for( Length zeroIndex = 0u; zeroIndex < numberOfZeroGlyphsPerCharacter; ++zeroIndex )
{
- mGlyphsPerCharacter.PushBack( 0u );
+ *glyphsPerCharacterBuffer = 0u;
+
+ // Point to the next position in the buffer.
+ ++glyphsPerCharacterBuffer;
}
- mGlyphsPerCharacter.PushBack( 1u + zeroCharactersPerGlyph );
+ *glyphsPerCharacterBuffer = zeroCharactersPerGlyph + 1u;
zeroCharactersPerGlyph = 0u;
+
+ // Point to the next position in the buffer.
+ ++glyphsPerCharacterBuffer;
}
}
+
+ // If the glyphs per character buffer is updated, it needs to be inserted in the model.
+ if( updateCurrentBuffer )
+ {
+ mGlyphsPerCharacter.Insert( mGlyphsPerCharacter.Begin() + startIndex,
+ newGlyphsPerCharacter.Begin(),
+ newGlyphsPerCharacter.End() );
+ }
}
void VisualModel::GetGlyphs( GlyphInfo* glyphs,
diff --git a/dali-toolkit/internal/text/visual-model-impl.h b/dali-toolkit/internal/text/visual-model-impl.h
index ca579e1..eb2e5a0 100644
--- a/dali-toolkit/internal/text/visual-model-impl.h
+++ b/dali-toolkit/internal/text/visual-model-impl.h
@@ -66,16 +66,20 @@ public:
*
* @pre The glyphs per character table needs to be created first.
*
+ * @param[in] startIndex The character from where the conversion table is created.
* @param[in] numberOfCharacters The number of characters.
*/
- void CreateCharacterToGlyphTable( Length numberOfCharacters = 0u );
+ void CreateCharacterToGlyphTable( CharacterIndex startIndex,
+ Length numberOfCharacters );
/**
* @brief Creates an array containing the number of glyphs per character.
*
+ * @param[in] startIndex The character from where the table is created.
* @param[in] numberOfCharacters The number of characters.
*/
- void CreateGlyphsPerCharacterTable( Length numberOfCharacters = 0u );
+ void CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+ Length numberOfCharacters );
/**
* @brief Retrieves glyphs in the given buffer.
diff --git a/dali-toolkit/public-api/dali-toolkit-version.cpp b/dali-toolkit/public-api/dali-toolkit-version.cpp
index 6189b91..8b743f4 100644
--- a/dali-toolkit/public-api/dali-toolkit-version.cpp
+++ b/dali-toolkit/public-api/dali-toolkit-version.cpp
@@ -31,7 +31,7 @@ namespace Toolkit
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 24;
+const unsigned int TOOLKIT_MICRO_VERSION = 25;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
diff --git a/packaging/dali-toolkit.spec b/packaging/dali-toolkit.spec
index 9e2f459..3be221d 100644
--- a/packaging/dali-toolkit.spec
+++ b/packaging/dali-toolkit.spec
@@ -1,6 +1,6 @@
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.1.24
+Version: 1.1.25
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-2-Clause and MIT