X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Ftext-controller-impl.cpp;h=3fe3322af8f2372033c4e87a6a4e78f1ec304d65;hp=ec00903e4629998a6cb693e63ec79979b03cc116;hb=2daa5af9afa208c6e58b5a69ff304b513777aa63;hpb=2ca1c3856ce848a94f54444f1014a820e91ee207 diff --git a/dali-toolkit/internal/text/text-controller-impl.cpp b/dali-toolkit/internal/text/text-controller-impl.cpp index ec00903..3fe3322 100644 --- a/dali-toolkit/internal/text/text-controller-impl.cpp +++ b/dali-toolkit/internal/text/text-controller-impl.cpp @@ -29,11 +29,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include @@ -57,6 +60,14 @@ struct BackgroundMesh Vector mIndices; ///< container of indices }; +// The relative luminance of a color is defined as (L = 0.2126 * R + 0.7152 * G + 0.0722 * B) +// based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) +const float BRIGHTNESS_THRESHOLD = 0.179f; +const float CONSTANT_R = 0.2126f; +const float CONSTANT_G = 0.7152f; +const float CONSTANT_B = 0.0722f; +const Dali::Vector4 BLACK(0.f, 0.f, 0.f, 1.f); +const Dali::Vector4 WHITE(1.f, 1.f, 1.f, 1.f); const Dali::Vector4 LIGHT_BLUE(0.75f, 0.96f, 1.f, 1.f); const Dali::Vector4 BACKGROUND_SUB4(0.58f, 0.87f, 0.96f, 1.f); const Dali::Vector4 BACKGROUND_SUB5(0.83f, 0.94f, 0.98f, 1.f); @@ -74,7 +85,7 @@ namespace Text EventData::EventData(DecoratorPtr decorator, InputMethodContext& inputMethodContext) : mDecorator(decorator), mInputMethodContext(inputMethodContext), - mPlaceholderFont(NULL), + mPlaceholderFont(nullptr), mPlaceholderTextActive(), mPlaceholderTextInactive(), mPlaceholderTextColor(0.8f, 0.8f, 0.8f, 0.8f), // This color has been published in the Public API (placeholder-properties.h). @@ -587,7 +598,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) Vector& srcCharacters = mModel->mLogicalModel->mText; Vector displayCharacters; bool useHiddenText = false; - if(mHiddenInput && mEventData != NULL && !mEventData->mIsShowingPlaceholderText) + if(mHiddenInput && mEventData != nullptr && !mEventData->mIsShowingPlaceholderText) { mHiddenInput->Substitute(srcCharacters, displayCharacters); useHiddenText = true; @@ -661,6 +672,39 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) requestedNumberOfCharacters, lineBreakInfo); + if(mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::HYPHENATION) || + mModel->mLineWrapMode == ((Text::LineWrap::Mode)DevelText::LineWrap::MIXED)) + { + CharacterIndex end = startIndex + requestedNumberOfCharacters; + LineBreakInfo* lineBreakInfoBuffer = lineBreakInfo.Begin(); + + for(CharacterIndex index = startIndex; index < end; index++) + { + CharacterIndex wordEnd = index; + while((*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_ALLOW_BREAK) && (*(lineBreakInfoBuffer + wordEnd) != TextAbstraction::LINE_MUST_BREAK)) + { + wordEnd++; + } + + if((wordEnd + 1) == end) // add last char + { + wordEnd++; + } + + Vector hyphens = GetWordHyphens(utf32Characters.Begin() + index, wordEnd - index, nullptr); + + for(CharacterIndex i = 0; i < (wordEnd - index); i++) + { + if(hyphens[i]) + { + *(lineBreakInfoBuffer + index + i) = TextAbstraction::LINE_HYPHENATION_BREAK; + } + } + + index = wordEnd; + } + } + // Create the paragraph info. mModel->mLogicalModel->CreateParagraphInfo(startIndex, requestedNumberOfCharacters); @@ -697,27 +741,30 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) TextAbstraction::FontDescription defaultFontDescription; TextAbstraction::PointSize26Dot6 defaultPointSize = TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale; - if(IsShowingPlaceholderText() && mEventData && (NULL != mEventData->mPlaceholderFont)) + //Get the number of points per one unit of point-size + uint32_t numberOfPointsPerOneUnitOfPointSize = mFontClient.GetNumberOfPointsPerOneUnitOfPointSize(); + + if(IsShowingPlaceholderText() && mEventData && (nullptr != mEventData->mPlaceholderFont)) { // If the placeholder font is set specifically, only placeholder font is changed. defaultFontDescription = mEventData->mPlaceholderFont->mFontDescription; if(mEventData->mPlaceholderFont->sizeDefined) { - defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * 64u; + defaultPointSize = mEventData->mPlaceholderFont->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; } } - else if(NULL != mFontDefaults) + else if(nullptr != mFontDefaults) { // Set the normal font and the placeholder font. defaultFontDescription = mFontDefaults->mFontDescription; if(mTextFitEnabled) { - defaultPointSize = mFontDefaults->mFitPointSize * 64u; + defaultPointSize = mFontDefaults->mFitPointSize * numberOfPointsPerOneUnitOfPointSize; } else { - defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * 64u; + defaultPointSize = mFontDefaults->mDefaultPointSize * mFontSizeScale * numberOfPointsPerOneUnitOfPointSize; } } @@ -750,7 +797,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) startIndex, requestedNumberOfCharacters, bidirectionalInfo, - mModel->mMatchSystemLanguageDirection, + (mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS), mLayoutDirection); if(0u != bidirectionalInfo.Count()) @@ -807,6 +854,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) // Create the 'number of glyphs' per character and the glyph to character conversion tables. mModel->mVisualModel->CreateGlyphsPerCharacterTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); mModel->mVisualModel->CreateCharacterToGlyphTable(startIndex, mTextUpdateInfo.mStartGlyphIndex, requestedNumberOfCharacters); + updated = true; } @@ -830,7 +878,7 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) updated = true; } - if((NULL != mEventData) && + if((nullptr != mEventData) && mEventData->mPreEditFlag && (0u != mModel->mVisualModel->mCharactersToGlyph.Count())) { @@ -858,6 +906,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::REVERSE: @@ -869,15 +923,36 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) backgroundColorRun.color = textColor; mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); - Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor(); + Vector4 backgroundColor = mModel->mVisualModel->GetBackgroundColor(); + if(backgroundColor.a == 0) // There is no text background color. + { + // Try use the control's background color. + if(nullptr != mEditableControlInterface) + { + mEditableControlInterface->GetControlBackgroundColor(backgroundColor); + if(backgroundColor.a == 0) // There is no control background color. + { + // Determines black or white color according to text color. + // Based on W3C Recommendations (https://www.w3.org/TR/WCAG20/) + float L = CONSTANT_R * textColor.r + CONSTANT_G * textColor.g + CONSTANT_B * textColor.b; + backgroundColor = L > BRIGHTNESS_THRESHOLD ? BLACK : WHITE; + } + } + } + Vector colorRuns; colorRuns.Resize(1u); ColorRun& colorRun = *(colorRuns.Begin()); colorRun.color = backgroundColor; colorRun.characterRun.characterIndex = attrData.startIndex + numberOfCommit; colorRun.characterRun.numberOfCharacters = numberOfIndices; - mModel->mLogicalModel->mColorRuns.PushBack(colorRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::HIGHLIGHT: @@ -887,6 +962,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) backgroundColorRun.characterRun.numberOfCharacters = numberOfIndices; backgroundColorRun.color = LIGHT_BLUE; mModel->mLogicalModel->mBackgroundColorRuns.PushBack(backgroundColorRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_1: @@ -902,6 +983,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_2: @@ -917,6 +1004,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_3: @@ -932,6 +1025,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::CUSTOM_PLATFORM_STYLE_4: @@ -947,6 +1046,12 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) underlineRun.glyphIndex = attrData.startIndex + numberOfCommit; underlineRun.numberOfGlyphs = numberOfIndices; mModel->mVisualModel->mUnderlineRuns.PushBack(underlineRun); + + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(false); + } break; } case Dali::InputMethodContext::PreeditStyle::NONE: @@ -985,6 +1090,20 @@ bool Controller::Impl::UpdateModel(OperationsMask operationsRequired) updated = true; } + if((NO_OPERATION != (SHAPE_TEXT & operations)) && + !((nullptr != mEventData) && + mEventData->mPreEditFlag && + (0u != mModel->mVisualModel->mCharactersToGlyph.Count()))) + { + //Mark-up processor case + if(mModel->mVisualModel->IsMarkupProcessorEnabled()) + { + CopyUnderlinedFromLogicalToVisualModels(true); + } + + updated = true; + } + // The estimated number of lines. Used to avoid reallocations when layouting. mTextUpdateInfo.mEstimatedNumberOfLines = std::max(mModel->mVisualModel->mLines.Count(), mModel->mLogicalModel->mParagraphInfo.Count()); @@ -1064,7 +1183,7 @@ void Controller::Impl::RetrieveDefaultInputStyle(InputStyle& inputStyle) float Controller::Impl::GetDefaultFontLineHeight() { FontId defaultFontId = 0u; - if(NULL == mFontDefaults) + if(nullptr == mFontDefaults) { TextAbstraction::FontDescription fontDescription; defaultFontId = mFontClient.GetFontId(fontDescription, TextAbstraction::FontClient::DEFAULT_POINT_SIZE * mFontSizeScale); @@ -1126,7 +1245,7 @@ CharacterIndex Controller::Impl::GetPrimaryCursorPosition() const return mEventData->mPrimaryCursorPosition; } -bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index) +bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index, bool focused) { if(nullptr == mEventData) { @@ -1142,10 +1261,14 @@ bool Controller::Impl::SetPrimaryCursorPosition(CharacterIndex index) uint32_t length = static_cast(mModel->mLogicalModel->mText.Count()); mEventData->mPrimaryCursorPosition = std::min(index, length); - ChangeState(EventData::EDITING); - mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition; - mEventData->mUpdateCursorPosition = true; - ScrollTextToMatchCursor(); + // If there is no focus, only the value is updated. + if(focused) + { + ChangeState(EventData::EDITING); + mEventData->mLeftSelectionPosition = mEventData->mRightSelectionPosition = mEventData->mPrimaryCursorPosition; + mEventData->mUpdateCursorPosition = true; + ScrollTextToMatchCursor(); + } return true; } @@ -1384,7 +1507,7 @@ void Controller::Impl::SetPopupButtons() void Controller::Impl::ChangeState(EventData::State newState) { - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. return; @@ -1618,7 +1741,7 @@ void Controller::Impl::GetCursorPosition(CharacterIndex logical, cursorInfo.primaryCursorHeight = cursorInfo.lineHeight; bool isRTL = false; - if(mModel->mMatchSystemLanguageDirection) + if(mModel->mMatchLayoutDirection != DevelText::MatchLayoutDirection::CONTENTS) { isRTL = mLayoutDirection == LayoutDirection::RIGHT_TO_LEFT; } @@ -1700,7 +1823,7 @@ void Controller::Impl::GetCursorPosition(CharacterIndex logical, CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) const { - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. return 0u; @@ -1750,7 +1873,7 @@ CharacterIndex Controller::Impl::CalculateNewCursorIndex(CharacterIndex index) c void Controller::Impl::UpdateCursorPosition(const CursorInfo& cursorInfo) { DALI_LOG_INFO(gLogFilter, Debug::Verbose, "-->Controller::UpdateCursorPosition %p\n", this); - if(NULL == mEventData) + if(nullptr == mEventData) { // Nothing to do if there is no text input. DALI_LOG_INFO(gLogFilter, Debug::Verbose, "<--Controller::UpdateCursorPosition no event data\n"); @@ -1925,7 +2048,7 @@ void Controller::Impl::ScrollTextToMatchCursor() void Controller::Impl::RequestRelayout() { - if(NULL != mControlInterface) + if(nullptr != mControlInterface) { mControlInterface->RequestTextRelayout(); } @@ -1933,8 +2056,7 @@ void Controller::Impl::RequestRelayout() Actor Controller::Impl::CreateBackgroundActor() { - // NOTE: Currently we only support background color for one line left-to-right text, - // so the following calculation is based on one line left-to-right text only! + // NOTE: Currently we only support background color for left-to-right text. Actor actor; @@ -1975,8 +2097,12 @@ Actor Controller::Impl::CreateBackgroundActor() const ColorIndex* const backgroundColorIndicesBuffer = mView.GetBackgroundColorIndices(); const Vector4& defaultBackgroundColor = mModel->mVisualModel->IsBackgroundEnabled() ? mModel->mVisualModel->GetBackgroundColor() : Color::TRANSPARENT; - Vector4 quad; - uint32_t numberOfQuads = 0u; + Vector4 quad; + uint32_t numberOfQuads = 0u; + Length yLineOffset = 0; + Length prevLineIndex = 0; + LineIndex lineIndex; + Length numberOfLines; for(uint32_t i = 0, glyphSize = glyphs.Size(); i < glyphSize; ++i) { @@ -1984,8 +2110,18 @@ Actor Controller::Impl::CreateBackgroundActor() // Get the background color of the character. // The color index zero is reserved for the default background color (i.e. Color::TRANSPARENT) - const ColorIndex backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + i); - const Vector4& backgroundColor = (0u == backgroundColorIndex) ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u); + const bool isMarkupBackground = mView.IsMarkupBackgroundColorSet(); + const ColorIndex backgroundColorIndex = isMarkupBackground ? *(backgroundColorIndicesBuffer + i) : 0u; + const bool isDefaultBackgroundColor = (0u == backgroundColorIndex); + const Vector4& backgroundColor = isDefaultBackgroundColor ? defaultBackgroundColor : *(backgroundColorsBuffer + backgroundColorIndex - 1u); + + mModel->mVisualModel->GetNumberOfLines(i, 1, lineIndex, numberOfLines); + Length lineHeight = lineRun[lineIndex].ascender + -(lineRun[lineIndex].descender) + lineRun[lineIndex].lineSpacing; + + if(lineIndex != prevLineIndex) + { + yLineOffset += lineHeight; + } // Only create quads for glyphs with a background color if(backgroundColor != Color::TRANSPARENT) @@ -1995,30 +2131,30 @@ Actor Controller::Impl::CreateBackgroundActor() if(i == 0u && glyphSize == 1u) // Only one glyph in the whole text { quad.x = position.x; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = textSize.height; + quad.w = lineHeight; } - else if(i == 0u) // The first glyph in the whole text + else if((lineIndex != prevLineIndex) || (i == 0u)) // The first glyph in the line { quad.x = position.x; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x - glyph.xBearing + glyph.advance; - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } else if(i == glyphSize - 1u) // The last glyph in the whole text { quad.x = position.x - glyph.xBearing; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + std::max(glyph.advance, glyph.xBearing + glyph.width); - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } else // The glyph in the middle of the text { quad.x = position.x - glyph.xBearing; - quad.y = 0.0f; + quad.y = yLineOffset; quad.z = quad.x + glyph.advance; - quad.w = textSize.height; + quad.w = quad.y + lineHeight; } BackgroundVertex vertex; @@ -2057,6 +2193,11 @@ Actor Controller::Impl::CreateBackgroundActor() numberOfQuads++; } + + if(lineIndex != prevLineIndex) + { + prevLineIndex = lineIndex; + } } // Only create the background actor if there are glyphs with background color @@ -2095,6 +2236,32 @@ Actor Controller::Impl::CreateBackgroundActor() return actor; } +void Controller::Impl::CopyUnderlinedFromLogicalToVisualModels(bool shouldClearPreUnderlineRuns) +{ + //Underlined character runs for markup-processor + const Vector& underlinedCharacterRuns = mModel->mLogicalModel->mUnderlinedCharacterRuns; + const Vector& charactersToGlyph = mModel->mVisualModel->mCharactersToGlyph; + const Vector& glyphsPerCharacter = mModel->mVisualModel->mGlyphsPerCharacter; + + if(shouldClearPreUnderlineRuns) + { + mModel->mVisualModel->mUnderlineRuns.Clear(); + } + + for(Vector::ConstIterator it = underlinedCharacterRuns.Begin(), endIt = underlinedCharacterRuns.End(); it != endIt; ++it) + { + CharacterIndex characterIndex = it->characterRun.characterIndex; + Length numberOfCharacters = it->characterRun.numberOfCharacters; + for(Length index = 0u; index < numberOfCharacters; index++) + { + GlyphRun underlineGlyphRun; + underlineGlyphRun.glyphIndex = charactersToGlyph[characterIndex + index]; + underlineGlyphRun.numberOfGlyphs = glyphsPerCharacter[characterIndex + index]; + mModel->mVisualModel->mUnderlineRuns.PushBack(underlineGlyphRun); + } + } +} + } // namespace Text } // namespace Toolkit