X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali-toolkit%2Finternal%2Ftext%2Frendering%2Ftext-typesetter.cpp;h=6fadaed32e01b8cd5c9b0562c22895176252a665;hb=8f2687c154d9fc859c58e5ee2fb42a18f9fe6e78;hp=40d96b847def2d645b0cec92a8eb099dd5f14206;hpb=1aa4664f4f29a1de0f5ee55630b753b81a83d089;p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git diff --git a/dali-toolkit/internal/text/rendering/text-typesetter.cpp b/dali-toolkit/internal/text/rendering/text-typesetter.cpp index 40d96b8..6fadaed 100644 --- a/dali-toolkit/internal/text/rendering/text-typesetter.cpp +++ b/dali-toolkit/internal/text/rendering/text-typesetter.cpp @@ -417,6 +417,116 @@ void DrawBackgroundColor( } } +Devel::PixelBuffer DrawGlyphsBackground(const ViewModel* model, Devel::PixelBuffer& buffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, int horizontalOffset, int verticalOffset) +{ + // Retrieve lines, glyphs, positions and colors from the view model. + const Length modelNumberOfLines = model->GetNumberOfLines(); + const LineRun* const modelLinesBuffer = model->GetLines(); + const Length numberOfGlyphs = model->GetNumberOfGlyphs(); + const GlyphInfo* const glyphsBuffer = model->GetGlyphs(); + const Vector2* const positionBuffer = model->GetLayout(); + const Vector4* const backgroundColorsBuffer = model->GetBackgroundColors(); + const ColorIndex* const backgroundColorIndicesBuffer = model->GetBackgroundColorIndices(); + + // Create and initialize the pixel buffer. + GlyphData glyphData; + glyphData.verticalOffset = verticalOffset; + glyphData.width = bufferWidth; + glyphData.height = bufferHeight; + glyphData.bitmapBuffer = buffer; + glyphData.horizontalOffset = 0; + + ColorIndex prevBackgroundColorIndex = 0; + ColorIndex backgroundColorIndex = 0; + + // Traverses the lines of the text. + for(LineIndex lineIndex = 0u; lineIndex < modelNumberOfLines; ++lineIndex) + { + const LineRun& line = *(modelLinesBuffer + lineIndex); + + // Sets the horizontal offset of the line. + glyphData.horizontalOffset = ignoreHorizontalAlignment ? 0 : static_cast(line.alignmentOffset); + glyphData.horizontalOffset += horizontalOffset; + + // Increases the vertical offset with the line's ascender. + glyphData.verticalOffset += static_cast(line.ascender); + + // Include line spacing after first line + if(lineIndex > 0u) + { + glyphData.verticalOffset += static_cast(line.lineSpacing); + } + + float left = bufferWidth; + float right = 0.0f; + float baseline = 0.0f; + + // Traverses the glyphs of the line. + const GlyphIndex endGlyphIndex = std::min(numberOfGlyphs, line.glyphRun.glyphIndex + line.glyphRun.numberOfGlyphs); + for(GlyphIndex glyphIndex = line.glyphRun.glyphIndex; glyphIndex < endGlyphIndex; ++glyphIndex) + { + // Retrieve the glyph's info. + const GlyphInfo* const glyphInfo = glyphsBuffer + glyphIndex; + + if((glyphInfo->width < Math::MACHINE_EPSILON_1000) || + (glyphInfo->height < Math::MACHINE_EPSILON_1000)) + { + // Nothing to do if default background color, the glyph's width or height is zero. + continue; + } + + backgroundColorIndex = (nullptr == backgroundColorsBuffer) ? 0u : *(backgroundColorIndicesBuffer + glyphIndex); + + if((backgroundColorIndex != prevBackgroundColorIndex) && + (prevBackgroundColorIndex != 0u)) + { + const Vector4& backgroundColor = *(backgroundColorsBuffer + prevBackgroundColorIndex - 1u); + DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right); + } + + if(backgroundColorIndex == 0u) + { + prevBackgroundColorIndex = backgroundColorIndex; + //if background color is the default do nothing + continue; + } + + // Retrieves the glyph's position. + const Vector2* const position = positionBuffer + glyphIndex; + + if(baseline < position->y + glyphInfo->yBearing) + { + baseline = position->y + glyphInfo->yBearing; + } + + // Calculate the positions of leftmost and rightmost glyphs in the current line + if((position->x < left) || (backgroundColorIndex != prevBackgroundColorIndex)) + { + left = position->x - glyphInfo->xBearing; + } + + if(position->x + glyphInfo->width > right) + { + right = position->x - glyphInfo->xBearing + glyphInfo->advance; + } + + prevBackgroundColorIndex = backgroundColorIndex; + } + + //draw last background at line end if not default + if(backgroundColorIndex != 0u) + { + const Vector4& backgroundColor = *(backgroundColorsBuffer + backgroundColorIndex - 1u); + DrawBackgroundColor(backgroundColor, bufferWidth, bufferHeight, glyphData, baseline, line, left, right); + } + + // Increases the vertical offset with the line's descender. + glyphData.verticalOffset += static_cast(-line.descender); + } + + return glyphData.bitmapBuffer; +} + } // namespace TypesetterPtr Typesetter::New(const ModelInterface* const model) @@ -429,6 +539,24 @@ ViewModel* Typesetter::GetViewModel() return mModel; } +Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, const unsigned int bufferHeight, Pixel::Format pixelFormat) +{ + Devel::PixelBuffer imageBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat); + + if(Pixel::RGBA8888 == pixelFormat) + { + const unsigned int bufferSizeInt = bufferWidth * bufferHeight; + const unsigned int bufferSizeChar = 4u * bufferSizeInt; + memset(imageBuffer.GetBuffer(), 0u, bufferSizeChar); + } + else + { + memset(imageBuffer.GetBuffer(), 0, bufferWidth * bufferHeight); + } + + return imageBuffer; +} + PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirection::Type textDirection, RenderBehaviour behaviour, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat) { // @todo. This initial implementation for a TextLabel has only one visible page. @@ -587,10 +715,25 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect } // Generate the background if enabled - const bool backgroundEnabled = mModel->IsBackgroundEnabled(); - if(backgroundEnabled) + const bool backgroundEnabled = mModel->IsBackgroundEnabled(); + const bool backgroundMarkupSet = mModel->IsMarkupBackgroundColorSet(); + if(backgroundEnabled || backgroundMarkupSet) { - Devel::PixelBuffer backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1); + Devel::PixelBuffer backgroundImageBuffer; + + if(backgroundEnabled) + { + backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_BACKGROUND, ignoreHorizontalAlignment, pixelFormat, penX, penY, 0u, numberOfGlyphs - 1); + } + else + { + backgroundImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat); + } + + if(backgroundMarkupSet) + { + DrawGlyphsBackground(mModel, backgroundImageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, penX, penY); + } // Combine the two buffers imageBuffer = CombineImageBuffer(imageBuffer, backgroundImageBuffer, bufferWidth, bufferHeight); @@ -599,7 +742,6 @@ PixelData Typesetter::Render(const Vector2& size, Toolkit::DevelText::TextDirect // Markup-Processor imageBuffer = ApplyMarkupProcessorOnPixelBuffer(imageBuffer, bufferWidth, bufferHeight, ignoreHorizontalAlignment, pixelFormat, penX, penY); - } // Create the final PixelData for the combined image buffer @@ -631,20 +773,9 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, glyphData.verticalOffset = verticalOffset; glyphData.width = bufferWidth; glyphData.height = bufferHeight; - glyphData.bitmapBuffer = Devel::PixelBuffer::New(bufferWidth, bufferHeight, pixelFormat); + glyphData.bitmapBuffer = CreateImageBuffer(bufferWidth, bufferHeight, pixelFormat); glyphData.horizontalOffset = 0; - if(Pixel::RGBA8888 == pixelFormat) - { - const unsigned int bufferSizeInt = bufferWidth * bufferHeight; - const unsigned int bufferSizeChar = 4u * bufferSizeInt; - memset(glyphData.bitmapBuffer.GetBuffer(), 0u, bufferSizeChar); - } - else - { - memset(glyphData.bitmapBuffer.GetBuffer(), 0, bufferWidth * bufferHeight); - } - // Get a handle of the font client. Used to retrieve the bitmaps of the glyphs. TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get(); Length hyphenIndex = 0; @@ -852,15 +983,18 @@ Devel::PixelBuffer Typesetter::CreateImageBuffer(const unsigned int bufferWidth, glyphData.glyphBitmap.buffer = NULL; } - while((hyphenIndex < hyphensCount) && (glyphIndex > hyphenIndices[hyphenIndex])) + if(hyphenIndices) { - hyphenIndex++; - } + while((hyphenIndex < hyphensCount) && (glyphIndex > hyphenIndices[hyphenIndex])) + { + hyphenIndex++; + } - addHyphen = ((hyphenIndex < hyphensCount) && hyphenIndices && ((glyphIndex + 1) == hyphenIndices[hyphenIndex])); - if(addHyphen) - { - glyphIndex--; + addHyphen = ((hyphenIndex < hyphensCount) && ((glyphIndex + 1) == hyphenIndices[hyphenIndex])); + if(addHyphen) + { + glyphIndex--; + } } } @@ -947,44 +1081,44 @@ Devel::PixelBuffer Typesetter::CombineImageBuffer(Devel::PixelBuffer topPixelBuf Devel::PixelBuffer Typesetter::ApplyMarkupProcessorOnPixelBuffer(Devel::PixelBuffer topPixelBuffer, const unsigned int bufferWidth, const unsigned int bufferHeight, bool ignoreHorizontalAlignment, Pixel::Format pixelFormat, int horizontalOffset, int verticalOffset) { - // Apply the markup-Processor if enabled - const bool markupProcessorEnabled = mModel->IsMarkupProcessorEnabled(); - if(markupProcessorEnabled) - { - // Underline-tags (this is for Markup case) - // Get the underline runs. - const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); - Vector underlineRuns; - underlineRuns.Resize(numberOfUnderlineRuns); - mModel->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); - - // Iterate on the consecutive underlined glyph run and connect them into one chunk of underlined characters. - Vector::ConstIterator itGlyphRun = underlineRuns.Begin(); - Vector::ConstIterator endItGlyphRun = underlineRuns.End(); - GlyphIndex startGlyphIndex, endGlyphIndex; - - //The outer loop to iterate on the separated chunks of underlined glyph runs - while(itGlyphRun != endItGlyphRun) - { - startGlyphIndex = itGlyphRun->glyphIndex; - endGlyphIndex = startGlyphIndex; - //The inner loop to make a connected underline for the consecutive characters - do - { - endGlyphIndex += itGlyphRun->numberOfGlyphs; - itGlyphRun++; - } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphIndex == endGlyphIndex); + // Apply the markup-Processor if enabled + const bool markupProcessorEnabled = mModel->IsMarkupProcessorEnabled(); + if(markupProcessorEnabled) + { + // Underline-tags (this is for Markup case) + // Get the underline runs. + const Length numberOfUnderlineRuns = mModel->GetNumberOfUnderlineRuns(); + Vector underlineRuns; + underlineRuns.Resize(numberOfUnderlineRuns); + mModel->GetUnderlineRuns(underlineRuns.Begin(), 0u, numberOfUnderlineRuns); - endGlyphIndex--; + // Iterate on the consecutive underlined glyph run and connect them into one chunk of underlined characters. + Vector::ConstIterator itGlyphRun = underlineRuns.Begin(); + Vector::ConstIterator endItGlyphRun = underlineRuns.End(); + GlyphIndex startGlyphIndex, endGlyphIndex; - // Create the image buffer for underline - Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex); - // Combine the two buffers - topPixelBuffer = CombineImageBuffer(topPixelBuffer, underlineImageBuffer, bufferWidth, bufferHeight); - } + //The outer loop to iterate on the separated chunks of underlined glyph runs + while(itGlyphRun != endItGlyphRun) + { + startGlyphIndex = itGlyphRun->glyphIndex; + endGlyphIndex = startGlyphIndex; + //The inner loop to make a connected underline for the consecutive characters + do + { + endGlyphIndex += itGlyphRun->numberOfGlyphs; + itGlyphRun++; + } while(itGlyphRun != endItGlyphRun && itGlyphRun->glyphIndex == endGlyphIndex); + + endGlyphIndex--; + + // Create the image buffer for underline + Devel::PixelBuffer underlineImageBuffer = CreateImageBuffer(bufferWidth, bufferHeight, Typesetter::STYLE_UNDERLINE, ignoreHorizontalAlignment, pixelFormat, horizontalOffset, verticalOffset, startGlyphIndex, endGlyphIndex); + // Combine the two buffers + topPixelBuffer = CombineImageBuffer(topPixelBuffer, underlineImageBuffer, bufferWidth, bufferHeight); } + } - return topPixelBuffer; + return topPixelBuffer; } Typesetter::Typesetter(const ModelInterface* const model)