X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Fshaper.cpp;h=de41d0e2961529d773108573394d0156dd272871;hp=8e2eed1cc120b6507c844020ad3cee4e13629132;hb=528aa3699cd51dab5115bca1aaebb65d4bc67c15;hpb=f3cd2c3c30817bbb889e8ba8ce6b1106a1617e82 diff --git a/dali-toolkit/internal/text/shaper.cpp b/dali-toolkit/internal/text/shaper.cpp old mode 100644 new mode 100755 index 8e2eed1..de41d0e --- a/dali-toolkit/internal/text/shaper.cpp +++ b/dali-toolkit/internal/text/shaper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -19,14 +19,7 @@ #include // EXTERNAL INCLUDES -#include -#include - -// INTERNAL INCLUDES -#include -#include -#include -#include +#include namespace Dali { @@ -47,12 +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& charactersPerGlyph, + Vector& newParagraphGlyphs ) { - const Length numberOfCharacters = text.Count(); - if( 0u == numberOfCharacters ) { // Nothing to do if there are no characters. @@ -62,25 +57,48 @@ 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. // Each chunk must contain characters with the same font id and script set. - // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk have to be created. + // A chunk of consecutive characters must not contain a LINE_MUST_BREAK, if there is one a new chunk has to be created. 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; @@ -93,20 +111,29 @@ 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 ); + GlyphInfo glyphInfo; + glyphInfo.isItalicRequired = false; + glyphInfo.isBoldRequired = false; + + const Length currentNumberOfGlyphs = glyphs.Count(); + const Length numberOfGlyphsReserved = static_cast( numberOfCharacters * 1.3f ); + glyphs.Reserve( currentNumberOfGlyphs + numberOfGlyphsReserved ); + glyphToCharacterMap.Reserve( currentNumberOfGlyphs + numberOfGlyphsReserved ); // The actual number of glyphs. - Length totalNumberOfGlyphs = 0u; + Length totalNumberOfGlyphs = currentNumberOfGlyphs; + // The number of new glyphs. + Length numberOfNewGlyphs = 0u; - const Character* textBuffer = text.Begin(); - const LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); - GlyphInfo* glyphsBuffer = glyphs.Begin(); + const Character* const textBuffer = text.Begin(); + const LineBreakInfo* const lineBreakInfoBuffer = lineBreakInfo.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; @@ -114,6 +141,8 @@ void ShapeText( const Vector& text, currentFontId = fontRun.fontId; currentScript = scriptRun.script; + const bool isItalicRequired = fontRun.isItalicRequired; + const bool isBoldRequired = fontRun.isBoldRequired; // Get the min index to the last character of both runs. CharacterIndex currentIndex = min( fontRun.characterRun.characterIndex + fontRun.characterRun.numberOfCharacters, @@ -121,75 +150,69 @@ void ShapeText( const Vector& text, // Check if there is a line must break. bool mustBreak = false; + + // Check if the current index is a new paragraph character. + // A new paragraph character is going to be shaped in order to not to mess the conversion tables. + // However, the metrics need to be changed in order to not to draw a square. + bool isNewParagraph = false; + for( CharacterIndex index = previousIndex; index < currentIndex; ++index ) { mustBreak = TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ); if( mustBreak ) { - currentIndex = index; + isNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + index ) ); + currentIndex = index + 1u; break; } } - // Check if the current index is a new paragraph character. - // A \n is going to be shaped in order to not to mess the conversion tables. - // After the \n character is shaped, the glyph is going to be reset to its - // default in order to not to get any metric or font index for it. - const bool isNewParagraph = TextAbstraction::IsNewParagraph( *( textBuffer + currentIndex ) ); - - // The last character is always a must-break even if it's not a \n. - Length numberOfCharactersToShape = currentIndex - previousIndex; - if( mustBreak ) - { - // Add one more character to shape. - ++numberOfCharactersToShape; - } - // Shape the text for the current chunk. const Length numberOfGlyphs = shaping.Shape( textBuffer + previousIndex, - numberOfCharactersToShape, + ( currentIndex - previousIndex ), // The number of characters to shape. currentFontId, currentScript ); - const Length glyphIndex = totalNumberOfGlyphs; - totalNumberOfGlyphs += numberOfGlyphs; + // Retrieve the glyphs and the glyph to character conversion map. + Vector tmpGlyphs; + Vector tmpGlyphToCharacterMap; - if( totalNumberOfGlyphs > numberOfGlyphsReserved ) - { - // 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(); - } + GlyphInfo glyphInfo; + glyphInfo.isItalicRequired = isItalicRequired; + glyphInfo.isBoldRequired = isBoldRequired; - // Retrieve the glyphs and the glyph to character conversion map. - shaping.GetGlyphs( glyphsBuffer + glyphIndex, - glyphToCharacterMapBuffer + glyphIndex ); + tmpGlyphs.Resize( numberOfGlyphs, glyphInfo ); + tmpGlyphToCharacterMap.Resize( numberOfGlyphs ); + shaping.GetGlyphs( tmpGlyphs.Begin(), + tmpGlyphToCharacterMap.Begin() ); - if( isNewParagraph ) + // Update the new indices of the glyph to character map. + if( 0u != totalNumberOfGlyphs ) { - // TODO : This is a work around to avoid drawing a square in the - // place of a new line character. + for( Vector::Iterator it = tmpGlyphToCharacterMap.Begin(), + endIt = tmpGlyphToCharacterMap.End(); + it != endIt; + ++it ) + { + *it += previousIndex; + } + } - // If the last character is a \n, it resets the glyph to the default - // to avoid getting any metric for it. - GlyphInfo& glyph = *( glyphsBuffer + glyphIndex + ( numberOfGlyphs - 1u ) ); + totalNumberOfGlyphs += numberOfGlyphs; + numberOfNewGlyphs += numberOfGlyphs; - glyph = GlyphInfo(); - } + 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(); - // Update indices. - if( 0u != glyphIndex ) + if( isNewParagraph ) { - for( Length index = glyphIndex; index < glyphIndex + numberOfGlyphs; ++index ) - { - CharacterIndex& characterIndex = *( glyphToCharacterMapBuffer + index ); - characterIndex += previousIndex; - } + // Add the index of the new paragraph glyph to a vector. + // Their metrics will be updated in a following step. + newParagraphGlyphs.PushBack( glyphIndex - 1u ); } // Update the iterators to get the next font or script run. @@ -202,37 +225,38 @@ void ShapeText( const Vector& text, ++scriptRunIt; } - // Update the previous index. Jumps the \n if needed. - previousIndex = mustBreak ? currentIndex + 1u : currentIndex; + // Update the previous index. + 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 ); glyphToCharacterMap.Resize( totalNumberOfGlyphs ); } -void ShapeText( const LogicalModel& logicalModel, - VisualModel& visualModel, - CharacterIndex characterIndex, - Length numberOfCharactersToRemove, - Length numberOfCharactersToInsert ) -{ -} - } // namespace Text } // namespace Toolkit