summaryrefslogtreecommitdiff
path: root/sd/source/ui/tools/SlideshowLayerRenderer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/tools/SlideshowLayerRenderer.cxx')
-rw-r--r--sd/source/ui/tools/SlideshowLayerRenderer.cxx172
1 files changed, 108 insertions, 64 deletions
diff --git a/sd/source/ui/tools/SlideshowLayerRenderer.cxx b/sd/source/ui/tools/SlideshowLayerRenderer.cxx
index e63e76be30b7..6729c3f23c57 100644
--- a/sd/source/ui/tools/SlideshowLayerRenderer.cxx
+++ b/sd/source/ui/tools/SlideshowLayerRenderer.cxx
@@ -95,20 +95,55 @@ public:
namespace
{
-bool hasFields(SdrObject* pObject)
+sal_Int32 getFieldType(SdrObject* pObject)
{
auto* pTextObject = dynamic_cast<SdrTextObj*>(pObject);
if (!pTextObject)
- return false;
+ return -2;
OutlinerParaObject* pOutlinerParagraphObject = pTextObject->GetOutlinerParaObject();
if (pOutlinerParagraphObject)
{
const EditTextObject& rEditText = pOutlinerParagraphObject->GetTextObject();
- if (rEditText.IsFieldObject())
- return true;
+ if (rEditText.IsFieldObject() && rEditText.GetField() && rEditText.GetField()->GetField())
+ return rEditText.GetField()->GetField()->GetClassId();
}
- return false;
+ return -2;
+}
+
+bool hasFields(SdrObject* pObject) { return getFieldType(pObject) > -2; }
+
+OUString getFieldName(sal_Int32 nType)
+{
+ switch (nType)
+ {
+ case text::textfield::Type::PAGE:
+ return u"Page"_ustr;
+ case text::textfield::Type::PAGE_NAME:
+ return u"PageName"_ustr;
+ default:
+ return u""_ustr;
+ }
+}
+
+OUString getMasterTextFieldType(SdrObject* pObject)
+{
+ OUString aType;
+
+ uno::Reference<drawing::XShape> xShape = pObject->getUnoShape();
+ if (!xShape.is())
+ return aType;
+
+ OUString sShapeType = xShape->getShapeType();
+
+ if (sShapeType == u"com.sun.star.presentation.SlideNumberShape")
+ aType = u"SlideNumber"_ustr;
+ else if (sShapeType == u"com.sun.star.presentation.FooterShape")
+ aType = u"Footer"_ustr;
+ else if (sShapeType == u"com.sun.star.presentation.DateTimeShape")
+ aType = u"DateTime"_ustr;
+
+ return aType;
}
/// Sets visible for all kinds of polypolys in the container
@@ -251,27 +286,11 @@ private:
mpCurrentRenderPass = newRenderPass();
}
- OUString getMasterTextFieldString(SdrObject* pObject)
+ bool isTextFieldVisible(std::u16string_view svType) const
{
- OUString aType;
-
- uno::Reference<drawing::XShape> xShape = pObject->getUnoShape();
- if (!xShape.is())
- return aType;
-
- OUString sShapeType = xShape->getShapeType();
-
- if (mrRenderState.mbSlideNumberEnabled
- && sShapeType == u"com.sun.star.presentation.SlideNumberShape")
- aType = u"SlideNumber"_ustr;
- else if (mrRenderState.mbFooterEnabled
- && sShapeType == u"com.sun.star.presentation.FooterShape")
- aType = u"Footer"_ustr;
- else if (mrRenderState.mbDateTimeEnabled
- && sShapeType == u"com.sun.star.presentation.DateTimeShape")
- aType = u"DateTime"_ustr;
-
- return aType;
+ return (mrRenderState.mbSlideNumberEnabled && svType == u"SlideNumber")
+ || (mrRenderState.mbFooterEnabled && svType == u"Footer")
+ || (mrRenderState.mbDateTimeEnabled && svType == u"DateTime");
}
public:
@@ -287,9 +306,13 @@ public:
if (mrRenderState.maRenderPasses.back().isEmpty())
mrRenderState.maRenderPasses.pop_back();
+ // Merge text field render passes into the main render pass list.
+ // We prepend them, so that they are rendered and sent to the client first.
+ // So, when the client try to draw a master page layer corresponding
+ // to a text field placeholder the content is already available.
for (auto& rRenderWork : mrRenderState.maTextFields)
{
- mrRenderState.maRenderPasses.push_back(rRenderWork);
+ mrRenderState.maRenderPasses.push_front(rRenderWork);
}
}
@@ -314,19 +337,58 @@ public:
const bool bVisible
= pObject->getSdrPageFromSdrObject()->checkVisibility(rOriginal, rDisplayInfo, true);
- if (!bVisible)
- return;
-
// Determine the current stage, depending on the page
RenderStage eCurrentStage
= pPage->IsMasterPage() ? RenderStage::Master : RenderStage::Slide;
+ OUString sTextFieldType = getMasterTextFieldType(pObject);
+ bool isPresentationTextField = !sTextFieldType.isEmpty();
+ if (!isPresentationTextField)
+ {
+ sTextFieldType = getFieldName(getFieldType(pObject));
+ }
+
+ // Check if the object has slide number, footer, date/time
+ if (eCurrentStage == RenderStage::Master && !sTextFieldType.isEmpty())
+ {
+ // it's not possible to set visibility for non-presentation text fields
+ bool bIsTextFieldVisible
+ = !isPresentationTextField || isTextFieldVisible(sTextFieldType);
+
+ // A placeholder always needs to be exported even if the content is hidden
+ // since it could be visible on another slide and master page layers should be cached
+ // on the client
+ closeRenderPass();
+
+ mpCurrentRenderPass->maObjectsAndParagraphs.emplace(pObject, std::deque<sal_Int32>());
+ mpCurrentRenderPass->meStage = eCurrentStage;
+ mpCurrentRenderPass->mbPlaceholder = true;
+ mpCurrentRenderPass->maFieldType = sTextFieldType;
+ mpCurrentRenderPass->mpObject = pObject;
+ closeRenderPass();
+
+ // Collect text field content if it's visible
+ // Both checks are needed!
+ if (bVisible && bIsTextFieldVisible)
+ {
+ RenderPass aTextFieldPass;
+ aTextFieldPass.maObjectsAndParagraphs.emplace(pObject, std::deque<sal_Int32>());
+ aTextFieldPass.meStage = RenderStage::TextFields;
+ aTextFieldPass.maFieldType = sTextFieldType;
+ aTextFieldPass.mpObject = pObject;
+
+ mrRenderState.maTextFields.push_back(aTextFieldPass);
+ }
+ return;
+ }
+
+ if (!bVisible)
+ return;
+
// We switched from master objects to slide objects
if (eCurrentStage == RenderStage::Slide && mePreviousStage == RenderStage::Master)
closeRenderPass();
- OUString sTextFieldString = getMasterTextFieldString(pObject);
-
// check if object is in an animation
auto aIterator = mrRenderState.maAnimationRenderInfoList.find(pObject);
if (aIterator != mrRenderState.maAnimationRenderInfoList.end())
@@ -382,36 +444,6 @@ public:
closeRenderPass();
}
}
- // Check if the object has slide number, footer, date/time
- else if (eCurrentStage == RenderStage::Master && !sTextFieldString.isEmpty())
- {
- closeRenderPass();
-
- mpCurrentRenderPass->maObjectsAndParagraphs.emplace(pObject, std::deque<sal_Int32>());
- mpCurrentRenderPass->meStage = eCurrentStage;
- mpCurrentRenderPass->mbPlaceholder = true;
- mpCurrentRenderPass->maFieldType = sTextFieldString;
- mpCurrentRenderPass->mpObject = pObject;
- closeRenderPass();
-
- RenderPass aTextFieldPass;
- aTextFieldPass.maObjectsAndParagraphs.emplace(pObject, std::deque<sal_Int32>());
- aTextFieldPass.meStage = RenderStage::TextFields;
- aTextFieldPass.maFieldType = sTextFieldString;
- aTextFieldPass.mpObject = pObject;
-
- mrRenderState.maTextFields.push_back(aTextFieldPass);
- }
- // Check if the object has fields
- else if (eCurrentStage == RenderStage::Master && hasFields(pObject))
- {
- closeRenderPass();
-
- mpCurrentRenderPass->maObjectsAndParagraphs.emplace(pObject, std::deque<sal_Int32>());
- mpCurrentRenderPass->meStage = eCurrentStage;
- mpCurrentRenderPass->mpObject = pObject;
- closeRenderPass();
- }
// No special handling is needed, just add the object to the current rendering pass
else
{
@@ -457,7 +489,10 @@ public:
auto const& rParagraphs = aIterator->second;
- if (!rParagraphs.empty())
+ // A render pass for the non-animated part of a text shapes whose paragraphs are all animated
+ // has no paragraphs (rParagraphs.empty()) anyway it still needs to be modified in order to
+ // render the text shape background only; on the contrary it will render all paragraphs.
+ if (!rParagraphs.empty() || mrRenderPass.mbRenderObjectBackground)
{
auto const& rViewInformation2D = rOriginal.GetObjectContact().getViewInformation2D();
auto rContainer
@@ -746,12 +781,16 @@ void SlideshowLayerRenderer::writeJSON(OString& rJsonMsg, RenderPass const& rRen
{
auto aContentNode = aJsonWriter.startNode("content");
aJsonWriter.put("type", rRenderPass.maFieldType);
+ std::string sHash = pObject ? std::to_string(pObject->GetUniqueID()) : "";
+ aJsonWriter.put("hash", sHash);
}
}
else if (rRenderPass.meStage == RenderStage::TextFields)
{
auto aContentNode = aJsonWriter.startNode("content");
aJsonWriter.put("type", rRenderPass.maFieldType);
+ std::string sHash = pObject ? std::to_string(pObject->GetUniqueID()) : "";
+ aJsonWriter.put("hash", sHash);
writeContentNode(aJsonWriter);
}
else
@@ -766,7 +805,8 @@ void SlideshowLayerRenderer::writeJSON(OString& rJsonMsg, RenderPass const& rRen
maRenderState.incrementIndex();
}
-bool SlideshowLayerRenderer::render(unsigned char* pBuffer, double& rScale, OString& rJsonMsg)
+bool SlideshowLayerRenderer::render(unsigned char* pBuffer, bool& bIsBitmapLayer, double& rScale,
+ OString& rJsonMsg)
{
// We want to render one pass (one iteration through objects)
@@ -780,6 +820,8 @@ bool SlideshowLayerRenderer::render(unsigned char* pBuffer, double& rScale, OStr
createViewAndDraw(aRenderContext, &aRedirector);
aRedirector.finalizeRenderPasses();
+ bIsBitmapLayer = true;
+
// Write JSON for the Background layer
writeBackgroundJSON(rJsonMsg);
@@ -792,7 +834,9 @@ bool SlideshowLayerRenderer::render(unsigned char* pBuffer, double& rScale, OStr
auto const& rRenderPass = maRenderState.maRenderPasses.front();
maRenderState.meStage = rRenderPass.meStage;
- if (!rRenderPass.mbPlaceholder) // no need to render if placehodler
+
+ bIsBitmapLayer = !rRenderPass.mbPlaceholder;
+ if (bIsBitmapLayer) // no need to render if placeholder
{
RenderPassObjectRedirector aRedirector(maRenderState, rRenderPass);
createViewAndDraw(aRenderContext, &aRedirector);