cool#13988 sw redline render mode: handle inline images
Load the bugdoc, dispatch .uno:RedlineRenderMode, anchored images in
deletions are grey, but this doesn't work with inline images.
There is some infrastructure for this added in commit
d845b91bcc (tdf#78864 sw track changes:
cross out deleted images, 2021-04-30), but that crosses out images
instead of shading.
Fix this by checking for the usual SwRedlineRenderMode flags in
sw::FlyContentPortion::Paint() to avoid the unwanted cross. Also extend
SwLineLayout::CalcLine() to set the inserted/deleted flags on the fly
frame for redlines, so SwGrfNode::GetGraphicAttr() can do its shading as
usual.
And add a GetMetaFileImages() in the test suite to reduce some
duplication.
Change-Id: I97f2311ad7e9a6ffc70d76c1811faa2c13e509fe
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197799
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
This commit is contained in:
Binary file not shown.
@@ -158,6 +158,23 @@ bool IsGrayScale(const Bitmap& rBitmap)
|
||||
return aColor.GetRed() == aColor.GetGreen() && aColor.GetRed() == aColor.GetBlue();
|
||||
}
|
||||
|
||||
std::vector<Bitmap> GetMetaFileImages(const GDIMetaFile& rMetaFile)
|
||||
{
|
||||
std::vector<Bitmap> aImages;
|
||||
for (size_t nAction = 0; nAction < rMetaFile.GetActionSize(); ++nAction)
|
||||
{
|
||||
MetaAction* pAction = rMetaFile.GetAction(nAction);
|
||||
if (pAction->GetType() != MetaActionType::BMPEXSCALE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pAct = static_cast<MetaBmpExScaleAction*>(pAction);
|
||||
aImages.push_back(pAct->GetBitmap());
|
||||
}
|
||||
return aImages;
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(Test, testAnchoredImageRedlineRenderModeOmitInsertDelete)
|
||||
{
|
||||
// Given a document with a normal, a deleted and an inserted image:
|
||||
@@ -168,18 +185,7 @@ CPPUNIT_TEST_FIXTURE(Test, testAnchoredImageRedlineRenderModeOmitInsertDelete)
|
||||
std::shared_ptr<GDIMetaFile> xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
// Then make sure none of the images are grayscale:
|
||||
std::vector<Bitmap> aImages;
|
||||
for (size_t nAction = 0; nAction < xMetaFile->GetActionSize(); ++nAction)
|
||||
{
|
||||
MetaAction* pAction = xMetaFile->GetAction(nAction);
|
||||
if (pAction->GetType() != MetaActionType::BMPEXSCALE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pAct = static_cast<MetaBmpExScaleAction*>(pAction);
|
||||
aImages.push_back(pAct->GetBitmap());
|
||||
}
|
||||
std::vector<Bitmap> aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[1]));
|
||||
@@ -193,18 +199,7 @@ CPPUNIT_TEST_FIXTURE(Test, testAnchoredImageRedlineRenderModeOmitInsertDelete)
|
||||
|
||||
xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
aImages.clear();
|
||||
for (size_t nAction = 0; nAction < xMetaFile->GetActionSize(); ++nAction)
|
||||
{
|
||||
MetaAction* pAction = xMetaFile->GetAction(nAction);
|
||||
if (pAction->GetType() != MetaActionType::BMPEXSCALE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pAct = static_cast<MetaBmpExScaleAction*>(pAction);
|
||||
aImages.push_back(pAct->GetBitmap());
|
||||
}
|
||||
aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[1]));
|
||||
@@ -218,18 +213,52 @@ CPPUNIT_TEST_FIXTURE(Test, testAnchoredImageRedlineRenderModeOmitInsertDelete)
|
||||
|
||||
xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
aImages.clear();
|
||||
for (size_t nAction = 0; nAction < xMetaFile->GetActionSize(); ++nAction)
|
||||
{
|
||||
MetaAction* pAction = xMetaFile->GetAction(nAction);
|
||||
if (pAction->GetType() != MetaActionType::BMPEXSCALE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(IsGrayScale(aImages[1]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[2]));
|
||||
}
|
||||
|
||||
auto pAct = static_cast<MetaBmpExScaleAction*>(pAction);
|
||||
aImages.push_back(pAct->GetBitmap());
|
||||
}
|
||||
CPPUNIT_TEST_FIXTURE(Test, testInlineImageRedlineRenderModeOmitInsertDelete)
|
||||
{
|
||||
// Given a document with a normal, a deleted and an inserted image:
|
||||
createSwDoc("redline-image-inline.docx");
|
||||
|
||||
// When using the standard redline render mode:
|
||||
SwDocShell* pDocShell = getSwDocShell();
|
||||
std::shared_ptr<GDIMetaFile> xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
// Then make sure none of the images are grayscale:
|
||||
std::vector<Bitmap> aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[1]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[2]));
|
||||
|
||||
// Omit insert: default, default, grayscale.
|
||||
SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
|
||||
SwViewOption aOpt(*pWrtShell->GetViewOptions());
|
||||
aOpt.SetRedlineRenderMode(SwRedlineRenderMode::OmitInserts);
|
||||
pWrtShell->ApplyViewOptions(aOpt);
|
||||
|
||||
xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[1]));
|
||||
// Without the accompanying fix in place, this test would have failed, the image's center pixel
|
||||
// wasn't gray.
|
||||
CPPUNIT_ASSERT(IsGrayScale(aImages[2]));
|
||||
|
||||
// Omit deletes: default, grayscale, default.
|
||||
aOpt.SetRedlineRenderMode(SwRedlineRenderMode::OmitDeletes);
|
||||
pWrtShell->ApplyViewOptions(aOpt);
|
||||
|
||||
xMetaFile = pDocShell->GetPreviewMetaFile();
|
||||
|
||||
aImages = GetMetaFileImages(*xMetaFile);
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), aImages.size());
|
||||
CPPUNIT_ASSERT(!IsGrayScale(aImages[0]));
|
||||
CPPUNIT_ASSERT(IsGrayScale(aImages[1]));
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <sortedobjs.hxx>
|
||||
#include <officecfg/Office/Common.hxx>
|
||||
#include <PostItMgr.hxx>
|
||||
#include <viewopt.hxx>
|
||||
|
||||
/**
|
||||
* class SwFlyPortion => we expect a frame-locale SwRect!
|
||||
@@ -223,9 +224,10 @@ void sw::FlyContentPortion::Paint(const SwTextPaintInfo& rInf) const
|
||||
if(rInf.GetTextFrame()->IsVertical())
|
||||
rInf.GetTextFrame()->SwitchHorizontalToVertical(aRepaintRect);
|
||||
|
||||
SwViewShell* pViewShell = m_pFly->getRootFrame()->GetCurrShell();
|
||||
if(!((m_pFly->IsCompletePaint() ||
|
||||
m_pFly->getFrameArea().Overlaps(aRepaintRect)) &&
|
||||
SwFlyFrame::IsPaint(m_pFly->GetVirtDrawObj(), *m_pFly->getRootFrame()->GetCurrShell())))
|
||||
SwFlyFrame::IsPaint(m_pFly->GetVirtDrawObj(), *pViewShell)))
|
||||
return;
|
||||
|
||||
SwRect aRect(m_pFly->getFrameArea());
|
||||
@@ -239,7 +241,11 @@ void sw::FlyContentPortion::Paint(const SwTextPaintInfo& rInf) const
|
||||
|
||||
// track changes: cross out the image, if it is deleted
|
||||
const SwFrame *pFrame = m_pFly->Lower();
|
||||
if ( GetAuthor() != std::string::npos && IsDeleted() && pFrame )
|
||||
const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
|
||||
SwRedlineRenderMode eRedlineRenderMode
|
||||
= pViewOptions ? pViewOptions->GetRedlineRenderMode() : SwRedlineRenderMode::Standard;
|
||||
if (GetAuthor() != std::string::npos && IsDeleted() && pFrame
|
||||
&& eRedlineRenderMode == SwRedlineRenderMode::Standard)
|
||||
{
|
||||
SwRect aPaintRect( pFrame->GetPaintArea() );
|
||||
|
||||
|
||||
@@ -672,6 +672,7 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, SwTextFormatInfo &rInf )
|
||||
if( pPos->IsFlyCntPortion() )
|
||||
{
|
||||
bool bDeleted = false;
|
||||
bool bInserted = false;
|
||||
size_t nAuthor = std::string::npos;
|
||||
if ( bHasRedline )
|
||||
{
|
||||
@@ -683,10 +684,21 @@ void SwLineLayout::CalcLine( SwTextFormatter &rLine, SwTextFormatInfo &rInf )
|
||||
bool bHasFlyRedline = rLine.GetRedln()->CheckLine(flyStart.first->GetIndex(),
|
||||
flyStart.second, flyStart.first->GetIndex(), flyStart.second, sRedlineText,
|
||||
bHasRedlineEnd, eRedlineEnd, /*pAuthorAtPos=*/&nAuthor);
|
||||
bDeleted = bHasFlyRedline && eRedlineEnd == RedlineType::Delete;
|
||||
if (bHasFlyRedline)
|
||||
{
|
||||
bDeleted = eRedlineEnd == RedlineType::Delete;
|
||||
bInserted = eRedlineEnd == RedlineType::Insert;
|
||||
}
|
||||
}
|
||||
static_cast<SwFlyCntPortion*>(pPos)->SetDeleted(bDeleted);
|
||||
static_cast<SwFlyCntPortion*>(pPos)->SetAuthor(nAuthor);
|
||||
|
||||
if (auto pFlyPortion = dynamic_cast<sw::FlyContentPortion*>(pPos))
|
||||
{
|
||||
SwFlyFrame* pFlyFrame = pFlyPortion->GetFlyFrame();
|
||||
pFlyFrame->SetDeleted(bDeleted);
|
||||
pFlyFrame->SetInserted(bInserted);
|
||||
}
|
||||
}
|
||||
// anchored to characters
|
||||
else if ( pPos->IsFlyPortion() )
|
||||
|
||||
Reference in New Issue
Block a user