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