From e97f897eca6d48fa16d2402f17f3aea5f0816ece Mon Sep 17 00:00:00 2001 From: Jere Tuliniemi Date: Fri, 12 Apr 2019 14:24:32 +0300 Subject: Add clipping to distance field fonts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes fallback to the old text renderer and adds the clipping feature to the distance field font renderer. Task-number: QT3DS-3329 Change-Id: Ie41b93c9a9ed791297349007c7e2b3bf10c982b1 Reviewed-by: Mahmoud Badri Reviewed-by: Tomi Korpipää --- .../runtimerender/Qt3DSDistanceFieldRenderer.cpp | 59 ++++++++++++++++++- ...Qt3DSRendererImplLayerRenderPreparationData.cpp | 67 +++++++++++----------- 2 files changed, 88 insertions(+), 38 deletions(-) diff --git a/src/Runtime/Source/runtimerender/Qt3DSDistanceFieldRenderer.cpp b/src/Runtime/Source/runtimerender/Qt3DSDistanceFieldRenderer.cpp index 64e5a737..2562ea79 100644 --- a/src/Runtime/Source/runtimerender/Qt3DSDistanceFieldRenderer.cpp +++ b/src/Runtime/Source/runtimerender/Qt3DSDistanceFieldRenderer.cpp @@ -115,6 +115,9 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo) return QHash(); QVector2D boundingBox = QVector2D(textInfo.m_BoundingBox.x, textInfo.m_BoundingBox.y); + const float halfWidth = boundingBox.x() / 2.0f; + const float halfHeight = boundingBox.y() / 2.0f; + bool hasValidBoundingBox = boundingBox.x() > 0 || boundingBox.y() > 0; QRawFont font = m_fontDatabase.findFont(textInfo.m_Font.c_str()); font.setPixelSize(qreal(textInfo.m_FontSize)); @@ -391,6 +394,43 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo) cy2 += float(shadowOffsetY * fontScale); } + float x1Clip = 1.0f; + float x2Clip = 1.0f; + float y1Clip = 1.0f; + float y2Clip = 1.0f; + + if (hasValidBoundingBox) { + if ((cx1 < -halfWidth && cx2 < -halfWidth) + || (cx1 > halfWidth && cx2 > halfWidth) + || (cy1 < -halfHeight && cy2 < -halfHeight) + || (cy1 > halfHeight && cy2 > halfHeight)) { + continue; + } + + float xDiff = qAbs(cx1 - cx2); + float yDiff = qAbs(cy1 - cy2); + + if (cx1 < -halfWidth) { + x1Clip = 1.0f - qAbs(cx1 - (-halfWidth)) / xDiff; + cx1 = -halfWidth; + } + + if (cx2 > halfWidth) { + x2Clip = 1.0f - qAbs(cx2 - halfWidth) / xDiff; + cx2 = halfWidth; + } + + if (cy1 < -halfHeight) { + y1Clip = 1.0f - qAbs(cy1 - (-halfHeight)) / yDiff; + cy1 = -halfHeight; + } + + if (cy2 > halfHeight) { + y2Clip = 1.0f - qAbs(cy2 - halfHeight) / yDiff; + cy2 = halfHeight; + } + } + cy1 = -cy1; cy2 = -cy2; @@ -414,9 +454,7 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo) else if (cy2 > maximum.y) maximum.y = cy2; - if (boundingBox.x() > 0 || boundingBox.y() > 0) { - const float halfWidth = boundingBox.x() / 2.0f; - const float halfHeight = boundingBox.y() / 2.0f; + if (hasValidBoundingBox) { if (maximum.x < halfWidth) maximum.x = halfWidth; if (minimum.x > -halfWidth) @@ -450,6 +488,21 @@ Q3DSDistanceFieldRenderer::buildGlyphsPerTexture(const SText &textInfo) ty2 += float(c.height * shadowOffsetY * fontScale) / float(metrics.height); } + if (hasValidBoundingBox) { + float tx1Orig = tx1; + float tx2Orig = tx2; + float ty1Orig = ty1; + float ty2Orig = ty2; + + float xDiff = qAbs(tx1 - tx2); + tx1 = tx2Orig - xDiff * x1Clip; + tx2 = tx1Orig + xDiff * x2Clip; + + float yDiff = qAbs(ty1 - ty2); + ty1 = ty2Orig - yDiff * y1Clip; + ty2 = ty1Orig + yDiff * y2Clip; + } + const QSGDistanceFieldGlyphCache::Texture *texture = cache->glyphTexture(glyphIndex); if (texture->textureId == 0) { diff --git a/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp b/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp index 2940f088..e1086304 100644 --- a/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp +++ b/src/Runtime/Source/runtimerender/rendererimpl/Qt3DSRendererImplLayerRenderPreparationData.cpp @@ -383,44 +383,41 @@ namespace render { inText.CalculateMVPAndNormalMatrix(inViewProjection, theMVP, theNormalMatrix); SRenderableObject *theRenderable = nullptr; + #if QT_VERSION >= QT_VERSION_CHECK(5,12,2) - // TODO: Implement clipping for the distance field renderer - if (inText.m_WordWrap != TextWordWrap::Clip || (inText.m_BoundingBox.x == 0.0f - && inText.m_BoundingBox.y == 0.0f)) { - QT3DSMat44 modelView = (inProjection.getInverse() * inViewProjection) - * inText.m_GlobalTransform; - Q3DSDistanceFieldRenderer *distanceFieldText - = static_cast( - m_Renderer.GetQt3DSContext().getDistanceFieldRenderer()); - theRenderable = RENDER_FRAME_NEW(SDistanceFieldRenderable)( - theFlags, inText.GetGlobalPos(), inText, inText.m_Bounds, theMVP, - modelView, *distanceFieldText); - } else + QT3DSMat44 modelView = (inProjection.getInverse() * inViewProjection) + * inText.m_GlobalTransform; + Q3DSDistanceFieldRenderer *distanceFieldText + = static_cast( + m_Renderer.GetQt3DSContext().getDistanceFieldRenderer()); + theRenderable = RENDER_FRAME_NEW(SDistanceFieldRenderable)( + theFlags, inText.GetGlobalPos(), inText, inText.m_Bounds, theMVP, + modelView, *distanceFieldText); +#else + TTPathObjectAndTexture theResult + = theTextRenderer->RenderText(inText, inTextScaleFactor); + inText.m_TextTexture = theResult.second.second.mPtr; + inText.m_TextTextureDetails = theResult.second.first; + inText.m_PathFontItem = theResult.first.second; + inText.m_PathFontDetails = theResult.first.first; + STextScaleAndOffset theScaleAndOffset(*inText.m_TextTexture, + inText.m_TextTextureDetails, inText); + QT3DSVec2 theTextScale(theScaleAndOffset.m_TextScale); + QT3DSVec2 theTextOffset(theScaleAndOffset.m_TextOffset); + QT3DSVec3 minimum(theTextOffset[0] - theTextScale[0], + theTextOffset[1] - theTextScale[1], 0); + QT3DSVec3 maximum(theTextOffset[0] + theTextScale[0], + theTextOffset[1] + theTextScale[1], 0); + inText.m_Bounds = NVBounds3(minimum, maximum); + + if (inText.m_PathFontDetails) + ioFlags.SetRequiresStencilBuffer(true); + + theRenderable = RENDER_FRAME_NEW(STextRenderable)( + theFlags, inText.GetGlobalPos(), m_Renderer, inText, inText.m_Bounds, theMVP, + inViewProjection, *inText.m_TextTexture, theTextOffset, theTextScale); #endif - { - TTPathObjectAndTexture theResult - = theTextRenderer->RenderText(inText, inTextScaleFactor); - inText.m_TextTexture = theResult.second.second.mPtr; - inText.m_TextTextureDetails = theResult.second.first; - inText.m_PathFontItem = theResult.first.second; - inText.m_PathFontDetails = theResult.first.first; - STextScaleAndOffset theScaleAndOffset(*inText.m_TextTexture, - inText.m_TextTextureDetails, inText); - QT3DSVec2 theTextScale(theScaleAndOffset.m_TextScale); - QT3DSVec2 theTextOffset(theScaleAndOffset.m_TextOffset); - QT3DSVec3 minimum(theTextOffset[0] - theTextScale[0], - theTextOffset[1] - theTextScale[1], 0); - QT3DSVec3 maximum(theTextOffset[0] + theTextScale[0], - theTextOffset[1] + theTextScale[1], 0); - inText.m_Bounds = NVBounds3(minimum, maximum); - - if (inText.m_PathFontDetails) - ioFlags.SetRequiresStencilBuffer(true); - theRenderable = RENDER_FRAME_NEW(STextRenderable)( - theFlags, inText.GetGlobalPos(), m_Renderer, inText, inText.m_Bounds, theMVP, - inViewProjection, *inText.m_TextTexture, theTextOffset, theTextScale); - } m_TransparentObjects.push_back(theRenderable); } return retval; -- cgit v1.2.3