+ LayoutOptions options;
+ CreateTextModel(data.text,
+ textArea,
+ fontDescriptionRuns,
+ options,
+ layoutSize,
+ textModel,
+ metrics,
+ false,
+ LineWrap::WORD,
+ false,
+ Toolkit::DevelText::EllipsisPosition::END,
+ 0.0f, // lineSpacing
+ 0.0f // characterSpacing
+ );
+
+ LogicalModelPtr logicalModel = textModel->mLogicalModel;
+ VisualModelPtr visualModel = textModel->mVisualModel;
+
+ for(unsigned int index = 0; index < data.numberOfTests; ++index)
+ {
+ bool isCharacterHit = false;
+ const CharacterIndex logicalCursorIndex = GetClosestCursorIndex(visualModel,
+ logicalModel,
+ metrics,
+ data.visualX[index],
+ data.visualY[index],
+ data.mode[index],
+ isCharacterHit);
+
+ if(logicalCursorIndex != data.logicalIndex[index])
+ {
+ std::cout << " test " << index << " failed. Different logical cursor index : " << logicalCursorIndex << ", expected : " << data.logicalIndex[index] << std::endl;
+ return false;
+ }
+ if(isCharacterHit != data.isCharacterHit[index])
+ {
+ std::cout << " test " << index << " failed. Different character hit value : " << isCharacterHit << ", expected : " << data.isCharacterHit[index] << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool GetCursorPositionTest(const GetCursorPositionData& data)
+{
+ std::cout << " testing : " << data.description << std::endl;
+
+ // 1) Create the model.
+ ModelPtr textModel;
+ MetricsPtr metrics;
+ Size textArea(400.f, 600.f);
+ Size layoutSize;
+
+ Vector<FontDescriptionRun> fontDescriptionRuns;
+ LayoutOptions options;
+ CreateTextModel(data.text,
+ textArea,
+ fontDescriptionRuns,
+ options,
+ layoutSize,
+ textModel,
+ metrics,
+ false,
+ LineWrap::WORD,
+ false,
+ Toolkit::DevelText::EllipsisPosition::END,
+ 0.0f, // lineSpacing
+ 0.0f // characterSpacing
+ );
+
+ LogicalModelPtr logicalModel = textModel->mLogicalModel;
+ VisualModelPtr visualModel = textModel->mVisualModel;
+
+ GetCursorPositionParameters parameters;
+ parameters.visualModel = visualModel;
+ parameters.logicalModel = logicalModel;
+ parameters.metrics = metrics;
+ parameters.isMultiline = true;
+
+ for(unsigned int index = 0; index < data.numberOfTests; ++index)
+ {
+ CursorInfo cursorInfo;
+ parameters.logical = data.logicalIndex[index];
+
+ GetCursorPosition(parameters,
+ 0.f, // Since this test case is not testing the primary cursor height, the default font line height can be set to 0.f.
+ cursorInfo);
+
+ if(floor(cursorInfo.primaryPosition.x) != data.visualX[index])
+ {
+ std::cout << " test " << index << " failed. Different 'x' cursor position : " << cursorInfo.primaryPosition.x << ", expected : " << data.visualX[index] << std::endl;
+ return false;
+ }
+ if(floor(cursorInfo.primaryPosition.y) != data.visualY[index])
+ {
+ std::cout << " test " << index << " failed. Different 'y' cursor position : " << cursorInfo.primaryPosition.y << ", expected : " << data.visualY[index] << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool FindSelectionIndicesTest(const FindSelectionIndicesData& data)
+{
+ std::cout << " testing : " << data.description << std::endl;
+
+ // 1) Create the model.
+ ModelPtr textModel;
+ MetricsPtr metrics;
+ Size textArea(400.f, 600.f);
+ Size layoutSize;
+
+ Vector<FontDescriptionRun> fontDescriptionRuns;
+ LayoutOptions options;
+ CreateTextModel(data.text,
+ textArea,
+ fontDescriptionRuns,
+ options,
+ layoutSize,
+ textModel,
+ metrics,
+ false,
+ LineWrap::WORD,
+ false,
+ Toolkit::DevelText::EllipsisPosition::END,
+ 0.0f, // lineSpacing
+ 0.0f // characterSpacing
+ );
+
+ LogicalModelPtr logicalModel = textModel->mLogicalModel;
+ VisualModelPtr visualModel = textModel->mVisualModel;
+
+ for(unsigned int index = 0; index < data.numberOfTests; ++index)
+ {
+ CharacterIndex startIndex = 0;
+ CharacterIndex endIndex = 0;
+ CharacterIndex noTextHitIndex = 0;
+ const bool found = FindSelectionIndices(visualModel,
+ logicalModel,
+ metrics,
+ data.visualX[index],
+ data.visualY[index],
+ startIndex,
+ endIndex,
+ noTextHitIndex);
+
+ if(found != data.found[index])
+ {
+ std::cout << " test " << index << " failed. Different found value : " << found << ", expected : " << data.found[index] << std::endl;
+ return false;
+ }
+ if(startIndex != data.startIndex[index])
+ {
+ std::cout << " test " << index << " failed. Different start index : " << startIndex << ", expected : " << data.startIndex[index] << std::endl;
+ return false;
+ }
+ if(endIndex != data.endIndex[index])
+ {
+ std::cout << " test " << index << " failed. Different end index : " << endIndex << ", expected : " << data.endIndex[index] << std::endl;
+ return false;
+ }
+ if(noTextHitIndex != data.noTextHitIndex[index])
+ {
+ std::cout << " test " << index << " failed. Different no text hit index : " << noTextHitIndex << ", expected : " << data.noTextHitIndex[index] << std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool PrimaryCursorHeightTest(const PrimaryCursorHeightData& data)
+{
+ std::cout << " testing : " << data.description << std::endl;
+
+ // 1) Create the model.
+ ModelPtr textModel;
+ MetricsPtr metrics;
+ Size textArea(400.f, 600.f);
+ Size layoutSize;
+
+ Vector<FontDescriptionRun> fontDescriptionRuns;
+
+ const std::string fontFamily("DejaVuSans");
+
+ // Set a known font description
+ FontDescriptionRun fontDescriptionRun1;
+ fontDescriptionRun1.characterRun.characterIndex = 0u;
+ fontDescriptionRun1.characterRun.numberOfCharacters = 13u;
+ fontDescriptionRun1.familyLength = fontFamily.size();
+ fontDescriptionRun1.familyName = new char[fontDescriptionRun1.familyLength];
+ memcpy(fontDescriptionRun1.familyName, fontFamily.c_str(), fontDescriptionRun1.familyLength);
+ fontDescriptionRun1.familyDefined = true;
+ fontDescriptionRun1.weightDefined = false;
+ fontDescriptionRun1.widthDefined = false;
+ fontDescriptionRun1.slantDefined = false;
+ fontDescriptionRun1.sizeDefined = true;
+ fontDescriptionRun1.size = 768u; //Font size = 12.0f (768/64 = 12)
+
+ fontDescriptionRuns.PushBack(fontDescriptionRun1);
+