/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * 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.
// CLASS HEADER
#include <dali-toolkit/internal/text/logical-model-impl.h>
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/input-style.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
+
namespace Dali
{
namespace Text
{
+void FreeFontFamilyNames( Vector<FontDescriptionRun>& fontDescriptionRuns )
+{
+ for( Vector<FontDescriptionRun>::Iterator it = fontDescriptionRuns.Begin(),
+ endIt = fontDescriptionRuns.End();
+ it != endIt;
+ ++it )
+ {
+ delete (*it).familyName;
+ }
+
+ fontDescriptionRuns.Clear();
+}
+
LogicalModelPtr LogicalModel::New()
{
return LogicalModelPtr( new LogicalModel() );
{
// If this operation is too slow, consider a binary search.
+ const ScriptRun* const scriptRunBuffer = mScriptRuns.Begin();
for( Length index = 0u, length = mScriptRuns.Count(); index < length; ++index )
{
- const ScriptRun* const scriptRun = mScriptRuns.Begin() + index;
+ const ScriptRun* const scriptRun = scriptRunBuffer + index;
if( ( scriptRun->characterRun.characterIndex <= characterIndex ) &&
( characterIndex < scriptRun->characterRun.characterIndex + scriptRun->characterRun.numberOfCharacters ) )
return *( mCharacterDirections.Begin() + characterIndex );
}
-void LogicalModel::SetVisualToLogicalMap( const BidirectionalLineInfoRun* const bidirectionalInfo,
- Length numberOfRuns )
+CharacterIndex LogicalModel::GetLogicalCursorIndex( CharacterIndex visualCursorIndex )
{
- if( 0u == numberOfRuns )
+ // The character's directions buffer.
+ const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
+
+ // The bidirectional line info.
+ const BidirectionalLineInfoRun* const bidirectionalLineInfo = mBidirectionalLineInfo.Begin() + mBidirectionalLineIndex;
+
+ // Whether the paragraph starts with a right to left character.
+ const bool isRightToLeftParagraph = bidirectionalLineInfo->direction;
+
+ // The total number of characters of the line.
+ const Length lastCharacterIndex = bidirectionalLineInfo->characterRun.characterIndex + bidirectionalLineInfo->characterRun.numberOfCharacters;
+
+ CharacterIndex logicalCursorIndex = 0u;
+
+ if( bidirectionalLineInfo->characterRun.characterIndex == visualCursorIndex )
{
- mVisualToLogicalMap.Clear();
- mLogicalToVisualMap.Clear();
- mVisualToLogicalCursorMap.Clear();
+ if( isRightToLeftParagraph )
+ {
+ logicalCursorIndex = lastCharacterIndex;
+ }
+ else // else logical position is the first of the line.
+ {
+ logicalCursorIndex = bidirectionalLineInfo->characterRun.characterIndex;
+ }
+ }
+ else if( lastCharacterIndex == visualCursorIndex )
+ {
+ if( isRightToLeftParagraph )
+ {
+ logicalCursorIndex = bidirectionalLineInfo->characterRun.characterIndex;
+ }
+ else // else logical position is the number of characters.
+ {
+ logicalCursorIndex = lastCharacterIndex;
+ }
}
else
{
- const Length numberOfCharacters = mText.Count();
- mVisualToLogicalMap.Resize( numberOfCharacters );
- mLogicalToVisualMap.Resize( numberOfCharacters );
+ // Get the character indexed by index - 1 and index
+ // and calculate the logical position according the directions of
+ // both characters and the direction of the paragraph.
- const Length numberOfCharactersPlus = numberOfCharacters + 1u;
- mVisualToLogicalCursorMap.Resize( numberOfCharactersPlus );
+ const CharacterIndex previousVisualCursorIndex = visualCursorIndex - 1u;
+ const CharacterIndex previousLogicalCursorIndex = *( bidirectionalLineInfo->visualToLogicalMap + previousVisualCursorIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
+ const CharacterIndex currentLogicalCursorIndex = *( bidirectionalLineInfo->visualToLogicalMap + visualCursorIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
- CharacterIndex* modelVisualToLogicalMapBuffer = mVisualToLogicalMap.Begin();
- CharacterIndex* modelLogicalToVisualMapBuffer = mLogicalToVisualMap.Begin();
+ const CharacterDirection previousCharacterDirection = *( modelCharacterDirections + previousLogicalCursorIndex );
+ const CharacterDirection currentCharacterDirection = *( modelCharacterDirections + currentLogicalCursorIndex );
- CharacterIndex* modelVisualToLogicalCursorMap = mVisualToLogicalCursorMap.Begin();
-
- CharacterIndex lastIndex = 0u;
- for( unsigned int bidiIndex = 0u; bidiIndex < numberOfRuns; ++bidiIndex )
+ if( previousCharacterDirection == currentCharacterDirection )
{
- const BidirectionalLineInfoRun& bidiLineInfo = *( bidirectionalInfo + bidiIndex );
-
- if( lastIndex < bidiLineInfo.characterRun.characterIndex )
+ // Both glyphs have the same direction.
+ if( previousCharacterDirection )
+ {
+ logicalCursorIndex = previousLogicalCursorIndex;
+ }
+ else
+ {
+ logicalCursorIndex = currentLogicalCursorIndex;
+ }
+ }
+ else
+ {
+ if( isRightToLeftParagraph )
+ {
+ if( currentCharacterDirection )
+ {
+ logicalCursorIndex = currentLogicalCursorIndex + 1u;
+ }
+ else
+ {
+ logicalCursorIndex = previousLogicalCursorIndex;
+ }
+ }
+ else
{
- // Fill with the identity.
- for( ; lastIndex < bidiLineInfo.characterRun.characterIndex; ++lastIndex )
+ if( previousCharacterDirection )
{
- *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+ logicalCursorIndex = currentLogicalCursorIndex;
+ }
+ else
+ {
+ logicalCursorIndex = previousLogicalCursorIndex + 1u;
}
}
+ }
+ }
- // Fill the conversion table of the run.
- for( CharacterIndex index = 0u;
- index < bidiLineInfo.characterRun.numberOfCharacters;
- ++index, ++lastIndex )
+ return logicalCursorIndex;
+}
+
+CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex )
+{
+ // The bidirectional line info.
+ const BidirectionalLineInfoRun* const bidirectionalLineInfo = mBidirectionalLineInfo.Begin() + mBidirectionalLineIndex;
+
+ return *( bidirectionalLineInfo->visualToLogicalMap + visualCharacterIndex - bidirectionalLineInfo->characterRun.characterIndex ) + bidirectionalLineInfo->characterRun.characterIndex;
+}
+
+bool LogicalModel::FetchBidirectionalLineInfo( CharacterIndex characterIndex )
+{
+ // The number of bidirectional lines.
+ const Length numberOfBidirectionalLines = mBidirectionalLineInfo.Count();
+
+ if( 0u == numberOfBidirectionalLines )
+ {
+ // If there is no bidirectional info.
+ return false;
+ }
+
+ // Find the bidi line where the character is laid-out.
+
+ const BidirectionalLineInfoRun* const bidirectionalLineInfoBuffer = mBidirectionalLineInfo.Begin();
+
+ // Check first if the character is in the previously fetched line.
+
+ BidirectionalLineRunIndex bidiLineIndex = 0u;
+ CharacterIndex lastCharacterOfRightToLeftRun = 0u;
+ if( mBidirectionalLineIndex < numberOfBidirectionalLines )
+ {
+ const BidirectionalLineInfoRun& bidiLineRun = *( bidirectionalLineInfoBuffer + mBidirectionalLineIndex );
+
+ const CharacterIndex lastCharacterOfRunPlusOne = bidiLineRun.characterRun.characterIndex + bidiLineRun.characterRun.numberOfCharacters;
+ if( ( bidiLineRun.characterRun.characterIndex <= characterIndex ) &&
+ ( characterIndex < lastCharacterOfRunPlusOne ) )
+ {
+ // The character is in the previously fetched bidi line.
+ return true;
+ }
+ else
+ {
+ // The character is not in the previously fetched line.
+ // Set the bidi line index from where to start the fetch.
+
+ if( characterIndex < bidiLineRun.characterRun.characterIndex )
+ {
+ // Start the fetch from the beginning.
+ bidiLineIndex = 0u;
+ }
+ else
{
- *( modelVisualToLogicalMapBuffer + lastIndex ) = bidiLineInfo.characterRun.characterIndex + *( bidiLineInfo.visualToLogicalMap + index );
+ // Start the fetch from the next line.
+ bidiLineIndex = mBidirectionalLineIndex + 1u;
+ lastCharacterOfRightToLeftRun = lastCharacterOfRunPlusOne - 1u;
}
}
+ }
- // Complete with the identity if there are some left to right characters after the last right to left.
- for( ; lastIndex < numberOfCharacters; ++lastIndex )
+ // The character has not been found in the previously fetched bidi line.
+ for( Vector<BidirectionalLineInfoRun>::ConstIterator it = bidirectionalLineInfoBuffer + bidiLineIndex,
+ endIt = mBidirectionalLineInfo.End();
+ it != endIt;
+ ++it, ++bidiLineIndex )
+ {
+ const BidirectionalLineInfoRun& bidiLineRun = *it;
+
+ if( ( lastCharacterOfRightToLeftRun < characterIndex ) &&
+ ( characterIndex < bidiLineRun.characterRun.characterIndex ) )
{
- *( modelVisualToLogicalMapBuffer + lastIndex ) = lastIndex;
+ // The character is not inside a bidi line.
+ return false;
}
- // Sets the logical to visual conversion map.
- for( CharacterIndex index = 0u; index < numberOfCharacters; ++index )
+ const CharacterIndex lastCharacterOfRunPlusOne = bidiLineRun.characterRun.characterIndex + bidiLineRun.characterRun.numberOfCharacters;
+ lastCharacterOfRightToLeftRun = lastCharacterOfRunPlusOne - 1u;
+ if( ( bidiLineRun.characterRun.characterIndex <= characterIndex ) &&
+ ( characterIndex < lastCharacterOfRunPlusOne ) )
{
- *( modelLogicalToVisualMapBuffer + *( modelVisualToLogicalMapBuffer + index ) ) = index;
+ // Bidi line found. Fetch the line.
+ mBidirectionalLineIndex = bidiLineIndex;
+ return true;
}
+ }
+
+ return false;
+}
+
+BidirectionalLineRunIndex LogicalModel::GetBidirectionalLineInfo() const
+{
+ return mBidirectionalLineIndex;
+}
- // Sets the visual to logical conversion map for cursor positions.
+void LogicalModel::UpdateTextStyleRuns( CharacterIndex index, int numberOfCharacters )
+{
+ const Length totalNumberOfCharacters = mText.Count();
+
+ // Process the color runs.
+ Vector<ColorRun> removedColorRuns;
+ UpdateCharacterRuns<ColorRun>( index,
+ numberOfCharacters,
+ totalNumberOfCharacters,
+ mColorRuns,
+ removedColorRuns );
+
+ // Process the font description runs.
+ Vector<FontDescriptionRun> removedFontDescriptionRuns;
+ UpdateCharacterRuns<FontDescriptionRun>( index,
+ numberOfCharacters,
+ totalNumberOfCharacters,
+ mFontDescriptionRuns,
+ removedFontDescriptionRuns );
+
+ // Free memory allocated for the font family name.
+ FreeFontFamilyNames( removedFontDescriptionRuns );
+}
+
+void LogicalModel::RetrieveStyle( CharacterIndex index, InputStyle& style )
+{
+ unsigned int runIndex = 0u;
+
+ // Set the text color.
+ bool colorOverriden = false;
+ unsigned int colorIndex = 0u;
+ const ColorRun* const colorRunsBuffer = mColorRuns.Begin();
+ for( Vector<ColorRun>::ConstIterator it = colorRunsBuffer,
+ endIt = mColorRuns.End();
+ it != endIt;
+ ++it, ++runIndex )
+ {
+ const ColorRun& colorRun = *it;
- const Length numberOfBidirectionalParagraphs = mBidirectionalParagraphInfo.Count();
- BidirectionalParagraphInfoRun* bidirectionalParagraphInfoBuffer = mBidirectionalParagraphInfo.Begin();
- BidirectionalParagraphInfoRun* bidirectionalParagraph = bidirectionalParagraphInfoBuffer;
+ if( ( colorRun.characterRun.characterIndex <= index ) &&
+ ( index < colorRun.characterRun.characterIndex + colorRun.characterRun.numberOfCharacters ) )
+ {
+ colorIndex = runIndex;
+ colorOverriden = true;
+ }
+ }
+
+ // Set the text's color if it's overriden.
+ if( colorOverriden )
+ {
+ style.textColor = ( *( colorRunsBuffer + colorIndex ) ).color;
+ style.isDefaultColor = false;
+ }
- const CharacterDirection* const modelCharacterDirections = mCharacterDirections.Begin();
+ // Reset the run index.
+ runIndex = 0u;
+
+ // Set the font's parameters.
+ bool nameOverriden = false;
+ bool weightOverriden = false;
+ bool widthOverriden = false;
+ bool slantOverriden = false;
+ bool sizeOverriden = false;
+ unsigned int nameIndex = 0u;
+ unsigned int weightIndex = 0u;
+ unsigned int widthIndex = 0u;
+ unsigned int slantIndex = 0u;
+ unsigned int sizeIndex = 0u;
+ const FontDescriptionRun* const fontDescriptionRunsBuffer = mFontDescriptionRuns.Begin();
+ for( Vector<FontDescriptionRun>::ConstIterator it = fontDescriptionRunsBuffer,
+ endIt = mFontDescriptionRuns.End();
+ it != endIt;
+ ++it, ++runIndex )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *it;
- Length bidirectionalParagraphIndex = 0u;
- bool isRightToLeftParagraph = false;
- for( CharacterIndex index = 0u; index < numberOfCharactersPlus; ++index )
+ if( ( fontDescriptionRun.characterRun.characterIndex <= index ) &&
+ ( index < fontDescriptionRun.characterRun.characterIndex + fontDescriptionRun.characterRun.numberOfCharacters ) )
{
- if( bidirectionalParagraph &&
- ( bidirectionalParagraph->characterRun.characterIndex == index ) )
+ if( fontDescriptionRun.familyDefined )
{
- isRightToLeftParagraph = *( modelCharacterDirections + index );
+ nameIndex = runIndex;
+ nameOverriden = true;
}
- if( 0u == index )
+ if( fontDescriptionRun.weightDefined )
{
- if( isRightToLeftParagraph )
- {
- *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
- }
- else // else logical position is zero.
- {
- *( modelVisualToLogicalCursorMap + index ) = 0u;
- }
+ weightIndex = runIndex;
+ weightOverriden = true;
}
- else if( numberOfCharacters == index )
+
+ if( fontDescriptionRun.widthDefined )
{
- if( isRightToLeftParagraph )
- {
- *( modelVisualToLogicalCursorMap + index ) = 0u;
- }
- else // else logical position is the number of characters.
- {
- *( modelVisualToLogicalCursorMap + index ) = numberOfCharacters;
- }
+ widthIndex = runIndex;
+ widthOverriden = true;
}
- else
+
+ if( fontDescriptionRun.slantDefined )
{
- // Get the character indexed by index - 1 and index
- // and calculate the logical position according the directions of
- // both characters and the direction of the paragraph.
+ slantIndex = runIndex;
+ slantOverriden = true;
+ }
- const CharacterIndex previousIndex = index - 1u;
- const CharacterIndex logicalPosition0 = *( modelVisualToLogicalMapBuffer + previousIndex );
- const CharacterIndex logicalPosition1 = *( modelVisualToLogicalMapBuffer + index );
+ if( fontDescriptionRun.sizeDefined )
+ {
+ sizeIndex = runIndex;
+ sizeOverriden = true;
+ }
+ }
+ }
- const CharacterDirection direction0 = *( modelCharacterDirections + logicalPosition0 );
- const CharacterDirection direction1 = *( modelCharacterDirections + logicalPosition1 );
+ // Set the font's family name if it's overriden.
+ if( nameOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + nameIndex );
- if( direction0 == direction1 )
- {
- // Both glyphs have the same direction.
- if( direction0 )
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
- }
- else
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
- }
- }
- else
- {
- if( isRightToLeftParagraph )
- {
- if( direction1 )
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1 + 1u;
- }
- else
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0;
- }
- }
- else
- {
- if( direction0 )
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition1;
- }
- else
- {
- *( modelVisualToLogicalCursorMap + index ) = logicalPosition0 + 1u;
- }
- }
- }
- }
+ style.familyName = std::string( fontDescriptionRun.familyName, fontDescriptionRun.familyLength );
+ style.isFamilyDefined = true;
+ }
+
+ // Set the font's weight if it's overriden.
+ if( weightOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + weightIndex );
+
+ style.weight = fontDescriptionRun.weight;
+ style.isWeightDefined = true;
+ }
+
+ // Set the font's width if it's overriden.
+ if( widthOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + widthIndex );
+
+ style.width = fontDescriptionRun.width;
+ style.isWidthDefined = true;
+ }
+
+ // Set the font's slant if it's overriden.
+ if( slantOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + slantIndex );
+
+ style.slant = fontDescriptionRun.slant;
+ style.isSlantDefined = true;
+ }
+
+ // Set the font's size if it's overriden.
+ if( sizeOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + sizeIndex );
+
+ style.size = static_cast<float>( fontDescriptionRun.size ) / 64.f;
+ style.isSizeDefined = true;
+ }
+}
+
+void LogicalModel::ClearFontDescriptionRuns()
+{
+ FreeFontFamilyNames( mFontDescriptionRuns );
+}
+
+void LogicalModel::CreateParagraphInfo( CharacterIndex startIndex,
+ Length numberOfCharacters )
+{
+ const Length totalNumberOfCharacters = mLineBreakInfo.Count();
+
+ // Count the number of LINE_MUST_BREAK to reserve some space for the vector of paragraph's info.
+ Vector<CharacterIndex> paragraphs;
+ paragraphs.Reserve( numberOfCharacters );
+ const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = mLineBreakInfo.Begin();
+ const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+ for( Length index = startIndex; index < lastCharacterIndexPlusOne; ++index )
+ {
+ if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
+ {
+ paragraphs.PushBack( index );
+ }
+ }
+
+ // Whether the current paragraphs are updated or set from scratch.
+ const bool updateCurrentParagraphs = numberOfCharacters < totalNumberOfCharacters;
+
+ // Reserve space for current paragraphs plus new ones.
+ const Length numberOfNewParagraphs = paragraphs.Count();
+ const Length totalNumberOfParagraphs = mParagraphInfo.Count() + numberOfNewParagraphs;
+ mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+ ParagraphRun* paragraphInfoBuffer = NULL;
+ Vector<ParagraphRun> newParagraphs;
+
+ if( updateCurrentParagraphs )
+ {
+ newParagraphs.Resize( numberOfNewParagraphs );
+ paragraphInfoBuffer = newParagraphs.Begin();
+ }
+ else
+ {
+ paragraphInfoBuffer = mParagraphInfo.Begin();
+ }
+
+ // Find where to insert the new paragraphs.
+ ParagraphRunIndex paragraphIndex = 0u;
+ CharacterIndex firstIndex = startIndex;
- if( bidirectionalParagraph &&
- ( bidirectionalParagraph->characterRun.characterIndex + bidirectionalParagraph->characterRun.numberOfCharacters == index ) )
+ if( updateCurrentParagraphs )
+ {
+ for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+ endIt = mParagraphInfo.Begin() + totalNumberOfParagraphs - numberOfNewParagraphs;
+ it != endIt;
+ ++it )
+ {
+ const ParagraphRun& paragraph( *it );
+
+ if( startIndex < paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters )
{
- isRightToLeftParagraph = false;
- ++bidirectionalParagraphIndex;
- if( bidirectionalParagraphIndex < numberOfBidirectionalParagraphs )
- {
- bidirectionalParagraph = bidirectionalParagraphInfoBuffer + bidirectionalParagraphIndex;
- }
- else
- {
- bidirectionalParagraph = NULL;
- }
+ firstIndex = paragraph.characterRun.characterIndex;
+ break;
}
+
+ ++paragraphIndex;
+ }
+ }
+
+ // Create the paragraph info.
+ ParagraphRunIndex newParagraphIndex = 0u;
+ for( Vector<CharacterIndex>::ConstIterator it = paragraphs.Begin(),
+ endIt = paragraphs.End();
+ it != endIt;
+ ++it, ++newParagraphIndex )
+ {
+ const CharacterIndex index = *it;
+
+ ParagraphRun& paragraph = *( paragraphInfoBuffer + newParagraphIndex );
+ paragraph.characterRun.characterIndex = firstIndex;
+ paragraph.characterRun.numberOfCharacters = 1u + index - firstIndex;
+
+ firstIndex += paragraph.characterRun.numberOfCharacters;
+ }
+
+
+ // Insert the new paragraphs.
+ if( updateCurrentParagraphs )
+ {
+ mParagraphInfo.Insert( mParagraphInfo.Begin() + paragraphIndex,
+ newParagraphs.Begin(),
+ newParagraphs.End() );
+
+ mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+ // Update the next paragraph indices.
+ for( Vector<ParagraphRun>::Iterator it = mParagraphInfo.Begin() + paragraphIndex + newParagraphs.Count(),
+ endIt = mParagraphInfo.End();
+ it != endIt;
+ ++it )
+ {
+ ParagraphRun& paragraph( *it );
+
+ paragraph.characterRun.characterIndex += numberOfCharacters;
}
}
}
-CharacterIndex LogicalModel::GetLogicalCharacterIndex( CharacterIndex visualCharacterIndex ) const
+void LogicalModel::FindParagraphs( CharacterIndex index,
+ Length numberOfCharacters,
+ Vector<ParagraphRunIndex>& paragraphs )
{
- if( 0u == mVisualToLogicalMap.Count() )
+ // Reserve som space for the paragraph indices.
+ paragraphs.Reserve( mParagraphInfo.Count() );
+
+ // Traverse the paragraphs to find which ones contain the given characters.
+ ParagraphRunIndex paragraphIndex = 0u;
+ for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+ endIt = mParagraphInfo.End();
+ it != endIt;
+ ++it, ++paragraphIndex )
{
- // If there is no visual to logical info is because the whole text is left to right.
- // Return the identity.
- return visualCharacterIndex;
- }
+ const ParagraphRun& paragraph( *it );
- return *( mVisualToLogicalMap.Begin() + visualCharacterIndex );
+ if( ( paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters > index ) &&
+ ( paragraph.characterRun.characterIndex < index + numberOfCharacters ) )
+ {
+ paragraphs.PushBack( paragraphIndex );
+ }
+ }
}
LogicalModel::~LogicalModel()
{
+ ClearFontDescriptionRuns();
}
LogicalModel::LogicalModel()
+: mBidirectionalLineIndex( 0u )
{
}