/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cell.hxx" #include "tablelayouter.hxx" ////////////////////////////////////////////////////////////////////////////// using editeng::SvxBorderLine; using namespace com::sun::star; ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer { namespace primitive2d { class SdrCellPrimitive2D : public BufferedDecompositionPrimitive2D { private: basegfx::B2DHomMatrix maTransform; attribute::SdrFillTextAttribute maSdrFTAttribute; protected: // local decomposition. virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const; public: SdrCellPrimitive2D( const basegfx::B2DHomMatrix& rTransform, const attribute::SdrFillTextAttribute& rSdrFTAttribute) : BufferedDecompositionPrimitive2D(), maTransform(rTransform), maSdrFTAttribute(rSdrFTAttribute) { } // data access const basegfx::B2DHomMatrix& getTransform() const { return maTransform; } const attribute::SdrFillTextAttribute& getSdrFTAttribute() const { return maSdrFTAttribute; } // compare operator virtual bool operator==(const BasePrimitive2D& rPrimitive) const; // provide unique ID DeclPrimitive2DIDBlock() }; Primitive2DSequence SdrCellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const { // prepare unit polygon Primitive2DSequence aRetval; const basegfx::B2DPolyPolygon aUnitPolyPolygon(basegfx::tools::createUnitPolygon()); // add fill if(!getSdrFTAttribute().getFill().isDefault()) { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createPolyPolygonFillPrimitive( aUnitPolyPolygon, getTransform(), getSdrFTAttribute().getFill(), getSdrFTAttribute().getFillFloatTransGradient())); } else { // if no fill create one for HitTest and BoundRect fallback appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createHiddenGeometryPrimitives2D( true, aUnitPolyPolygon, getTransform())); } // add text if(!getSdrFTAttribute().getText().isDefault()) { appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, createTextPrimitive( aUnitPolyPolygon, getTransform(), getSdrFTAttribute().getText(), attribute::SdrLineAttribute(), true, false, false)); } return aRetval; } bool SdrCellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const { if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) { const SdrCellPrimitive2D& rCompare = (SdrCellPrimitive2D&)rPrimitive; return (getTransform() == rCompare.getTransform() && getSdrFTAttribute() == rCompare.getSdrFTAttribute()); } return false; } // provide unique ID ImplPrimitive2DIDBlock(SdrCellPrimitive2D, PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D) } // end of namespace primitive2d } // end of namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// namespace drawinglayer { namespace primitive2d { class SdrBorderlinePrimitive2D : public BufferedDecompositionPrimitive2D { private: basegfx::B2DHomMatrix maTransform; SvxBorderLine maLeftLine; SvxBorderLine maBottomLine; SvxBorderLine maRightLine; SvxBorderLine maTopLine; // Neighbor cells' borders SvxBorderLine maLeftFromTLine; SvxBorderLine maLeftFromBLine; SvxBorderLine maRightFromTLine; SvxBorderLine maRightFromBLine; SvxBorderLine maTopFromLLine; SvxBorderLine maTopFromRLine; SvxBorderLine maBottomFromLLine; SvxBorderLine maBottomFromRLine; // bitfield bool mbLeftIsOutside : 1; bool mbBottomIsOutside : 1; bool mbRightIsOutside : 1; bool mbTopIsOutside : 1; bool mbInTwips : 1; protected: // local decomposition. virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const; public: SdrBorderlinePrimitive2D( const basegfx::B2DHomMatrix& rTransform, const SvxBorderLine& rLeftLine, const SvxBorderLine& rBottomLine, const SvxBorderLine& rRightLine, const SvxBorderLine& rTopLine, const SvxBorderLine& rLeftFromTLine, const SvxBorderLine& rLeftFromBLine, const SvxBorderLine& rRightFromTLine, const SvxBorderLine& rRightFromBLine, const SvxBorderLine& rTopFromLLine, const SvxBorderLine& rTopFromRLine, const SvxBorderLine& rBottomFromLLine, const SvxBorderLine& rBottomFromRLine, bool bLeftIsOutside, bool bBottomIsOutside, bool bRightIsOutside, bool bTopIsOutside, bool bInTwips) : BufferedDecompositionPrimitive2D(), maTransform(rTransform), maLeftLine(rLeftLine), maBottomLine(rBottomLine), maRightLine(rRightLine), maTopLine(rTopLine), maLeftFromTLine(rLeftFromTLine), maLeftFromBLine(rLeftFromBLine), maRightFromTLine(rRightFromTLine), maRightFromBLine(rRightFromBLine), maTopFromLLine(rTopFromLLine), maTopFromRLine(rTopFromRLine), maBottomFromLLine(rBottomFromLLine), maBottomFromRLine(rBottomFromRLine), mbLeftIsOutside(bLeftIsOutside), mbBottomIsOutside(bBottomIsOutside), mbRightIsOutside(bRightIsOutside), mbTopIsOutside(bTopIsOutside), mbInTwips(bInTwips) { } // data access const basegfx::B2DHomMatrix& getTransform() const { return maTransform; } const SvxBorderLine& getLeftLine() const { return maLeftLine; } const SvxBorderLine& getBottomLine() const { return maBottomLine; } const SvxBorderLine& getRightLine() const { return maRightLine; } const SvxBorderLine& getTopLine() const { return maTopLine; } bool getLeftIsOutside() const { return mbLeftIsOutside; } bool getBottomIsOutside() const { return mbBottomIsOutside; } bool getRightIsOutside() const { return mbRightIsOutside; } bool getTopIsOutside() const { return mbTopIsOutside; } bool getInTwips() const { return mbInTwips; } // compare operator virtual bool operator==(const BasePrimitive2D& rPrimitive) const; // provide unique ID DeclPrimitive2DIDBlock() }; sal_uInt16 getBorderLineOutWidth(const SvxBorderLine& rLineA) { return (1 == rLineA.GetOutWidth() ? 0 : rLineA.GetOutWidth()); } sal_uInt16 getBorderLineDistance(const SvxBorderLine& rLineA) { return (1 == rLineA.GetDistance() ? 0 : rLineA.GetDistance()); } sal_uInt16 getBorderLineInWidth(const SvxBorderLine& rLineA) { return (1 == rLineA.GetInWidth() ? 0 : rLineA.GetInWidth()); } sal_uInt16 getBorderLineWidth(const SvxBorderLine& rLineA) { return getBorderLineOutWidth(rLineA) + getBorderLineDistance(rLineA) + getBorderLineInWidth(rLineA); } double getExtend(const SvxBorderLine& rLineSide, const SvxBorderLine& rLineOpposite) { double nExtend = 0.0; if(!rLineSide.isEmpty()) { // reduce to inner edge of associated matching line nExtend = -((getBorderLineWidth(rLineSide) / 2.0)); } else { nExtend = ((getBorderLineWidth(rLineOpposite) / 2.0)); } return nExtend; } double getChangedValue(sal_uInt16 nValue, bool bChangeToMM) { if(1 == nValue) return 1.0; if(bChangeToMM) return nValue * (127.0 / 72.0); return (double)nValue; } Primitive2DSequence SdrBorderlinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const { Primitive2DSequence xRetval(4); sal_uInt32 nInsert(0); const double fTwipsToMM(getInTwips() ? (127.0 / 72.0) : 1.0); if(!getLeftLine().isEmpty()) { // create left line from top to bottom const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0)); const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(0.0, 1.0)); if(!aStart.equal(aEnd)) { const double fExtendIS(getExtend(getTopLine(), maTopFromLLine)); const double fExtendIE(getExtend(getBottomLine(), maBottomFromLLine)); const double fExtendOS(getExtend(maTopFromLLine, getTopLine())); const double fExtendOE(getExtend(maBottomFromLLine, getBottomLine())); xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D( aStart, aEnd, getChangedValue(getLeftLine().GetOutWidth(), getInTwips()), getChangedValue(getLeftLine().GetDistance(), getInTwips()), getChangedValue(getLeftLine().GetInWidth(), getInTwips()), fExtendIS * fTwipsToMM, fExtendIE * fTwipsToMM, fExtendOS * fTwipsToMM, fExtendOE * fTwipsToMM, getLeftLine().GetColorOut(true).getBColor(), getLeftLine().GetColorIn(true).getBColor(), getLeftLine().GetColorGap().getBColor(), getLeftLine().HasGapColor(), getLeftLine().GetBorderLineStyle())); } } if(!getBottomLine().isEmpty() && getBottomIsOutside()) { // create bottom line from left to right const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 1.0)); const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0)); if(!aStart.equal(aEnd)) { const double fExtendIS(getExtend(getLeftLine(), maLeftFromBLine )); const double fExtendIE(getExtend(getRightLine(), maRightFromBLine)); const double fExtendOS(getExtend(maLeftFromBLine, getLeftLine())); const double fExtendOE(getExtend(maRightFromBLine, getRightLine())); xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D( aStart, aEnd, getChangedValue(getBottomLine().GetOutWidth(), getInTwips()), getChangedValue(getBottomLine().GetDistance(), getInTwips()), getChangedValue(getBottomLine().GetInWidth(), getInTwips()), fExtendIS * fTwipsToMM, fExtendIE * fTwipsToMM, fExtendOS * fTwipsToMM, fExtendOE * fTwipsToMM, getBottomLine().GetColorOut(false).getBColor(), getBottomLine().GetColorIn(false).getBColor(), getBottomLine().GetColorGap().getBColor(), getBottomLine().HasGapColor(), getBottomLine().GetBorderLineStyle())); } } if(!getRightLine().isEmpty()) { // create right line from top to bottom const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(1.0, 0.0)); const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0)); if(!aStart.equal(aEnd)) { const double fExtendIS(getExtend(getTopLine(), maTopFromRLine)); const double fExtendIE(getExtend(getBottomLine(), maBottomFromRLine)); const double fExtendOS(getExtend(maTopFromRLine, getTopLine())); const double fExtendOE(getExtend(maBottomFromRLine, getBottomLine())); xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D( aStart, aEnd, getChangedValue(getRightLine().GetOutWidth(), getInTwips()), getChangedValue(getRightLine().GetDistance(), getInTwips()), getChangedValue(getRightLine().GetInWidth(), getInTwips()), fExtendOS * fTwipsToMM, fExtendOE * fTwipsToMM, fExtendIS * fTwipsToMM, fExtendIE * fTwipsToMM, getRightLine().GetColorOut(true).getBColor(), getRightLine().GetColorIn(true).getBColor(), getRightLine().GetColorGap().getBColor(), getRightLine().HasGapColor(), getRightLine().GetBorderLineStyle())); } } if(!getTopLine().isEmpty()) { // create top line from left to right const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0)); const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 0.0)); if(!aStart.equal(aEnd)) { const double fExtendIS(getExtend(getLeftLine(), maLeftFromTLine)); const double fExtendIE(getExtend(getRightLine(), maRightFromTLine)); const double fExtendOS(getExtend(maLeftFromTLine, getLeftLine())); const double fExtendOE(getExtend(maRightFromTLine, getRightLine())); xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D( aStart, aEnd, getChangedValue(getTopLine().GetOutWidth(), getInTwips()), getChangedValue(getTopLine().GetDistance(), getInTwips()), getChangedValue(getTopLine().GetInWidth(), getInTwips()), fExtendOS * fTwipsToMM, fExtendOE * fTwipsToMM, fExtendIS * fTwipsToMM, fExtendIE * fTwipsToMM, getTopLine().GetColorOut(false).getBColor(), getTopLine().GetColorIn(false).getBColor(), getTopLine().GetColorGap().getBColor(), getTopLine().HasGapColor(), getTopLine().GetBorderLineStyle())); } } xRetval.realloc(nInsert); return xRetval; } bool SdrBorderlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const { if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) { const SdrBorderlinePrimitive2D& rCompare = (SdrBorderlinePrimitive2D&)rPrimitive; return (getTransform() == rCompare.getTransform() && getLeftLine() == rCompare.getLeftLine() && getBottomLine() == rCompare.getBottomLine() && getRightLine() == rCompare.getRightLine() && getTopLine() == rCompare.getTopLine() && maLeftFromTLine == rCompare.maLeftFromTLine && maLeftFromBLine == rCompare.maLeftFromBLine && maRightFromTLine == rCompare.maRightFromTLine && maRightFromBLine == rCompare.maRightFromBLine && maTopFromLLine == rCompare.maTopFromLLine && maTopFromRLine == rCompare.maTopFromRLine && maBottomFromLLine == rCompare.maBottomFromLLine && maBottomFromRLine == rCompare.maBottomFromRLine && getLeftIsOutside() == rCompare.getLeftIsOutside() && getBottomIsOutside() == rCompare.getBottomIsOutside() && getRightIsOutside() == rCompare.getRightIsOutside() && getTopIsOutside() == rCompare.getTopIsOutside() && getInTwips() == rCompare.getInTwips()); } return false; } // provide unique ID ImplPrimitive2DIDBlock(SdrBorderlinePrimitive2D, PRIMITIVE2D_ID_SDRBORDERLINEPRIMITIVE2D) } // end of namespace primitive2d } // end of namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// namespace sdr { namespace contact { void impGetLine(SvxBorderLine& aLine, 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 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( ); } return; } } // no success, copy empty line const SvxBorderLine aEmptyLine; aLine = aEmptyLine; } drawinglayer::primitive2d::Primitive2DSequence ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const { const sdr::table::SdrTableObj& rTableObj = GetTableObj(); const uno::Reference< com::sun::star::table::XTable > xTable = rTableObj.getTable(); if(xTable.is()) { // create primitive representation for table drawinglayer::primitive2d::Primitive2DSequence xRetval; const sal_Int32 nRowCount(xTable->getRowCount()); const sal_Int32 nColCount(xTable->getColumnCount()); const sal_Int32 nAllCount(nRowCount * nColCount); if(nAllCount) { const sdr::table::TableLayouter& rTableLayouter = rTableObj.getTableLayouter(); const bool bIsRTL(com::sun::star::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 Rectangle& rObjectRectangle(rTableObj.GetGeoRect()); const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom()); // for each cell we need potentially a cell primitive and a border primitive // (e.g. single cell). Prepare sequences and input counters drawinglayer::primitive2d::Primitive2DSequence xCellSequence(nAllCount); drawinglayer::primitive2d::Primitive2DSequence xBorderSequence(nAllCount); sal_uInt32 nCellInsert(0); sal_uInt32 nBorderInsert(0); // variables for border lines SvxBorderLine aLeftLine; SvxBorderLine aBottomLine; SvxBorderLine aRightLine; SvxBorderLine aTopLine; SvxBorderLine aLeftFromTLine; SvxBorderLine aLeftFromBLine; SvxBorderLine aRightFromTLine; SvxBorderLine aRightFromBLine; SvxBorderLine aTopFromLLine; SvxBorderLine aTopFromRLine; SvxBorderLine aBottomFromLLine; SvxBorderLine aBottomFromRLine; // create single primitives per cell for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++) { for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++) { xCurrentCell.set(dynamic_cast< sdr::table::Cell* >(xTable->getCellByPosition(aCellPos.mnCol, aCellPos.mnRow).get())); if(xCurrentCell.is() && !xCurrentCell->isMerged()) { if(rTableLayouter.getCellArea(aCellPos, aCellArea)) { // create cell transformation matrix basegfx::B2DHomMatrix aCellMatrix; aCellMatrix.set(0, 0, (double)aCellArea.getWidth()); aCellMatrix.set(1, 1, (double)aCellArea.getHeight()); aCellMatrix.set(0, 2, (double)aCellArea.getMinX() + aObjectRange.getMinX()); aCellMatrix.set(1, 2, (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)); xCellSequence[nCellInsert++] = xCellReference; } // handle cell borders const sal_Int32 nX(bIsRTL ? nColCount - aCellPos.mnCol : aCellPos.mnCol); const sal_Int32 nY(aCellPos.mnRow); // get access values for X,Y at the cell's end const sal_Int32 nXSpan(xCurrentCell->getColumnSpan()); const sal_Int32 nYSpan(xCurrentCell->getRowSpan()); const sal_Int32 nXRight(bIsRTL ? nX - nXSpan : nX + nXSpan); const sal_Int32 nYBottom(nY + nYSpan); // get basic lines impGetLine(aLeftLine, rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL); //To resolve the bug fdo#59117 //In RTL table as BottomLine & TopLine are drawn from Left Side to Right, nX should be nX-1 impGetLine(aBottomLine, rTableLayouter, bIsRTL?nX-1:nX, nYBottom, true, nColCount, nRowCount, bIsRTL); impGetLine(aRightLine, rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL); impGetLine(aTopLine, rTableLayouter, bIsRTL?nX-1:nX, nY, true, nColCount, nRowCount, bIsRTL); // get the neighbor cells' borders impGetLine(aLeftFromTLine, rTableLayouter, nX, nY - 1, false, nColCount, nRowCount, bIsRTL); impGetLine(aLeftFromBLine, rTableLayouter, nX, nYBottom + 1, false, nColCount, nRowCount, bIsRTL); impGetLine(aRightFromTLine, rTableLayouter, nXRight, nY - 1, false, nColCount, nRowCount, bIsRTL); impGetLine(aRightFromBLine, rTableLayouter, nXRight, nYBottom + 1, false, nColCount, nRowCount, bIsRTL); impGetLine(aTopFromLLine, rTableLayouter, nX - 1, nY, true, nColCount, nRowCount, bIsRTL); impGetLine(aTopFromRLine, rTableLayouter, nXRight + 1, nY, true, nColCount, nRowCount, bIsRTL); impGetLine(aBottomFromLLine, rTableLayouter, nX - 1, nYBottom, true, nColCount, nRowCount, bIsRTL); impGetLine(aBottomFromRLine, rTableLayouter, nXRight + 1, nYBottom, true, nColCount, nRowCount, bIsRTL); // create the primtive containing all data for one cell with borders xBorderSequence[nBorderInsert++] = drawinglayer::primitive2d::Primitive2DReference( new drawinglayer::primitive2d::SdrBorderlinePrimitive2D( aCellMatrix, aLeftLine, aBottomLine, aRightLine, aTopLine, aLeftFromTLine, aLeftFromBLine, aRightFromTLine, aRightFromBLine, aTopFromLLine, aTopFromRLine, aBottomFromLLine, aBottomFromRLine, bIsRTL ? nX == nColCount : 0 == nX, nRowCount == nYBottom, bIsRTL ? 0 == nXRight : nXRight == nColCount, 0 == nY, true)); } } } } // no empty references; reallocate sequences by used count xCellSequence.realloc(nCellInsert); xBorderSequence.realloc(nBorderInsert); // append to target. We want fillings and text first xRetval = xCellSequence; drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, xBorderSequence); } if(xRetval.hasElements()) { // 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()) { xRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(xRetval, aNewShadowAttribute); } } return xRetval; } else { // take unrotated snap rect (direct model data) for position and size const Rectangle& rRectangle = rTableObj.GetGeoRect(); const basegfx::B2DRange aObjectRange( rRectangle.Left(), rRectangle.Top(), rRectangle.Right(), rRectangle.Bottom()); // create object matrix const GeoStat& rGeoStat(rTableObj.GetGeoStat()); const double fShearX(rGeoStat.nShearWink ? tan((36000 - rGeoStat.nShearWink) * F_PI18000) : 0.0); const double fRotate(rGeoStat.nDrehWink ? (36000 - rGeoStat.nDrehWink) * F_PI18000 : 0.0); const basegfx::B2DHomMatrix aObjectMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate, aObjectRange.getMinX(), aObjectRange.getMinY())); // credate an invisible outline for the cases where no visible content exists const drawinglayer::primitive2d::Primitive2DReference xReference( drawinglayer::primitive2d::createHiddenGeometryPrimitives2D( false, aObjectMatrix)); return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1); } } ViewContactOfTableObj::ViewContactOfTableObj(::sdr::table::SdrTableObj& rTableObj) : ViewContactOfSdrObj(rTableObj) { } ViewContactOfTableObj::~ViewContactOfTableObj() { } } // end of namespace contact } // end of namespace sdr /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ > LibreOffice 核心代码仓库文档基金会
summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2025-01-10ITEM: Refactor ItemTypeArmin Le Grand (Collabora)
ItemType is useful and faster than RTTI. Until now it was implemented by a 16-bit member in the base class, plus (potentially) all constructors having to hand a value in at item construction type (of type SfxItemType) to get that member set correctly. This works, but there is no reliable way to guarantee coverage, and there have already been cases with missing SfxItemType - these fallback to '0' and thus all Items with ItemType() == 0 are assumed equal and might be static_cast'ed to the wrong classes. Note that I identified *35* Items that had no correct ItemType set/implemented actually. It also uses 16-bit per incarnated Item at runtime. I thought and realized now a more systematic approach to do that with a pure virtual function at the Item itself. That can also be secured by a clang compiler plugin in the future to keep it working. It uses one virtual function per derived class, no longer space in incarnated Items. Also the constructors will get more simple again. But the main aspect is security - we cannot afford Items potentially being held as equal if they are not. Unfortunately C++ does not offer something like a 'strict pure virtual function' that would force to be overloaded in every derivation, but the used methotology and adding a clang test is reasonably safe. Have now done the cleanup of previous method. Change-Id: I04768285f1e9b73d64b0bb87df401944b5d35678 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/180017 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
2024-07-26fix in some missing SfxItemTypesNoel Grandin
Change-Id: I7dcb9768a8cd63200b8f8c50d8170e78ff5aeec2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171068 Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk> Tested-by: Jenkins
2020-02-02tdf#128302: Split SVXCORE_DLLPUBLIC from SVX_DLLPUBLICStephan Bergmann
Using SVX_DLLPUBLIC for both Library_svxcore and Library_svx had started to cause failures with clang-cl on Windows now, presumably due to devirtualization: > linectrl.o : error LNK2001: unresolved external symbol "protected: virtual void __cdecl SvxMetricField::DataChanged(class DataChangedEvent const &)" (?DataChanged@SvxMetricField@@MEAAXAEBVDataChangedEvent@@@Z) > linectrl.o : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl SvxMetricField::PreNotify(class NotifyEvent &)" (?PreNotify@SvxMetricField@@MEAA_NAEAVNotifyEvent@@@Z) > linectrl.o : error LNK2001: unresolved external symbol "protected: virtual bool __cdecl SvxMetricField::EventNotify(class NotifyEvent &)" (?EventNotify@SvxMetricField@@MEAA_NAEAVNotifyEvent@@@Z) > linectrl.o : error LNK2001: unresolved external symbol "protected: virtual void __cdecl SvxMetricField::Modify(void)" (?Modify@SvxMetricField@@MEAAXXZ) > linectrl.o : error LNK2001: unresolved external symbol "private: virtual bool __cdecl SvxFillAttrBox::PreNotify(class NotifyEvent &)" (?PreNotify@SvxFillAttrBox@@EEAA_NAEAVNotifyEvent@@@Z) > linectrl.o : error LNK2001: unresolved external symbol "private: virtual bool __cdecl SvxFillAttrBox::EventNotify(class NotifyEvent &)" (?EventNotify@SvxFillAttrBox@@EEAA_NAEAVNotifyEvent@@@Z) > C:\lo-clang\core\instdir\program\svxcorelo.dll : fatal error LNK1120: 6 unresolved externals Replacing certain uses of SVX_DLLPUBLIC with the newly introduced SVXCORE_DLLPUBLIC (include/svx/svxdllapi.h) has been done on Linux as follows: > git grep -w --line-number -e SVX_DLLPUBLIC --and --not -e '#define SVX_DLLPUBLIC' >LINES to produce a file LINES containing all 640 uses. (Conveniently, all uses happen to be on different lines.) Manually create a file TOKENS with 640 corresponding lines, each containing the (class or function) name that is made SVX_DLLPUBLIC by in the corresponding line in LINES. Then > nm -D --def instdir/program/libsvxcorelo.so | grep -ivw '[vw]' | c++filt >SVXCORESYMS > nm -D --def instdir/program/libsvxlo.so | grep -ivw '[vw]' | c++filt >SVXSYMS > n=$(cat TOKENS | wc -l) > for ((i=1;i<="$n";++i)); do > tok=$(head -n "$i" TOKENS | tail -1) > printf @ > grep -Fw "$tok" SVXCORESYMS >/dev/null && printf svxcore > printf @ > grep -Fw "$tok" SVXSYMS >/dev/null && printf svx > printf '@ ' > head -n "$i" LINES | tail -1 > done to generate 640 output lines detailing for each SVX_DLLPUBLIC name occurrene whether it is mentioned in exports from neither (@@@), only from svx (@@svx@), only from svxcore (@svxcore@@), or from both libraries (@svxcore@svx@). The numbers that gives is 10 @@@ 180 @@svx@ 424 @svxcore@@ 26 @svxcore@svx@ The 10 @@@ ask for follow-up clean up, but most of them are just left as SVX_DLLPUBLIC for now. The exceptions are sxv::ITextProvider (include/svx/itextprovider.hxx) and SdrCustomShapeGeometryItem::PropertyPairHash (include/svx/sdasitm.hxx, where PropertyPairHash is a member struct of SVXCORE_DLLPUBLIC SdrCustomShapeGeometryItem). Keeping them as SVX_DLLPUBLIC would cause "unresolved externals" errors when linking Library_svxcore on Windows. The 180 @@svx@ are fine to keep as-is, and the 424 @svxcore@@ need rewriting. The 26 @svxcore@svx@ needed manual inspection to decide (in some cases, the chosen name in TOKENS was a too generic function name like Fill, in other cases it was the name of a class exported from one library but also mentioned in the arguments of a function exported from the other). And for sdr::table::SdrTableObj the class itself is defined in svxcore while the static member functions ExportAsRTF and ImportAsRTF are defined in svx. But MSVC does not allow to mark the class as SVXCORE_DLLPUBLIC and the two static member functions as SVX_DLLPLUBIC, so move the two functions out of the class. (There appears to be no real necessity that they were static member functions in the first place; they don't even need to be friends of the class. Nevertheless, this mixture of functionality from svxcore and svx in include/svx/svdotable.hxx may ask for follow-up clean up, one way or another.) All the output lines that need rewriting (all the @svxcore@@ ones, and the manually picked subset of @@@ and @svxcore@svx@ ones) are copied into a new file CHANGE (containing 451 lines). Then > sed -E -e 's|^@.*@.*@ ([^:]+):([0-9]+):.*$|sed -i -e "\2 s/SVX_DLLPUBLIC/SVXCORE_DLLPUBLIC/" \1|' <CHANGE >COMMANDS > . COMMANDS to do the changes. Change-Id: If9b6dd1c9e9ba2eb883dbdac4385d28c6fc8a203 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87794 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-12-12use covariant return type for SfxPoolItem::CloneCaolán McNamara
and can then remove some casting Change-Id: Id821c32ca2cbcdb7f57ef7a5fa1960042e630ffc Reviewed-on: https://gerrit.libreoffice.org/85022 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
2019-12-03remove some useless comment linesNoel Grandin
which merely announce that the next declaration is a class Change-Id: Ifdb1398bcd99816b13e0b3769b46d0562bfbc1dc Reviewed-on: https://gerrit.libreoffice.org/84229 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
2019-10-30loplugin:finalclasses svxNoel Grandin
Change-Id: If55e51b8627083ba3ece2b3270adb47668b25e9d Reviewed-on: https://gerrit.libreoffice.org/81705 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>