/src/libreoffice/svx/source/table/viewcontactoftableobj.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | |
21 | | #include "viewcontactoftableobj.hxx" |
22 | | #include <svx/svdotable.hxx> |
23 | | #include <com/sun/star/table/XTable.hpp> |
24 | | #include <basegfx/polygon/b2dpolygontools.hxx> |
25 | | #include <sdr/primitive2d/sdrattributecreator.hxx> |
26 | | #include <sdr/primitive2d/sdrdecompositiontools.hxx> |
27 | | #include <sdr/primitive2d/sdrcellprimitive.hxx> |
28 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
29 | | #include <sdr/attribute/sdrtextattribute.hxx> |
30 | | #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx> |
31 | | #include <editeng/borderline.hxx> |
32 | | #include <drawinglayer/attribute/sdrlineattribute.hxx> |
33 | | #include <drawinglayer/attribute/sdrshadowattribute.hxx> |
34 | | #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx> |
35 | | #include <drawinglayer/primitive2d/structuretagprimitive2d.hxx> |
36 | | #include <drawinglayer/primitive2d/transformprimitive2d.hxx> |
37 | | #include <basegfx/matrix/b2dhommatrixtools.hxx> |
38 | | #include <svx/sdr/contact/viewobjectcontactofsdrobj.hxx> |
39 | | #include <svx/sdr/contact/objectcontact.hxx> |
40 | | #include <svx/svdpage.hxx> |
41 | | #include <svx/framelink.hxx> |
42 | | #include <svx/framelinkarray.hxx> |
43 | | #include <svx/sdooitm.hxx> |
44 | | #include <utility> |
45 | | #include <vcl/canvastools.hxx> |
46 | | #include <vcl/pdfwriter.hxx> |
47 | | #include <o3tl/unit_conversion.hxx> |
48 | | #include <svx/xfltrit.hxx> |
49 | | |
50 | | #include <cell.hxx> |
51 | | #include "tablelayouter.hxx" |
52 | | |
53 | | |
54 | | using editeng::SvxBorderLine; |
55 | | using namespace com::sun::star; |
56 | | |
57 | | |
58 | | namespace drawinglayer::primitive2d |
59 | | { |
60 | | Primitive2DReference SdrCellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const |
61 | 0 | { |
62 | 0 | Primitive2DContainer aContainer; |
63 | | // prepare unit polygon |
64 | 0 | const basegfx::B2DPolyPolygon aUnitPolyPolygon(basegfx::utils::createUnitPolygon()); |
65 | | |
66 | | // add fill |
67 | 0 | if(!getSdrFTAttribute().getFill().isDefault()) |
68 | 0 | { |
69 | 0 | basegfx::B2DPolyPolygon aTransformed(aUnitPolyPolygon); |
70 | |
|
71 | 0 | aTransformed.transform(getTransform()); |
72 | 0 | aContainer.push_back( |
73 | 0 | createPolyPolygonFillPrimitive( |
74 | 0 | aTransformed, |
75 | 0 | getSdrFTAttribute().getFill(), |
76 | 0 | getSdrFTAttribute().getFillFloatTransGradient())); |
77 | 0 | } |
78 | 0 | else |
79 | 0 | { |
80 | | // if no fill create one for HitTest and BoundRect fallback |
81 | 0 | aContainer.push_back( |
82 | 0 | createHiddenGeometryPrimitives2D( |
83 | 0 | true, |
84 | 0 | aUnitPolyPolygon, |
85 | 0 | getTransform())); |
86 | 0 | } |
87 | | |
88 | | // add text |
89 | 0 | if(!getSdrFTAttribute().getText().isDefault()) |
90 | 0 | { |
91 | 0 | aContainer.push_back( |
92 | 0 | createTextPrimitive( |
93 | 0 | aUnitPolyPolygon, |
94 | 0 | getTransform(), |
95 | 0 | getSdrFTAttribute().getText(), |
96 | 0 | attribute::SdrLineAttribute(), |
97 | 0 | true, |
98 | 0 | false)); |
99 | 0 | } |
100 | 0 | return new GroupPrimitive2D(std::move(aContainer)); |
101 | 0 | } |
102 | | |
103 | | bool SdrCellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const |
104 | 0 | { |
105 | 0 | if(BufferedDecompositionPrimitive2D::operator==(rPrimitive)) |
106 | 0 | { |
107 | 0 | const SdrCellPrimitive2D& rCompare = static_cast<const SdrCellPrimitive2D&>(rPrimitive); |
108 | |
|
109 | 0 | return (getTransform() == rCompare.getTransform() |
110 | 0 | && getSdrFTAttribute() == rCompare.getSdrFTAttribute()); |
111 | 0 | } |
112 | | |
113 | 0 | return false; |
114 | 0 | } |
115 | | |
116 | | // provide unique ID |
117 | | sal_uInt32 SdrCellPrimitive2D::getPrimitive2DID() const |
118 | 0 | { |
119 | 0 | return PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D; |
120 | 0 | } |
121 | | |
122 | | } // end of namespace |
123 | | |
124 | | namespace sdr::contact |
125 | | { |
126 | | |
127 | | namespace { |
128 | | class ViewObjectContactOfTableObj : public ViewObjectContactOfSdrObj |
129 | | { |
130 | | public: |
131 | | ViewObjectContactOfTableObj(ObjectContact& rObjectContact, ViewContact& rViewContact) |
132 | 0 | : ViewObjectContactOfSdrObj(rObjectContact, rViewContact) |
133 | 0 | { |
134 | 0 | } |
135 | | |
136 | | protected: |
137 | | virtual void createPrimitive2DSequence(DisplayInfo const& rDisplayInfo, drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const override; |
138 | | }; |
139 | | } // namespace |
140 | | |
141 | | static svx::frame::Style impGetLineStyle( |
142 | | const sdr::table::TableLayouter& rLayouter, |
143 | | sal_Int32 nX, |
144 | | sal_Int32 nY, |
145 | | bool bHorizontal, |
146 | | sal_Int32 nColCount, |
147 | | sal_Int32 nRowCount, |
148 | | bool bIsRTL) |
149 | 0 | { |
150 | 0 | if(nX >= 0 && nX <= nColCount && nY >= 0 && nY <= nRowCount) |
151 | 0 | { |
152 | 0 | const SvxBorderLine* pLine = rLayouter.getBorderLine(nX, nY, bHorizontal); |
153 | |
|
154 | 0 | if(pLine) |
155 | 0 | { |
156 | | // copy line content |
157 | 0 | SvxBorderLine aLine(*pLine); |
158 | | |
159 | | // check for mirroring. This shall always be done when it is |
160 | | // not a top- or rightmost line |
161 | 0 | bool bMirror(aLine.isDouble()); |
162 | |
|
163 | 0 | if(bMirror) |
164 | 0 | { |
165 | 0 | if(bHorizontal) |
166 | 0 | { |
167 | | // mirror all bottom lines |
168 | 0 | bMirror = (0 != nY); |
169 | 0 | } |
170 | 0 | else |
171 | 0 | { |
172 | | // mirror all left lines |
173 | 0 | bMirror = (bIsRTL ? 0 != nX : nX != nColCount); |
174 | 0 | } |
175 | 0 | } |
176 | |
|
177 | 0 | if(bMirror) |
178 | 0 | { |
179 | 0 | aLine.SetMirrorWidths( ); |
180 | 0 | } |
181 | |
|
182 | 0 | constexpr double fTwipsToMM( |
183 | 0 | o3tl::convert(1.0, o3tl::Length::twip, o3tl::Length::mm100)); |
184 | 0 | return svx::frame::Style(&aLine, fTwipsToMM); |
185 | 0 | } |
186 | 0 | } |
187 | | |
188 | | // no success, copy empty line |
189 | 0 | return svx::frame::Style(); |
190 | 0 | } |
191 | | |
192 | | static void createPrimitive2DSequenceImpl( |
193 | | sdr::table::SdrTableObj const& rTableObj, |
194 | | bool const isTaggedPDF, |
195 | | drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) |
196 | 0 | { |
197 | 0 | const rtl::Reference< table::TableModel >& xTable = rTableObj.getUnoTable(); |
198 | |
|
199 | 0 | if(xTable.is()) |
200 | 0 | { |
201 | | // create primitive representation for table. Cell info goes |
202 | | // directly to aRetval, Border info to aBorderSequence and added |
203 | | // later to get the correct overlapping |
204 | 0 | drawinglayer::primitive2d::Primitive2DContainer aRetval; |
205 | 0 | drawinglayer::primitive2d::Primitive2DContainer aRetvalForShadow; |
206 | 0 | const sal_Int32 nRowCount(xTable->getRowCount()); |
207 | 0 | const sal_Int32 nColCount(xTable->getColumnCount()); |
208 | 0 | const sal_Int32 nAllCount(nRowCount * nColCount); |
209 | 0 | SdrPage const*const pPage(rTableObj.getSdrPageFromSdrObject()); |
210 | |
|
211 | 0 | if(nAllCount) |
212 | 0 | { |
213 | 0 | const sdr::table::TableLayouter& rTableLayouter(rTableObj.getTableLayouter()); |
214 | 0 | const bool bIsRTL(css::text::WritingMode_RL_TB == rTableObj.GetWritingMode()); |
215 | 0 | sdr::table::CellPos aCellPos; |
216 | 0 | sdr::table::CellRef xCurrentCell; |
217 | 0 | basegfx::B2IRectangle aCellArea; |
218 | | |
219 | | // create range using the model data directly. This is in SdrTextObj::aRect which i will access using |
220 | | // GetGeoRect() to not trigger any calculations. It's the unrotated geometry. |
221 | 0 | const basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(rTableObj.GetGeoRect()); |
222 | | |
223 | | // To create the CellBorderPrimitives, use the tooling from svx::frame::Array |
224 | | // which is capable of creating the needed visualization. Fill it during the |
225 | | // anyways needed run over the table. |
226 | 0 | svx::frame::Array aArray; |
227 | | |
228 | | // initialize CellBorderArray for primitive creation |
229 | 0 | aArray.Initialize(nColCount, nRowCount); |
230 | | |
231 | | // create single primitives per cell |
232 | 0 | for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++) |
233 | 0 | { |
234 | 0 | drawinglayer::primitive2d::Primitive2DContainer row; |
235 | | // add RowHeight to CellBorderArray for primitive creation |
236 | 0 | aArray.SetRowHeight(aCellPos.mnRow, rTableLayouter.getRowHeight(aCellPos.mnRow)); |
237 | |
|
238 | 0 | for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++) |
239 | 0 | { |
240 | 0 | drawinglayer::primitive2d::Primitive2DContainer cell; |
241 | | // add ColWidth to CellBorderArray for primitive creation, only |
242 | | // needs to be done in the 1st run |
243 | 0 | if(0 == aCellPos.mnRow) |
244 | 0 | { |
245 | 0 | aArray.SetColWidth(aCellPos.mnCol, rTableLayouter.getColumnWidth(aCellPos.mnCol)); |
246 | 0 | } |
247 | | |
248 | | // access the cell |
249 | 0 | xCurrentCell = xTable->getCell(aCellPos.mnCol, aCellPos.mnRow); |
250 | |
|
251 | 0 | if(xCurrentCell.is()) |
252 | 0 | { |
253 | | // tdf#135843: Find correct neighbor cell index for merged cells |
254 | 0 | auto nNextCol = aCellPos.mnCol + xCurrentCell->getColumnSpan(); |
255 | 0 | auto nNextRow = aCellPos.mnRow + xCurrentCell->getRowSpan(); |
256 | | |
257 | | // copy styles for current cell to CellBorderArray for primitive creation |
258 | 0 | aArray.SetCellStyleLeft( |
259 | 0 | aCellPos.mnCol, aCellPos.mnRow, |
260 | 0 | impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, |
261 | 0 | false, nColCount, nRowCount, bIsRTL)); |
262 | 0 | aArray.SetCellStyleRight( |
263 | 0 | aCellPos.mnCol, aCellPos.mnRow, |
264 | 0 | impGetLineStyle(rTableLayouter, nNextCol, aCellPos.mnRow, false, |
265 | 0 | nColCount, nRowCount, bIsRTL)); |
266 | 0 | aArray.SetCellStyleTop( |
267 | 0 | aCellPos.mnCol, aCellPos.mnRow, |
268 | 0 | impGetLineStyle(rTableLayouter, aCellPos.mnCol, aCellPos.mnRow, |
269 | 0 | true, nColCount, nRowCount, bIsRTL)); |
270 | 0 | aArray.SetCellStyleBottom( |
271 | 0 | aCellPos.mnCol, aCellPos.mnRow, |
272 | 0 | impGetLineStyle(rTableLayouter, aCellPos.mnCol, nNextRow, true, |
273 | 0 | nColCount, nRowCount, bIsRTL)); |
274 | | |
275 | | // ignore merged cells (all except the top-left of a merged cell) |
276 | 0 | if(!xCurrentCell->isMerged()) |
277 | 0 | { |
278 | | // check if we are the top-left of a merged cell |
279 | 0 | const sal_Int32 nXSpan(xCurrentCell->getColumnSpan()); |
280 | 0 | const sal_Int32 nYSpan(xCurrentCell->getRowSpan()); |
281 | |
|
282 | 0 | if(nXSpan > 1 || nYSpan > 1) |
283 | 0 | { |
284 | | // if merged, set so at CellBorderArray for primitive creation |
285 | 0 | aArray.SetMergedRange(aCellPos.mnCol, aCellPos.mnRow, aCellPos.mnCol + nXSpan - 1, aCellPos.mnRow + nYSpan - 1); |
286 | 0 | } |
287 | 0 | } |
288 | 0 | } |
289 | |
|
290 | 0 | if(xCurrentCell.is() && !xCurrentCell->isMerged()) |
291 | 0 | { |
292 | 0 | if(rTableLayouter.getCellArea(xCurrentCell, aCellPos, aCellArea)) |
293 | 0 | { |
294 | | // create cell transformation matrix |
295 | 0 | basegfx::B2DHomMatrix aCellMatrix; |
296 | 0 | aCellMatrix.set(0, 0, static_cast<double>(aCellArea.getWidth())); |
297 | 0 | aCellMatrix.set(1, 1, static_cast<double>(aCellArea.getHeight())); |
298 | 0 | aCellMatrix.set(0, 2, static_cast<double>(aCellArea.getMinX()) + aObjectRange.getMinX()); |
299 | 0 | aCellMatrix.set(1, 2, static_cast<double>(aCellArea.getMinY()) + aObjectRange.getMinY()); |
300 | | |
301 | | // handle cell fillings and text |
302 | 0 | const SfxItemSet& rCellItemSet = xCurrentCell->GetItemSet(); |
303 | 0 | const sal_uInt32 nTextIndex(nColCount * aCellPos.mnRow + aCellPos.mnCol); |
304 | 0 | const SdrText* pSdrText = rTableObj.getText(nTextIndex); |
305 | 0 | drawinglayer::attribute::SdrFillTextAttribute aAttribute; |
306 | |
|
307 | 0 | if(pSdrText) |
308 | 0 | { |
309 | | // #i101508# take cell's local text frame distances into account |
310 | 0 | const sal_Int32 nLeft(xCurrentCell->GetTextLeftDistance()); |
311 | 0 | const sal_Int32 nRight(xCurrentCell->GetTextRightDistance()); |
312 | 0 | const sal_Int32 nUpper(xCurrentCell->GetTextUpperDistance()); |
313 | 0 | const sal_Int32 nLower(xCurrentCell->GetTextLowerDistance()); |
314 | |
|
315 | 0 | aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute( |
316 | 0 | rCellItemSet, |
317 | 0 | pSdrText, |
318 | 0 | &nLeft, |
319 | 0 | &nUpper, |
320 | 0 | &nRight, |
321 | 0 | &nLower); |
322 | 0 | } |
323 | 0 | else |
324 | 0 | { |
325 | 0 | aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute( |
326 | 0 | rCellItemSet, |
327 | 0 | pSdrText); |
328 | 0 | } |
329 | | |
330 | | // always create cell primitives for BoundRect and HitTest |
331 | 0 | { |
332 | 0 | const drawinglayer::primitive2d::Primitive2DReference xCellReference( |
333 | 0 | new drawinglayer::primitive2d::SdrCellPrimitive2D( |
334 | 0 | aCellMatrix, aAttribute)); |
335 | 0 | cell.append(xCellReference); |
336 | 0 | } |
337 | | |
338 | | // Create cell primitive without text. |
339 | 0 | aAttribute |
340 | 0 | = drawinglayer::primitive2d::createNewSdrFillTextAttribute( |
341 | 0 | rCellItemSet, nullptr); |
342 | 0 | rtl::Reference pCellReference |
343 | 0 | = new drawinglayer::primitive2d::SdrCellPrimitive2D( |
344 | 0 | aCellMatrix, aAttribute); |
345 | |
|
346 | 0 | sal_uInt16 nTransparence( |
347 | 0 | rCellItemSet.Get(XATTR_FILLTRANSPARENCE).GetValue()); |
348 | 0 | if (nTransparence != 0) |
349 | 0 | { |
350 | 0 | pCellReference->setTransparenceForShadow(nTransparence); |
351 | 0 | } |
352 | |
|
353 | 0 | const drawinglayer::primitive2d::Primitive2DReference |
354 | 0 | xCellReference(pCellReference); |
355 | 0 | aRetvalForShadow.append(xCellReference); |
356 | 0 | } |
357 | 0 | } |
358 | 0 | if (isTaggedPDF && pPage) |
359 | 0 | { |
360 | | // heuristic: if there's a special formatting on |
361 | | // first row, assume that it's a header row |
362 | 0 | auto const eType( |
363 | 0 | aCellPos.mnRow == 0 && rTableObj.getTableStyleSettings().mbUseFirstRow |
364 | 0 | ? vcl::pdf::StructElement::TableHeader |
365 | 0 | : vcl::pdf::StructElement::TableData); |
366 | 0 | cell = drawinglayer::primitive2d::Primitive2DContainer { |
367 | 0 | new drawinglayer::primitive2d::StructureTagPrimitive2D( |
368 | 0 | eType, |
369 | 0 | pPage->IsMasterPage(), |
370 | 0 | false, |
371 | 0 | false, |
372 | 0 | std::move(cell)) }; |
373 | 0 | } |
374 | 0 | row.append(cell); |
375 | 0 | } |
376 | |
|
377 | 0 | if (isTaggedPDF && pPage) |
378 | 0 | { |
379 | 0 | row = drawinglayer::primitive2d::Primitive2DContainer { |
380 | 0 | new drawinglayer::primitive2d::StructureTagPrimitive2D( |
381 | 0 | vcl::pdf::StructElement::TableRow, |
382 | 0 | pPage->IsMasterPage(), |
383 | 0 | false, |
384 | 0 | false, |
385 | 0 | std::move(row)) }; |
386 | 0 | } |
387 | 0 | aRetval.append(row); |
388 | 0 | } |
389 | | |
390 | | // now create all CellBorderPrimitives |
391 | 0 | drawinglayer::primitive2d::Primitive2DContainer aCellBorderPrimitives(aArray.CreateB2DPrimitiveArray()); |
392 | |
|
393 | 0 | if(!aCellBorderPrimitives.empty()) |
394 | 0 | { |
395 | | // this is already scaled (due to Table in non-uniform coordinates), so |
396 | | // first transform removing scale |
397 | 0 | basegfx::B2DHomMatrix aTransform( |
398 | 0 | basegfx::utils::createScaleB2DHomMatrix( |
399 | 0 | 1.0 / aObjectRange.getWidth(), |
400 | 0 | 1.0 / aObjectRange.getHeight())); |
401 | | |
402 | | // If RTL, mirror the whole unified table in X and move right. |
403 | | // This is much easier than taking this into account for the whole |
404 | | // index calculations |
405 | 0 | if(bIsRTL) |
406 | 0 | { |
407 | 0 | aTransform.scale(-1.0, 1.0); |
408 | 0 | aTransform.translate(1.0, 0.0); |
409 | 0 | } |
410 | | |
411 | | // create object matrix |
412 | 0 | const GeoStat& rGeoStat(rTableObj.GetGeoStat()); |
413 | 0 | const double fShearX(-rGeoStat.mfTanShearAngle); |
414 | 0 | const double fRotate(rGeoStat.m_nRotationAngle ? toRadians(36000_deg100 - rGeoStat.m_nRotationAngle) : 0.0); |
415 | 0 | const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
416 | 0 | aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate, |
417 | 0 | aObjectRange.getMinX(), aObjectRange.getMinY())); |
418 | | |
419 | | // add object matrix to transform. By doing so theoretically |
420 | | // CellBorders could be also rotated/sheared for the first time ever. |
421 | | // To completely make that work, the primitives already created in |
422 | | // aRetval would also have to be based on ObjectMatrix, not only on |
423 | | // ObjectRange as it currently is. |
424 | 0 | aTransform *= aObjectMatrix; |
425 | | |
426 | | // create a transform primitive with this and embed CellBorders |
427 | | // and append to retval |
428 | 0 | aRetval.append( |
429 | 0 | new drawinglayer::primitive2d::TransformPrimitive2D( |
430 | 0 | aTransform, |
431 | 0 | drawinglayer::primitive2d::Primitive2DContainer(aCellBorderPrimitives))); |
432 | | |
433 | | // Borders are always the same for shadow as well. |
434 | 0 | aRetvalForShadow.append(new drawinglayer::primitive2d::TransformPrimitive2D( |
435 | 0 | aTransform, std::move(aCellBorderPrimitives))); |
436 | 0 | } |
437 | |
|
438 | 0 | if(!aRetval.empty()) |
439 | 0 | { |
440 | | // check and create evtl. shadow for created content |
441 | 0 | const SfxItemSet& rObjectItemSet = rTableObj.GetMergedItemSet(); |
442 | 0 | const drawinglayer::attribute::SdrShadowAttribute aNewShadowAttribute( |
443 | 0 | drawinglayer::primitive2d::createNewSdrShadowAttribute(rObjectItemSet)); |
444 | |
|
445 | 0 | if(!aNewShadowAttribute.isDefault()) |
446 | 0 | { |
447 | | // pass in table's transform and scale matrix, to |
448 | | // correctly scale and align shadows |
449 | 0 | const basegfx::B2DHomMatrix aTransformScaleMatrix |
450 | 0 | = basegfx::utils::createScaleTranslateB2DHomMatrix( |
451 | 0 | aObjectRange.getRange(), aObjectRange.getMinimum()); |
452 | |
|
453 | 0 | bool bDirectShadow |
454 | 0 | = rObjectItemSet.Get(SDRATTR_SHADOW, /*bSrchInParent=*/false) |
455 | 0 | .GetValue(); |
456 | 0 | if (bDirectShadow) |
457 | 0 | { |
458 | | // Shadow as direct formatting: no shadow for text, to be compatible |
459 | | // with PowerPoint. |
460 | 0 | aRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive( |
461 | 0 | std::move(aRetval), aNewShadowAttribute, aTransformScaleMatrix, |
462 | 0 | &aRetvalForShadow); |
463 | 0 | } |
464 | 0 | else |
465 | 0 | { |
466 | | // Shadow as style: shadow for text, to be backwards-compatible. |
467 | 0 | aRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive( |
468 | 0 | std::move(aRetval), aNewShadowAttribute, aTransformScaleMatrix); |
469 | 0 | } |
470 | 0 | } |
471 | 0 | } |
472 | 0 | } |
473 | |
|
474 | 0 | rVisitor.visit(std::move(aRetval)); |
475 | 0 | } |
476 | 0 | else |
477 | 0 | { |
478 | | // take unrotated snap rect (direct model data) for position and size |
479 | 0 | const basegfx::B2DRange aObjectRange = vcl::unotools::b2DRectangleFromRectangle(rTableObj.GetGeoRect()); |
480 | | |
481 | | // create object matrix |
482 | 0 | const GeoStat& rGeoStat(rTableObj.GetGeoStat()); |
483 | 0 | const double fShearX(-rGeoStat.mfTanShearAngle); |
484 | 0 | const double fRotate(rGeoStat.m_nRotationAngle ? toRadians(36000_deg100 - rGeoStat.m_nRotationAngle) : 0.0); |
485 | 0 | const basegfx::B2DHomMatrix aObjectMatrix(basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix( |
486 | 0 | aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate, |
487 | 0 | aObjectRange.getMinX(), aObjectRange.getMinY())); |
488 | | |
489 | | // created an invisible outline for the cases where no visible content exists |
490 | 0 | const drawinglayer::primitive2d::Primitive2DReference xReference( |
491 | 0 | drawinglayer::primitive2d::createHiddenGeometryPrimitives2D( |
492 | 0 | aObjectMatrix)); |
493 | |
|
494 | 0 | rVisitor.visit(xReference); |
495 | 0 | } |
496 | 0 | } |
497 | | |
498 | | void ViewObjectContactOfTableObj::createPrimitive2DSequence( |
499 | | DisplayInfo const& rDisplayInfo, |
500 | | drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const |
501 | 0 | { |
502 | 0 | bool const isTaggedPDF(GetObjectContact().isExportTaggedPDF()); |
503 | 0 | if (isTaggedPDF) |
504 | 0 | { |
505 | | // this will be unbuffered and contain structure tags |
506 | 0 | const sdr::table::SdrTableObj& rTableObj = |
507 | 0 | static_cast<const sdr::table::SdrTableObj&>(*GetViewContact().TryToGetSdrObject()); |
508 | 0 | return createPrimitive2DSequenceImpl(rTableObj, true, rVisitor); |
509 | 0 | } |
510 | 0 | else |
511 | 0 | { |
512 | | // call it via the base class - this is supposed to be buffered |
513 | 0 | return sdr::contact::ViewObjectContactOfSdrObj::createPrimitive2DSequence(rDisplayInfo, rVisitor); |
514 | 0 | } |
515 | 0 | } |
516 | | |
517 | | void ViewContactOfTableObj::createViewIndependentPrimitive2DSequence( |
518 | | drawinglayer::primitive2d::Primitive2DDecompositionVisitor& rVisitor) const |
519 | 0 | { |
520 | 0 | const sdr::table::SdrTableObj& rTableObj = |
521 | 0 | static_cast<const sdr::table::SdrTableObj&>(GetSdrObject()); |
522 | 0 | return createPrimitive2DSequenceImpl(rTableObj, false, rVisitor); |
523 | 0 | } |
524 | | |
525 | | ViewObjectContact& ViewContactOfTableObj::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact) |
526 | 0 | { |
527 | 0 | return *new ViewObjectContactOfTableObj(rObjectContact, *this); |
528 | 0 | } |
529 | | |
530 | | ViewContactOfTableObj::ViewContactOfTableObj(sdr::table::SdrTableObj& rTableObj) |
531 | 1.21k | : ViewContactOfSdrObj(rTableObj) |
532 | 1.21k | { |
533 | 1.21k | } |
534 | | |
535 | | ViewContactOfTableObj::~ViewContactOfTableObj() |
536 | 1.21k | { |
537 | 1.21k | } |
538 | | } // end of namespace |
539 | | |
540 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |