+
+ // 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;
+
+ if( ( fontDescriptionRun.characterRun.characterIndex <= index ) &&
+ ( index < fontDescriptionRun.characterRun.characterIndex + fontDescriptionRun.characterRun.numberOfCharacters ) )
+ {
+ if( fontDescriptionRun.familyDefined )
+ {
+ nameIndex = runIndex;
+ nameOverriden = true;
+ }
+
+ if( fontDescriptionRun.weightDefined )
+ {
+ weightIndex = runIndex;
+ weightOverriden = true;
+ }
+
+ if( fontDescriptionRun.widthDefined )
+ {
+ widthIndex = runIndex;
+ widthOverriden = true;
+ }
+
+ if( fontDescriptionRun.slantDefined )
+ {
+ slantIndex = runIndex;
+ slantOverriden = true;
+ }
+
+ if( fontDescriptionRun.sizeDefined )
+ {
+ sizeIndex = runIndex;
+ sizeOverriden = true;
+ }
+ }
+ }
+
+ // Set the font's family name if it's overriden.
+ if( nameOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + nameIndex );
+
+ style.familyName = std::string( fontDescriptionRun.familyName, fontDescriptionRun.familyLength );
+ style.familyDefined = true;
+ }
+
+ // Set the font's weight if it's overriden.
+ if( weightOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + weightIndex );
+
+ style.weight = fontDescriptionRun.weight;
+ style.weightDefined = true;
+ }
+
+ // Set the font's width if it's overriden.
+ if( widthOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + widthIndex );
+
+ style.width = fontDescriptionRun.width;
+ style.widthDefined = true;
+ }
+
+ // Set the font's slant if it's overriden.
+ if( slantOverriden )
+ {
+ const FontDescriptionRun& fontDescriptionRun = *( fontDescriptionRunsBuffer + slantIndex );
+
+ style.slant = fontDescriptionRun.slant;
+ style.slantDefined = 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.sizeDefined = true;
+ }
+
+ // Reset the run index.
+ runIndex = 0u;
+}
+
+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( 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 )
+ {
+ 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;
+ }
+ }
+}
+
+void LogicalModel::FindParagraphs( CharacterIndex index,
+ Length numberOfCharacters,
+ Vector<ParagraphRunIndex>& paragraphs )
+{
+ // 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 )
+ {
+ const ParagraphRun& paragraph( *it );
+
+ if( ( paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters > index ) &&
+ ( paragraph.characterRun.characterIndex < index + numberOfCharacters ) )
+ {
+ paragraphs.PushBack( paragraphIndex );
+ }
+ }