mirror of
https://github.com/LibreOffice/core.git
synced 2025-07-26 15:45:26 +00:00

This change fixes a bug causing borders to fail to render for merged
cells in RTL spreadsheets.
The root cause for this bug was framelinkarray utility code using the
top-left cell as the source for border styles of merged cells. This use
was correct for LTR spreadsheets. However, this framelinkarray data is
mirrored for RTL documents. After mirroring, the correct cell containing
border styles is the top-right one.
This change also reverts and reimplements a prior fix for tdf#135843
(commit 586a0f149f
), which violated the
framelinkarray contract that edge styles for merged cells must be added
to the top-left underlying cell of a merged cell.
Change-Id: I27eec416d54f9f99cd5df1151a12c758f350c789
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180256
Tested-by: Jenkins
Reviewed-by: Jonathan Clark <jonathan@libreoffice.org>
540 lines
26 KiB
C++
540 lines
26 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
|
|
#include "viewcontactoftableobj.hxx"
|
|
#include <svx/svdotable.hxx>
|
|
#include <com/sun/star/table/XTable.hpp>
|
|
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
#include <sdr/primitive2d/sdrattributecreator.hxx>
|
|
#include <sdr/primitive2d/sdrdecompositiontools.hxx>
|
|
#include <sdr/primitive2d/sdrcellprimitive.hxx>
|
|
#include <basegfx/matrix/b2dhommatrix.hxx>
|
|
#include <sdr/attribute/sdrtextattribute.hxx>
|
|
#include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
|
|
#include <editeng/borderline.hxx>
|
|
#include <drawinglayer/attribute/sdrlineattribute.hxx>
|
|
#include <drawinglayer/attribute/sdrshadowattribute.hxx>
|
|
#include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
|
|
#include <drawinglayer/primitive2d/structuretagprimitive2d.hxx>
|
|
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
|
|
#include <basegfx/matrix/b2dhommatrixtools.hxx>
|
|
#include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx>
|
|
#include <svx/sdr/contact/objectcontact.hxx>
|
|
#include <svx/svdpage.hxx>
|
|
#include <svx/framelink.hxx>
|
|
#include <svx/framelinkarray.hxx>
|
|
#include <svx/sdooitm.hxx>
|
|
#include <utility>
|
|
#include <vcl/canvastools.hxx>
|
|
#include <o3tl/unit_conversion.hxx>
|
|
#include <svx/xfltrit.hxx>
|
|
|
|
#include <cell.hxx>
|
|
#include "tablelayouter.hxx"
|
|
|
|
|
|
using editeng::SvxBorderLine;
|
|
using namespace com::sun::star;
|
|
|
|
|
|
namespace drawinglayer::primitive2d
|
|
{
|
|
Primitive2DReference SdrCellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const
|
|
{
|
|
Primitive2DContainer aContainer;
|
|
// prepare unit polygon
|
|
const basegfx::B2DPolyPolygon aUnitPolyPolygon(basegfx::utils::createUnitPolygon());
|
|
|
|
// add fill
|
|
if(!getSdrFTAttribute().getFill().isDefault())
|
|
{
|
|
basegfx::B2DPolyPolygon aTransformed(aUnitPolyPolygon);
|
|
|
|
aTransformed.transform(getTransform());
|
|
aContainer.push_back(
|
|
createPolyPolygonFillPrimitive(
|
|
aTransformed,
|
|
getSdrFTAttribute().getFill(),
|
|
getSdrFTAttribute().getFillFloatTransGradient()));
|
|
}
|
|
else
|
|
{
|
|
// if no fill create one for HitTest and BoundRect fallback
|
|
aContainer.push_back(
|
|
createHiddenGeometryPrimitives2D(
|
|
true,
|
|
aUnitPolyPolygon,
|
|
getTransform()));
|
|
}
|
|
|
|
// add text
|
|
if(!getSdrFTAttribute().getText().isDefault())
|
|
{
|
|
aContainer.push_back(
|
|
createTextPrimitive(
|
|
aUnitPolyPolygon,
|
|
getTransform(),
|
|
getSdrFTAttribute().getText(),
|
|
attribute::SdrLineAttribute(),
|
|
true,
|
|
false));
|
|
}
|
|
return new GroupPrimitive2D(std::move(aContainer));
|
|
}
|
|
|
|
bool SdrCellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
|
|
{
|
|
if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
|
|
{
|
|
const SdrCellPrimitive2D& rCompare = static_cast<const SdrCellPrimitive2D&>(rPrimitive);
|
|
|
|
return (getTransform() == rCompare.getTransform()
|
|
&& getSdrFTAttribute() == rCompare.getSdrFTAttribute());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// provide unique ID
|
|
sal_uInt32 SdrCellPrimitive2D::getPrimitive2DID() const
|
|
{
|
|
return PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D;
|
|
}
|
|
|
|
} // end of namespace
|
|
|
|
namespace sdr::contact
|
|
{
|
|
|
|
namespace {
|
|
class ViewObjectContactOfTableObj : public ViewObjectContactOfSdrObj
|
|
{
|
|
public:
|
|
ViewObjectContactOfTableObj(ObjectContact& rObjectContact, ViewContact& rViewContact)
|
|
: ViewObjectContactOfSdrObj(rObjectContact, rViewContact)
|
|
{
|
|
}
|
|
|
|
protected:
|
|
virtual void createPrimitive2DSequence(DisplayInfo const& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const override;
|
|
};
|
|
} // namespace
|
|
|
|
static svx::frame::Style impGetLineStyle(
|
|
const sdr::table::TableLayouter& rLayouter,
|
|
sal_Int32 nX,
|
|
sal_Int32 nY,
|
|
bool bHorizontal,
|
|
sal_Int32 nColCount,
|
|
sal_Int32 nRowCount,
|
|
bool bIsRTL)
|
|
{
|
|
if(nX >= 0 && nX <= nColCount && nY >= 0 && nY <= nRowCount)
|
|
{
|
|
const SvxBorderLine* pLine = rLayouter.getBorderLine(nX, nY, bHorizontal);
|
|
|
|
if(pLine)
|
|
{
|
|
// copy line content
|
|
SvxBorderLine aLine(*pLine);
|
|
|
|
// check for mirroring. This shall always be done when it is
|
|
// not a top- or rightmost line
|
|
bool bMirror(aLine.isDouble());
|
|
|
|
if(bMirror)
|
|
{
|
|
if(bHorizontal)
|
|
{
|
|
// mirror all bottom lines
|
|
bMirror = (0 != nY);
|
|
}
|
|
else
|
|
{
|
|
// mirror all left lines
|
|
bMirror = (bIsRTL ? 0 != nX : nX != nColCount);
|
|
}
|
|
}
|
|
|
|
if(bMirror)
|
|
{
|
|
aLine.SetMirrorWidths( );
|
|
}
|
|
|
|
constexpr double fTwipsToMM(
|
|
o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::mm100));
|
|
return svx::frame::Style(&aLine, fTwipsToMM);
|
|
}
|
|
}
|
|
|
|
// no success, copy empty line
|
|
return svx::frame::Style();
|
|
}
|
|
|
|
static void createPrimitive2DSequenceImpl(
|
|
sdr::table::SdrTableObj const& rTableObj,
|
|
bool const isTaggedPDF,
|
|
drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor)
|
|
{
|
|
const rtl::Reference< table::TableModel >& xTable = rTableObj.getUnoTable();
|
|
|
|
if(xTable.is())
|
|
{
|
|
// create primitive representation for table. Cell info goes
|
|
// directly to aRetval, Border info to aBorderSequence and added
|
|
// later to get the correct overlapping
|
|
drawinglayer::primitive2d::Primitive2DContainer aRetval;
|
|
drawinglayer::primitive2d::Primitive2DContainer aRetvalForShadow;
|
|
const sal_Int32 nRowCount(xTable->getRowCount());
|
|
const sal_Int32 nColCount(xTable->getColumnCount());
|
|
const sal_Int32 nAllCount(nRowCount * nColCount);
|
|
SdrPage const*const pPage(rTableObj.getSdrPageFromSdrObject());
|
|
|
|
if(nAllCount)
|
|
{
|
|
const sdr::table::TableLayouter& rTableLayouter(rTableObj.getTableLayouter());
|
|
const bool bIsRTL(css::text::WritingMode_RL_TB == rTableObj.GetWritingMode());
|
|
sdr::table::CellPos aCellPos;
|
|
sdr::table::CellRef xCurrentCell;
|
|
basegfx::B2IRectangle aCellArea;
|
|
|
|
// create range using the model data directly. This is in SdrTextObj::aRect which i will access using
|
|
// GetGeoRect() to not trigger any calculations. It's the unrotated geometry.
|
|
const basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(rTableObj.GetGeoRect());
|
|
|
|
// To create the CellBorderPrimitives, use the tooling from svx::frame::Array
|
|
// which is capable of creating the needed visualization. Fill it during the
|
|
// anyways needed run over the table.
|
|
svx::frame::Array aArray;
|
|
|
|
// initialize CellBorderArray for primitive creation
|
|
aArray.Initialize(nColCount, nRowCount);
|
|
|
|
// create single primitives per cell
|
|
for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
|
|
{
|
|
drawinglayer::primitive2d::Primitive2DContainer row;
|
|
// add RowHeight to CellBorderArray for primitive creation
|
|
aArray.SetRowHeight(aCellPos.mnRow, rTableLayouter.getRowHeight(aCellPos.mnRow));
|
|
|
|
for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++)
|
|
{
|
|
drawinglayer::primitive2d::Primitive2DContainer cell;
|
|
// add ColWidth to CellBorderArray for primitive creation, only
|
|
// needs to be done in the 1st run
|
|
if(0 == aCellPos.mnRow)
|
|
{
|
|
aArray.SetColWidth(aCellPos.mnCol, rTableLayouter.getColumnWidth(aCellPos.mnCol));
|
|
}
|
|
|
|
// access the cell
|
|
xCurrentCell = xTable->getCell(aCellPos.mnCol, aCellPos.mnRow);
|
|
|
|
if(xCurrentCell.is())
|
|
{
|
|
// tdf#135843: Find correct neighbor cell index for merged cells
|
|
auto nNextCol = aCellPos.mnCol + xCurrentCell->getColumnSpan();
|
|
auto nNextRow = aCellPos.mnRow + xCurrentCell->getRowSpan();
|
|
|
|
// copy styles for current cell to CellBorderArray for primitive creation
|
|
aArray.SetCellStyleLeft(
|
|
aCellPos.mnCol, aCellPos.mnRow,
|
|
impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow,
|
|
false, nColCount, nRowCount, bIsRTL));
|
|
aArray.SetCellStyleRight(
|
|
aCellPos.mnCol, aCellPos.mnRow,
|
|
impGetLineStyle(rTableLayouter, nNextCol, aCellPos.mnRow, false,
|
|
nColCount, nRowCount, bIsRTL));
|
|
aArray.SetCellStyleTop(
|
|
aCellPos.mnCol, aCellPos.mnRow,
|
|
impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow,
|
|
true, nColCount, nRowCount, bIsRTL));
|
|
aArray.SetCellStyleBottom(
|
|
aCellPos.mnCol, aCellPos.mnRow,
|
|
impGetLineStyle(rTableLayouter, aCellPos.mnCol, nNextRow, true,
|
|
nColCount, nRowCount, bIsRTL));
|
|
|
|
// ignore merged cells (all except the top-left of a merged cell)
|
|
if(!xCurrentCell->isMerged())
|
|
{
|
|
// check if we are the top-left of a merged cell
|
|
const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
|
|
const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
|
|
|
|
if(nXSpan > 1 || nYSpan > 1)
|
|
{
|
|
// if merged, set so at CellBorderArray for primitive creation
|
|
aArray.SetMergedRange(aCellPos.mnCol, aCellPos.mnRow, aCellPos.mnCol + nXSpan - 1, aCellPos.mnRow + nYSpan - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(xCurrentCell.is() && !xCurrentCell->isMerged())
|
|
{
|
|
if(rTableLayouter.getCellArea(xCurrentCell, aCellPos, aCellArea))
|
|
{
|
|
// create cell transformation matrix
|
|
basegfx::B2DHomMatrix aCellMatrix;
|
|
aCellMatrix.set(0, 0, static_cast<double>(aCellArea.getWidth()));
|
|
aCellMatrix.set(1, 1, static_cast<double>(aCellArea.getHeight()));
|
|
aCellMatrix.set(0, 2, static_cast<double>(aCellArea.getMinX()) + aObjectRange.getMinX());
|
|
aCellMatrix.set(1, 2, static_cast<double>(aCellArea.getMinY()) + aObjectRange.getMinY());
|
|
|
|
// handle cell fillings and text
|
|
const SfxItemSet& rCellItemSet = xCurrentCell->GetItemSet();
|
|
const sal_uInt32 nTextIndex(nColCount * aCellPos.mnRow + aCellPos.mnCol);
|
|
const SdrText* pSdrText = rTableObj.getText(nTextIndex);
|
|
drawinglayer::attribute::SdrFillTextAttribute aAttribute;
|
|
|
|
if(pSdrText)
|
|
{
|
|
// #i101508# take cell's local text frame distances into account
|
|
const sal_Int32 nLeft(xCurrentCell->GetTextLeftDistance());
|
|
const sal_Int32 nRight(xCurrentCell->GetTextRightDistance());
|
|
const sal_Int32 nUpper(xCurrentCell->GetTextUpperDistance());
|
|
const sal_Int32 nLower(xCurrentCell->GetTextLowerDistance());
|
|
|
|
aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute(
|
|
rCellItemSet,
|
|
pSdrText,
|
|
&nLeft,
|
|
&nUpper,
|
|
&nRight,
|
|
&nLower);
|
|
}
|
|
else
|
|
{
|
|
aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute(
|
|
rCellItemSet,
|
|
pSdrText);
|
|
}
|
|
|
|
// always create cell primitives for BoundRect and HitTest
|
|
{
|
|
const drawinglayer::primitive2d::Primitive2DReference xCellReference(
|
|
new drawinglayer::primitive2d::SdrCellPrimitive2D(
|
|
aCellMatrix, aAttribute));
|
|
cell.append(xCellReference);
|
|
}
|
|
|
|
// Create cell primitive without text.
|
|
aAttribute
|
|
= drawinglayer::primitive2d::createNewSdrFillTextAttribute(
|
|
rCellItemSet, nullptr);
|
|
rtl::Reference pCellReference
|
|
= new drawinglayer::primitive2d::SdrCellPrimitive2D(
|
|
aCellMatrix, aAttribute);
|
|
|
|
sal_uInt16 nTransparence(
|
|
rCellItemSet.Get(XATTR_FILLTRANSPARENCE).GetValue());
|
|
if (nTransparence != 0)
|
|
{
|
|
pCellReference->setTransparenceForShadow(nTransparence);
|
|
}
|
|
|
|
const drawinglayer::primitive2d::Primitive2DReference
|
|
xCellReference(pCellReference);
|
|
aRetvalForShadow.append(xCellReference);
|
|
}
|
|
}
|
|
if (isTaggedPDF && pPage)
|
|
{
|
|
// heuristic: if there's a special formatting on
|
|
// first row, assume that it's a header row
|
|
auto const eType(
|
|
aCellPos.mnRow == 0 && rTableObj.getTableStyleSettings().mbUseFirstRow
|
|
? vcl::pdf::StructElement::TableHeader
|
|
: vcl::pdf::StructElement::TableData);
|
|
cell = drawinglayer::primitive2d::Primitive2DContainer {
|
|
new drawinglayer::primitive2d::StructureTagPrimitive2D(
|
|
eType,
|
|
pPage->IsMasterPage(),
|
|
false,
|
|
false,
|
|
std::move(cell)) };
|
|
}
|
|
row.append(cell);
|
|
}
|
|
|
|
if (isTaggedPDF && pPage)
|
|
{
|
|
row = drawinglayer::primitive2d::Primitive2DContainer {
|
|
new drawinglayer::primitive2d::StructureTagPrimitive2D(
|
|
vcl::pdf::StructElement::TableRow,
|
|
pPage->IsMasterPage(),
|
|
false,
|
|
false,
|
|
std::move(row)) };
|
|
}
|
|
aRetval.append(row);
|
|
}
|
|
|
|
// now create all CellBorderPrimitives
|
|
drawinglayer::primitive2d::Primitive2DContainer aCellBorderPrimitives(aArray.CreateB2DPrimitiveArray());
|
|
|
|
if(!aCellBorderPrimitives.empty())
|
|
{
|
|
// this is already scaled (due to Table in non-uniform coordinates), so
|
|
// first transform removing scale
|
|
basegfx::B2DHomMatrix aTransform(
|
|
basegfx::utils::createScaleB2DHomMatrix(
|
|
1.0 / aObjectRange.getWidth(),
|
|
1.0 / aObjectRange.getHeight()));
|
|
|
|
// If RTL, mirror the whole unified table in X and move right.
|
|
// This is much easier than taking this into account for the whole
|
|
// index calculations
|
|
if(bIsRTL)
|
|
{
|
|
aTransform.scale(-1.0, 1.0);
|
|
aTransform.translate(1.0, 0.0);
|
|
}
|
|
|
|
// create object matrix
|
|
const GeoStat& rGeoStat(rTableObj.GetGeoStat());
|
|
const double fShearX(-rGeoStat.mfTanShearAngle);
|
|
const double fRotate(rGeoStat.m_nRotationAngle ? toRadians(36000_deg100 - rGeoStat.m_nRotationAngle) : 0.0);
|
|
const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
|
|
aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
|
|
aObjectRange.getMinX(), aObjectRange.getMinY()));
|
|
|
|
// add object matrix to transform. By doing so theoretically
|
|
// CellBorders could be also rotated/sheared for the first time ever.
|
|
// To completely make that work, the primitives already created in
|
|
// aRetval would also have to be based on ObjectMatrix, not only on
|
|
// ObjectRange as it currently is.
|
|
aTransform *= aObjectMatrix;
|
|
|
|
// create a transform primitive with this and embed CellBorders
|
|
// and append to retval
|
|
aRetval.append(
|
|
new drawinglayer::primitive2d::TransformPrimitive2D(
|
|
aTransform,
|
|
drawinglayer::primitive2d::Primitive2DContainer(aCellBorderPrimitives)));
|
|
|
|
// Borders are always the same for shadow as well.
|
|
aRetvalForShadow.append(new drawinglayer::primitive2d::TransformPrimitive2D(
|
|
aTransform, std::move(aCellBorderPrimitives)));
|
|
}
|
|
|
|
if(!aRetval.empty())
|
|
{
|
|
// check and create evtl. shadow for created content
|
|
const SfxItemSet& rObjectItemSet = rTableObj.GetMergedItemSet();
|
|
const drawinglayer::attribute::SdrShadowAttribute aNewShadowAttribute(
|
|
drawinglayer::primitive2d::createNewSdrShadowAttribute(rObjectItemSet));
|
|
|
|
if(!aNewShadowAttribute.isDefault())
|
|
{
|
|
// pass in table's transform and scale matrix, to
|
|
// correctly scale and align shadows
|
|
const basegfx::B2DHomMatrix aTransformScaleMatrix
|
|
= basegfx::utils::createScaleTranslateB2DHomMatrix(
|
|
aObjectRange.getRange(), aObjectRange.getMinimum());
|
|
|
|
bool bDirectShadow
|
|
= rObjectItemSet.Get(SDRATTR_SHADOW, /*bSrchInParent=*/false)
|
|
.GetValue();
|
|
if (bDirectShadow)
|
|
{
|
|
// Shadow as direct formatting: no shadow for text, to be compatible
|
|
// with PowerPoint.
|
|
aRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(
|
|
std::move(aRetval), aNewShadowAttribute, aTransformScaleMatrix,
|
|
&aRetvalForShadow);
|
|
}
|
|
else
|
|
{
|
|
// Shadow as style: shadow for text, to be backwards-compatible.
|
|
aRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(
|
|
std::move(aRetval), aNewShadowAttribute, aTransformScaleMatrix);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
rVisitor.visit(std::move(aRetval));
|
|
}
|
|
else
|
|
{
|
|
// take unrotated snap rect (direct model data) for position and size
|
|
const basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(rTableObj.GetGeoRect());
|
|
|
|
// create object matrix
|
|
const GeoStat& rGeoStat(rTableObj.GetGeoStat());
|
|
const double fShearX(-rGeoStat.mfTanShearAngle);
|
|
const double fRotate(rGeoStat.m_nRotationAngle ? toRadians(36000_deg100 - rGeoStat.m_nRotationAngle) : 0.0);
|
|
const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
|
|
aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
|
|
aObjectRange.getMinX(), aObjectRange.getMinY()));
|
|
|
|
// created an invisible outline for the cases where no visible content exists
|
|
const drawinglayer::primitive2d::Primitive2DReference xReference(
|
|
drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
|
|
aObjectMatrix));
|
|
|
|
rVisitor.visit(xReference);
|
|
}
|
|
}
|
|
|
|
void ViewObjectContactOfTableObj::createPrimitive2DSequence(
|
|
DisplayInfo const& rDisplayInfo,
|
|
drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
|
|
{
|
|
bool const isTaggedPDF(GetObjectContact().isExportTaggedPDF());
|
|
if (isTaggedPDF)
|
|
{
|
|
// this will be unbuffered and contain structure tags
|
|
const sdr::table::SdrTableObj& rTableObj =
|
|
static_cast<const sdr::table::SdrTableObj&>(*GetViewContact().TryToGetSdrObject());
|
|
return createPrimitive2DSequenceImpl(rTableObj, true, rVisitor);
|
|
}
|
|
else
|
|
{
|
|
// call it via the base class - this is supposed to be buffered
|
|
return sdr::contact::ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo, rVisitor);
|
|
}
|
|
}
|
|
|
|
void ViewContactOfTableObj::createViewIndependentPrimitive2DSequence(
|
|
drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const
|
|
{
|
|
const sdr::table::SdrTableObj& rTableObj =
|
|
static_cast<const sdr::table::SdrTableObj&>(GetSdrObject());
|
|
return createPrimitive2DSequenceImpl(rTableObj, false, rVisitor);
|
|
}
|
|
|
|
ViewObjectContact& ViewContactOfTableObj::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
|
|
{
|
|
return *new ViewObjectContactOfTableObj(rObjectContact, *this);
|
|
}
|
|
|
|
ViewContactOfTableObj::ViewContactOfTableObj(sdr::table::SdrTableObj& rTableObj)
|
|
: ViewContactOfSdrObj(rTableObj)
|
|
{
|
|
}
|
|
|
|
ViewContactOfTableObj::~ViewContactOfTableObj()
|
|
{
|
|
}
|
|
} // end of namespace
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|