Line data Source code
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 : #include "scitems.hxx"
21 : #include <editeng/eeitem.hxx>
22 :
23 : #include <editeng/adjustitem.hxx>
24 : #include <svx/algitem.hxx>
25 : #include <editeng/brushitem.hxx>
26 : #include <svtools/colorcfg.hxx>
27 : #include <editeng/colritem.hxx>
28 : #include <editeng/editobj.hxx>
29 : #include <editeng/editstat.hxx>
30 : #include <editeng/fhgtitem.hxx>
31 : #include <editeng/forbiddencharacterstable.hxx>
32 : #include <editeng/frmdiritem.hxx>
33 : #include <editeng/langitem.hxx>
34 : #include <editeng/justifyitem.hxx>
35 : #include <svx/rotmodit.hxx>
36 : #include <editeng/scripttypeitem.hxx>
37 : #include <editeng/udlnitem.hxx>
38 : #include <editeng/unolingu.hxx>
39 : #include <editeng/fontitem.hxx>
40 : #include <svl/zforlist.hxx>
41 : #include <svl/zformat.hxx>
42 : #include <vcl/svapp.hxx>
43 : #include <vcl/metric.hxx>
44 : #include <vcl/outdev.hxx>
45 : #include <vcl/pdfextoutdevdata.hxx>
46 :
47 : #include "output.hxx"
48 : #include "document.hxx"
49 : #include "formulacell.hxx"
50 : #include "attrib.hxx"
51 : #include "patattr.hxx"
52 : #include "cellform.hxx"
53 : #include "editutil.hxx"
54 : #include "progress.hxx"
55 : #include "scmod.hxx"
56 : #include "fillinfo.hxx"
57 : #include "viewdata.hxx"
58 : #include "tabvwsh.hxx"
59 : #include "docsh.hxx"
60 : #include "markdata.hxx"
61 : #include "stlsheet.hxx"
62 :
63 : #include <com/sun/star/i18n/DirectionProperty.hpp>
64 : #include <comphelper/string.hxx>
65 :
66 : #include <boost/ptr_container/ptr_vector.hpp>
67 :
68 : #include <math.h>
69 :
70 : using namespace com::sun::star;
71 :
72 : //! Autofilter-Breite mit column.cxx zusammenfassen
73 : #define DROPDOWN_BITMAP_SIZE 18
74 :
75 : #define DRAWTEXT_MAX 32767
76 :
77 : const sal_uInt16 SC_SHRINKAGAIN_MAX = 7;
78 :
79 : // STATIC DATA -----------------------------------------------------------
80 :
81 :
82 : // -----------------------------------------------------------------------
83 :
84 : class ScDrawStringsVars
85 : {
86 : ScOutputData* pOutput; // Verbindung
87 :
88 : const ScPatternAttr* pPattern; // Attribute
89 : const SfxItemSet* pCondSet; // aus bedingter Formatierung
90 :
91 : Font aFont; // aus Attributen erzeugt
92 : FontMetric aMetric;
93 : long nAscentPixel; // always pixels
94 : SvxCellOrientation eAttrOrient;
95 : SvxCellHorJustify eAttrHorJust;
96 : SvxCellVerJustify eAttrVerJust;
97 : SvxCellJustifyMethod eAttrHorJustMethod;
98 : SvxCellJustifyMethod eAttrVerJustMethod;
99 : const SvxMarginItem* pMargin;
100 : sal_uInt16 nIndent;
101 : sal_Bool bRotated;
102 :
103 : String aString; // Inhalte
104 : Size aTextSize;
105 : long nOriginalWidth;
106 : long nMaxDigitWidth;
107 : long nSignWidth;
108 : long nDotWidth;
109 : long nExpWidth;
110 :
111 : ScRefCellValue maLastCell;
112 : sal_uLong nValueFormat;
113 : sal_Bool bLineBreak;
114 : sal_Bool bRepeat;
115 : sal_Bool bShrink;
116 :
117 : sal_Bool bPixelToLogic;
118 : sal_Bool bCellContrast;
119 :
120 : Color aBackConfigColor; // used for ScPatternAttr::GetFont calls
121 : Color aTextConfigColor;
122 : sal_Int32 nPos;
123 : sal_Unicode nChar;
124 :
125 : public:
126 : ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL);
127 : ~ScDrawStringsVars();
128 :
129 : // SetPattern = ex-SetVars
130 : // SetPatternSimple: ohne Font
131 :
132 : void SetPattern(
133 : const ScPatternAttr* pNew, const SfxItemSet* pSet, const ScRefCellValue& rCell,
134 : sal_uInt8 nScript );
135 :
136 : void SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet );
137 :
138 : bool SetText( ScRefCellValue& rCell ); // TRUE -> pOldPattern vergessen
139 : void SetHashText();
140 : void SetTextToWidthOrHash( ScRefCellValue& rCell, long nWidth );
141 : void SetAutoText( const String& rAutoText );
142 :
143 : const ScPatternAttr* GetPattern() const { return pPattern; }
144 32534 : SvxCellOrientation GetOrient() const { return eAttrOrient; }
145 35994 : SvxCellHorJustify GetHorJust() const { return eAttrHorJust; }
146 11076 : SvxCellVerJustify GetVerJust() const { return eAttrVerJust; }
147 0 : SvxCellJustifyMethod GetHorJustMethod() const { return eAttrHorJustMethod; }
148 : SvxCellJustifyMethod GetVerJustMethod() const { return eAttrVerJustMethod; }
149 22951 : const SvxMarginItem* GetMargin() const { return pMargin; }
150 :
151 17177 : sal_uInt16 GetLeftTotal() const { return pMargin->GetLeftMargin() + nIndent; }
152 5631 : sal_uInt16 GetRightTotal() const { return pMargin->GetRightMargin() + nIndent; }
153 :
154 20934 : const String& GetString() const { return aString; }
155 39772 : const Size& GetTextSize() const { return aTextSize; }
156 310 : long GetOriginalWidth() const { return nOriginalWidth; }
157 :
158 : sal_uLong GetResultValueFormat() const;
159 :
160 9152 : sal_uLong GetValueFormat() const { return nValueFormat; }
161 11516 : sal_Bool GetLineBreak() const { return bLineBreak; }
162 11516 : sal_Bool IsRepeat() const { return bRepeat; }
163 11516 : sal_Bool IsShrink() const { return bShrink; }
164 : void RepeatToFill( long colWidth );
165 :
166 11076 : long GetAscent() const { return nAscentPixel; }
167 11892 : sal_Bool IsRotated() const { return bRotated; }
168 :
169 : void SetShrinkScale( long nScale, sal_uInt8 nScript );
170 :
171 30 : sal_Bool HasCondHeight() const { return pCondSet && SFX_ITEM_SET ==
172 30 : pCondSet->GetItemState( ATTR_FONT_HEIGHT, sal_True ); }
173 :
174 : sal_Bool HasEditCharacters() const;
175 :
176 : private:
177 : long GetMaxDigitWidth(); // in logic units
178 : long GetSignWidth();
179 : long GetDotWidth();
180 : long GetExpWidth();
181 : void TextChanged();
182 : };
183 :
184 : //==================================================================
185 :
186 1179 : ScDrawStringsVars::ScDrawStringsVars(ScOutputData* pData, sal_Bool bPTL) :
187 : pOutput ( pData ),
188 : pPattern ( NULL ),
189 : pCondSet ( NULL ),
190 : nAscentPixel(0),
191 : eAttrOrient ( SVX_ORIENTATION_STANDARD ),
192 : eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD ),
193 : eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM ),
194 : eAttrHorJustMethod( SVX_JUSTIFY_METHOD_AUTO ),
195 : eAttrVerJustMethod( SVX_JUSTIFY_METHOD_AUTO ),
196 : pMargin ( NULL ),
197 : nIndent ( 0 ),
198 : bRotated ( false ),
199 : nOriginalWidth( 0 ),
200 : nMaxDigitWidth( 0 ),
201 : nSignWidth( 0 ),
202 : nDotWidth( 0 ),
203 : nExpWidth( 0 ),
204 : nValueFormat( 0 ),
205 : bLineBreak ( false ),
206 : bRepeat ( false ),
207 : bShrink ( false ),
208 : bPixelToLogic( bPTL ),
209 : nPos( STRING_NOTFOUND ),
210 1179 : nChar( 0x0 )
211 : {
212 1179 : ScModule* pScMod = SC_MOD();
213 2355 : bCellContrast = pOutput->mbUseStyleColor &&
214 2355 : Application::GetSettings().GetStyleSettings().GetHighContrastMode();
215 :
216 1179 : const svtools::ColorConfig& rColorConfig = pScMod->GetColorConfig();
217 1179 : aBackConfigColor.SetColor( rColorConfig.GetColorValue(svtools::DOCCOLOR).nColor );
218 1179 : aTextConfigColor.SetColor( rColorConfig.GetColorValue(svtools::FONTCOLOR).nColor );
219 1179 : }
220 :
221 1179 : ScDrawStringsVars::~ScDrawStringsVars()
222 : {
223 1179 : }
224 :
225 0 : void ScDrawStringsVars::SetShrinkScale( long nScale, sal_uInt8 nScript )
226 : {
227 : // text remains valid, size is updated
228 :
229 0 : OutputDevice* pDev = pOutput->mpDev;
230 0 : OutputDevice* pRefDevice = pOutput->mpRefDevice;
231 0 : OutputDevice* pFmtDevice = pOutput->pFmtDevice;
232 :
233 : // call GetFont with a modified fraction, use only the height
234 :
235 0 : Fraction aFraction( nScale, 100 );
236 0 : if ( !bPixelToLogic )
237 0 : aFraction *= pOutput->aZoomY;
238 0 : Font aTmpFont;
239 0 : pPattern->GetFont( aTmpFont, SC_AUTOCOL_RAW, pFmtDevice, &aFraction, pCondSet, nScript );
240 0 : long nNewHeight = aTmpFont.GetHeight();
241 0 : if ( nNewHeight > 0 )
242 0 : aFont.SetHeight( nNewHeight );
243 :
244 : // set font and dependent variables as in SetPattern
245 :
246 0 : pDev->SetFont( aFont );
247 0 : if ( pFmtDevice != pDev )
248 0 : pFmtDevice->SetFont( aFont );
249 :
250 0 : aMetric = pFmtDevice->GetFontMetric();
251 0 : if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
252 : {
253 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
254 0 : MapMode aOld = pDefaultDev->GetMapMode();
255 0 : pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
256 0 : aMetric = pDefaultDev->GetFontMetric( aFont );
257 0 : pDefaultDev->SetMapMode( aOld );
258 : }
259 :
260 0 : nAscentPixel = aMetric.GetAscent();
261 0 : if ( bPixelToLogic )
262 0 : nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
263 :
264 0 : SetAutoText( aString ); // same text again, to get text size
265 0 : }
266 :
267 : namespace {
268 :
269 : template<typename _ItemType, typename _EnumType>
270 7910 : _EnumType lcl_GetValue(const ScPatternAttr& rPattern, sal_uInt16 nWhich, const SfxItemSet* pCondSet)
271 : {
272 7910 : const _ItemType& rItem = static_cast<const _ItemType&>(rPattern.GetItem(nWhich, pCondSet));
273 7910 : return static_cast<_EnumType>(rItem.GetValue());
274 : }
275 :
276 741 : bool lcl_GetBoolValue(const ScPatternAttr& rPattern, sal_uInt16 nWhich, const SfxItemSet* pCondSet)
277 : {
278 741 : return lcl_GetValue<SfxBoolItem, bool>(rPattern, nWhich, pCondSet);
279 : }
280 :
281 : }
282 :
283 2193 : void ScDrawStringsVars::SetPattern(
284 : const ScPatternAttr* pNew, const SfxItemSet* pSet, const ScRefCellValue& rCell,
285 : sal_uInt8 nScript )
286 : {
287 2193 : nMaxDigitWidth = 0;
288 2193 : nSignWidth = 0;
289 2193 : nDotWidth = 0;
290 2193 : nExpWidth = 0;
291 :
292 2193 : pPattern = pNew;
293 2193 : pCondSet = pSet;
294 :
295 : // pPattern auswerten
296 :
297 2193 : OutputDevice* pDev = pOutput->mpDev;
298 2193 : OutputDevice* pRefDevice = pOutput->mpRefDevice;
299 2193 : OutputDevice* pFmtDevice = pOutput->pFmtDevice;
300 :
301 : // Font
302 :
303 : ScAutoFontColorMode eColorMode;
304 2193 : if ( pOutput->mbUseStyleColor )
305 : {
306 2192 : if ( pOutput->mbForceAutoColor )
307 0 : eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREALL : SC_AUTOCOL_IGNOREFONT;
308 : else
309 2192 : eColorMode = bCellContrast ? SC_AUTOCOL_IGNOREBACK : SC_AUTOCOL_DISPLAY;
310 : }
311 : else
312 1 : eColorMode = SC_AUTOCOL_PRINT;
313 :
314 2193 : if ( bPixelToLogic )
315 : pPattern->GetFont( aFont, eColorMode, pFmtDevice, NULL, pCondSet, nScript,
316 23 : &aBackConfigColor, &aTextConfigColor );
317 : else
318 : pPattern->GetFont( aFont, eColorMode, pFmtDevice, &pOutput->aZoomY, pCondSet, nScript,
319 2170 : &aBackConfigColor, &aTextConfigColor );
320 2193 : aFont.SetAlign(ALIGN_BASELINE);
321 :
322 : // Orientierung
323 :
324 2193 : eAttrOrient = pPattern->GetCellOrientation( pCondSet );
325 :
326 : // alignment
327 :
328 2193 : eAttrHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)pPattern->GetItem( ATTR_HOR_JUSTIFY, pCondSet )).GetValue();
329 :
330 2193 : eAttrVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)pPattern->GetItem( ATTR_VER_JUSTIFY, pCondSet )).GetValue();
331 2193 : if ( eAttrVerJust == SVX_VER_JUSTIFY_STANDARD )
332 1981 : eAttrVerJust = SVX_VER_JUSTIFY_BOTTOM;
333 :
334 : // justification method
335 :
336 2193 : eAttrHorJustMethod = lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_HOR_JUSTIFY_METHOD, pCondSet);
337 2193 : eAttrVerJustMethod = lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_VER_JUSTIFY_METHOD, pCondSet);
338 :
339 : // line break
340 :
341 2193 : bLineBreak = ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK, pCondSet )).GetValue();
342 :
343 : // handle "repeat" alignment
344 :
345 2193 : bRepeat = ( eAttrHorJust == SVX_HOR_JUSTIFY_REPEAT );
346 2193 : if ( bRepeat )
347 : {
348 : // "repeat" disables rotation (before constructing the font)
349 0 : eAttrOrient = SVX_ORIENTATION_STANDARD;
350 :
351 : // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
352 0 : if ( bLineBreak )
353 0 : eAttrHorJust = SVX_HOR_JUSTIFY_STANDARD;
354 : }
355 :
356 : short nRot;
357 2193 : switch (eAttrOrient)
358 : {
359 : case SVX_ORIENTATION_STANDARD:
360 2135 : nRot = 0;
361 2307 : bRotated = (((const SfxInt32Item&)pPattern->GetItem( ATTR_ROTATE_VALUE, pCondSet )).GetValue() != 0) &&
362 2307 : !bRepeat;
363 2135 : break;
364 : case SVX_ORIENTATION_STACKED:
365 0 : nRot = 0;
366 0 : bRotated = false;
367 0 : break;
368 : case SVX_ORIENTATION_TOPBOTTOM:
369 58 : nRot = 2700;
370 58 : bRotated = false;
371 58 : break;
372 : case SVX_ORIENTATION_BOTTOMTOP:
373 0 : nRot = 900;
374 0 : bRotated = false;
375 0 : break;
376 : default:
377 : OSL_FAIL("Falscher SvxCellOrientation Wert");
378 0 : nRot = 0;
379 0 : bRotated = false;
380 0 : break;
381 : }
382 2193 : aFont.SetOrientation( nRot );
383 :
384 : // Syntax-Modus
385 :
386 2193 : if (pOutput->mbSyntaxMode)
387 0 : pOutput->SetSyntaxColor(&aFont, rCell);
388 :
389 2193 : pDev->SetFont( aFont );
390 2193 : if ( pFmtDevice != pDev )
391 53 : pFmtDevice->SetFont( aFont );
392 :
393 2193 : aMetric = pFmtDevice->GetFontMetric();
394 :
395 : //
396 : // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
397 : // -> Metric vom Bildschirm nehmen (wie EditEngine!)
398 : //
399 :
400 2193 : if ( pFmtDevice->GetOutDevType() == OUTDEV_PRINTER && aMetric.GetIntLeading() == 0 )
401 : {
402 0 : OutputDevice* pDefaultDev = Application::GetDefaultDevice();
403 0 : MapMode aOld = pDefaultDev->GetMapMode();
404 0 : pDefaultDev->SetMapMode( pFmtDevice->GetMapMode() );
405 0 : aMetric = pDefaultDev->GetFontMetric( aFont );
406 0 : pDefaultDev->SetMapMode( aOld );
407 : }
408 :
409 2193 : nAscentPixel = aMetric.GetAscent();
410 2193 : if ( bPixelToLogic )
411 23 : nAscentPixel = pRefDevice->LogicToPixel( Size( 0, nAscentPixel ) ).Height();
412 :
413 2193 : Color aULineColor( ((const SvxUnderlineItem&)pPattern->GetItem( ATTR_FONT_UNDERLINE, pCondSet )).GetColor() );
414 2193 : pDev->SetTextLineColor( aULineColor );
415 :
416 2193 : Color aOLineColor( ((const SvxOverlineItem&)pPattern->GetItem( ATTR_FONT_OVERLINE, pCondSet )).GetColor() );
417 2193 : pDev->SetOverlineColor( aOLineColor );
418 :
419 : // Zahlenformat
420 :
421 2193 : nValueFormat = pPattern->GetNumberFormat( pOutput->mpDoc->GetFormatTable(), pCondSet );
422 :
423 : // Raender
424 :
425 2193 : pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
426 2193 : if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT || eAttrHorJust == SVX_HOR_JUSTIFY_RIGHT )
427 820 : nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
428 : else
429 1373 : nIndent = 0;
430 :
431 : // "Shrink to fit"
432 :
433 2193 : bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
434 :
435 : // zumindest die Text-Groesse muss neu geholt werden
436 : //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
437 :
438 2193 : maLastCell.clear();
439 2193 : }
440 :
441 5997 : void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr* pNew, const SfxItemSet* pSet )
442 : {
443 5997 : nMaxDigitWidth = 0;
444 5997 : nSignWidth = 0;
445 5997 : nDotWidth = 0;
446 5997 : nExpWidth = 0;
447 : // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
448 :
449 5997 : pPattern = pNew;
450 5997 : pCondSet = pSet; //! noetig ???
451 :
452 : // Zahlenformat
453 :
454 5997 : sal_uLong nOld = nValueFormat;
455 : const SfxPoolItem* pFormItem;
456 5997 : if ( !pCondSet || pCondSet->GetItemState(ATTR_VALUE_FORMAT,sal_True,&pFormItem) != SFX_ITEM_SET )
457 5997 : pFormItem = &pPattern->GetItem(ATTR_VALUE_FORMAT);
458 : const SfxPoolItem* pLangItem;
459 5997 : if ( !pCondSet || pCondSet->GetItemState(ATTR_LANGUAGE_FORMAT,sal_True,&pLangItem) != SFX_ITEM_SET )
460 5997 : pLangItem = &pPattern->GetItem(ATTR_LANGUAGE_FORMAT);
461 : nValueFormat = pOutput->mpDoc->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
462 : ((SfxUInt32Item*)pFormItem)->GetValue(),
463 5997 : ((SvxLanguageItem*)pLangItem)->GetLanguage() );
464 :
465 5997 : if (nValueFormat != nOld)
466 172 : maLastCell.clear(); // immer neu formatieren
467 :
468 : // Raender
469 :
470 5997 : pMargin = (const SvxMarginItem*)&pPattern->GetItem( ATTR_MARGIN, pCondSet );
471 :
472 5997 : if ( eAttrHorJust == SVX_HOR_JUSTIFY_LEFT )
473 610 : nIndent = ((const SfxUInt16Item&)pPattern->GetItem( ATTR_INDENT, pCondSet )).GetValue();
474 : else
475 5387 : nIndent = 0;
476 :
477 : // "Shrink to fit"
478 :
479 5997 : bShrink = static_cast<const SfxBoolItem&>(pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
480 5997 : }
481 :
482 11516 : inline bool SameValue( const ScRefCellValue& rCell, const ScRefCellValue& rOldCell )
483 : {
484 16413 : return rOldCell.meType == CELLTYPE_VALUE && rCell.meType == CELLTYPE_VALUE &&
485 16413 : rCell.mfValue == rOldCell.mfValue;
486 : }
487 :
488 11516 : bool ScDrawStringsVars::SetText( ScRefCellValue& rCell )
489 : {
490 11516 : bool bChanged = false;
491 :
492 11516 : if (!rCell.isEmpty())
493 : {
494 11516 : if (!SameValue(rCell, maLastCell))
495 : {
496 9152 : maLastCell = rCell; // Zelle merken
497 :
498 : Color* pColor;
499 9152 : sal_uLong nFormat = GetValueFormat();
500 9152 : OUString aOUString = aString;
501 : ScCellFormat::GetString( rCell,
502 : nFormat, aOUString, &pColor,
503 9152 : *pOutput->mpDoc->GetFormatTable(),
504 : pOutput->mbShowNullValues,
505 : pOutput->mbShowFormulas,
506 18304 : ftCheck, true );
507 9152 : aString = aOUString;
508 9152 : if ( nFormat )
509 : {
510 269 : nPos = aString.Search( 0x1B );
511 269 : if ( nPos != STRING_NOTFOUND )
512 : {
513 0 : nChar = aString.GetChar( nPos + 1 );
514 : // delete placeholder and char to repeat
515 0 : aString.Erase( nPos, 2 );
516 : }
517 : }
518 : else
519 : {
520 8883 : nPos = STRING_NOTFOUND;
521 8883 : nChar = 0x0;
522 : }
523 9152 : if (aString.Len() > DRAWTEXT_MAX)
524 0 : aString.Erase(DRAWTEXT_MAX);
525 :
526 9152 : if ( pColor && !pOutput->mbSyntaxMode && !( pOutput->mbUseStyleColor && pOutput->mbForceAutoColor ) )
527 : {
528 0 : OutputDevice* pDev = pOutput->mpDev;
529 0 : aFont.SetColor(*pColor);
530 0 : pDev->SetFont( aFont ); // nur fuer Ausgabe
531 0 : bChanged = true;
532 0 : maLastCell.clear(); // naechstes Mal wieder hierherkommen
533 : }
534 :
535 9152 : TextChanged();
536 : }
537 : // sonst String/Groesse behalten
538 : }
539 : else
540 : {
541 0 : aString.Erase();
542 0 : maLastCell.clear();
543 0 : aTextSize = Size(0,0);
544 0 : nOriginalWidth = 0;
545 : }
546 :
547 11516 : return bChanged;
548 : }
549 :
550 76 : void ScDrawStringsVars::SetHashText()
551 : {
552 76 : SetAutoText(OUString("###"));
553 76 : }
554 :
555 11516 : void ScDrawStringsVars::RepeatToFill( long colWidth )
556 : {
557 11516 : if ( nPos == STRING_NOTFOUND || nPos > aString.Len() )
558 23032 : return;
559 :
560 0 : long charWidth = pOutput->pFmtDevice->GetTextWidth(OUString(nChar));
561 0 : if ( charWidth < 1) return;
562 0 : if (bPixelToLogic)
563 0 : colWidth = pOutput->mpRefDevice->PixelToLogic(Size(colWidth,0)).Width();
564 : // Are there restrictions on the cell type we should filter out here ?
565 0 : long aSpaceToFill = ( colWidth - aTextSize.Width() );
566 :
567 0 : if ( aSpaceToFill <= charWidth )
568 0 : return;
569 :
570 0 : long nCharsToInsert = aSpaceToFill / charWidth;
571 0 : OUStringBuffer aFill;
572 0 : comphelper::string::padToLength(aFill, nCharsToInsert, nChar);
573 0 : aString.Insert( aFill.makeStringAndClear(), nPos);
574 0 : TextChanged();
575 : }
576 :
577 216 : void ScDrawStringsVars::SetTextToWidthOrHash( ScRefCellValue& rCell, long nWidth )
578 : {
579 : // #i113045# do the single-character width calculations in logic units
580 216 : if (bPixelToLogic)
581 0 : nWidth = pOutput->mpRefDevice->PixelToLogic(Size(nWidth,0)).Width();
582 :
583 216 : CellType eType = rCell.meType;
584 216 : if (eType != CELLTYPE_VALUE && eType != CELLTYPE_FORMULA)
585 : // must be a value or formula cell.
586 0 : return;
587 :
588 216 : if (eType == CELLTYPE_FORMULA)
589 : {
590 50 : ScFormulaCell* pFCell = rCell.mpFormula;
591 50 : if (pFCell->GetErrCode() != 0 || pOutput->mbShowFormulas)
592 : {
593 0 : SetHashText(); // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
594 0 : return;
595 : }
596 : // If it's formula, the result must be a value.
597 50 : if (!pFCell->IsValue())
598 0 : return;
599 : }
600 :
601 216 : sal_uLong nFormat = GetResultValueFormat();
602 216 : if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0)
603 : {
604 : // Not 'General' number format. Set hash text and bail out.
605 40 : SetHashText();
606 40 : return;
607 : }
608 :
609 176 : double fVal = rCell.getValue();
610 :
611 176 : const SvNumberformat* pNumFormat = pOutput->mpDoc->GetFormatTable()->GetEntry(nFormat);
612 176 : if (!pNumFormat)
613 0 : return;
614 :
615 176 : long nMaxDigit = GetMaxDigitWidth();
616 176 : sal_uInt16 nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
617 : {
618 176 : OUString sTempOut(aString);
619 176 : if (!pNumFormat->GetOutputString(fVal, nNumDigits, sTempOut))
620 : {
621 0 : aString = sTempOut;
622 : // Failed to get output string. Bail out.
623 0 : return;
624 : }
625 176 : aString = sTempOut;
626 : }
627 176 : sal_uInt8 nSignCount = 0, nDecimalCount = 0, nExpCount = 0;
628 176 : xub_StrLen nLen = aString.Len();
629 176 : sal_Unicode cDecSep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator.getStr()[0];
630 1812 : for (xub_StrLen i = 0; i < nLen; ++i)
631 : {
632 1636 : sal_Unicode c = aString.GetChar(i);
633 1636 : if (c == sal_Unicode('-'))
634 71 : ++nSignCount;
635 1565 : else if (c == cDecSep)
636 140 : ++nDecimalCount;
637 1425 : else if (c == sal_Unicode('E'))
638 37 : ++nExpCount;
639 : }
640 :
641 : // #i112250# A small value might be formatted as "0" when only counting the digits,
642 : // but fit into the column when considering the smaller width of the decimal separator.
643 176 : if (aString.EqualsAscii("0") && fVal != 0.0)
644 0 : nDecimalCount = 1;
645 :
646 176 : if (nDecimalCount)
647 140 : nWidth += (nMaxDigit - GetDotWidth()) * nDecimalCount;
648 176 : if (nSignCount)
649 71 : nWidth += (nMaxDigit - GetSignWidth()) * nSignCount;
650 176 : if (nExpCount)
651 37 : nWidth += (nMaxDigit - GetExpWidth()) * nExpCount;
652 :
653 176 : if (nDecimalCount || nSignCount || nExpCount)
654 : {
655 : // Re-calculate.
656 176 : nNumDigits = static_cast<sal_uInt16>(nWidth / nMaxDigit);
657 176 : OUString sTempOut(aString);
658 176 : if (!pNumFormat->GetOutputString(fVal, nNumDigits, sTempOut))
659 : {
660 0 : aString = sTempOut;
661 : // Failed to get output string. Bail out.
662 0 : return;
663 : }
664 176 : aString = sTempOut;
665 : }
666 :
667 176 : long nActualTextWidth = pOutput->pFmtDevice->GetTextWidth(aString);
668 176 : if (nActualTextWidth > nWidth)
669 : {
670 : // Even after the decimal adjustment the text doesn't fit. Give up.
671 36 : SetHashText();
672 36 : return;
673 : }
674 :
675 140 : TextChanged();
676 140 : maLastCell.clear(); // #i113022# equal cell and format in another column may give different string
677 : }
678 :
679 76 : void ScDrawStringsVars::SetAutoText( const String& rAutoText )
680 : {
681 76 : aString = rAutoText;
682 :
683 76 : OutputDevice* pRefDevice = pOutput->mpRefDevice;
684 76 : OutputDevice* pFmtDevice = pOutput->pFmtDevice;
685 76 : aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
686 76 : aTextSize.Height() = pFmtDevice->GetTextHeight();
687 :
688 76 : if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
689 : {
690 76 : double fMul = pOutput->GetStretch();
691 76 : aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
692 : }
693 :
694 76 : aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
695 76 : if ( GetOrient() != SVX_ORIENTATION_STANDARD )
696 : {
697 40 : long nTemp = aTextSize.Height();
698 40 : aTextSize.Height() = aTextSize.Width();
699 40 : aTextSize.Width() = nTemp;
700 : }
701 :
702 76 : nOriginalWidth = aTextSize.Width();
703 76 : if ( bPixelToLogic )
704 0 : aTextSize = pRefDevice->LogicToPixel( aTextSize );
705 :
706 76 : maLastCell.clear(); // derselbe Text kann in der naechsten Zelle wieder passen
707 76 : }
708 :
709 176 : long ScDrawStringsVars::GetMaxDigitWidth()
710 : {
711 176 : if (nMaxDigitWidth > 0)
712 37 : return nMaxDigitWidth;
713 :
714 139 : sal_Char cZero = '0';
715 1529 : for (sal_Char i = 0; i < 10; ++i)
716 : {
717 1390 : sal_Char cDigit = cZero + i;
718 1390 : long n = pOutput->pFmtDevice->GetTextWidth(OUString(cDigit));
719 1390 : nMaxDigitWidth = ::std::max(nMaxDigitWidth, n);
720 : }
721 139 : return nMaxDigitWidth;
722 : }
723 :
724 71 : long ScDrawStringsVars::GetSignWidth()
725 : {
726 71 : if (nSignWidth > 0)
727 9 : return nSignWidth;
728 :
729 62 : nSignWidth = pOutput->pFmtDevice->GetTextWidth(OUString('-'));
730 62 : return nSignWidth;
731 : }
732 :
733 140 : long ScDrawStringsVars::GetDotWidth()
734 : {
735 140 : if (nDotWidth > 0)
736 9 : return nDotWidth;
737 :
738 131 : const OUString& sep = ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator;
739 131 : nDotWidth = pOutput->pFmtDevice->GetTextWidth(sep);
740 131 : return nDotWidth;
741 : }
742 :
743 37 : long ScDrawStringsVars::GetExpWidth()
744 : {
745 37 : if (nExpWidth > 0)
746 28 : return nExpWidth;
747 :
748 9 : nExpWidth = pOutput->pFmtDevice->GetTextWidth(OUString('E'));
749 9 : return nExpWidth;
750 : }
751 :
752 9292 : void ScDrawStringsVars::TextChanged()
753 : {
754 9292 : OutputDevice* pRefDevice = pOutput->mpRefDevice;
755 9292 : OutputDevice* pFmtDevice = pOutput->pFmtDevice;
756 9292 : aTextSize.Width() = pFmtDevice->GetTextWidth( aString );
757 9292 : aTextSize.Height() = pFmtDevice->GetTextHeight();
758 :
759 9292 : if ( !pRefDevice->GetConnectMetaFile() || pRefDevice->GetOutDevType() == OUTDEV_PRINTER )
760 : {
761 9291 : double fMul = pOutput->GetStretch();
762 9291 : aTextSize.Width() = (long)(aTextSize.Width() / fMul + 0.5);
763 : }
764 :
765 9292 : aTextSize.Height() = aMetric.GetAscent() + aMetric.GetDescent();
766 9292 : if ( GetOrient() != SVX_ORIENTATION_STANDARD )
767 : {
768 138 : long nTemp = aTextSize.Height();
769 138 : aTextSize.Height() = aTextSize.Width();
770 138 : aTextSize.Width() = nTemp;
771 : }
772 :
773 9292 : nOriginalWidth = aTextSize.Width();
774 9292 : if ( bPixelToLogic )
775 358 : aTextSize = pRefDevice->LogicToPixel( aTextSize );
776 9292 : }
777 :
778 11516 : sal_Bool ScDrawStringsVars::HasEditCharacters() const
779 : {
780 : static const sal_Unicode pChars[] =
781 : {
782 : CHAR_NBSP, CHAR_SHY, CHAR_ZWSP, CHAR_LRM, CHAR_RLM, CHAR_NBHY, CHAR_ZWNBSP, 0
783 : };
784 11516 : return aString.SearchChar( pChars ) != STRING_NOTFOUND;
785 : }
786 :
787 224 : sal_uLong ScDrawStringsVars::GetResultValueFormat() const
788 : {
789 : // Get the effective number format, including formula result types.
790 : // This assumes that a formula cell has already been calculated.
791 :
792 224 : return nValueFormat;
793 : }
794 :
795 : //==================================================================
796 :
797 9753 : double ScOutputData::GetStretch()
798 : {
799 9753 : if ( mpRefDevice->IsMapMode() )
800 : {
801 : // If a non-trivial MapMode is set, its scale is now already
802 : // taken into account in the OutputDevice's font handling
803 : // (OutputDevice::ImplNewFont, see #95414#).
804 : // The old handling below is only needed for pixel output.
805 774 : return 1.0;
806 : }
807 :
808 : // calculation in double is faster than Fraction multiplication
809 : // and doesn't overflow
810 :
811 8979 : if ( mpRefDevice == pFmtDevice )
812 : {
813 8979 : MapMode aOld = mpRefDevice->GetMapMode();
814 8979 : return ((double)aOld.GetScaleY()) / ((double)aOld.GetScaleX()) * ((double)aZoomY) / ((double)aZoomX);
815 : }
816 : else
817 : {
818 : // when formatting for printer, device map mode has already been taken care of
819 0 : return ((double)aZoomY) / ((double)aZoomX);
820 : }
821 : }
822 :
823 : //==================================================================
824 :
825 : //
826 : // output strings
827 : //
828 :
829 0 : static void lcl_DoHyperlinkResult( OutputDevice* pDev, const Rectangle& rRect, ScRefCellValue& rCell )
830 : {
831 0 : vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
832 :
833 0 : OUString aCellText;
834 0 : OUString aURL;
835 0 : if (rCell.meType == CELLTYPE_FORMULA)
836 : {
837 0 : ScFormulaCell* pFCell = rCell.mpFormula;
838 0 : if ( pFCell->IsHyperLinkCell() )
839 0 : pFCell->GetURLResult( aURL, aCellText );
840 : }
841 :
842 0 : if ( !aURL.isEmpty() && pPDFData )
843 : {
844 0 : vcl::PDFExtOutDevBookmarkEntry aBookmark;
845 0 : aBookmark.nLinkId = pPDFData->CreateLink( rRect );
846 0 : aBookmark.aBookmark = aURL;
847 0 : std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks();
848 0 : rBookmarks.push_back( aBookmark );
849 0 : }
850 0 : }
851 :
852 0 : void ScOutputData::SetSyntaxColor( Font* pFont, const ScRefCellValue& rCell )
853 : {
854 0 : switch (rCell.meType)
855 : {
856 : case CELLTYPE_VALUE:
857 0 : pFont->SetColor(*pValueColor);
858 0 : break;
859 : case CELLTYPE_STRING:
860 0 : pFont->SetColor(*pTextColor);
861 0 : break;
862 : case CELLTYPE_FORMULA:
863 0 : pFont->SetColor(*pFormulaColor);
864 0 : break;
865 : default:
866 : {
867 : // added to avoid warnings
868 : }
869 : }
870 0 : }
871 :
872 0 : static void lcl_SetEditColor( EditEngine& rEngine, const Color& rColor )
873 : {
874 0 : ESelection aSel( 0, 0, rEngine.GetParagraphCount(), 0 );
875 0 : SfxItemSet aSet( rEngine.GetEmptyItemSet() );
876 0 : aSet.Put( SvxColorItem( rColor, EE_CHAR_COLOR ) );
877 0 : rEngine.QuickSetAttribs( aSet, aSel );
878 : // function is called with update mode set to FALSE
879 0 : }
880 :
881 0 : void ScOutputData::SetEditSyntaxColor( EditEngine& rEngine, ScRefCellValue& rCell )
882 : {
883 0 : Color aColor;
884 0 : switch (rCell.meType)
885 : {
886 : case CELLTYPE_VALUE:
887 0 : aColor = *pValueColor;
888 0 : break;
889 : case CELLTYPE_STRING:
890 0 : aColor = *pTextColor;
891 0 : break;
892 : case CELLTYPE_FORMULA:
893 0 : aColor = *pFormulaColor;
894 0 : break;
895 : default:
896 : {
897 : // added to avoid warnings
898 : }
899 : }
900 0 : lcl_SetEditColor( rEngine, aColor );
901 0 : }
902 :
903 114 : sal_Bool ScOutputData::GetMergeOrigin( SCCOL nX, SCROW nY, SCSIZE nArrY,
904 : SCCOL& rOverX, SCROW& rOverY,
905 : sal_Bool bVisRowChanged )
906 : {
907 114 : sal_Bool bDoMerge = false;
908 114 : sal_Bool bIsLeft = ( nX == nVisX1 );
909 114 : sal_Bool bIsTop = ( nY == nVisY1 ) || bVisRowChanged;
910 :
911 114 : CellInfo* pInfo = &pRowInfo[nArrY].pCellInfo[nX+1];
912 114 : if ( pInfo->bHOverlapped && pInfo->bVOverlapped )
913 48 : bDoMerge = bIsLeft && bIsTop;
914 66 : else if ( pInfo->bHOverlapped )
915 20 : bDoMerge = bIsLeft;
916 46 : else if ( pInfo->bVOverlapped )
917 46 : bDoMerge = bIsTop;
918 :
919 114 : rOverX = nX;
920 114 : rOverY = nY;
921 114 : sal_Bool bHOver = pInfo->bHOverlapped;
922 114 : sal_Bool bVOver = pInfo->bVOverlapped;
923 : sal_Bool bHidden;
924 :
925 228 : while (bHOver) // nY konstant
926 : {
927 68 : --rOverX;
928 68 : bHidden = mpDoc->ColHidden(rOverX, nTab);
929 68 : if ( !bDoMerge && !bHidden )
930 68 : return false;
931 :
932 0 : if (rOverX >= nX1 && !bHidden)
933 : {
934 0 : bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
935 0 : bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
936 : }
937 : else
938 : {
939 : sal_uInt16 nOverlap = ((ScMergeFlagAttr*)mpDoc->GetAttr(
940 0 : rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
941 0 : bHOver = ((nOverlap & SC_MF_HOR) != 0);
942 0 : bVOver = ((nOverlap & SC_MF_VER) != 0);
943 : }
944 : }
945 :
946 94 : while (bVOver)
947 : {
948 46 : --rOverY;
949 46 : bHidden = mpDoc->RowHidden(rOverY, nTab);
950 46 : if ( !bDoMerge && !bHidden )
951 44 : return false;
952 :
953 2 : if (nArrY>0)
954 2 : --nArrY; // lokale Kopie !
955 :
956 6 : if (rOverX >= nX1 && rOverY >= nY1 &&
957 0 : !mpDoc->ColHidden(rOverX, nTab) &&
958 2 : !mpDoc->RowHidden(rOverY, nTab) &&
959 0 : pRowInfo[nArrY].nRowNo == rOverY)
960 : {
961 0 : bHOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bHOverlapped;
962 0 : bVOver = pRowInfo[nArrY].pCellInfo[rOverX+1].bVOverlapped;
963 : }
964 : else
965 : {
966 : sal_uInt16 nOverlap = ((ScMergeFlagAttr*)mpDoc->GetAttr(
967 2 : rOverX, rOverY, nTab, ATTR_MERGE_FLAG ))->GetValue();
968 2 : bHOver = ((nOverlap & SC_MF_HOR) != 0);
969 2 : bVOver = ((nOverlap & SC_MF_VER) != 0);
970 : }
971 : }
972 :
973 2 : return sal_True;
974 : }
975 :
976 8190 : inline sal_Bool StringDiffer( const ScPatternAttr*& rpOldPattern, const ScPatternAttr*& rpNewPattern )
977 : {
978 : OSL_ENSURE( rpNewPattern, "pNewPattern" );
979 :
980 8190 : if ( rpNewPattern == rpOldPattern )
981 0 : return false;
982 8190 : else if ( !rpOldPattern )
983 730 : return sal_True;
984 7460 : else if ( &rpNewPattern->GetItem( ATTR_FONT ) != &rpOldPattern->GetItem( ATTR_FONT ) )
985 319 : return sal_True;
986 7141 : else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT ) )
987 92 : return sal_True;
988 7049 : else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT ) )
989 40 : return sal_True;
990 7009 : else if ( &rpNewPattern->GetItem( ATTR_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_HEIGHT ) )
991 424 : return sal_True;
992 6585 : else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_HEIGHT ) )
993 14 : return sal_True;
994 6571 : else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_HEIGHT ) )
995 10 : return sal_True;
996 6561 : else if ( &rpNewPattern->GetItem( ATTR_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_FONT_WEIGHT ) )
997 178 : return sal_True;
998 6383 : else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_WEIGHT ) )
999 0 : return sal_True;
1000 6383 : else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_WEIGHT ) )
1001 0 : return sal_True;
1002 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_FONT_POSTURE ) )
1003 0 : return sal_True;
1004 6383 : else if ( &rpNewPattern->GetItem( ATTR_CJK_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CJK_FONT_POSTURE ) )
1005 0 : return sal_True;
1006 6383 : else if ( &rpNewPattern->GetItem( ATTR_CTL_FONT_POSTURE ) != &rpOldPattern->GetItem( ATTR_CTL_FONT_POSTURE ) )
1007 0 : return sal_True;
1008 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_UNDERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_UNDERLINE ) )
1009 0 : return sal_True;
1010 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_OVERLINE ) != &rpOldPattern->GetItem( ATTR_FONT_OVERLINE ) )
1011 0 : return sal_True;
1012 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_WORDLINE ) != &rpOldPattern->GetItem( ATTR_FONT_WORDLINE ) )
1013 0 : return sal_True;
1014 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_CROSSEDOUT ) != &rpOldPattern->GetItem( ATTR_FONT_CROSSEDOUT ) )
1015 0 : return sal_True;
1016 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_CONTOUR ) != &rpOldPattern->GetItem( ATTR_FONT_CONTOUR ) )
1017 0 : return sal_True;
1018 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_SHADOWED ) != &rpOldPattern->GetItem( ATTR_FONT_SHADOWED ) )
1019 0 : return sal_True;
1020 6383 : else if ( &rpNewPattern->GetItem( ATTR_FONT_COLOR ) != &rpOldPattern->GetItem( ATTR_FONT_COLOR ) )
1021 16 : return sal_True;
1022 6367 : else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY ) )
1023 272 : return true;
1024 6095 : else if ( &rpNewPattern->GetItem( ATTR_HOR_JUSTIFY_METHOD ) != &rpOldPattern->GetItem( ATTR_HOR_JUSTIFY_METHOD ) )
1025 0 : return true;
1026 6095 : else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY ) )
1027 40 : return true;
1028 6055 : else if ( &rpNewPattern->GetItem( ATTR_VER_JUSTIFY_METHOD ) != &rpOldPattern->GetItem( ATTR_VER_JUSTIFY_METHOD ) )
1029 0 : return true;
1030 6055 : else if ( &rpNewPattern->GetItem( ATTR_STACKED ) != &rpOldPattern->GetItem( ATTR_STACKED ) )
1031 0 : return sal_True;
1032 6055 : else if ( &rpNewPattern->GetItem( ATTR_LINEBREAK ) != &rpOldPattern->GetItem( ATTR_LINEBREAK ) )
1033 54 : return sal_True;
1034 6001 : else if ( &rpNewPattern->GetItem( ATTR_MARGIN ) != &rpOldPattern->GetItem( ATTR_MARGIN ) )
1035 0 : return sal_True;
1036 6001 : else if ( &rpNewPattern->GetItem( ATTR_ROTATE_VALUE ) != &rpOldPattern->GetItem( ATTR_ROTATE_VALUE ) )
1037 0 : return sal_True;
1038 6001 : else if ( &rpNewPattern->GetItem( ATTR_FORBIDDEN_RULES ) != &rpOldPattern->GetItem( ATTR_FORBIDDEN_RULES ) )
1039 0 : return sal_True;
1040 6001 : else if ( &rpNewPattern->GetItem( ATTR_FONT_EMPHASISMARK ) != &rpOldPattern->GetItem( ATTR_FONT_EMPHASISMARK ) )
1041 0 : return sal_True;
1042 6001 : else if ( &rpNewPattern->GetItem( ATTR_FONT_RELIEF ) != &rpOldPattern->GetItem( ATTR_FONT_RELIEF ) )
1043 0 : return sal_True;
1044 6001 : else if ( &rpNewPattern->GetItem( ATTR_BACKGROUND ) != &rpOldPattern->GetItem( ATTR_BACKGROUND ) )
1045 0 : return sal_True; // needed with automatic text color
1046 : else
1047 : {
1048 6001 : rpOldPattern = rpNewPattern;
1049 6001 : return false;
1050 : }
1051 : }
1052 :
1053 306 : static inline void lcl_CreateInterpretProgress( sal_Bool& bProgress, ScDocument* pDoc,
1054 : ScFormulaCell* pFCell )
1055 : {
1056 306 : if ( !bProgress && pFCell->GetDirty() )
1057 : {
1058 2 : ScProgress::CreateInterpretProgress( pDoc, sal_True );
1059 2 : bProgress = sal_True;
1060 : }
1061 306 : }
1062 :
1063 0 : inline sal_Bool IsAmbiguousScript( sal_uInt8 nScript )
1064 : {
1065 0 : return ( nScript != SCRIPTTYPE_LATIN &&
1066 0 : nScript != SCRIPTTYPE_ASIAN &&
1067 0 : nScript != SCRIPTTYPE_COMPLEX );
1068 : }
1069 :
1070 50995 : bool ScOutputData::IsEmptyCellText( RowInfo* pThisRowInfo, SCCOL nX, SCROW nY )
1071 : {
1072 : // pThisRowInfo may be NULL
1073 :
1074 : bool bEmpty;
1075 50995 : if ( pThisRowInfo && nX <= nX2 )
1076 34232 : bEmpty = pThisRowInfo->pCellInfo[nX+1].bEmptyCellText;
1077 : else
1078 : {
1079 16763 : ScRefCellValue aCell;
1080 16763 : aCell.assign(*mpDoc, ScAddress(nX, nY, nTab));
1081 16763 : bEmpty = aCell.isEmpty();
1082 : }
1083 :
1084 50995 : if ( !bEmpty && ( nX < nX1 || nX > nX2 || !pThisRowInfo ) )
1085 : {
1086 : // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
1087 : // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
1088 :
1089 1204 : bool bIsPrint = ( eType == OUTTYPE_PRINTER );
1090 :
1091 1204 : if ( bIsPrint || bTabProtected )
1092 : {
1093 : const ScProtectionAttr* pAttr = (const ScProtectionAttr*)
1094 0 : mpDoc->GetEffItem( nX, nY, nTab, ATTR_PROTECTION );
1095 0 : if ( bIsPrint && pAttr->GetHidePrint() )
1096 0 : bEmpty = true;
1097 0 : else if ( bTabProtected )
1098 : {
1099 0 : if ( pAttr->GetHideCell() )
1100 0 : bEmpty = true;
1101 0 : else if ( mbShowFormulas && pAttr->GetHideFormula() )
1102 : {
1103 0 : if (mpDoc->GetCellType(ScAddress(nX, nY, nTab)) == CELLTYPE_FORMULA)
1104 0 : bEmpty = true;
1105 : }
1106 : }
1107 : }
1108 : }
1109 50995 : return bEmpty;
1110 : }
1111 :
1112 372 : void ScOutputData::GetVisibleCell( SCCOL nCol, SCROW nRow, SCTAB nTabP, ScRefCellValue& rCell )
1113 : {
1114 372 : rCell.assign(*mpDoc, ScAddress(nCol, nRow, nTabP));
1115 372 : if (!rCell.isEmpty() && IsEmptyCellText(NULL, nCol, nRow))
1116 0 : rCell.clear();
1117 372 : }
1118 :
1119 764 : bool ScOutputData::IsAvailable( SCCOL nX, SCROW nY )
1120 : {
1121 : // apply the same logic here as in DrawStrings/DrawEdit:
1122 : // Stop at non-empty or merged or overlapped cell,
1123 : // where a note is empty as well as a cell that's hidden by protection settings
1124 :
1125 764 : ScRefCellValue aCell;
1126 764 : aCell.assign(*mpDoc, ScAddress(nX, nY, nTab));
1127 764 : if (!aCell.isEmpty() && !IsEmptyCellText(NULL, nX, nY))
1128 216 : return false;
1129 :
1130 548 : const ScPatternAttr* pPattern = mpDoc->GetPattern( nX, nY, nTab );
1131 1096 : if ( ((const ScMergeAttr&)pPattern->GetItem(ATTR_MERGE)).IsMerged() ||
1132 548 : ((const ScMergeFlagAttr&)pPattern->GetItem(ATTR_MERGE_FLAG)).IsOverlapped() )
1133 : {
1134 0 : return false;
1135 : }
1136 :
1137 548 : return sal_True;
1138 : }
1139 :
1140 : // nX, nArrY: loop variables from DrawStrings / DrawEdit
1141 : // nPosX, nPosY: corresponding positions for nX, nArrY
1142 : // nCellX, nCellY: position of the cell that contains the text
1143 : // nNeeded: Text width, including margin
1144 : // rPattern: cell format at nCellX, nCellY
1145 : // nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings
1146 : // bCellIsValue: if set, don't extend into empty cells
1147 : // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
1148 : // bOverwrite: if set, also extend into non-empty cells (for rotated text)
1149 : // rParam output: various area parameters.
1150 :
1151 12066 : void ScOutputData::GetOutputArea( SCCOL nX, SCSIZE nArrY, long nPosX, long nPosY,
1152 : SCCOL nCellX, SCROW nCellY, long nNeeded,
1153 : const ScPatternAttr& rPattern,
1154 : sal_uInt16 nHorJustify, bool bCellIsValue,
1155 : bool bBreak, bool bOverwrite,
1156 : OutputAreaParam& rParam )
1157 : {
1158 : // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
1159 12066 : RowInfo& rThisRowInfo = pRowInfo[nArrY];
1160 :
1161 12066 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1162 :
1163 12066 : long nCellPosX = nPosX; // find nCellX position, starting at nX/nPosX
1164 12066 : SCCOL nCompCol = nX;
1165 24794 : while ( nCellX > nCompCol )
1166 : {
1167 : //! extra member function for width?
1168 662 : long nColWidth = ( nCompCol <= nX2 ) ?
1169 174 : pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
1170 836 : (long) ( mpDoc->GetColWidth( nCompCol, nTab ) * mnPPTX );
1171 662 : nCellPosX += nColWidth * nLayoutSign;
1172 662 : ++nCompCol;
1173 : }
1174 27969 : while ( nCellX < nCompCol )
1175 : {
1176 3837 : --nCompCol;
1177 3837 : long nColWidth = ( nCompCol <= nX2 ) ?
1178 3837 : pRowInfo[0].pCellInfo[nCompCol+1].nWidth :
1179 7674 : (long) ( mpDoc->GetColWidth( nCompCol, nTab ) * mnPPTX );
1180 3837 : nCellPosX -= nColWidth * nLayoutSign;
1181 : }
1182 :
1183 12066 : long nCellPosY = nPosY; // find nCellY position, starting at nArrY/nPosY
1184 12066 : SCSIZE nCompArr = nArrY;
1185 12066 : SCROW nCompRow = pRowInfo[nCompArr].nRowNo;
1186 24132 : while ( nCellY > nCompRow )
1187 : {
1188 0 : if ( nCompArr + 1 < nArrCount )
1189 : {
1190 0 : nCellPosY += pRowInfo[nCompArr].nHeight;
1191 0 : ++nCompArr;
1192 0 : nCompRow = pRowInfo[nCompArr].nRowNo;
1193 : }
1194 : else
1195 : {
1196 0 : sal_uInt16 nDocHeight = mpDoc->GetRowHeight( nCompRow, nTab );
1197 0 : if ( nDocHeight )
1198 0 : nCellPosY += (long) ( nDocHeight * mnPPTY );
1199 0 : ++nCompRow;
1200 : }
1201 : }
1202 12066 : nCellPosY -= (long) mpDoc->GetScaledRowHeight( nCellY, nCompRow-1, nTab, mnPPTY );
1203 :
1204 12066 : const ScMergeAttr* pMerge = (const ScMergeAttr*)&rPattern.GetItem( ATTR_MERGE );
1205 12066 : sal_Bool bMerged = pMerge->IsMerged();
1206 12066 : long nMergeCols = pMerge->GetColMerge();
1207 12066 : if ( nMergeCols == 0 )
1208 12064 : nMergeCols = 1;
1209 12066 : long nMergeRows = pMerge->GetRowMerge();
1210 12066 : if ( nMergeRows == 0 )
1211 12064 : nMergeRows = 1;
1212 :
1213 : long i;
1214 12066 : long nMergeSizeX = 0;
1215 24136 : for ( i=0; i<nMergeCols; i++ )
1216 : {
1217 12070 : long nColWidth = ( nCellX+i <= nX2 ) ?
1218 11896 : pRowInfo[0].pCellInfo[nCellX+i+1].nWidth :
1219 23966 : (long) ( mpDoc->GetColWidth( sal::static_int_cast<SCCOL>(nCellX+i), nTab ) * mnPPTX );
1220 12070 : nMergeSizeX += nColWidth;
1221 : }
1222 12066 : long nMergeSizeY = 0;
1223 12066 : short nDirect = 0;
1224 12066 : if ( rThisRowInfo.nRowNo == nCellY )
1225 : {
1226 : // take first row's height from row info
1227 12066 : nMergeSizeY += rThisRowInfo.nHeight;
1228 12066 : nDirect = 1; // skip in loop
1229 : }
1230 : // following rows always from document
1231 12066 : nMergeSizeY += (long) mpDoc->GetScaledRowHeight( nCellY+nDirect, nCellY+nMergeRows-1, nTab, mnPPTY);
1232 :
1233 12066 : --nMergeSizeX; // leave out the grid horizontally, also for alignment (align between grid lines)
1234 :
1235 12066 : rParam.mnColWidth = nMergeSizeX; // store the actual column width.
1236 :
1237 : //
1238 : // construct the rectangles using logical left/right values (justify is called at the end)
1239 : //
1240 :
1241 : // rAlignRect is the single cell or merged area, used for alignment.
1242 :
1243 12066 : rParam.maAlignRect.Left() = nCellPosX;
1244 12066 : rParam.maAlignRect.Right() = nCellPosX + ( nMergeSizeX - 1 ) * nLayoutSign;
1245 12066 : rParam.maAlignRect.Top() = nCellPosY;
1246 12066 : rParam.maAlignRect.Bottom() = nCellPosY + nMergeSizeY - 1;
1247 :
1248 : // rClipRect is all cells that are used for output.
1249 : // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1250 :
1251 12066 : rParam.maClipRect = rParam.maAlignRect;
1252 12066 : if ( nNeeded > nMergeSizeX )
1253 : {
1254 995 : SvxCellHorJustify eHorJust = (SvxCellHorJustify)nHorJustify;
1255 :
1256 995 : long nMissing = nNeeded - nMergeSizeX;
1257 995 : long nLeftMissing = 0;
1258 995 : long nRightMissing = 0;
1259 995 : switch ( eHorJust )
1260 : {
1261 : case SVX_HOR_JUSTIFY_LEFT:
1262 546 : nRightMissing = nMissing;
1263 546 : break;
1264 : case SVX_HOR_JUSTIFY_RIGHT:
1265 246 : nLeftMissing = nMissing;
1266 246 : break;
1267 : case SVX_HOR_JUSTIFY_CENTER:
1268 172 : nLeftMissing = nMissing / 2;
1269 172 : nRightMissing = nMissing - nLeftMissing;
1270 172 : break;
1271 : default:
1272 : {
1273 : // added to avoid warnings
1274 : }
1275 : }
1276 :
1277 : // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1278 995 : if ( bLayoutRTL )
1279 0 : ::std::swap( nLeftMissing, nRightMissing );
1280 :
1281 995 : SCCOL nRightX = nCellX;
1282 995 : SCCOL nLeftX = nCellX;
1283 995 : if ( !bMerged && !bCellIsValue && !bBreak )
1284 : {
1285 : // look for empty cells into which the text can be extended
1286 :
1287 2231 : while ( nRightMissing > 0 && nRightX < MAXCOL && ( bOverwrite || IsAvailable( nRightX+1, nCellY ) ) )
1288 : {
1289 703 : ++nRightX;
1290 703 : long nAdd = (long) ( mpDoc->GetColWidth( nRightX, nTab ) * mnPPTX );
1291 703 : nRightMissing -= nAdd;
1292 703 : rParam.maClipRect.Right() += nAdd * nLayoutSign;
1293 :
1294 703 : if ( rThisRowInfo.nRowNo == nCellY && nRightX >= nX1 && nRightX <= nX2 )
1295 626 : rThisRowInfo.pCellInfo[nRightX].bHideGrid = sal_True;
1296 : }
1297 :
1298 1644 : while ( nLeftMissing > 0 && nLeftX > 0 && ( bOverwrite || IsAvailable( nLeftX-1, nCellY ) ) )
1299 : {
1300 116 : if ( rThisRowInfo.nRowNo == nCellY && nLeftX >= nX1 && nLeftX <= nX2 )
1301 116 : rThisRowInfo.pCellInfo[nLeftX].bHideGrid = sal_True;
1302 :
1303 116 : --nLeftX;
1304 116 : long nAdd = (long) ( mpDoc->GetColWidth( nLeftX, nTab ) * mnPPTX );
1305 116 : nLeftMissing -= nAdd;
1306 116 : rParam.maClipRect.Left() -= nAdd * nLayoutSign;
1307 : }
1308 : }
1309 :
1310 : // Set flag and reserve space for clipping mark triangle,
1311 : // even if rThisRowInfo isn't for nCellY (merged cells).
1312 995 : if ( nRightMissing > 0 && bMarkClipped && nRightX >= nX1 && nRightX <= nX2 && !bBreak && !bCellIsValue )
1313 : {
1314 207 : rThisRowInfo.pCellInfo[nRightX+1].nClipMark |= SC_CLIPMARK_RIGHT;
1315 207 : bAnyClipped = sal_True;
1316 207 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
1317 207 : rParam.maClipRect.Right() -= nMarkPixel * nLayoutSign;
1318 : }
1319 995 : if ( nLeftMissing > 0 && bMarkClipped && nLeftX >= nX1 && nLeftX <= nX2 && !bBreak && !bCellIsValue )
1320 : {
1321 128 : rThisRowInfo.pCellInfo[nLeftX+1].nClipMark |= SC_CLIPMARK_LEFT;
1322 128 : bAnyClipped = sal_True;
1323 128 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
1324 128 : rParam.maClipRect.Left() += nMarkPixel * nLayoutSign;
1325 : }
1326 :
1327 995 : rParam.mbLeftClip = ( nLeftMissing > 0 );
1328 995 : rParam.mbRightClip = ( nRightMissing > 0 );
1329 : }
1330 : else
1331 : {
1332 11071 : rParam.mbLeftClip = rParam.mbRightClip = false;
1333 :
1334 : // leave space for AutoFilter on screen
1335 : // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1336 :
1337 33184 : if ( eType==OUTTYPE_WINDOW &&
1338 11331 : ( static_cast<const ScMergeFlagAttr&>(rPattern.GetItem(ATTR_MERGE_FLAG)).GetValue() & (SC_MF_AUTO|SC_MF_BUTTON|SC_MF_BUTTON_POPUP) ) &&
1339 130 : ( !bBreak || mpRefDevice == pFmtDevice ) )
1340 : {
1341 : // filter drop-down width is now independent from row height
1342 130 : const long nFilter = DROPDOWN_BITMAP_SIZE;
1343 130 : sal_Bool bFit = ( nNeeded + nFilter <= nMergeSizeX );
1344 130 : if ( bFit || bCellIsValue )
1345 : {
1346 : // content fits even in the remaining area without the filter button
1347 : // -> align within that remaining area
1348 :
1349 130 : rParam.maAlignRect.Right() -= nFilter * nLayoutSign;
1350 130 : rParam.maClipRect.Right() -= nFilter * nLayoutSign;
1351 :
1352 : // if a number doesn't fit, don't hide part of the number behind the button
1353 : // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1354 :
1355 130 : if ( !bFit )
1356 0 : rParam.mbLeftClip = rParam.mbRightClip = sal_True;
1357 : }
1358 : }
1359 : }
1360 :
1361 : // justify both rectangles for alignment calculation, use with DrawText etc.
1362 :
1363 12066 : rParam.maAlignRect.Justify();
1364 12066 : rParam.maClipRect.Justify();
1365 12066 : }
1366 :
1367 : namespace {
1368 :
1369 10408 : bool beginsWithRTLCharacter(const OUString& rStr)
1370 : {
1371 10408 : if (rStr.isEmpty())
1372 2 : return false;
1373 :
1374 10406 : switch (ScGlobal::pCharClass->getCharacterDirection(rStr, 0))
1375 : {
1376 : case i18n::DirectionProperty_RIGHT_TO_LEFT:
1377 : case i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC:
1378 : case i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING:
1379 : case i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE:
1380 0 : return true;
1381 : default:
1382 : ;
1383 : }
1384 :
1385 10406 : return false;
1386 : }
1387 :
1388 : }
1389 :
1390 1179 : void ScOutputData::DrawStrings( sal_Bool bPixelToLogic )
1391 : {
1392 : OSL_ENSURE( mpDev == mpRefDevice ||
1393 : mpDev->GetMapMode().GetMapUnit() == mpRefDevice->GetMapMode().GetMapUnit(),
1394 : "DrawStrings: unterschiedliche MapUnits ?!?!" );
1395 :
1396 1179 : vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, mpDev->GetExtOutDevData() );
1397 :
1398 1179 : bool bWasIdleEnabled = mpDoc->IsIdleEnabled();
1399 1179 : mpDoc->EnableIdle(false);
1400 :
1401 1179 : ScDrawStringsVars aVars( this, bPixelToLogic );
1402 :
1403 1179 : sal_Bool bProgress = false;
1404 :
1405 1179 : long nInitPosX = nScrX;
1406 1179 : if ( bLayoutRTL )
1407 1 : nInitPosX += nMirrorW - 1; // pixels
1408 1179 : long nLayoutSign = bLayoutRTL ? -1 : 1;
1409 :
1410 1179 : SCCOL nLastContentCol = MAXCOL;
1411 1179 : if ( nX2 < MAXCOL )
1412 : nLastContentCol = sal::static_int_cast<SCCOL>(
1413 1178 : nLastContentCol - mpDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
1414 1179 : SCCOL nLoopStartX = nX1;
1415 1179 : if ( nX1 > 0 )
1416 178 : --nLoopStartX; // start before nX1 for rest of long text to the left
1417 :
1418 : // variables for GetOutputArea
1419 1179 : OutputAreaParam aAreaParam;
1420 1179 : sal_Bool bCellIsValue = false;
1421 1179 : long nNeededWidth = 0;
1422 1179 : SvxCellHorJustify eOutHorJust = SVX_HOR_JUSTIFY_STANDARD;
1423 1179 : const ScPatternAttr* pPattern = NULL;
1424 1179 : const SfxItemSet* pCondSet = NULL;
1425 1179 : const ScPatternAttr* pOldPattern = NULL;
1426 1179 : const SfxItemSet* pOldCondSet = NULL;
1427 1179 : sal_uInt8 nOldScript = 0;
1428 :
1429 : // alternative pattern instances in case we need to modify the pattern
1430 : // before processing the cell value.
1431 2358 : ::boost::ptr_vector<ScPatternAttr> aAltPatterns;
1432 :
1433 1179 : long nPosY = nScrY;
1434 19858 : for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++)
1435 : {
1436 18679 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
1437 18679 : if ( pThisRowInfo->bChanged )
1438 : {
1439 18679 : SCROW nY = pThisRowInfo->nRowNo;
1440 18679 : long nPosX = nInitPosX;
1441 18679 : if ( nLoopStartX < nX1 )
1442 1312 : nPosX -= pRowInfo[0].pCellInfo[nLoopStartX+1].nWidth * nLayoutSign;
1443 206136 : for (SCCOL nX=nLoopStartX; nX<=nX2; nX++)
1444 : {
1445 187457 : sal_Bool bMergeEmpty = false;
1446 187457 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
1447 187457 : sal_Bool bEmpty = nX < nX1 || pInfo->bEmptyCellText;
1448 :
1449 187457 : SCCOL nCellX = nX; // position where the cell really starts
1450 187457 : SCROW nCellY = nY;
1451 187457 : sal_Bool bDoCell = false;
1452 187457 : sal_Bool bNeedEdit = false;
1453 :
1454 : //
1455 : // Part of a merged cell?
1456 : //
1457 :
1458 187457 : sal_Bool bOverlapped = ( pInfo->bHOverlapped || pInfo->bVOverlapped );
1459 187457 : if ( bOverlapped )
1460 : {
1461 114 : bEmpty = sal_True;
1462 :
1463 : SCCOL nOverX; // start of the merged cells
1464 : SCROW nOverY;
1465 114 : sal_Bool bVisChanged = !pRowInfo[nArrY-1].bChanged;
1466 114 : if (GetMergeOrigin( nX,nY, nArrY, nOverX,nOverY, bVisChanged ))
1467 : {
1468 2 : nCellX = nOverX;
1469 2 : nCellY = nOverY;
1470 2 : bDoCell = sal_True;
1471 : }
1472 : else
1473 112 : bMergeEmpty = sal_True;
1474 : }
1475 :
1476 : //
1477 : // Rest of a long text further to the left?
1478 : //
1479 :
1480 187457 : if ( bEmpty && !bMergeEmpty && nX < nX1 && !bOverlapped )
1481 : {
1482 1312 : SCCOL nTempX=nX1;
1483 33438 : while (nTempX > 0 && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1484 30814 : --nTempX;
1485 :
1486 3304 : if ( nTempX < nX1 &&
1487 1514 : !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1488 202 : !mpDoc->HasAttrib( nTempX,nY,nTab, nX1,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1489 : {
1490 196 : nCellX = nTempX;
1491 196 : bDoCell = sal_True;
1492 : }
1493 : }
1494 :
1495 : //
1496 : // Rest of a long text further to the right?
1497 : //
1498 :
1499 187457 : if ( bEmpty && !bMergeEmpty && nX == nX2 && !bOverlapped )
1500 : {
1501 : // don't have to look further than nLastContentCol
1502 :
1503 17946 : SCCOL nTempX=nX;
1504 51965 : while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
1505 16073 : ++nTempX;
1506 :
1507 19536 : if ( nTempX > nX &&
1508 18120 : !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
1509 174 : !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1510 : {
1511 174 : nCellX = nTempX;
1512 174 : bDoCell = sal_True;
1513 : }
1514 : }
1515 :
1516 : //
1517 : // normal visible cell
1518 : //
1519 :
1520 187457 : if (!bEmpty)
1521 11626 : bDoCell = sal_True;
1522 :
1523 : //
1524 : // don't output the cell that's being edited
1525 : //
1526 :
1527 187457 : if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
1528 0 : bDoCell = false;
1529 :
1530 : // skip text in cell if data bar/icon set is set and only value selected
1531 187457 : if ( bDoCell )
1532 : {
1533 11998 : if(pInfo->pDataBar && !pInfo->pDataBar->mbShowValue)
1534 0 : bDoCell = false;
1535 11998 : if(pInfo->pIconSet && !pInfo->pIconSet->mbShowValue)
1536 0 : bDoCell = false;
1537 : }
1538 :
1539 : //
1540 : // output the cell text
1541 : //
1542 :
1543 187457 : ScRefCellValue aCell;
1544 187457 : if (bDoCell)
1545 : {
1546 11998 : if ( nCellY == nY && nCellX == nX && nCellX >= nX1 && nCellX <= nX2 )
1547 11626 : aCell = pThisRowInfo->pCellInfo[nCellX+1].maCell;
1548 : else
1549 372 : GetVisibleCell( nCellX, nCellY, nTab, aCell ); // get from document
1550 11998 : if (aCell.isEmpty())
1551 2 : bDoCell = false;
1552 11996 : else if (aCell.meType == CELLTYPE_EDIT)
1553 104 : bNeedEdit = true;
1554 : }
1555 187457 : if (bDoCell && !bNeedEdit)
1556 : {
1557 11892 : if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 )
1558 : {
1559 11522 : CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
1560 11522 : pPattern = rCellInfo.pPatternAttr;
1561 11522 : pCondSet = rCellInfo.pConditionSet;
1562 :
1563 11522 : if ( !pPattern )
1564 : {
1565 : // #i68085# pattern from cell info for hidden columns is null,
1566 : // test for null is quicker than using column flags
1567 0 : pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
1568 0 : pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
1569 11522 : }
1570 : }
1571 : else // get from document
1572 : {
1573 370 : pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
1574 370 : pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
1575 : }
1576 11892 : if ( mpDoc->GetPreviewFont() )
1577 : {
1578 7176 : aAltPatterns.push_back(new ScPatternAttr(*pPattern));
1579 7176 : ScPatternAttr* pAltPattern = &aAltPatterns.back();
1580 7176 : if ( SfxItemSet* pFontSet = mpDoc->GetPreviewFont( nCellX, nCellY, nTab ) )
1581 : {
1582 : const SfxPoolItem* pItem;
1583 209 : if ( pFontSet->GetItemState( ATTR_FONT, true, &pItem ) == SFX_ITEM_SET )
1584 209 : pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
1585 209 : if ( pFontSet->GetItemState( ATTR_CJK_FONT, true, &pItem ) == SFX_ITEM_SET )
1586 0 : pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
1587 209 : if ( pFontSet->GetItemState( ATTR_CTL_FONT, true, &pItem ) == SFX_ITEM_SET )
1588 0 : pAltPattern->GetItemSet().Put( (const SvxFontItem&)*pItem );
1589 : }
1590 7176 : pPattern = pAltPattern;
1591 : }
1592 :
1593 18668 : if (aCell.hasNumeric() &&
1594 : static_cast<const SfxBoolItem&>(
1595 6776 : pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue())
1596 : {
1597 : // Disable line break when the cell content is numeric.
1598 329 : aAltPatterns.push_back(new ScPatternAttr(*pPattern));
1599 329 : ScPatternAttr* pAltPattern = &aAltPatterns.back();
1600 329 : SfxBoolItem aLineBreak(ATTR_LINEBREAK, false);
1601 329 : pAltPattern->GetItemSet().Put(aLineBreak);
1602 329 : pPattern = pAltPattern;
1603 : }
1604 :
1605 : sal_uInt8 nScript = mpDoc->GetCellScriptType(
1606 : ScAddress(nCellX, nCellY, nTab),
1607 11892 : pPattern->GetNumberFormat(mpDoc->GetFormatTable(), pCondSet));
1608 :
1609 11892 : if (nScript == 0)
1610 50 : nScript = ScGlobal::GetDefaultScriptType();
1611 :
1612 11892 : if ( pPattern != pOldPattern || pCondSet != pOldCondSet ||
1613 3702 : nScript != nOldScript || mbSyntaxMode )
1614 : {
1615 22381 : if ( StringDiffer(pOldPattern,pPattern) ||
1616 14187 : pCondSet != pOldCondSet || nScript != nOldScript || mbSyntaxMode )
1617 : {
1618 2193 : aVars.SetPattern(pPattern, pCondSet, aCell, nScript);
1619 : }
1620 : else
1621 5997 : aVars.SetPatternSimple( pPattern, pCondSet );
1622 8190 : pOldPattern = pPattern;
1623 8190 : pOldCondSet = pCondSet;
1624 8190 : nOldScript = nScript;
1625 : }
1626 :
1627 : // use edit engine for rotated, stacked or mixed-script text
1628 35676 : if ( aVars.GetOrient() == SVX_ORIENTATION_STACKED ||
1629 23408 : aVars.IsRotated() || IsAmbiguousScript(nScript) )
1630 376 : bNeedEdit = sal_True;
1631 : }
1632 187457 : if (bDoCell && !bNeedEdit)
1633 : {
1634 11516 : bool bFormulaCell = (aCell.meType == CELLTYPE_FORMULA);
1635 11516 : if ( bFormulaCell )
1636 306 : lcl_CreateInterpretProgress(bProgress, mpDoc, aCell.mpFormula);
1637 11516 : if ( aVars.SetText(aCell) )
1638 0 : pOldPattern = NULL;
1639 11516 : bNeedEdit = aVars.HasEditCharacters() || (bFormulaCell && aCell.mpFormula->IsMultilineResult());
1640 : }
1641 187457 : long nTotalMargin = 0;
1642 187457 : if (bDoCell && !bNeedEdit)
1643 : {
1644 11516 : CellType eCellType = aCell.meType;
1645 11516 : bCellIsValue = ( eCellType == CELLTYPE_VALUE );
1646 11516 : if ( eCellType == CELLTYPE_FORMULA )
1647 : {
1648 306 : ScFormulaCell* pFCell = aCell.mpFormula;
1649 306 : bCellIsValue = pFCell->IsRunning() || pFCell->IsValue();
1650 : }
1651 :
1652 11516 : if (aVars.GetHorJust() == SVX_HOR_JUSTIFY_STANDARD)
1653 : {
1654 : // fdo#32530: Default alignment depends on value vs
1655 : // string, and the direction of the 1st letter.
1656 9858 : if (beginsWithRTLCharacter(aVars.GetString()))
1657 0 : eOutHorJust = bCellIsValue ? SVX_HOR_JUSTIFY_LEFT : SVX_HOR_JUSTIFY_RIGHT;
1658 : else
1659 9858 : eOutHorJust = bCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
1660 : }
1661 : else
1662 1658 : eOutHorJust = aVars.GetHorJust();
1663 :
1664 11516 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
1665 : {
1666 12 : const SfxPoolItem* pItem = mpDoc->GetAttr( nCellX, nCellY, nTab, ATTR_WRITINGDIR );
1667 12 : const SvxFrameDirectionItem* pCurrentWritingMode = (const SvxFrameDirectionItem*) pItem;
1668 12 : if (pCurrentWritingMode->GetValue() == FRMDIR_HORI_LEFT_TOP)
1669 0 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT;
1670 : else
1671 12 : eOutHorJust = SVX_HOR_JUSTIFY_RIGHT;
1672 : }
1673 :
1674 11516 : bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK );
1675 : // #i111387# #o11817313# disable automatic line breaks only for "General" number format
1676 11516 : if (bBreak && bCellIsValue && (aVars.GetResultValueFormat() % SV_COUNTRY_LANGUAGE_OFFSET) == 0)
1677 0 : bBreak = false;
1678 :
1679 11516 : bool bRepeat = aVars.IsRepeat() && !bBreak;
1680 11516 : bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat;
1681 :
1682 : nTotalMargin =
1683 23032 : static_cast<long>(aVars.GetLeftTotal() * mnPPTX) +
1684 23032 : static_cast<long>(aVars.GetMargin()->GetRightMargin() * mnPPTX);
1685 :
1686 11516 : nNeededWidth = aVars.GetTextSize().Width() + nTotalMargin;
1687 :
1688 : // GetOutputArea gives justfied rectangles
1689 : GetOutputArea( nX, nArrY, nPosX, nPosY, nCellX, nCellY, nNeededWidth,
1690 11516 : *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
1691 11516 : bCellIsValue || bRepeat || bShrink, bBreak, false,
1692 34548 : aAreaParam );
1693 :
1694 11516 : aVars.RepeatToFill( aAreaParam.mnColWidth - nTotalMargin );
1695 11516 : if ( bShrink )
1696 : {
1697 44 : if ( aVars.GetOrient() != SVX_ORIENTATION_STANDARD )
1698 : {
1699 : // Only horizontal scaling is handled here.
1700 : // DrawEdit is used to vertically scale 90 deg rotated text.
1701 44 : bNeedEdit = sal_True;
1702 : }
1703 0 : else if ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) // horizontal
1704 : {
1705 0 : long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
1706 0 : long nScaleSize = aVars.GetTextSize().Width(); // without margin
1707 :
1708 0 : if ( nScaleSize > 0 ) // 0 if the text is empty (formulas, number formats)
1709 : {
1710 0 : long nScale = ( nAvailable * 100 ) / nScaleSize;
1711 :
1712 0 : aVars.SetShrinkScale( nScale, nOldScript );
1713 0 : long nNewSize = aVars.GetTextSize().Width();
1714 :
1715 0 : sal_uInt16 nShrinkAgain = 0;
1716 0 : while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
1717 : {
1718 : // If the text is still too large, reduce the scale again by 10%, until it fits,
1719 : // at most 7 times (it's less than 50% of the calculated scale then).
1720 :
1721 0 : nScale = ( nScale * 9 ) / 10;
1722 0 : aVars.SetShrinkScale( nScale, nOldScript );
1723 0 : nNewSize = aVars.GetTextSize().Width();
1724 0 : ++nShrinkAgain;
1725 : }
1726 : // If even at half the size the font still isn't rendered smaller,
1727 : // fall back to normal clipping (showing ### for numbers).
1728 0 : if ( nNewSize <= nAvailable )
1729 0 : aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
1730 :
1731 0 : pOldPattern = NULL;
1732 : }
1733 : }
1734 : }
1735 :
1736 11516 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip )
1737 : {
1738 0 : long nAvailable = aAreaParam.maAlignRect.GetWidth() - nTotalMargin;
1739 0 : long nRepeatSize = aVars.GetTextSize().Width(); // without margin
1740 : // When formatting for the printer, the text sizes don't always add up.
1741 : // Round down (too few repetitions) rather than exceeding the cell size then:
1742 0 : if ( pFmtDevice != mpRefDevice )
1743 0 : ++nRepeatSize;
1744 0 : if ( nRepeatSize > 0 )
1745 : {
1746 0 : long nRepeatCount = nAvailable / nRepeatSize;
1747 0 : if ( nRepeatCount > 1 )
1748 : {
1749 0 : String aCellStr = aVars.GetString();
1750 0 : String aRepeated = aCellStr;
1751 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
1752 0 : aRepeated.Append( aCellStr );
1753 0 : aVars.SetAutoText( aRepeated );
1754 : }
1755 : }
1756 : }
1757 :
1758 : // use edit engine if automatic line breaks are needed
1759 11516 : if ( bBreak )
1760 : {
1761 154 : if ( aVars.GetOrient() == SVX_ORIENTATION_STANDARD )
1762 118 : bNeedEdit = ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip );
1763 : else
1764 : {
1765 72 : long nHeight = aVars.GetTextSize().Height() +
1766 72 : (long)(aVars.GetMargin()->GetTopMargin()*mnPPTY) +
1767 72 : (long)(aVars.GetMargin()->GetBottomMargin()*mnPPTY);
1768 36 : bNeedEdit = ( nHeight > aAreaParam.maClipRect.GetHeight() );
1769 : }
1770 : }
1771 11516 : if (!bNeedEdit)
1772 : {
1773 : bNeedEdit =
1774 11446 : aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK &&
1775 11446 : aVars.GetHorJustMethod() == SVX_JUSTIFY_METHOD_DISTRIBUTE;
1776 : }
1777 : }
1778 187457 : if (bNeedEdit)
1779 : {
1780 : // mark the cell in CellInfo to be drawn in DrawEdit:
1781 : // Cells to the left are marked directly, cells to the
1782 : // right are handled by the flag for nX2
1783 550 : SCCOL nMarkX = ( nCellX <= nX2 ) ? nCellX : nX2;
1784 550 : RowInfo* pMarkRowInfo = ( nCellY == nY ) ? pThisRowInfo : &pRowInfo[0];
1785 550 : pMarkRowInfo->pCellInfo[nMarkX+1].bEditEngine = sal_True;
1786 550 : bDoCell = false; // don't draw here
1787 : }
1788 187457 : if ( bDoCell )
1789 : {
1790 11446 : if ( bCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
1791 : {
1792 216 : if (mbShowFormulas)
1793 0 : aVars.SetHashText();
1794 : else
1795 : // Adjust the decimals to fit the available column width.
1796 216 : aVars.SetTextToWidthOrHash(aCell, aAreaParam.mnColWidth - nTotalMargin);
1797 :
1798 432 : nNeededWidth = aVars.GetTextSize().Width() +
1799 432 : (long) ( aVars.GetLeftTotal() * mnPPTX ) +
1800 432 : (long) ( aVars.GetMargin()->GetRightMargin() * mnPPTX );
1801 216 : if ( nNeededWidth <= aAreaParam.maClipRect.GetWidth() )
1802 176 : aAreaParam.mbLeftClip = aAreaParam.mbRightClip = false;
1803 :
1804 : // If the "###" replacement doesn't fit into the cells, no clip marks
1805 : // are shown, as the "###" already denotes too little space.
1806 : // The rectangles from the first GetOutputArea call remain valid.
1807 : }
1808 :
1809 11446 : long nJustPosX = aAreaParam.maAlignRect.Left(); // "justified" - effect of alignment will be added
1810 11446 : long nJustPosY = aAreaParam.maAlignRect.Top();
1811 11446 : long nAvailWidth = aAreaParam.maAlignRect.GetWidth();
1812 11446 : long nOutHeight = aAreaParam.maAlignRect.GetHeight();
1813 :
1814 11446 : sal_Bool bOutside = ( aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW );
1815 11446 : if ( aAreaParam.maClipRect.Left() < nScrX )
1816 : {
1817 196 : aAreaParam.maClipRect.Left() = nScrX;
1818 196 : aAreaParam.mbLeftClip = sal_True;
1819 : }
1820 11446 : if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
1821 : {
1822 189 : aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
1823 189 : aAreaParam.mbRightClip = sal_True;
1824 : }
1825 :
1826 11446 : sal_Bool bHClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
1827 11446 : sal_Bool bVClip = false;
1828 :
1829 11446 : if ( aAreaParam.maClipRect.Top() < nScrY )
1830 : {
1831 0 : aAreaParam.maClipRect.Top() = nScrY;
1832 0 : bVClip = sal_True;
1833 : }
1834 11446 : if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
1835 : {
1836 0 : aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
1837 0 : bVClip = sal_True;
1838 : }
1839 :
1840 : //
1841 : // horizontalen Platz testen
1842 : //
1843 :
1844 11446 : sal_Bool bRightAdjusted = false; // to correct text width calculation later
1845 11446 : sal_Bool bNeedEditEngine = false;
1846 11446 : if ( !bNeedEditEngine && !bOutside )
1847 : {
1848 11076 : switch (eOutHorJust)
1849 : {
1850 : case SVX_HOR_JUSTIFY_LEFT:
1851 5386 : nJustPosX += (long) ( aVars.GetLeftTotal() * mnPPTX );
1852 5386 : break;
1853 : case SVX_HOR_JUSTIFY_RIGHT:
1854 11262 : nJustPosX += nAvailWidth - aVars.GetTextSize().Width() -
1855 11262 : (long) ( aVars.GetRightTotal() * mnPPTX );
1856 5631 : bRightAdjusted = sal_True;
1857 5631 : break;
1858 : case SVX_HOR_JUSTIFY_CENTER:
1859 118 : nJustPosX += ( nAvailWidth - aVars.GetTextSize().Width() +
1860 118 : (long) ( aVars.GetLeftTotal() * mnPPTX ) -
1861 118 : (long) ( aVars.GetMargin()->GetRightMargin() * mnPPTX ) ) / 2;
1862 59 : break;
1863 : default:
1864 : {
1865 : // added to avoid warnings
1866 : }
1867 : }
1868 :
1869 11076 : long nTestClipHeight = aVars.GetTextSize().Height();
1870 11076 : switch (aVars.GetVerJust())
1871 : {
1872 : case SVX_VER_JUSTIFY_TOP:
1873 : case SVX_VER_JUSTIFY_BLOCK:
1874 : {
1875 217 : long nTop = (long)( aVars.GetMargin()->GetTopMargin() * mnPPTY );
1876 217 : nJustPosY += nTop;
1877 217 : nTestClipHeight += nTop;
1878 : }
1879 217 : break;
1880 : case SVX_VER_JUSTIFY_BOTTOM:
1881 : {
1882 10847 : long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
1883 10847 : nJustPosY += nOutHeight - aVars.GetTextSize().Height() - nBot;
1884 10847 : nTestClipHeight += nBot;
1885 : }
1886 10847 : break;
1887 : case SVX_VER_JUSTIFY_CENTER:
1888 : {
1889 12 : long nTop = (long)( aVars.GetMargin()->GetTopMargin() * mnPPTY );
1890 12 : long nBot = (long)( aVars.GetMargin()->GetBottomMargin() * mnPPTY );
1891 24 : nJustPosY += ( nOutHeight + nTop -
1892 24 : aVars.GetTextSize().Height() - nBot ) / 2;
1893 12 : nTestClipHeight += std::abs( nTop - nBot );
1894 : }
1895 12 : break;
1896 : default:
1897 : {
1898 : // added to avoid warnings
1899 : }
1900 : }
1901 :
1902 11076 : if ( nTestClipHeight > nOutHeight )
1903 : {
1904 : // kein vertikales Clipping beim Drucken von Zellen mit
1905 : // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1906 204 : if ( eType != OUTTYPE_PRINTER ||
1907 117 : ( mpDoc->GetRowFlags( nCellY, nTab ) & CR_MANUALSIZE ) ||
1908 30 : ( aVars.HasCondHeight() ) )
1909 57 : bVClip = sal_True;
1910 : }
1911 :
1912 11076 : if ( bHClip || bVClip )
1913 : {
1914 : // nur die betroffene Dimension clippen,
1915 : // damit bei nicht-proportionalem Resize nicht alle
1916 : // rechtsbuendigen Zahlen abgeschnitten werden:
1917 :
1918 285 : if (!bHClip)
1919 : {
1920 17 : aAreaParam.maClipRect.Left() = nScrX;
1921 17 : aAreaParam.maClipRect.Right() = nScrX+nScrW;
1922 : }
1923 285 : if (!bVClip)
1924 : {
1925 228 : aAreaParam.maClipRect.Top() = nScrY;
1926 228 : aAreaParam.maClipRect.Bottom() = nScrY+nScrH;
1927 : }
1928 :
1929 : // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1930 : // so it can be modified here
1931 285 : if (bPixelToLogic)
1932 0 : aAreaParam.maClipRect = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
1933 :
1934 285 : if (bMetaFile)
1935 : {
1936 0 : mpDev->Push();
1937 0 : mpDev->IntersectClipRegion( aAreaParam.maClipRect );
1938 : }
1939 : else
1940 285 : mpDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
1941 : }
1942 :
1943 11076 : Point aURLStart( nJustPosX, nJustPosY ); // copy before modifying for orientation
1944 :
1945 11076 : switch (aVars.GetOrient())
1946 : {
1947 : case SVX_ORIENTATION_STANDARD:
1948 11007 : nJustPosY += aVars.GetAscent();
1949 11007 : break;
1950 : case SVX_ORIENTATION_TOPBOTTOM:
1951 69 : nJustPosX += aVars.GetTextSize().Width() - aVars.GetAscent();
1952 69 : break;
1953 : case SVX_ORIENTATION_BOTTOMTOP:
1954 0 : nJustPosY += aVars.GetTextSize().Height();
1955 0 : nJustPosX += aVars.GetAscent();
1956 0 : break;
1957 : default:
1958 : {
1959 : // added to avoid warnings
1960 : }
1961 : }
1962 :
1963 : // When clipping, the visible part is now completely defined by the alignment,
1964 : // there's no more special handling to show the right part of RTL text.
1965 :
1966 11076 : Point aDrawTextPos( nJustPosX, nJustPosY );
1967 11076 : if ( bPixelToLogic )
1968 : {
1969 : // undo text width adjustment in pixels
1970 356 : if (bRightAdjusted)
1971 310 : aDrawTextPos.X() += aVars.GetTextSize().Width();
1972 :
1973 356 : aDrawTextPos = mpRefDevice->PixelToLogic( aDrawTextPos );
1974 :
1975 : // redo text width adjustment in logic units
1976 356 : if (bRightAdjusted)
1977 310 : aDrawTextPos.X() -= aVars.GetOriginalWidth();
1978 : }
1979 :
1980 : // in Metafiles immer DrawTextArray, damit die Positionen mit
1981 : // aufgezeichnet werden (fuer nicht-proportionales Resize):
1982 :
1983 11076 : String aString = aVars.GetString();
1984 11076 : if (bMetaFile || pFmtDevice != mpDev || aZoomX != aZoomY)
1985 : {
1986 387 : sal_Int32* pDX = new sal_Int32[aString.Len()];
1987 387 : pFmtDevice->GetTextArray( aString, pDX );
1988 :
1989 388 : if ( !mpRefDevice->GetConnectMetaFile() ||
1990 1 : mpRefDevice->GetOutDevType() == OUTDEV_PRINTER )
1991 : {
1992 386 : double fMul = GetStretch();
1993 386 : xub_StrLen nLen = aString.Len();
1994 1468 : for (xub_StrLen i=0; i<nLen; i++)
1995 1082 : pDX[i] = (long)(pDX[i] / fMul + 0.5);
1996 : }
1997 :
1998 387 : mpDev->DrawTextArray( aDrawTextPos, aString, pDX );
1999 387 : delete[] pDX;
2000 : }
2001 : else
2002 10689 : mpDev->DrawText( aDrawTextPos, aString );
2003 :
2004 11076 : if ( bHClip || bVClip )
2005 : {
2006 285 : if (bMetaFile)
2007 0 : mpDev->Pop();
2008 : else
2009 285 : mpDev->SetClipRegion();
2010 : }
2011 :
2012 : // PDF: whole-cell hyperlink from formula?
2013 11076 : bool bHasURL = pPDFData && aCell.meType == CELLTYPE_FORMULA && aCell.mpFormula->IsHyperLinkCell();
2014 11076 : if ( bHasURL )
2015 : {
2016 0 : Rectangle aURLRect( aURLStart, aVars.GetTextSize() );
2017 0 : lcl_DoHyperlinkResult(mpDev, aURLRect, aCell);
2018 11076 : }
2019 : }
2020 : }
2021 187457 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
2022 187457 : }
2023 : }
2024 18679 : nPosY += pRowInfo[nArrY].nHeight;
2025 : }
2026 1179 : if ( bProgress )
2027 2 : ScProgress::DeleteInterpretProgress();
2028 2358 : mpDoc->EnableIdle(bWasIdleEnabled);
2029 1179 : }
2030 :
2031 : // -------------------------------------------------------------------------------
2032 :
2033 251 : ScFieldEditEngine* ScOutputData::CreateOutputEditEngine()
2034 : {
2035 251 : ScFieldEditEngine* pEngine = new ScFieldEditEngine(mpDoc, mpDoc->GetEnginePool());
2036 251 : pEngine->SetUpdateMode( false );
2037 : // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
2038 251 : pEngine->SetRefDevice( pFmtDevice );
2039 251 : sal_uLong nCtrl = pEngine->GetControlWord();
2040 251 : if ( bShowSpellErrors )
2041 248 : nCtrl |= EE_CNTRL_ONLINESPELLING;
2042 251 : if ( eType == OUTTYPE_PRINTER )
2043 3 : nCtrl &= ~EE_CNTRL_MARKFIELDS;
2044 251 : if ( eType == OUTTYPE_WINDOW && mpRefDevice == pFmtDevice )
2045 248 : nCtrl &= ~EE_CNTRL_FORMAT100; // use the actual MapMode
2046 251 : pEngine->SetControlWord( nCtrl );
2047 251 : mpDoc->ApplyAsianEditSettings( *pEngine );
2048 251 : pEngine->EnableAutoColor( mbUseStyleColor );
2049 251 : pEngine->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection)mpDoc->GetEditTextDirection( nTab ) );
2050 251 : return pEngine;
2051 : }
2052 :
2053 1329 : static void lcl_ClearEdit( EditEngine& rEngine ) // Text und Attribute
2054 : {
2055 1329 : rEngine.SetUpdateMode( false );
2056 :
2057 1329 : rEngine.SetText(EMPTY_STRING);
2058 : // keine Para-Attribute uebrigbehalten...
2059 1329 : const SfxItemSet& rPara = rEngine.GetParaAttribs(0);
2060 1329 : if (rPara.Count())
2061 : rEngine.SetParaAttribs( 0,
2062 435 : SfxItemSet( *rPara.GetPool(), rPara.GetRanges() ) );
2063 1329 : }
2064 :
2065 550 : static bool lcl_SafeIsValue( ScRefCellValue& rCell )
2066 : {
2067 550 : switch (rCell.meType)
2068 : {
2069 : case CELLTYPE_VALUE:
2070 294 : return true;
2071 : case CELLTYPE_FORMULA:
2072 : {
2073 0 : ScFormulaCell* pFCell = rCell.mpFormula;
2074 0 : if (pFCell->IsRunning() || pFCell->IsValue())
2075 0 : return true;
2076 : }
2077 0 : break;
2078 : default:
2079 : {
2080 : // added to avoid warnings
2081 : }
2082 : }
2083 256 : return false;
2084 : }
2085 :
2086 0 : static void lcl_ScaleFonts( EditEngine& rEngine, long nPercent )
2087 : {
2088 0 : sal_Bool bUpdateMode = rEngine.GetUpdateMode();
2089 0 : if ( bUpdateMode )
2090 0 : rEngine.SetUpdateMode( false );
2091 :
2092 0 : sal_Int32 nParCount = rEngine.GetParagraphCount();
2093 0 : for (sal_Int32 nPar=0; nPar<nParCount; nPar++)
2094 : {
2095 0 : std::vector<sal_uInt16> aPortions;
2096 0 : rEngine.GetPortions( nPar, aPortions );
2097 :
2098 0 : sal_uInt16 nStart = 0;
2099 0 : for ( std::vector<sal_uInt16>::const_iterator it(aPortions.begin()); it != aPortions.end(); ++it )
2100 : {
2101 0 : sal_uInt16 nEnd = *it;
2102 0 : ESelection aSel( nPar, nStart, nPar, nEnd );
2103 0 : SfxItemSet aAttribs = rEngine.GetAttribs( aSel );
2104 :
2105 0 : long nWestern = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT)).GetHeight();
2106 0 : long nCJK = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CJK)).GetHeight();
2107 0 : long nCTL = static_cast<const SvxFontHeightItem&>(aAttribs.Get(EE_CHAR_FONTHEIGHT_CTL)).GetHeight();
2108 :
2109 0 : nWestern = ( nWestern * nPercent ) / 100;
2110 0 : nCJK = ( nCJK * nPercent ) / 100;
2111 0 : nCTL = ( nCTL * nPercent ) / 100;
2112 :
2113 0 : aAttribs.Put( SvxFontHeightItem( nWestern, 100, EE_CHAR_FONTHEIGHT ) );
2114 0 : aAttribs.Put( SvxFontHeightItem( nCJK, 100, EE_CHAR_FONTHEIGHT_CJK ) );
2115 0 : aAttribs.Put( SvxFontHeightItem( nCTL, 100, EE_CHAR_FONTHEIGHT_CTL ) );
2116 :
2117 0 : rEngine.QuickSetAttribs( aAttribs, aSel ); //! remove paragraph attributes from aAttribs?
2118 :
2119 0 : nStart = nEnd;
2120 0 : }
2121 0 : }
2122 :
2123 0 : if ( bUpdateMode )
2124 0 : rEngine.SetUpdateMode( sal_True );
2125 0 : }
2126 :
2127 0 : static long lcl_GetEditSize( EditEngine& rEngine, sal_Bool bWidth, sal_Bool bSwap, long nAttrRotate )
2128 : {
2129 0 : if ( bSwap )
2130 0 : bWidth = !bWidth;
2131 :
2132 0 : if ( nAttrRotate )
2133 : {
2134 0 : long nRealWidth = (long) rEngine.CalcTextWidth();
2135 0 : long nRealHeight = rEngine.GetTextHeight();
2136 :
2137 : // assuming standard mode, otherwise width isn't used
2138 :
2139 0 : double nRealOrient = nAttrRotate * F_PI18000; // 1/100th degrees
2140 0 : double nAbsCos = fabs( cos( nRealOrient ) );
2141 0 : double nAbsSin = fabs( sin( nRealOrient ) );
2142 0 : if ( bWidth )
2143 0 : return (long) ( nRealWidth * nAbsCos + nRealHeight * nAbsSin );
2144 : else
2145 0 : return (long) ( nRealHeight * nAbsCos + nRealWidth * nAbsSin );
2146 : }
2147 0 : else if ( bWidth )
2148 0 : return (long) rEngine.CalcTextWidth();
2149 : else
2150 0 : return rEngine.GetTextHeight();
2151 : }
2152 :
2153 :
2154 156 : void ScOutputData::ShrinkEditEngine( EditEngine& rEngine, const Rectangle& rAlignRect,
2155 : long nLeftM, long nTopM, long nRightM, long nBottomM,
2156 : sal_Bool bWidth, sal_uInt16 nOrient, long nAttrRotate, sal_Bool bPixelToLogic,
2157 : long& rEngineWidth, long& rEngineHeight, long& rNeededPixel, bool& rLeftClip, bool& rRightClip )
2158 : {
2159 156 : if ( !bWidth )
2160 : {
2161 : // vertical
2162 :
2163 : long nScaleSize = bPixelToLogic ?
2164 78 : mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2165 :
2166 : // Don't scale if it fits already.
2167 : // Allowing to extend into the margin, to avoid scaling at optimal height.
2168 78 : if ( nScaleSize <= rAlignRect.GetHeight() )
2169 78 : return;
2170 :
2171 0 : sal_Bool bSwap = ( nOrient == SVX_ORIENTATION_TOPBOTTOM || nOrient == SVX_ORIENTATION_BOTTOMTOP );
2172 0 : long nAvailable = rAlignRect.GetHeight() - nTopM - nBottomM;
2173 0 : long nScale = ( nAvailable * 100 ) / nScaleSize;
2174 :
2175 0 : lcl_ScaleFonts( rEngine, nScale );
2176 0 : rEngineHeight = lcl_GetEditSize( rEngine, false, bSwap, nAttrRotate );
2177 : long nNewSize = bPixelToLogic ?
2178 0 : mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2179 :
2180 0 : sal_uInt16 nShrinkAgain = 0;
2181 0 : while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
2182 : {
2183 : // further reduce, like in DrawStrings
2184 0 : lcl_ScaleFonts( rEngine, 90 ); // reduce by 10%
2185 0 : rEngineHeight = lcl_GetEditSize( rEngine, false, bSwap, nAttrRotate );
2186 : nNewSize = bPixelToLogic ?
2187 0 : mpRefDevice->LogicToPixel(Size(0,rEngineHeight)).Height() : rEngineHeight;
2188 0 : ++nShrinkAgain;
2189 : }
2190 :
2191 : // sizes for further processing (alignment etc):
2192 0 : rEngineWidth = lcl_GetEditSize( rEngine, sal_True, bSwap, nAttrRotate );
2193 : long nPixelWidth = bPixelToLogic ?
2194 0 : mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2195 0 : rNeededPixel = nPixelWidth + nLeftM + nRightM;
2196 : }
2197 78 : else if ( rLeftClip || rRightClip )
2198 : {
2199 : // horizontal
2200 :
2201 78 : long nAvailable = rAlignRect.GetWidth() - nLeftM - nRightM;
2202 78 : long nScaleSize = rNeededPixel - nLeftM - nRightM; // without margin
2203 :
2204 78 : if ( nScaleSize <= nAvailable )
2205 78 : return;
2206 :
2207 0 : long nScale = ( nAvailable * 100 ) / nScaleSize;
2208 :
2209 0 : lcl_ScaleFonts( rEngine, nScale );
2210 0 : rEngineWidth = lcl_GetEditSize( rEngine, sal_True, false, nAttrRotate );
2211 : long nNewSize = bPixelToLogic ?
2212 0 : mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2213 :
2214 0 : sal_uInt16 nShrinkAgain = 0;
2215 0 : while ( nNewSize > nAvailable && nShrinkAgain < SC_SHRINKAGAIN_MAX )
2216 : {
2217 : // further reduce, like in DrawStrings
2218 0 : lcl_ScaleFonts( rEngine, 90 ); // reduce by 10%
2219 0 : rEngineWidth = lcl_GetEditSize( rEngine, sal_True, false, nAttrRotate );
2220 : nNewSize = bPixelToLogic ?
2221 0 : mpRefDevice->LogicToPixel(Size(rEngineWidth,0)).Width() : rEngineWidth;
2222 0 : ++nShrinkAgain;
2223 : }
2224 0 : if ( nNewSize <= nAvailable )
2225 0 : rLeftClip = rRightClip = false;
2226 :
2227 : // sizes for further processing (alignment etc):
2228 0 : rNeededPixel = nNewSize + nLeftM + nRightM;
2229 0 : rEngineHeight = lcl_GetEditSize( rEngine, false, false, nAttrRotate );
2230 : }
2231 : }
2232 :
2233 550 : ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr* pPattern, const SfxItemSet* pCondSet, bool bCellIsValue) :
2234 550 : meHorJust( lcl_GetValue<SvxHorJustifyItem, SvxCellHorJustify>(*pPattern, ATTR_HOR_JUSTIFY, pCondSet) ),
2235 550 : meVerJust( lcl_GetValue<SvxVerJustifyItem, SvxCellVerJustify>(*pPattern, ATTR_VER_JUSTIFY, pCondSet) ),
2236 550 : meHorJustMethod( lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_HOR_JUSTIFY_METHOD, pCondSet) ),
2237 550 : meVerJustMethod( lcl_GetValue<SvxJustifyMethodItem, SvxCellJustifyMethod>(*pPattern, ATTR_VER_JUSTIFY_METHOD, pCondSet) ),
2238 550 : meOrient( pPattern->GetCellOrientation(pCondSet) ),
2239 : mnArrY(0),
2240 : mnX(0), mnY(0), mnCellX(0), mnCellY(0),
2241 : mnPosX(0), mnPosY(0), mnInitPosX(0),
2242 550 : mbBreak( (meHorJust == SVX_HOR_JUSTIFY_BLOCK) || lcl_GetBoolValue(*pPattern, ATTR_LINEBREAK, pCondSet) ),
2243 : mbCellIsValue(bCellIsValue),
2244 : mbAsianVertical(false),
2245 : mbPixelToLogic(false),
2246 : mbHyphenatorSet(false),
2247 : mbRTL(false),
2248 : mpEngine(NULL),
2249 : mpPattern(pPattern),
2250 : mpCondSet(pCondSet),
2251 : mpPreviewFontSet(NULL),
2252 : mpOldPattern(NULL),
2253 : mpOldCondSet(NULL),
2254 3300 : mpThisRowInfo(NULL)
2255 550 : {}
2256 :
2257 172 : bool ScOutputData::DrawEditParam::readCellContent(
2258 : ScDocument* pDoc, bool bShowNullValues, bool bShowFormulas, bool bSyntaxMode, bool bUseStyleColor, bool bForceAutoColor, bool& rWrapFields)
2259 : {
2260 172 : if (maCell.meType == CELLTYPE_EDIT)
2261 : {
2262 102 : const EditTextObject* pData = maCell.mpEditText;
2263 102 : if (pData)
2264 : {
2265 102 : mpEngine->SetText(*pData);
2266 :
2267 102 : if ( mbBreak && !mbAsianVertical && pData->HasField() )
2268 : {
2269 : // Fields aren't wrapped, so clipping is enabled to prevent
2270 : // a field from being drawn beyond the cell size
2271 :
2272 0 : rWrapFields = true;
2273 : }
2274 : }
2275 : else
2276 : {
2277 : OSL_FAIL("pData == 0");
2278 0 : return false;
2279 : }
2280 : }
2281 : else
2282 : {
2283 : sal_uLong nFormat = mpPattern->GetNumberFormat(
2284 70 : pDoc->GetFormatTable(), mpCondSet );
2285 70 : OUString aString;
2286 : Color* pColor;
2287 : ScCellFormat::GetString( maCell,
2288 : nFormat,aString, &pColor,
2289 70 : *pDoc->GetFormatTable(),
2290 : bShowNullValues,
2291 : bShowFormulas,
2292 140 : ftCheck );
2293 :
2294 70 : mpEngine->SetText(aString);
2295 70 : if ( pColor && !bSyntaxMode && !( bUseStyleColor && bForceAutoColor ) )
2296 0 : lcl_SetEditColor( *mpEngine, *pColor );
2297 : }
2298 172 : return true;
2299 : }
2300 :
2301 172 : void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor)
2302 : {
2303 : // syntax highlighting mode is ignored here
2304 : // StringDiffer doesn't look at hyphenate, language items
2305 :
2306 172 : if (mpPattern == mpOldPattern && mpCondSet == mpOldCondSet && !mpPreviewFontSet)
2307 229 : return;
2308 :
2309 115 : sal_Int32 nConfBackColor = SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
2310 230 : bool bCellContrast = bUseStyleColor &&
2311 230 : Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2312 :
2313 115 : SfxItemSet* pSet = new SfxItemSet( mpEngine->GetEmptyItemSet() );
2314 115 : mpPattern->FillEditItemSet( pSet, mpCondSet );
2315 115 : if ( mpPreviewFontSet )
2316 : {
2317 : const SfxPoolItem* pItem;
2318 7 : if ( mpPreviewFontSet->GetItemState( ATTR_FONT, true, &pItem ) == SFX_ITEM_SET )
2319 : {
2320 7 : SvxFontItem aFontItem(EE_CHAR_FONTINFO);
2321 7 : aFontItem = (const SvxFontItem&)*pItem;
2322 7 : pSet->Put( aFontItem );
2323 : }
2324 7 : if ( mpPreviewFontSet->GetItemState( ATTR_CJK_FONT, true, &pItem ) == SFX_ITEM_SET )
2325 : {
2326 0 : SvxFontItem aCjkFontItem(EE_CHAR_FONTINFO_CJK);
2327 0 : aCjkFontItem = (const SvxFontItem&)*pItem;
2328 0 : pSet->Put( aCjkFontItem );
2329 : }
2330 7 : if ( mpPreviewFontSet->GetItemState( ATTR_CTL_FONT, true, &pItem ) == SFX_ITEM_SET )
2331 : {
2332 0 : SvxFontItem aCtlFontItem(EE_CHAR_FONTINFO_CTL);
2333 0 : aCtlFontItem = (const SvxFontItem&)*pItem;
2334 0 : pSet->Put( aCtlFontItem );
2335 : }
2336 : }
2337 115 : mpEngine->SetDefaults( pSet );
2338 115 : mpOldPattern = mpPattern;
2339 115 : mpOldCondSet = mpCondSet;
2340 :
2341 115 : sal_uLong nControl = mpEngine->GetControlWord();
2342 115 : if (meOrient == SVX_ORIENTATION_STACKED)
2343 0 : nControl |= EE_CNTRL_ONECHARPERLINE;
2344 : else
2345 115 : nControl &= ~EE_CNTRL_ONECHARPERLINE;
2346 115 : mpEngine->SetControlWord( nControl );
2347 :
2348 115 : if ( !mbHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
2349 : {
2350 : // set hyphenator the first time it is needed
2351 3 : com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
2352 3 : mpEngine->SetHyphenator( xXHyphenator );
2353 3 : mbHyphenatorSet = true;
2354 : }
2355 :
2356 115 : Color aBackCol = ((const SvxBrushItem&)mpPattern->GetItem( ATTR_BACKGROUND, mpCondSet )).GetColor();
2357 115 : if ( bUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
2358 104 : aBackCol.SetColor( nConfBackColor );
2359 115 : mpEngine->SetBackgroundColor( aBackCol );
2360 : }
2361 :
2362 245 : void ScOutputData::DrawEditParam::calcMargins(long& rTopM, long& rLeftM, long& rBottomM, long& rRightM, double nPPTX, double nPPTY) const
2363 : {
2364 : const SvxMarginItem& rMargin =
2365 245 : static_cast<const SvxMarginItem&>(mpPattern->GetItem(ATTR_MARGIN, mpCondSet));
2366 :
2367 245 : sal_uInt16 nIndent = 0;
2368 245 : if (meHorJust == SVX_HOR_JUSTIFY_LEFT || meHorJust == SVX_HOR_JUSTIFY_RIGHT)
2369 102 : nIndent = lcl_GetValue<SfxUInt16Item, sal_uInt16>(*mpPattern, ATTR_INDENT, mpCondSet);
2370 :
2371 245 : rLeftM = static_cast<long>(((rMargin.GetLeftMargin() + nIndent) * nPPTX));
2372 245 : rTopM = static_cast<long>((rMargin.GetTopMargin() * nPPTY));
2373 245 : rRightM = static_cast<long>((rMargin.GetRightMargin() * nPPTX));
2374 245 : rBottomM = static_cast<long>((rMargin.GetBottomMargin() * nPPTY));
2375 245 : if(meHorJust == SVX_HOR_JUSTIFY_RIGHT)
2376 : {
2377 0 : rLeftM = static_cast<long>((rMargin.GetLeftMargin() * nPPTX));
2378 0 : rRightM = static_cast<long>(((rMargin.GetRightMargin() + nIndent) * nPPTX));
2379 : }
2380 245 : }
2381 :
2382 73 : void ScOutputData::DrawEditParam::calcPaperSize(
2383 : Size& rPaperSize, const Rectangle& rAlignRect, double nPPTX, double nPPTY) const
2384 : {
2385 : long nTopM, nLeftM, nBottomM, nRightM;
2386 73 : calcMargins(nTopM, nLeftM, nBottomM, nRightM, nPPTX, nPPTY);
2387 :
2388 73 : if (isVerticallyOriented())
2389 : {
2390 69 : rPaperSize.Width() = rAlignRect.GetHeight() - nTopM - nBottomM;
2391 69 : rPaperSize.Height() = rAlignRect.GetWidth() - nLeftM - nRightM;
2392 : }
2393 : else
2394 : {
2395 4 : rPaperSize.Width() = rAlignRect.GetWidth() - nLeftM - nRightM;
2396 4 : rPaperSize.Height() = rAlignRect.GetHeight() - nTopM - nBottomM;
2397 : }
2398 :
2399 73 : if (mbAsianVertical)
2400 : {
2401 0 : rPaperSize.Height() = rAlignRect.GetHeight() - nTopM - nBottomM;
2402 : // Subtract some extra value from the height or else the text would go
2403 : // outside the cell area. The value of 5 is arbitrary, and is based
2404 : // entirely on heuristics.
2405 0 : rPaperSize.Height() -= 5;
2406 : }
2407 73 : }
2408 :
2409 172 : void ScOutputData::DrawEditParam::getEngineSize(ScFieldEditEngine* pEngine, long& rWidth, long& rHeight) const
2410 : {
2411 172 : long nEngineWidth = 0;
2412 172 : if (!mbBreak || meOrient == SVX_ORIENTATION_STACKED || mbAsianVertical)
2413 99 : nEngineWidth = static_cast<long>(pEngine->CalcTextWidth());
2414 :
2415 172 : long nEngineHeight = pEngine->GetTextHeight();
2416 :
2417 172 : if (isVerticallyOriented())
2418 : {
2419 69 : long nTemp = nEngineWidth;
2420 69 : nEngineWidth = nEngineHeight;
2421 69 : nEngineHeight = nTemp;
2422 : }
2423 :
2424 172 : if (meOrient == SVX_ORIENTATION_STACKED)
2425 0 : nEngineWidth = nEngineWidth * 11 / 10;
2426 :
2427 172 : rWidth = nEngineWidth;
2428 172 : rHeight = nEngineHeight;
2429 172 : }
2430 :
2431 69 : bool ScOutputData::DrawEditParam::hasLineBreak() const
2432 : {
2433 69 : return (mbBreak || (meOrient == SVX_ORIENTATION_STACKED) || mbAsianVertical);
2434 : }
2435 :
2436 0 : bool ScOutputData::DrawEditParam::isHyperlinkCell() const
2437 : {
2438 0 : if (maCell.meType != CELLTYPE_FORMULA)
2439 0 : return false;
2440 :
2441 0 : return maCell.mpFormula->IsHyperLinkCell();
2442 : }
2443 :
2444 417 : bool ScOutputData::DrawEditParam::isVerticallyOriented() const
2445 : {
2446 417 : return (meOrient == SVX_ORIENTATION_TOPBOTTOM || meOrient == SVX_ORIENTATION_BOTTOMTOP);
2447 : }
2448 :
2449 69 : void ScOutputData::DrawEditParam::calcStartPosForVertical(
2450 : Point& rLogicStart, long nCellWidth, long nEngineWidth, long nTopM, OutputDevice* pRefDevice)
2451 : {
2452 : OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
2453 :
2454 69 : if (mbPixelToLogic)
2455 69 : rLogicStart = pRefDevice->PixelToLogic(rLogicStart);
2456 :
2457 69 : if (mbBreak)
2458 : {
2459 : // vertical adjustment is within the EditEngine
2460 69 : if (mbPixelToLogic)
2461 69 : rLogicStart.Y() += pRefDevice->PixelToLogic(Size(0,nTopM)).Height();
2462 : else
2463 0 : rLogicStart.Y() += nTopM;
2464 :
2465 69 : switch (meHorJust)
2466 : {
2467 : case SVX_HOR_JUSTIFY_CENTER:
2468 7 : rLogicStart.X() += (nCellWidth - nEngineWidth) / 2;
2469 7 : break;
2470 : case SVX_HOR_JUSTIFY_RIGHT:
2471 0 : rLogicStart.X() += nCellWidth - nEngineWidth;
2472 0 : break;
2473 : default:
2474 : ; // do nothing
2475 : }
2476 : }
2477 69 : }
2478 :
2479 172 : void ScOutputData::DrawEditParam::setAlignmentToEngine()
2480 : {
2481 172 : if (isVerticallyOriented() || mbAsianVertical)
2482 : {
2483 69 : SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
2484 69 : switch (meVerJust)
2485 : {
2486 : case SVX_VER_JUSTIFY_TOP:
2487 0 : eSvxAdjust = (meOrient == SVX_ORIENTATION_TOPBOTTOM || mbAsianVertical) ?
2488 0 : SVX_ADJUST_LEFT : SVX_ADJUST_RIGHT;
2489 0 : break;
2490 : case SVX_VER_JUSTIFY_CENTER:
2491 0 : eSvxAdjust = SVX_ADJUST_CENTER;
2492 0 : break;
2493 : case SVX_VER_JUSTIFY_BOTTOM:
2494 : case SVX_VER_JUSTIFY_STANDARD:
2495 69 : eSvxAdjust = (meOrient == SVX_ORIENTATION_TOPBOTTOM || mbAsianVertical) ?
2496 138 : SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2497 69 : break;
2498 : case SVX_VER_JUSTIFY_BLOCK:
2499 0 : eSvxAdjust = SVX_ADJUST_BLOCK;
2500 0 : break;
2501 : }
2502 :
2503 69 : mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
2504 69 : mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
2505 :
2506 69 : if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
2507 12 : mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
2508 : }
2509 : else
2510 : {
2511 : // horizontal alignment now may depend on cell content
2512 : // (for values with number formats with mixed script types)
2513 : // -> always set adjustment
2514 :
2515 103 : SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
2516 103 : if (meOrient == SVX_ORIENTATION_STACKED)
2517 0 : eSvxAdjust = SVX_ADJUST_CENTER;
2518 103 : else if (mbBreak)
2519 : {
2520 4 : if (meOrient == SVX_ORIENTATION_STANDARD)
2521 4 : switch (meHorJust)
2522 : {
2523 : case SVX_HOR_JUSTIFY_STANDARD:
2524 4 : eSvxAdjust = mbCellIsValue ? SVX_ADJUST_RIGHT : SVX_ADJUST_LEFT;
2525 4 : break;
2526 : case SVX_HOR_JUSTIFY_LEFT:
2527 : case SVX_HOR_JUSTIFY_REPEAT: // nicht implementiert
2528 0 : eSvxAdjust = SVX_ADJUST_LEFT;
2529 0 : break;
2530 : case SVX_HOR_JUSTIFY_RIGHT:
2531 0 : eSvxAdjust = SVX_ADJUST_RIGHT;
2532 0 : break;
2533 : case SVX_HOR_JUSTIFY_CENTER:
2534 0 : eSvxAdjust = SVX_ADJUST_CENTER;
2535 0 : break;
2536 : case SVX_HOR_JUSTIFY_BLOCK:
2537 0 : eSvxAdjust = SVX_ADJUST_BLOCK;
2538 0 : break;
2539 : }
2540 : else
2541 0 : switch (meVerJust)
2542 : {
2543 : case SVX_VER_JUSTIFY_TOP:
2544 0 : eSvxAdjust = SVX_ADJUST_RIGHT;
2545 0 : break;
2546 : case SVX_VER_JUSTIFY_CENTER:
2547 0 : eSvxAdjust = SVX_ADJUST_CENTER;
2548 0 : break;
2549 : case SVX_VER_JUSTIFY_BOTTOM:
2550 : case SVX_VER_JUSTIFY_STANDARD:
2551 0 : eSvxAdjust = SVX_ADJUST_LEFT;
2552 0 : break;
2553 : case SVX_VER_JUSTIFY_BLOCK:
2554 0 : eSvxAdjust = SVX_ADJUST_BLOCK;
2555 0 : break;
2556 : }
2557 : }
2558 :
2559 103 : mpEngine->SetDefaultItem( SvxAdjustItem(eSvxAdjust, EE_PARA_JUST) );
2560 :
2561 103 : if (mbAsianVertical)
2562 : {
2563 0 : mpEngine->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod, EE_PARA_JUST_METHOD) );
2564 0 : if (meHorJust == SVX_HOR_JUSTIFY_BLOCK)
2565 0 : mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
2566 : }
2567 : else
2568 : {
2569 103 : mpEngine->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod, EE_PARA_JUST_METHOD) );
2570 103 : if (meVerJust == SVX_VER_JUSTIFY_BLOCK)
2571 0 : mpEngine->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK, EE_PARA_VER_JUST) );
2572 : }
2573 : }
2574 :
2575 172 : mpEngine->SetVertical(mbAsianVertical);
2576 172 : if (maCell.meType == CELLTYPE_EDIT)
2577 : {
2578 : // We need to synchronize the vertical mode in the EditTextObject
2579 : // instance too. No idea why we keep this state in two separate
2580 : // instances.
2581 102 : const EditTextObject* pData = maCell.mpEditText;
2582 102 : if (pData)
2583 102 : const_cast<EditTextObject*>(pData)->SetVertical(mbAsianVertical);
2584 : }
2585 172 : }
2586 :
2587 99 : bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine* pEngine)
2588 : {
2589 198 : if (meHorJust == SVX_HOR_JUSTIFY_RIGHT || meHorJust == SVX_HOR_JUSTIFY_CENTER ||
2590 196 : (meHorJust == SVX_HOR_JUSTIFY_STANDARD && mbCellIsValue))
2591 : {
2592 0 : SvxAdjust eEditAdjust = (meHorJust == SVX_HOR_JUSTIFY_CENTER) ?
2593 0 : SVX_ADJUST_CENTER : SVX_ADJUST_RIGHT;
2594 :
2595 0 : pEngine->SetUpdateMode(false);
2596 0 : pEngine->SetDefaultItem( SvxAdjustItem(eEditAdjust, EE_PARA_JUST) );
2597 0 : pEngine->SetUpdateMode(true);
2598 0 : return true;
2599 : }
2600 99 : return false;
2601 : }
2602 :
2603 172 : void ScOutputData::DrawEditParam::adjustForRTL()
2604 : {
2605 172 : if (!mpEngine->IsRightToLeft(0))
2606 : // No RTL mode.
2607 344 : return;
2608 :
2609 : // For right-to-left, EditEngine always calculates its lines
2610 : // beginning from the right edge, but EditLine::nStartPosX is
2611 : // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
2612 0 : Size aLogicPaper = mpEngine->GetPaperSize();
2613 0 : if ( aLogicPaper.Width() > USHRT_MAX )
2614 : {
2615 0 : aLogicPaper.Width() = USHRT_MAX;
2616 0 : mpEngine->SetPaperSize(aLogicPaper);
2617 : }
2618 : }
2619 :
2620 172 : void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart, OutputDevice* pDev)
2621 : {
2622 : // PDF: whole-cell hyperlink from formula?
2623 172 : vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() );
2624 172 : bool bHasURL = pPDFData && isHyperlinkCell();
2625 172 : if (!bHasURL)
2626 344 : return;
2627 :
2628 0 : long nURLWidth = (long) mpEngine->CalcTextWidth();
2629 0 : long nURLHeight = mpEngine->GetTextHeight();
2630 0 : if (mbBreak)
2631 : {
2632 0 : Size aPaper = mpEngine->GetPaperSize();
2633 0 : if ( mbAsianVertical )
2634 0 : nURLHeight = aPaper.Height();
2635 : else
2636 0 : nURLWidth = aPaper.Width();
2637 : }
2638 0 : if (isVerticallyOriented())
2639 0 : std::swap( nURLWidth, nURLHeight );
2640 0 : else if (mbAsianVertical)
2641 0 : aURLStart.X() -= nURLWidth;
2642 :
2643 0 : Rectangle aURLRect( aURLStart, Size( nURLWidth, nURLHeight ) );
2644 0 : lcl_DoHyperlinkResult(pDev, aURLRect, maCell);
2645 : }
2646 :
2647 481 : void ScOutputData::DrawEditStandard(DrawEditParam& rParam)
2648 : {
2649 : OSL_ASSERT(rParam.meOrient == SVX_ORIENTATION_STANDARD);
2650 : OSL_ASSERT(!rParam.mbAsianVertical);
2651 :
2652 481 : Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
2653 :
2654 481 : bool bHidden = false;
2655 481 : bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
2656 481 : bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
2657 481 : long nAttrRotate = lcl_GetValue<SfxInt32Item, long>(*rParam.mpPattern, ATTR_ROTATE_VALUE, rParam.mpCondSet);
2658 :
2659 481 : if ( rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT )
2660 : {
2661 : // ignore orientation/rotation if "repeat" is active
2662 0 : rParam.meOrient = SVX_ORIENTATION_STANDARD;
2663 0 : nAttrRotate = 0;
2664 :
2665 : // #i31843# "repeat" with "line breaks" is treated as default alignment
2666 : // (but rotation is still disabled)
2667 0 : if ( rParam.mbBreak )
2668 0 : rParam.meHorJust = SVX_HOR_JUSTIFY_STANDARD;
2669 : }
2670 :
2671 481 : if (nAttrRotate)
2672 : {
2673 : //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2674 : //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2675 378 : bHidden = true; // gedreht wird getrennt ausgegeben
2676 : }
2677 :
2678 481 : SvxCellHorJustify eOutHorJust = rParam.meHorJust;
2679 481 : if (eOutHorJust == SVX_HOR_JUSTIFY_STANDARD)
2680 : {
2681 : // fdo#32530: Default alignment depends on value vs string, and the
2682 : // direction of the 1st letter.
2683 101 : if (rParam.mbRTL)
2684 0 : eOutHorJust = rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_LEFT : SVX_HOR_JUSTIFY_RIGHT;
2685 : else
2686 101 : eOutHorJust = rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
2687 : }
2688 :
2689 481 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
2690 36 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
2691 :
2692 481 : if (bHidden)
2693 756 : return;
2694 :
2695 : //! mirror margin values for RTL?
2696 : //! move margin down to after final GetOutputArea call
2697 : long nTopM, nLeftM, nBottomM, nRightM;
2698 103 : rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
2699 :
2700 103 : SCCOL nXForPos = rParam.mnX;
2701 103 : if ( nXForPos < nX1 )
2702 : {
2703 0 : nXForPos = nX1;
2704 0 : rParam.mnPosX = rParam.mnInitPosX;
2705 : }
2706 103 : SCSIZE nArrYForPos = rParam.mnArrY;
2707 103 : if ( nArrYForPos < 1 )
2708 : {
2709 0 : nArrYForPos = 1;
2710 0 : rParam.mnPosY = nScrY;
2711 : }
2712 :
2713 103 : OutputAreaParam aAreaParam;
2714 :
2715 : //
2716 : // Initial page size - large for normal text, cell size for automatic line breaks
2717 : //
2718 :
2719 103 : Size aPaperSize = Size( 1000000, 1000000 );
2720 103 : if (rParam.mbBreak)
2721 : {
2722 : // call GetOutputArea with nNeeded=0, to get only the cell width
2723 :
2724 : //! handle nArrY == 0
2725 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
2726 4 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
2727 8 : rParam.mbCellIsValue, true, false, aAreaParam );
2728 :
2729 : //! special ScEditUtil handling if formatting for printer
2730 4 : rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
2731 : }
2732 103 : if (rParam.mbPixelToLogic)
2733 : {
2734 100 : Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
2735 100 : if ( rParam.mbBreak && !rParam.mbAsianVertical && mpRefDevice != pFmtDevice )
2736 : {
2737 : // #i85342# screen display and formatting for printer,
2738 : // use same GetEditArea call as in ScViewData::SetEditEngine
2739 :
2740 0 : Fraction aFract(1,1);
2741 : Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
2742 0 : HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
2743 0 : aLogicSize.Width() = aUtilRect.GetWidth();
2744 : }
2745 100 : rParam.mpEngine->SetPaperSize(aLogicSize);
2746 : }
2747 : else
2748 3 : rParam.mpEngine->SetPaperSize(aPaperSize);
2749 :
2750 : //
2751 : // Fill the EditEngine (cell attributes and text)
2752 : //
2753 :
2754 : // default alignment for asian vertical mode is top-right
2755 103 : if ( rParam.mbAsianVertical && rParam.meVerJust == SVX_VER_JUSTIFY_STANDARD )
2756 0 : rParam.meVerJust = SVX_VER_JUSTIFY_TOP;
2757 :
2758 103 : rParam.setPatternToEngine(mbUseStyleColor);
2759 103 : rParam.setAlignmentToEngine();
2760 :
2761 : // Read content from cell
2762 :
2763 103 : bool bWrapFields = false;
2764 103 : if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
2765 : // Failed to read cell content. Bail out.
2766 0 : return;
2767 :
2768 103 : if ( mbSyntaxMode )
2769 0 : SetEditSyntaxColor(*rParam.mpEngine, rParam.maCell);
2770 103 : else if ( mbUseStyleColor && mbForceAutoColor )
2771 0 : lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
2772 :
2773 103 : rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
2774 :
2775 : //
2776 : // Get final output area using the calculated width
2777 : //
2778 :
2779 : long nEngineWidth, nEngineHeight;
2780 103 : rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
2781 :
2782 103 : long nNeededPixel = nEngineWidth;
2783 103 : if (rParam.mbPixelToLogic)
2784 100 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
2785 103 : nNeededPixel += nLeftM + nRightM;
2786 :
2787 103 : if (!rParam.mbBreak || bShrink)
2788 : {
2789 : // for break, the first GetOutputArea call is sufficient
2790 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
2791 99 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
2792 198 : rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
2793 :
2794 99 : if ( bShrink )
2795 : {
2796 : ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
2797 : nLeftM, nTopM, nRightM, nBottomM, true,
2798 0 : sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
2799 : nEngineWidth, nEngineHeight, nNeededPixel,
2800 0 : aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
2801 : }
2802 99 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
2803 : {
2804 : // First check if twice the space for the formatted text is available
2805 : // (otherwise just keep it unchanged).
2806 :
2807 0 : long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
2808 0 : long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
2809 0 : if ( nAvailable >= 2 * nFormatted )
2810 : {
2811 : // "repeat" is handled with unformatted text (for performance reasons)
2812 0 : String aCellStr = rParam.mpEngine->GetText();
2813 0 : rParam.mpEngine->SetText( aCellStr );
2814 :
2815 0 : long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
2816 0 : if (rParam.mbPixelToLogic)
2817 0 : nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
2818 0 : if ( pFmtDevice != mpRefDevice )
2819 0 : ++nRepeatSize;
2820 0 : if ( nRepeatSize > 0 )
2821 : {
2822 0 : long nRepeatCount = nAvailable / nRepeatSize;
2823 0 : if ( nRepeatCount > 1 )
2824 : {
2825 0 : String aRepeated = aCellStr;
2826 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
2827 0 : aRepeated.Append( aCellStr );
2828 0 : rParam.mpEngine->SetText( aRepeated );
2829 :
2830 0 : nEngineHeight = rParam.mpEngine->GetTextHeight();
2831 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
2832 0 : if (rParam.mbPixelToLogic)
2833 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2834 : else
2835 0 : nNeededPixel = nEngineWidth;
2836 0 : nNeededPixel += nLeftM + nRightM;
2837 : }
2838 0 : }
2839 : }
2840 : }
2841 :
2842 99 : if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
2843 : {
2844 0 : rParam.mpEngine->SetText(OUString("###"));
2845 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
2846 0 : if (rParam.mbPixelToLogic)
2847 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
2848 : else
2849 0 : nNeededPixel = nEngineWidth;
2850 0 : nNeededPixel += nLeftM + nRightM;
2851 :
2852 : // No clip marks if "###" doesn't fit (same as in DrawStrings)
2853 : }
2854 :
2855 99 : if (eOutHorJust != SVX_HOR_JUSTIFY_LEFT)
2856 : {
2857 0 : aPaperSize.Width() = nNeededPixel + 1;
2858 0 : if (rParam.mbPixelToLogic)
2859 0 : rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
2860 : else
2861 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
2862 : }
2863 : }
2864 :
2865 103 : long nStartX = aAreaParam.maAlignRect.Left();
2866 103 : long nStartY = aAreaParam.maAlignRect.Top();
2867 103 : long nCellWidth = aAreaParam.maAlignRect.GetWidth();
2868 103 : long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
2869 103 : long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
2870 :
2871 103 : if (rParam.mbBreak)
2872 : {
2873 : // text with automatic breaks is aligned only within the
2874 : // edit engine's paper size, the output of the whole area
2875 : // is always left-aligned
2876 :
2877 4 : nStartX += nLeftM;
2878 : }
2879 : else
2880 : {
2881 99 : if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
2882 0 : nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
2883 99 : else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
2884 0 : nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
2885 : else
2886 99 : nStartX += nLeftM;
2887 : }
2888 :
2889 103 : bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
2890 103 : if (bOutside)
2891 0 : return;
2892 :
2893 103 : if ( aAreaParam.maClipRect.Left() < nScrX )
2894 : {
2895 0 : aAreaParam.maClipRect.Left() = nScrX;
2896 0 : aAreaParam.mbLeftClip = true;
2897 : }
2898 103 : if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
2899 : {
2900 3 : aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
2901 3 : aAreaParam.mbRightClip = true;
2902 : }
2903 :
2904 103 : bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
2905 103 : bool bSimClip = false;
2906 :
2907 103 : if ( bWrapFields )
2908 : {
2909 : // Fields in a cell with automatic breaks: clip to cell width
2910 0 : bClip = true;
2911 : }
2912 :
2913 103 : if ( aAreaParam.maClipRect.Top() < nScrY )
2914 : {
2915 0 : aAreaParam.maClipRect.Top() = nScrY;
2916 0 : bClip = true;
2917 : }
2918 103 : if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
2919 : {
2920 0 : aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
2921 0 : bClip = true;
2922 : }
2923 :
2924 103 : Size aCellSize; // output area, excluding margins, in logical units
2925 103 : if (rParam.mbPixelToLogic)
2926 100 : aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
2927 : else
2928 3 : aCellSize = Size( nOutWidth, nOutHeight );
2929 :
2930 103 : if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
2931 : {
2932 : const ScMergeAttr* pMerge =
2933 62 : (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
2934 62 : bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
2935 :
2936 : // Don't clip for text height when printing rows with optimal height,
2937 : // except when font size is from conditional formatting.
2938 : //! Allow clipping when vertically merged?
2939 127 : if ( eType != OUTTYPE_PRINTER ||
2940 124 : ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
2941 0 : ( rParam.mpCondSet && SFX_ITEM_SET ==
2942 0 : rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
2943 59 : bClip = true;
2944 : else
2945 3 : bSimClip = true;
2946 :
2947 : // Show clip marks if height is at least 5pt too small and
2948 : // there are several lines of text.
2949 : // Not for asian vertical text, because that would interfere
2950 : // with the default right position of the text.
2951 : // Only with automatic line breaks, to avoid having to find
2952 : // the cells with the horizontal end of the text again.
2953 127 : if ( nEngineHeight - aCellSize.Height() > 100 &&
2954 62 : rParam.mbBreak && bMarkClipped &&
2955 0 : ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
2956 : {
2957 0 : CellInfo* pClipMarkCell = NULL;
2958 0 : if ( bMerged )
2959 : {
2960 : // anywhere in the merged area...
2961 0 : SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
2962 0 : pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
2963 : }
2964 : else
2965 0 : pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
2966 :
2967 0 : pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
2968 0 : bAnyClipped = true;
2969 :
2970 0 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
2971 0 : if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
2972 0 : aAreaParam.maClipRect.Right() -= nMarkPixel;
2973 : }
2974 : }
2975 :
2976 103 : Rectangle aLogicClip;
2977 103 : if (bClip || bSimClip)
2978 : {
2979 : // Clip marks are already handled in GetOutputArea
2980 :
2981 62 : if (rParam.mbPixelToLogic)
2982 59 : aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
2983 : else
2984 3 : aLogicClip = aAreaParam.maClipRect;
2985 :
2986 62 : if (bClip) // bei bSimClip nur aClipRect initialisieren
2987 : {
2988 62 : if (bMetaFile)
2989 : {
2990 0 : mpDev->Push();
2991 0 : mpDev->IntersectClipRegion( aLogicClip );
2992 : }
2993 : else
2994 62 : mpDev->SetClipRegion( Region( aLogicClip ) );
2995 : }
2996 : }
2997 :
2998 103 : Point aLogicStart;
2999 103 : if (rParam.mbPixelToLogic)
3000 100 : aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
3001 : else
3002 3 : aLogicStart = Point(nStartX, nStartY);
3003 :
3004 103 : if (!rParam.mbBreak)
3005 : {
3006 : // horizontal alignment
3007 99 : if (rParam.adjustHorAlignment(rParam.mpEngine))
3008 : // reset adjustment for the next cell
3009 0 : rParam.mpOldPattern = NULL;
3010 : }
3011 :
3012 206 : if (rParam.meVerJust==SVX_VER_JUSTIFY_BOTTOM ||
3013 103 : rParam.meVerJust==SVX_VER_JUSTIFY_STANDARD)
3014 : {
3015 : //! if pRefDevice != pFmtDevice, keep heights in logic units,
3016 : //! only converting margin?
3017 :
3018 196 : if (rParam.mbPixelToLogic)
3019 190 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM +
3020 190 : mpRefDevice->LogicToPixel(aCellSize).Height() -
3021 190 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
3022 190 : )).Height();
3023 : else
3024 3 : aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
3025 : }
3026 5 : else if (rParam.meVerJust==SVX_VER_JUSTIFY_CENTER)
3027 : {
3028 0 : if (rParam.mbPixelToLogic)
3029 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM + (
3030 0 : mpRefDevice->LogicToPixel(aCellSize).Height() -
3031 0 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
3032 0 : / 2)).Height();
3033 : else
3034 0 : aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
3035 : }
3036 : else // top
3037 : {
3038 5 : if (rParam.mbPixelToLogic)
3039 5 : aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
3040 : else
3041 0 : aLogicStart.Y() += nTopM;
3042 : }
3043 :
3044 103 : Point aURLStart = aLogicStart; // copy before modifying for orientation
3045 :
3046 103 : rParam.adjustForRTL();
3047 :
3048 : // bMoveClipped handling has been replaced by complete alignment
3049 : // handling (also extending to the left).
3050 :
3051 103 : if (bSimClip)
3052 : {
3053 : // kein hartes Clipping, aber nur die betroffenen
3054 : // Zeilen ausgeben
3055 :
3056 3 : Point aDocStart = aLogicClip.TopLeft();
3057 3 : aDocStart -= aLogicStart;
3058 3 : rParam.mpEngine->Draw( mpDev, aLogicClip, aDocStart, false );
3059 : }
3060 : else
3061 : {
3062 100 : rParam.mpEngine->Draw(mpDev, aLogicStart, 0);
3063 : }
3064 :
3065 103 : if (bClip)
3066 : {
3067 62 : if (bMetaFile)
3068 0 : mpDev->Pop();
3069 : else
3070 62 : mpDev->SetClipRegion();
3071 : }
3072 :
3073 103 : rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
3074 : }
3075 :
3076 0 : void ScOutputData::ShowClipMarks( DrawEditParam& rParam, long nEngineHeight, const Size& aCellSize,
3077 : bool bMerged, OutputAreaParam& aAreaParam)
3078 : {
3079 : // Show clip marks if height is at least 5pt too small and
3080 : // there are several lines of text.
3081 : // Not for asian vertical text, because that would interfere
3082 : // with the default right position of the text.
3083 : // Only with automatic line breaks, to avoid having to find
3084 : // the cells with the horizontal end of the text again.
3085 0 : if ( nEngineHeight - aCellSize.Height() > 100 &&
3086 0 : rParam.mbBreak && bMarkClipped &&
3087 0 : ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
3088 : {
3089 0 : CellInfo* pClipMarkCell = NULL;
3090 0 : if ( bMerged )
3091 : {
3092 : // anywhere in the merged area...
3093 0 : SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
3094 0 : pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
3095 : }
3096 : else
3097 0 : pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
3098 :
3099 0 : pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
3100 0 : bAnyClipped = true;
3101 :
3102 0 : const long nMarkPixel = static_cast<long>( SC_CLIPMARK_SIZE * mnPPTX );
3103 0 : if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
3104 0 : aAreaParam.maClipRect.Right() -= nMarkPixel;
3105 : }
3106 0 : }
3107 :
3108 69 : bool ScOutputData::Clip( DrawEditParam& rParam, const Size& aCellSize,
3109 : OutputAreaParam& aAreaParam, long nEngineHeight,
3110 : bool bWrapFields)
3111 : {
3112 69 : if ( aAreaParam.maClipRect.Left() < nScrX )
3113 : {
3114 0 : aAreaParam.maClipRect.Left() = nScrX;
3115 0 : aAreaParam.mbLeftClip = true;
3116 : }
3117 69 : if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
3118 : {
3119 0 : aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
3120 0 : aAreaParam.mbRightClip = true;
3121 : }
3122 :
3123 69 : bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
3124 69 : bool bSimClip = false;
3125 :
3126 69 : if ( bWrapFields )
3127 : {
3128 : // Fields in a cell with automatic breaks: clip to cell width
3129 0 : bClip = true;
3130 : }
3131 :
3132 69 : if ( aAreaParam.maClipRect.Top() < nScrY )
3133 : {
3134 0 : aAreaParam.maClipRect.Top() = nScrY;
3135 0 : bClip = true;
3136 : }
3137 69 : if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
3138 : {
3139 0 : aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
3140 0 : bClip = true;
3141 : }
3142 :
3143 69 : const Size& aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
3144 69 : if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
3145 : {
3146 : const ScMergeAttr* pMerge =
3147 0 : (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
3148 0 : const bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
3149 :
3150 : // Don't clip for text height when printing rows with optimal height,
3151 : // except when font size is from conditional formatting.
3152 : //! Allow clipping when vertically merged?
3153 0 : if ( eType != OUTTYPE_PRINTER ||
3154 0 : ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
3155 0 : ( rParam.mpCondSet && SFX_ITEM_SET ==
3156 0 : rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
3157 0 : bClip = true;
3158 : else
3159 0 : bSimClip = true;
3160 :
3161 0 : ShowClipMarks( rParam, nEngineHeight, aCellSize, bMerged, aAreaParam);
3162 : }
3163 :
3164 69 : Rectangle aLogicClip;
3165 69 : if (bClip || bSimClip)
3166 : {
3167 : // Clip marks are already handled in GetOutputArea
3168 :
3169 0 : if (rParam.mbPixelToLogic)
3170 0 : aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
3171 : else
3172 0 : aLogicClip = aAreaParam.maClipRect;
3173 :
3174 0 : if (bClip) // bei bSimClip nur aClipRect initialisieren
3175 : {
3176 0 : if (bMetaFile)
3177 : {
3178 0 : mpDev->Push();
3179 0 : mpDev->IntersectClipRegion( aLogicClip );
3180 : }
3181 : else
3182 0 : mpDev->SetClipRegion( Region( aLogicClip ) );
3183 : }
3184 : }
3185 :
3186 69 : return bClip;
3187 : }
3188 :
3189 0 : void ScOutputData::DrawEditBottomTop(DrawEditParam& rParam)
3190 : {
3191 : OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
3192 :
3193 0 : const bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
3194 0 : const bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
3195 :
3196 : SvxCellHorJustify eOutHorJust =
3197 0 : ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
3198 0 : ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
3199 :
3200 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
3201 0 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
3202 :
3203 : //! mirror margin values for RTL?
3204 : //! move margin down to after final GetOutputArea call
3205 : long nTopM, nLeftM, nBottomM, nRightM;
3206 0 : rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
3207 :
3208 0 : SCCOL nXForPos = rParam.mnX;
3209 0 : if ( nXForPos < nX1 )
3210 : {
3211 0 : nXForPos = nX1;
3212 0 : rParam.mnPosX = rParam.mnInitPosX;
3213 : }
3214 0 : SCSIZE nArrYForPos = rParam.mnArrY;
3215 0 : if ( nArrYForPos < 1 )
3216 : {
3217 0 : nArrYForPos = 1;
3218 0 : rParam.mnPosY = nScrY;
3219 : }
3220 :
3221 0 : OutputAreaParam aAreaParam;
3222 :
3223 : //
3224 : // Initial page size - large for normal text, cell size for automatic line breaks
3225 : //
3226 :
3227 0 : Size aPaperSize = Size( 1000000, 1000000 );
3228 0 : if (rParam.mbBreak)
3229 : {
3230 : // call GetOutputArea with nNeeded=0, to get only the cell width
3231 :
3232 : //! handle nArrY == 0
3233 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
3234 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3235 0 : rParam.mbCellIsValue, true, false, aAreaParam );
3236 :
3237 : //! special ScEditUtil handling if formatting for printer
3238 0 : rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
3239 : }
3240 0 : if (rParam.mbPixelToLogic)
3241 : {
3242 0 : Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
3243 0 : rParam.mpEngine->SetPaperSize(aLogicSize);
3244 : }
3245 : else
3246 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
3247 :
3248 : //
3249 : // Fill the EditEngine (cell attributes and text)
3250 : //
3251 :
3252 0 : rParam.setPatternToEngine(mbUseStyleColor);
3253 0 : rParam.setAlignmentToEngine();
3254 :
3255 : // Read content from cell
3256 :
3257 0 : bool bWrapFields = false;
3258 0 : if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
3259 : // Failed to read cell content. Bail out.
3260 0 : return;
3261 :
3262 0 : if ( mbSyntaxMode )
3263 0 : SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
3264 0 : else if ( mbUseStyleColor && mbForceAutoColor )
3265 0 : lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
3266 :
3267 0 : rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3268 :
3269 : //
3270 : // Get final output area using the calculated width
3271 : //
3272 :
3273 : long nEngineWidth, nEngineHeight;
3274 0 : rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
3275 :
3276 0 : long nNeededPixel = nEngineWidth;
3277 0 : if (rParam.mbPixelToLogic)
3278 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
3279 0 : nNeededPixel += nLeftM + nRightM;
3280 :
3281 0 : if (!rParam.mbBreak || bShrink)
3282 : {
3283 : // for break, the first GetOutputArea call is sufficient
3284 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
3285 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3286 0 : rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
3287 :
3288 0 : if ( bShrink )
3289 : {
3290 : ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
3291 : nLeftM, nTopM, nRightM, nBottomM, false,
3292 0 : sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
3293 : nEngineWidth, nEngineHeight, nNeededPixel,
3294 0 : aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
3295 : }
3296 0 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
3297 : {
3298 : // First check if twice the space for the formatted text is available
3299 : // (otherwise just keep it unchanged).
3300 :
3301 0 : const long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
3302 0 : const long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
3303 0 : if ( nAvailable >= 2 * nFormatted )
3304 : {
3305 : // "repeat" is handled with unformatted text (for performance reasons)
3306 0 : String aCellStr = rParam.mpEngine->GetText();
3307 0 : rParam.mpEngine->SetText( aCellStr );
3308 :
3309 0 : long nRepeatSize = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
3310 0 : if (rParam.mbPixelToLogic)
3311 0 : nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
3312 0 : if ( pFmtDevice != mpRefDevice )
3313 0 : ++nRepeatSize;
3314 0 : if ( nRepeatSize > 0 )
3315 : {
3316 0 : const long nRepeatCount = nAvailable / nRepeatSize;
3317 0 : if ( nRepeatCount > 1 )
3318 : {
3319 0 : String aRepeated = aCellStr;
3320 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
3321 0 : aRepeated.Append( aCellStr );
3322 0 : rParam.mpEngine->SetText( aRepeated );
3323 :
3324 0 : nEngineHeight = rParam.mpEngine->GetTextHeight();
3325 0 : nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
3326 0 : if (rParam.mbPixelToLogic)
3327 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3328 : else
3329 0 : nNeededPixel = nEngineWidth;
3330 0 : nNeededPixel += nLeftM + nRightM;
3331 : }
3332 0 : }
3333 : }
3334 : }
3335 :
3336 0 : if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
3337 : {
3338 0 : rParam.mpEngine->SetText(OUString("###"));
3339 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
3340 0 : if (rParam.mbPixelToLogic)
3341 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3342 : else
3343 0 : nNeededPixel = nEngineWidth;
3344 0 : nNeededPixel += nLeftM + nRightM;
3345 :
3346 : // No clip marks if "###" doesn't fit (same as in DrawStrings)
3347 : }
3348 : }
3349 :
3350 0 : long nStartX = aAreaParam.maAlignRect.Left();
3351 0 : const long nStartY = aAreaParam.maAlignRect.Top();
3352 0 : const long nCellWidth = aAreaParam.maAlignRect.GetWidth();
3353 0 : const long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
3354 0 : const long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
3355 :
3356 0 : if (rParam.mbBreak)
3357 : {
3358 : // text with automatic breaks is aligned only within the
3359 : // edit engine's paper size, the output of the whole area
3360 : // is always left-aligned
3361 :
3362 0 : nStartX += nLeftM;
3363 : }
3364 : else
3365 : {
3366 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
3367 0 : nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
3368 0 : else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
3369 0 : nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
3370 : else
3371 0 : nStartX += nLeftM;
3372 : }
3373 :
3374 0 : const bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
3375 0 : if (bOutside)
3376 0 : return;
3377 :
3378 : // output area, excluding margins, in logical units
3379 : const Size& aCellSize = rParam.mbPixelToLogic
3380 0 : ? mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) )
3381 0 : : Size( nOutWidth, nOutHeight );
3382 :
3383 0 : const bool bClip = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields );
3384 :
3385 0 : Point aLogicStart(nStartX, nStartY);
3386 0 : rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice);
3387 :
3388 0 : Point aURLStart = aLogicStart; // copy before modifying for orientation
3389 :
3390 0 : if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK || rParam.mbBreak)
3391 : {
3392 0 : Size aPSize = rParam.mpEngine->GetPaperSize();
3393 0 : aPSize.Width() = aCellSize.Height();
3394 0 : rParam.mpEngine->SetPaperSize(aPSize);
3395 0 : aLogicStart.Y() +=
3396 0 : rParam.mbBreak ? aPSize.Width() : nEngineHeight;
3397 : }
3398 : else
3399 : {
3400 : // Note that the "paper" is rotated 90 degrees to the left, so
3401 : // paper's width is in vertical direction. Also, the whole text
3402 : // is on a single line, as text wrap is not in effect.
3403 :
3404 : // Set the paper width to be the width of the text.
3405 0 : Size aPSize = rParam.mpEngine->GetPaperSize();
3406 0 : aPSize.Width() = rParam.mpEngine->CalcTextWidth();
3407 0 : rParam.mpEngine->SetPaperSize(aPSize);
3408 :
3409 0 : long nGap = 0;
3410 0 : long nTopOffset = 0;
3411 0 : if (rParam.mbPixelToLogic)
3412 : {
3413 0 : nGap = mpRefDevice->LogicToPixel(aCellSize).Height() - mpRefDevice->LogicToPixel(aPSize).Width();
3414 0 : nGap = mpRefDevice->PixelToLogic(Size(0, nGap)).Height();
3415 0 : nTopOffset = mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
3416 : }
3417 : else
3418 : {
3419 0 : nGap = aCellSize.Height() - aPSize.Width();
3420 0 : nTopOffset = nTopM;
3421 : }
3422 :
3423 : // First, align text to bottom.
3424 0 : aLogicStart.Y() += aCellSize.Height();
3425 0 : aLogicStart.Y() += nTopOffset;
3426 :
3427 0 : switch (rParam.meVerJust)
3428 : {
3429 : case SVX_VER_JUSTIFY_STANDARD:
3430 : case SVX_VER_JUSTIFY_BOTTOM:
3431 : // align to bottom (do nothing).
3432 0 : break;
3433 : case SVX_VER_JUSTIFY_CENTER:
3434 : // center it.
3435 0 : aLogicStart.Y() -= nGap / 2;
3436 0 : break;
3437 : case SVX_VER_JUSTIFY_BLOCK:
3438 : case SVX_VER_JUSTIFY_TOP:
3439 : // align to top
3440 0 : aLogicStart.Y() -= nGap;
3441 : default:
3442 : ;
3443 : }
3444 : }
3445 :
3446 0 : rParam.adjustForRTL();
3447 0 : rParam.mpEngine->Draw(mpDev, aLogicStart, 900);
3448 :
3449 0 : if (bClip)
3450 : {
3451 0 : if (bMetaFile)
3452 0 : mpDev->Pop();
3453 : else
3454 0 : mpDev->SetClipRegion();
3455 : }
3456 :
3457 0 : rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
3458 : }
3459 :
3460 69 : void ScOutputData::DrawEditTopBottom(DrawEditParam& rParam)
3461 : {
3462 : OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
3463 :
3464 69 : const bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
3465 69 : const bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
3466 :
3467 : SvxCellHorJustify eOutHorJust =
3468 69 : ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
3469 69 : ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
3470 :
3471 69 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
3472 12 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
3473 :
3474 : //! mirror margin values for RTL?
3475 : //! move margin down to after final GetOutputArea call
3476 : long nTopM, nLeftM, nBottomM, nRightM;
3477 69 : rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
3478 :
3479 69 : SCCOL nXForPos = rParam.mnX;
3480 69 : if ( nXForPos < nX1 )
3481 : {
3482 0 : nXForPos = nX1;
3483 0 : rParam.mnPosX = rParam.mnInitPosX;
3484 : }
3485 69 : SCSIZE nArrYForPos = rParam.mnArrY;
3486 69 : if ( nArrYForPos < 1 )
3487 : {
3488 0 : nArrYForPos = 1;
3489 0 : rParam.mnPosY = nScrY;
3490 : }
3491 :
3492 69 : OutputAreaParam aAreaParam;
3493 :
3494 : //
3495 : // Initial page size - large for normal text, cell size for automatic line breaks
3496 : //
3497 :
3498 69 : Size aPaperSize = Size( 1000000, 1000000 );
3499 69 : if (rParam.hasLineBreak())
3500 : {
3501 : // call GetOutputArea with nNeeded=0, to get only the cell width
3502 :
3503 : //! handle nArrY == 0
3504 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
3505 69 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3506 138 : rParam.mbCellIsValue, true, false, aAreaParam );
3507 :
3508 : //! special ScEditUtil handling if formatting for printer
3509 69 : rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
3510 : }
3511 69 : if (rParam.mbPixelToLogic)
3512 : {
3513 69 : Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
3514 69 : rParam.mpEngine->SetPaperSize(aLogicSize);
3515 : }
3516 : else
3517 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
3518 :
3519 : //
3520 : // Fill the EditEngine (cell attributes and text)
3521 : //
3522 :
3523 69 : rParam.setPatternToEngine(mbUseStyleColor);
3524 69 : rParam.setAlignmentToEngine();
3525 :
3526 : // Read content from cell
3527 :
3528 69 : bool bWrapFields = false;
3529 69 : if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
3530 : // Failed to read cell content. Bail out.
3531 0 : return;
3532 :
3533 69 : if ( mbSyntaxMode )
3534 0 : SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
3535 69 : else if ( mbUseStyleColor && mbForceAutoColor )
3536 0 : lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
3537 :
3538 69 : rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3539 :
3540 : //
3541 : // Get final output area using the calculated width
3542 : //
3543 :
3544 : long nEngineWidth, nEngineHeight;
3545 69 : rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
3546 :
3547 69 : long nNeededPixel = nEngineWidth;
3548 69 : if (rParam.mbPixelToLogic)
3549 69 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
3550 69 : nNeededPixel += nLeftM + nRightM;
3551 :
3552 69 : if (!rParam.mbBreak || bShrink)
3553 : {
3554 : // for break, the first GetOutputArea call is sufficient
3555 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
3556 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3557 0 : rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
3558 :
3559 0 : if ( bShrink )
3560 : {
3561 : ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
3562 : nLeftM, nTopM, nRightM, nBottomM, false,
3563 0 : sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
3564 : nEngineWidth, nEngineHeight, nNeededPixel,
3565 0 : aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
3566 : }
3567 0 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
3568 : {
3569 : // First check if twice the space for the formatted text is available
3570 : // (otherwise just keep it unchanged).
3571 :
3572 0 : const long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
3573 0 : const long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
3574 0 : if ( nAvailable >= 2 * nFormatted )
3575 : {
3576 : // "repeat" is handled with unformatted text (for performance reasons)
3577 0 : String aCellStr = rParam.mpEngine->GetText();
3578 0 : rParam.mpEngine->SetText( aCellStr );
3579 :
3580 0 : long nRepeatSize = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
3581 0 : if (rParam.mbPixelToLogic)
3582 0 : nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
3583 0 : if ( pFmtDevice != mpRefDevice )
3584 0 : ++nRepeatSize;
3585 0 : if ( nRepeatSize > 0 )
3586 : {
3587 0 : const long nRepeatCount = nAvailable / nRepeatSize;
3588 0 : if ( nRepeatCount > 1 )
3589 : {
3590 0 : String aRepeated = aCellStr;
3591 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
3592 0 : aRepeated.Append( aCellStr );
3593 0 : rParam.mpEngine->SetText( aRepeated );
3594 :
3595 0 : nEngineHeight = rParam.mpEngine->GetTextHeight();
3596 0 : nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
3597 0 : if (rParam.mbPixelToLogic)
3598 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3599 : else
3600 0 : nNeededPixel = nEngineWidth;
3601 0 : nNeededPixel += nLeftM + nRightM;
3602 : }
3603 0 : }
3604 : }
3605 : }
3606 :
3607 0 : if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
3608 : {
3609 0 : rParam.mpEngine->SetText(OUString("###"));
3610 0 : nEngineWidth = static_cast<long>( rParam.mpEngine->CalcTextWidth() );
3611 0 : if (rParam.mbPixelToLogic)
3612 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3613 : else
3614 0 : nNeededPixel = nEngineWidth;
3615 0 : nNeededPixel += nLeftM + nRightM;
3616 :
3617 : // No clip marks if "###" doesn't fit (same as in DrawStrings)
3618 : }
3619 : }
3620 :
3621 69 : long nStartX = aAreaParam.maAlignRect.Left();
3622 69 : const long nStartY = aAreaParam.maAlignRect.Top();
3623 69 : const long nCellWidth = aAreaParam.maAlignRect.GetWidth();
3624 69 : const long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
3625 69 : const long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
3626 :
3627 69 : if (rParam.mbBreak)
3628 : {
3629 : // text with automatic breaks is aligned only within the
3630 : // edit engine's paper size, the output of the whole area
3631 : // is always left-aligned
3632 :
3633 69 : nStartX += nLeftM;
3634 69 : if (rParam.meHorJust == SVX_HOR_JUSTIFY_BLOCK)
3635 12 : nStartX += aPaperSize.Height();
3636 : }
3637 : else
3638 : {
3639 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
3640 0 : nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
3641 0 : else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
3642 0 : nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
3643 : else
3644 0 : nStartX += nLeftM;
3645 : }
3646 :
3647 69 : const bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
3648 69 : if (bOutside)
3649 0 : return;
3650 :
3651 : // output area, excluding margins, in logical units
3652 : const Size& aCellSize = rParam.mbPixelToLogic
3653 276 : ? mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) )
3654 207 : : Size( nOutWidth, nOutHeight );
3655 :
3656 69 : const bool bClip = Clip( rParam, aCellSize, aAreaParam, nEngineHeight, bWrapFields );
3657 :
3658 69 : Point aLogicStart(nStartX, nStartY);
3659 69 : rParam.calcStartPosForVertical(aLogicStart, aCellSize.Width(), nEngineWidth, nTopM, mpRefDevice);
3660 :
3661 69 : Point aURLStart = aLogicStart; // copy before modifying for orientation
3662 :
3663 69 : if (rParam.meHorJust != SVX_HOR_JUSTIFY_BLOCK)
3664 : {
3665 57 : aLogicStart.X() += nEngineWidth;
3666 57 : if (!rParam.mbBreak)
3667 : {
3668 : // Set the paper width to text size.
3669 0 : Size aPSize = rParam.mpEngine->GetPaperSize();
3670 0 : aPSize.Width() = rParam.mpEngine->CalcTextWidth();
3671 0 : rParam.mpEngine->SetPaperSize(aPSize);
3672 :
3673 0 : long nGap = 0;
3674 0 : long nTopOffset = 0; // offset by top margin
3675 0 : if (rParam.mbPixelToLogic)
3676 : {
3677 0 : nGap = mpRefDevice->LogicToPixel(aPSize).Width() - mpRefDevice->LogicToPixel(aCellSize).Height();
3678 0 : nGap = mpRefDevice->PixelToLogic(Size(0, nGap)).Height();
3679 0 : nTopOffset = mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
3680 : }
3681 : else
3682 : {
3683 0 : nGap = aPSize.Width() - aCellSize.Height();
3684 0 : nTopOffset = nTopM;
3685 : }
3686 0 : aLogicStart.Y() += nTopOffset;
3687 :
3688 0 : switch (rParam.meVerJust)
3689 : {
3690 : case SVX_VER_JUSTIFY_STANDARD:
3691 : case SVX_VER_JUSTIFY_BOTTOM:
3692 : // align to bottom
3693 0 : aLogicStart.Y() -= nGap;
3694 0 : break;
3695 : case SVX_VER_JUSTIFY_CENTER:
3696 : // center it.
3697 0 : aLogicStart.Y() -= nGap / 2;
3698 0 : break;
3699 : case SVX_VER_JUSTIFY_BLOCK:
3700 : case SVX_VER_JUSTIFY_TOP:
3701 : // align to top (do nothing)
3702 : default:
3703 : ;
3704 : }
3705 : }
3706 : }
3707 :
3708 69 : rParam.adjustForRTL();
3709 :
3710 : // bMoveClipped handling has been replaced by complete alignment
3711 : // handling (also extending to the left).
3712 :
3713 69 : rParam.mpEngine->Draw(mpDev, aLogicStart, 2700);
3714 :
3715 69 : if (bClip)
3716 : {
3717 0 : if (bMetaFile)
3718 0 : mpDev->Pop();
3719 : else
3720 0 : mpDev->SetClipRegion();
3721 : }
3722 :
3723 69 : rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
3724 : }
3725 :
3726 0 : void ScOutputData::DrawEditStacked(DrawEditParam& rParam)
3727 : {
3728 : OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
3729 0 : Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
3730 :
3731 0 : bool bRepeat = (rParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT && !rParam.mbBreak);
3732 0 : bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
3733 :
3734 : rParam.mbAsianVertical =
3735 0 : lcl_GetBoolValue(*rParam.mpPattern, ATTR_VERTICAL_ASIAN, rParam.mpCondSet);
3736 :
3737 0 : if ( rParam.mbAsianVertical )
3738 : {
3739 : // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
3740 0 : rParam.meOrient = SVX_ORIENTATION_STANDARD;
3741 0 : DrawEditAsianVertical(rParam);
3742 0 : return;
3743 : }
3744 :
3745 : SvxCellHorJustify eOutHorJust =
3746 0 : ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
3747 0 : ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
3748 :
3749 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
3750 0 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
3751 :
3752 : //! mirror margin values for RTL?
3753 : //! move margin down to after final GetOutputArea call
3754 : long nTopM, nLeftM, nBottomM, nRightM;
3755 0 : rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
3756 :
3757 0 : SCCOL nXForPos = rParam.mnX;
3758 0 : if ( nXForPos < nX1 )
3759 : {
3760 0 : nXForPos = nX1;
3761 0 : rParam.mnPosX = rParam.mnInitPosX;
3762 : }
3763 0 : SCSIZE nArrYForPos = rParam.mnArrY;
3764 0 : if ( nArrYForPos < 1 )
3765 : {
3766 0 : nArrYForPos = 1;
3767 0 : rParam.mnPosY = nScrY;
3768 : }
3769 :
3770 0 : OutputAreaParam aAreaParam;
3771 :
3772 : //
3773 : // Initial page size - large for normal text, cell size for automatic line breaks
3774 : //
3775 :
3776 0 : Size aPaperSize = Size( 1000000, 1000000 );
3777 : // call GetOutputArea with nNeeded=0, to get only the cell width
3778 :
3779 : //! handle nArrY == 0
3780 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
3781 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3782 0 : rParam.mbCellIsValue, true, false, aAreaParam );
3783 :
3784 : //! special ScEditUtil handling if formatting for printer
3785 0 : rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
3786 :
3787 0 : if (rParam.mbPixelToLogic)
3788 : {
3789 0 : Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
3790 0 : if ( rParam.mbBreak && mpRefDevice != pFmtDevice )
3791 : {
3792 : // #i85342# screen display and formatting for printer,
3793 : // use same GetEditArea call as in ScViewData::SetEditEngine
3794 :
3795 0 : Fraction aFract(1,1);
3796 : Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
3797 0 : HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
3798 0 : aLogicSize.Width() = aUtilRect.GetWidth();
3799 : }
3800 0 : rParam.mpEngine->SetPaperSize(aLogicSize);
3801 : }
3802 : else
3803 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
3804 :
3805 : //
3806 : // Fill the EditEngine (cell attributes and text)
3807 : //
3808 :
3809 0 : rParam.setPatternToEngine(mbUseStyleColor);
3810 0 : rParam.setAlignmentToEngine();
3811 :
3812 : // Read content from cell
3813 :
3814 0 : bool bWrapFields = false;
3815 0 : if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
3816 : // Failed to read cell content. Bail out.
3817 0 : return;
3818 :
3819 0 : if ( mbSyntaxMode )
3820 0 : SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
3821 0 : else if ( mbUseStyleColor && mbForceAutoColor )
3822 0 : lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
3823 :
3824 0 : rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3825 :
3826 : //
3827 : // Get final output area using the calculated width
3828 : //
3829 :
3830 : long nEngineWidth, nEngineHeight;
3831 0 : rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
3832 :
3833 0 : long nNeededPixel = nEngineWidth;
3834 0 : if (rParam.mbPixelToLogic)
3835 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
3836 0 : nNeededPixel += nLeftM + nRightM;
3837 :
3838 0 : if (bShrink)
3839 : {
3840 : // for break, the first GetOutputArea call is sufficient
3841 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
3842 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
3843 0 : true, false, false, aAreaParam );
3844 :
3845 : ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
3846 : nLeftM, nTopM, nRightM, nBottomM, true,
3847 0 : sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
3848 : nEngineWidth, nEngineHeight, nNeededPixel,
3849 0 : aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
3850 :
3851 0 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
3852 : {
3853 : // First check if twice the space for the formatted text is available
3854 : // (otherwise just keep it unchanged).
3855 :
3856 0 : long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
3857 0 : long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
3858 0 : if ( nAvailable >= 2 * nFormatted )
3859 : {
3860 : // "repeat" is handled with unformatted text (for performance reasons)
3861 0 : String aCellStr = rParam.mpEngine->GetText();
3862 0 : rParam.mpEngine->SetText( aCellStr );
3863 :
3864 0 : long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
3865 0 : if (rParam.mbPixelToLogic)
3866 0 : nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
3867 0 : if ( pFmtDevice != mpRefDevice )
3868 0 : ++nRepeatSize;
3869 0 : if ( nRepeatSize > 0 )
3870 : {
3871 0 : long nRepeatCount = nAvailable / nRepeatSize;
3872 0 : if ( nRepeatCount > 1 )
3873 : {
3874 0 : String aRepeated = aCellStr;
3875 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
3876 0 : aRepeated.Append( aCellStr );
3877 0 : rParam.mpEngine->SetText( aRepeated );
3878 :
3879 0 : nEngineHeight = rParam.mpEngine->GetTextHeight();
3880 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
3881 0 : if (rParam.mbPixelToLogic)
3882 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3883 : else
3884 0 : nNeededPixel = nEngineWidth;
3885 0 : nNeededPixel += nLeftM + nRightM;
3886 : }
3887 0 : }
3888 : }
3889 : }
3890 :
3891 0 : if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
3892 : {
3893 0 : rParam.mpEngine->SetText(OUString("###"));
3894 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
3895 0 : if (rParam.mbPixelToLogic)
3896 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
3897 : else
3898 0 : nNeededPixel = nEngineWidth;
3899 0 : nNeededPixel += nLeftM + nRightM;
3900 :
3901 : // No clip marks if "###" doesn't fit (same as in DrawStrings)
3902 : }
3903 :
3904 0 : if ( eOutHorJust != SVX_HOR_JUSTIFY_LEFT )
3905 : {
3906 0 : aPaperSize.Width() = nNeededPixel + 1;
3907 0 : if (rParam.mbPixelToLogic)
3908 0 : rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
3909 : else
3910 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
3911 : }
3912 : }
3913 :
3914 0 : long nStartX = aAreaParam.maAlignRect.Left();
3915 0 : long nStartY = aAreaParam.maAlignRect.Top();
3916 0 : long nCellWidth = aAreaParam.maAlignRect.GetWidth();
3917 0 : long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
3918 0 : long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
3919 :
3920 0 : if (rParam.mbBreak)
3921 : {
3922 : // text with automatic breaks is aligned only within the
3923 : // edit engine's paper size, the output of the whole area
3924 : // is always left-aligned
3925 :
3926 0 : nStartX += nLeftM;
3927 : }
3928 : else
3929 : {
3930 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_RIGHT )
3931 0 : nStartX -= nNeededPixel - nCellWidth + nRightM + 1;
3932 0 : else if ( eOutHorJust == SVX_HOR_JUSTIFY_CENTER )
3933 0 : nStartX -= ( nNeededPixel - nCellWidth + nRightM + 1 - nLeftM ) / 2;
3934 : else
3935 0 : nStartX += nLeftM;
3936 : }
3937 :
3938 0 : bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
3939 0 : if (bOutside)
3940 0 : return;
3941 :
3942 0 : if ( aAreaParam.maClipRect.Left() < nScrX )
3943 : {
3944 0 : aAreaParam.maClipRect.Left() = nScrX;
3945 0 : aAreaParam.mbLeftClip = true;
3946 : }
3947 0 : if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
3948 : {
3949 0 : aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
3950 0 : aAreaParam.mbRightClip = true;
3951 : }
3952 :
3953 0 : bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
3954 0 : bool bSimClip = false;
3955 :
3956 0 : if ( bWrapFields )
3957 : {
3958 : // Fields in a cell with automatic breaks: clip to cell width
3959 0 : bClip = true;
3960 : }
3961 :
3962 0 : if ( aAreaParam.maClipRect.Top() < nScrY )
3963 : {
3964 0 : aAreaParam.maClipRect.Top() = nScrY;
3965 0 : bClip = true;
3966 : }
3967 0 : if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
3968 : {
3969 0 : aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
3970 0 : bClip = true;
3971 : }
3972 :
3973 0 : Size aCellSize; // output area, excluding margins, in logical units
3974 0 : if (rParam.mbPixelToLogic)
3975 0 : aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
3976 : else
3977 0 : aCellSize = Size( nOutWidth, nOutHeight );
3978 :
3979 0 : if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
3980 : {
3981 : const ScMergeAttr* pMerge =
3982 0 : (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
3983 0 : bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
3984 :
3985 : // Don't clip for text height when printing rows with optimal height,
3986 : // except when font size is from conditional formatting.
3987 : //! Allow clipping when vertically merged?
3988 0 : if ( eType != OUTTYPE_PRINTER ||
3989 0 : ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
3990 0 : ( rParam.mpCondSet && SFX_ITEM_SET ==
3991 0 : rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
3992 0 : bClip = true;
3993 : else
3994 0 : bSimClip = true;
3995 :
3996 : // Show clip marks if height is at least 5pt too small and
3997 : // there are several lines of text.
3998 : // Not for asian vertical text, because that would interfere
3999 : // with the default right position of the text.
4000 : // Only with automatic line breaks, to avoid having to find
4001 : // the cells with the horizontal end of the text again.
4002 0 : if ( nEngineHeight - aCellSize.Height() > 100 &&
4003 0 : rParam.mbBreak && bMarkClipped &&
4004 0 : ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
4005 : {
4006 0 : CellInfo* pClipMarkCell = NULL;
4007 0 : if ( bMerged )
4008 : {
4009 : // anywhere in the merged area...
4010 0 : SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
4011 0 : pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
4012 : }
4013 : else
4014 0 : pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
4015 :
4016 0 : pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
4017 0 : bAnyClipped = true;
4018 :
4019 0 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
4020 0 : if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
4021 0 : aAreaParam.maClipRect.Right() -= nMarkPixel;
4022 : }
4023 : }
4024 :
4025 0 : Rectangle aLogicClip;
4026 0 : if (bClip || bSimClip)
4027 : {
4028 : // Clip marks are already handled in GetOutputArea
4029 :
4030 0 : if (rParam.mbPixelToLogic)
4031 0 : aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
4032 : else
4033 0 : aLogicClip = aAreaParam.maClipRect;
4034 :
4035 0 : if (bClip) // bei bSimClip nur aClipRect initialisieren
4036 : {
4037 0 : if (bMetaFile)
4038 : {
4039 0 : mpDev->Push();
4040 0 : mpDev->IntersectClipRegion( aLogicClip );
4041 : }
4042 : else
4043 0 : mpDev->SetClipRegion( Region( aLogicClip ) );
4044 : }
4045 : }
4046 :
4047 0 : Point aLogicStart;
4048 0 : if (rParam.mbPixelToLogic)
4049 0 : aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
4050 : else
4051 0 : aLogicStart = Point(nStartX, nStartY);
4052 :
4053 0 : if (rParam.meVerJust==SVX_VER_JUSTIFY_BOTTOM ||
4054 0 : rParam.meVerJust==SVX_VER_JUSTIFY_STANDARD)
4055 : {
4056 : //! if pRefDevice != pFmtDevice, keep heights in logic units,
4057 : //! only converting margin?
4058 :
4059 0 : if (rParam.mbPixelToLogic)
4060 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM +
4061 0 : mpRefDevice->LogicToPixel(aCellSize).Height() -
4062 0 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
4063 0 : )).Height();
4064 : else
4065 0 : aLogicStart.Y() += nTopM + aCellSize.Height() - nEngineHeight;
4066 : }
4067 0 : else if (rParam.meVerJust==SVX_VER_JUSTIFY_CENTER)
4068 : {
4069 0 : if (rParam.mbPixelToLogic)
4070 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0, nTopM + (
4071 0 : mpRefDevice->LogicToPixel(aCellSize).Height() -
4072 0 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height() )
4073 0 : / 2)).Height();
4074 : else
4075 0 : aLogicStart.Y() += nTopM + (aCellSize.Height() - nEngineHeight) / 2;
4076 : }
4077 : else // top
4078 : {
4079 0 : if (rParam.mbPixelToLogic)
4080 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
4081 : else
4082 0 : aLogicStart.Y() += nTopM;
4083 : }
4084 :
4085 0 : Point aURLStart = aLogicStart; // copy before modifying for orientation
4086 :
4087 0 : Size aPaperLogic = rParam.mpEngine->GetPaperSize();
4088 0 : aPaperLogic.Width() = nEngineWidth;
4089 0 : rParam.mpEngine->SetPaperSize(aPaperLogic);
4090 :
4091 0 : rParam.adjustForRTL();
4092 :
4093 : // bMoveClipped handling has been replaced by complete alignment
4094 : // handling (also extending to the left).
4095 :
4096 0 : if (bSimClip)
4097 : {
4098 : // kein hartes Clipping, aber nur die betroffenen
4099 : // Zeilen ausgeben
4100 :
4101 0 : Point aDocStart = aLogicClip.TopLeft();
4102 0 : aDocStart -= aLogicStart;
4103 0 : rParam.mpEngine->Draw( mpDev, aLogicClip, aDocStart, false );
4104 : }
4105 : else
4106 : {
4107 0 : rParam.mpEngine->Draw( mpDev, aLogicStart, 0 );
4108 : }
4109 :
4110 0 : if (bClip)
4111 : {
4112 0 : if (bMetaFile)
4113 0 : mpDev->Pop();
4114 : else
4115 0 : mpDev->SetClipRegion();
4116 : }
4117 :
4118 0 : rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
4119 : }
4120 :
4121 0 : void ScOutputData::DrawEditAsianVertical(DrawEditParam& rParam)
4122 : {
4123 : // When in asian vertical orientation, the orientation value is STANDARD,
4124 : // and the asian vertical boolean is true.
4125 : OSL_ASSERT(rParam.meOrient == SVX_ORIENTATION_STANDARD);
4126 : OSL_ASSERT(rParam.mbAsianVertical);
4127 : OSL_ASSERT(rParam.meHorJust != SVX_HOR_JUSTIFY_REPEAT);
4128 :
4129 0 : Size aRefOne = mpRefDevice->PixelToLogic(Size(1,1));
4130 :
4131 0 : bool bHidden = false;
4132 0 : bool bRepeat = false;
4133 0 : bool bShrink = !rParam.mbBreak && !bRepeat && lcl_GetBoolValue(*rParam.mpPattern, ATTR_SHRINKTOFIT, rParam.mpCondSet);
4134 0 : long nAttrRotate = lcl_GetValue<SfxInt32Item, long>(*rParam.mpPattern, ATTR_ROTATE_VALUE, rParam.mpCondSet);
4135 :
4136 0 : if (nAttrRotate)
4137 : {
4138 : //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
4139 : //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
4140 0 : bHidden = true; // gedreht wird getrennt ausgegeben
4141 : }
4142 :
4143 : // default alignment for asian vertical mode is top-right
4144 0 : if ( rParam.meHorJust == SVX_HOR_JUSTIFY_STANDARD )
4145 0 : rParam.meHorJust = SVX_HOR_JUSTIFY_RIGHT;
4146 :
4147 : SvxCellHorJustify eOutHorJust =
4148 0 : ( rParam.meHorJust != SVX_HOR_JUSTIFY_STANDARD ) ? rParam.meHorJust :
4149 0 : ( rParam.mbCellIsValue ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT );
4150 :
4151 0 : if ( eOutHorJust == SVX_HOR_JUSTIFY_BLOCK || eOutHorJust == SVX_HOR_JUSTIFY_REPEAT )
4152 0 : eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented
4153 :
4154 0 : if (bHidden)
4155 0 : return;
4156 :
4157 : //! mirror margin values for RTL?
4158 : //! move margin down to after final GetOutputArea call
4159 : long nTopM, nLeftM, nBottomM, nRightM;
4160 0 : rParam.calcMargins(nTopM, nLeftM, nBottomM, nRightM, mnPPTX, mnPPTY);
4161 :
4162 0 : SCCOL nXForPos = rParam.mnX;
4163 0 : if ( nXForPos < nX1 )
4164 : {
4165 0 : nXForPos = nX1;
4166 0 : rParam.mnPosX = rParam.mnInitPosX;
4167 : }
4168 0 : SCSIZE nArrYForPos = rParam.mnArrY;
4169 0 : if ( nArrYForPos < 1 )
4170 : {
4171 0 : nArrYForPos = 1;
4172 0 : rParam.mnPosY = nScrY;
4173 : }
4174 :
4175 0 : OutputAreaParam aAreaParam;
4176 :
4177 : //
4178 : // Initial page size - large for normal text, cell size for automatic line breaks
4179 : //
4180 :
4181 0 : Size aPaperSize = Size( 1000000, 1000000 );
4182 : // call GetOutputArea with nNeeded=0, to get only the cell width
4183 :
4184 : //! handle nArrY == 0
4185 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, 0,
4186 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
4187 0 : rParam.mbCellIsValue, true, false, aAreaParam );
4188 :
4189 : //! special ScEditUtil handling if formatting for printer
4190 0 : rParam.calcPaperSize(aPaperSize, aAreaParam.maAlignRect, mnPPTX, mnPPTY);
4191 :
4192 0 : if (rParam.mbPixelToLogic)
4193 : {
4194 0 : Size aLogicSize = mpRefDevice->PixelToLogic(aPaperSize);
4195 0 : if ( rParam.mbBreak && !rParam.mbAsianVertical && mpRefDevice != pFmtDevice )
4196 : {
4197 : // #i85342# screen display and formatting for printer,
4198 : // use same GetEditArea call as in ScViewData::SetEditEngine
4199 :
4200 0 : Fraction aFract(1,1);
4201 : Rectangle aUtilRect = ScEditUtil( mpDoc, rParam.mnCellX, rParam.mnCellY, nTab, Point(0,0), pFmtDevice,
4202 0 : HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( rParam.mpPattern, false );
4203 0 : aLogicSize.Width() = aUtilRect.GetWidth();
4204 : }
4205 0 : rParam.mpEngine->SetPaperSize(aLogicSize);
4206 : }
4207 : else
4208 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
4209 :
4210 : //
4211 : // Fill the EditEngine (cell attributes and text)
4212 : //
4213 :
4214 : // default alignment for asian vertical mode is top-right
4215 0 : if ( rParam.meVerJust == SVX_VER_JUSTIFY_STANDARD )
4216 0 : rParam.meVerJust = SVX_VER_JUSTIFY_TOP;
4217 :
4218 0 : rParam.setPatternToEngine(mbUseStyleColor);
4219 0 : rParam.setAlignmentToEngine();
4220 :
4221 : // Read content from cell
4222 :
4223 0 : bool bWrapFields = false;
4224 0 : if (!rParam.readCellContent(mpDoc, mbShowNullValues, mbShowFormulas, mbSyntaxMode, mbUseStyleColor, mbForceAutoColor, bWrapFields))
4225 : // Failed to read cell content. Bail out.
4226 0 : return;
4227 :
4228 0 : if ( mbSyntaxMode )
4229 0 : SetEditSyntaxColor( *rParam.mpEngine, rParam.maCell );
4230 0 : else if ( mbUseStyleColor && mbForceAutoColor )
4231 0 : lcl_SetEditColor( *rParam.mpEngine, COL_AUTO ); //! or have a flag at EditEngine
4232 :
4233 0 : rParam.mpEngine->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
4234 :
4235 : //
4236 : // Get final output area using the calculated width
4237 : //
4238 :
4239 : long nEngineWidth, nEngineHeight;
4240 0 : rParam.getEngineSize(rParam.mpEngine, nEngineWidth, nEngineHeight);
4241 :
4242 0 : long nNeededPixel = nEngineWidth;
4243 0 : if (rParam.mbPixelToLogic)
4244 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nNeededPixel,0)).Width();
4245 0 : nNeededPixel += nLeftM + nRightM;
4246 :
4247 : // for break, the first GetOutputArea call is sufficient
4248 : GetOutputArea( nXForPos, nArrYForPos, rParam.mnPosX, rParam.mnPosY, rParam.mnCellX, rParam.mnCellY, nNeededPixel,
4249 0 : *rParam.mpPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
4250 0 : rParam.mbCellIsValue || bRepeat || bShrink, false, false, aAreaParam );
4251 :
4252 0 : if ( bShrink )
4253 : {
4254 : ShrinkEditEngine( *rParam.mpEngine, aAreaParam.maAlignRect,
4255 : nLeftM, nTopM, nRightM, nBottomM, false,
4256 0 : sal::static_int_cast<sal_uInt16>(rParam.meOrient), 0, rParam.mbPixelToLogic,
4257 : nEngineWidth, nEngineHeight, nNeededPixel,
4258 0 : aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
4259 : }
4260 0 : if ( bRepeat && !aAreaParam.mbLeftClip && !aAreaParam.mbRightClip && rParam.mpEngine->GetParagraphCount() == 1 )
4261 : {
4262 : // First check if twice the space for the formatted text is available
4263 : // (otherwise just keep it unchanged).
4264 :
4265 0 : long nFormatted = nNeededPixel - nLeftM - nRightM; // without margin
4266 0 : long nAvailable = aAreaParam.maAlignRect.GetWidth() - nLeftM - nRightM;
4267 0 : if ( nAvailable >= 2 * nFormatted )
4268 : {
4269 : // "repeat" is handled with unformatted text (for performance reasons)
4270 0 : String aCellStr = rParam.mpEngine->GetText();
4271 0 : rParam.mpEngine->SetText( aCellStr );
4272 :
4273 0 : long nRepeatSize = (long) rParam.mpEngine->CalcTextWidth();
4274 0 : if (rParam.mbPixelToLogic)
4275 0 : nRepeatSize = mpRefDevice->LogicToPixel(Size(nRepeatSize,0)).Width();
4276 0 : if ( pFmtDevice != mpRefDevice )
4277 0 : ++nRepeatSize;
4278 0 : if ( nRepeatSize > 0 )
4279 : {
4280 0 : long nRepeatCount = nAvailable / nRepeatSize;
4281 0 : if ( nRepeatCount > 1 )
4282 : {
4283 0 : String aRepeated = aCellStr;
4284 0 : for ( long nRepeat = 1; nRepeat < nRepeatCount; nRepeat++ )
4285 0 : aRepeated.Append( aCellStr );
4286 0 : rParam.mpEngine->SetText( aRepeated );
4287 :
4288 0 : nEngineHeight = rParam.mpEngine->GetTextHeight();
4289 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
4290 0 : if (rParam.mbPixelToLogic)
4291 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
4292 : else
4293 0 : nNeededPixel = nEngineWidth;
4294 0 : nNeededPixel += nLeftM + nRightM;
4295 : }
4296 0 : }
4297 : }
4298 : }
4299 :
4300 0 : if ( rParam.mbCellIsValue && ( aAreaParam.mbLeftClip || aAreaParam.mbRightClip ) )
4301 : {
4302 0 : rParam.mpEngine->SetText(OUString("###"));
4303 0 : nEngineWidth = (long) rParam.mpEngine->CalcTextWidth();
4304 0 : if (rParam.mbPixelToLogic)
4305 0 : nNeededPixel = mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width();
4306 : else
4307 0 : nNeededPixel = nEngineWidth;
4308 0 : nNeededPixel += nLeftM + nRightM;
4309 :
4310 : // No clip marks if "###" doesn't fit (same as in DrawStrings)
4311 : }
4312 :
4313 0 : if (eOutHorJust != SVX_HOR_JUSTIFY_LEFT)
4314 : {
4315 0 : aPaperSize.Width() = nNeededPixel + 1;
4316 0 : if (rParam.mbPixelToLogic)
4317 0 : rParam.mpEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
4318 : else
4319 0 : rParam.mpEngine->SetPaperSize(aPaperSize);
4320 : }
4321 :
4322 0 : long nStartX = aAreaParam.maAlignRect.Left();
4323 0 : long nStartY = aAreaParam.maAlignRect.Top();
4324 0 : long nCellWidth = aAreaParam.maAlignRect.GetWidth();
4325 0 : long nOutWidth = nCellWidth - 1 - nLeftM - nRightM;
4326 0 : long nOutHeight = aAreaParam.maAlignRect.GetHeight() - nTopM - nBottomM;
4327 :
4328 : // text with automatic breaks is aligned only within the
4329 : // edit engine's paper size, the output of the whole area
4330 : // is always left-aligned
4331 :
4332 0 : nStartX += nLeftM;
4333 :
4334 0 : bool bOutside = (aAreaParam.maClipRect.Right() < nScrX || aAreaParam.maClipRect.Left() >= nScrX + nScrW);
4335 0 : if (bOutside)
4336 0 : return;
4337 :
4338 0 : if ( aAreaParam.maClipRect.Left() < nScrX )
4339 : {
4340 0 : aAreaParam.maClipRect.Left() = nScrX;
4341 0 : aAreaParam.mbLeftClip = true;
4342 : }
4343 0 : if ( aAreaParam.maClipRect.Right() > nScrX + nScrW )
4344 : {
4345 0 : aAreaParam.maClipRect.Right() = nScrX + nScrW; //! minus one?
4346 0 : aAreaParam.mbRightClip = true;
4347 : }
4348 :
4349 0 : bool bClip = aAreaParam.mbLeftClip || aAreaParam.mbRightClip;
4350 0 : bool bSimClip = false;
4351 :
4352 0 : if ( bWrapFields )
4353 : {
4354 : // Fields in a cell with automatic breaks: clip to cell width
4355 0 : bClip = true;
4356 : }
4357 :
4358 0 : if ( aAreaParam.maClipRect.Top() < nScrY )
4359 : {
4360 0 : aAreaParam.maClipRect.Top() = nScrY;
4361 0 : bClip = true;
4362 : }
4363 0 : if ( aAreaParam.maClipRect.Bottom() > nScrY + nScrH )
4364 : {
4365 0 : aAreaParam.maClipRect.Bottom() = nScrY + nScrH; //! minus one?
4366 0 : bClip = true;
4367 : }
4368 :
4369 0 : Size aCellSize; // output area, excluding margins, in logical units
4370 0 : if (rParam.mbPixelToLogic)
4371 0 : aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
4372 : else
4373 0 : aCellSize = Size( nOutWidth, nOutHeight );
4374 :
4375 0 : if ( nEngineHeight >= aCellSize.Height() + aRefOne.Height() )
4376 : {
4377 : const ScMergeAttr* pMerge =
4378 0 : (ScMergeAttr*)&rParam.mpPattern->GetItem(ATTR_MERGE);
4379 0 : bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
4380 :
4381 : // Don't clip for text height when printing rows with optimal height,
4382 : // except when font size is from conditional formatting.
4383 : //! Allow clipping when vertically merged?
4384 0 : if ( eType != OUTTYPE_PRINTER ||
4385 0 : ( mpDoc->GetRowFlags( rParam.mnCellY, nTab ) & CR_MANUALSIZE ) ||
4386 0 : ( rParam.mpCondSet && SFX_ITEM_SET ==
4387 0 : rParam.mpCondSet->GetItemState(ATTR_FONT_HEIGHT, true) ) )
4388 0 : bClip = true;
4389 : else
4390 0 : bSimClip = true;
4391 :
4392 : // Show clip marks if height is at least 5pt too small and
4393 : // there are several lines of text.
4394 : // Not for asian vertical text, because that would interfere
4395 : // with the default right position of the text.
4396 : // Only with automatic line breaks, to avoid having to find
4397 : // the cells with the horizontal end of the text again.
4398 0 : if ( nEngineHeight - aCellSize.Height() > 100 &&
4399 0 : ( rParam.mbBreak || rParam.meOrient == SVX_ORIENTATION_STACKED ) &&
4400 0 : !rParam.mbAsianVertical && bMarkClipped &&
4401 0 : ( rParam.mpEngine->GetParagraphCount() > 1 || rParam.mpEngine->GetLineCount(0) > 1 ) )
4402 : {
4403 0 : CellInfo* pClipMarkCell = NULL;
4404 0 : if ( bMerged )
4405 : {
4406 : // anywhere in the merged area...
4407 0 : SCCOL nClipX = ( rParam.mnX < nX1 ) ? nX1 : rParam.mnX;
4408 0 : pClipMarkCell = &pRowInfo[(rParam.mnArrY != 0) ? rParam.mnArrY : 1].pCellInfo[nClipX+1];
4409 : }
4410 : else
4411 0 : pClipMarkCell = &rParam.mpThisRowInfo->pCellInfo[rParam.mnX+1];
4412 :
4413 0 : pClipMarkCell->nClipMark |= SC_CLIPMARK_RIGHT; //! also allow left?
4414 0 : bAnyClipped = true;
4415 :
4416 0 : long nMarkPixel = (long)( SC_CLIPMARK_SIZE * mnPPTX );
4417 0 : if ( aAreaParam.maClipRect.Right() - nMarkPixel > aAreaParam.maClipRect.Left() )
4418 0 : aAreaParam.maClipRect.Right() -= nMarkPixel;
4419 : }
4420 : }
4421 :
4422 0 : Rectangle aLogicClip;
4423 0 : if (bClip || bSimClip)
4424 : {
4425 : // Clip marks are already handled in GetOutputArea
4426 :
4427 0 : if (rParam.mbPixelToLogic)
4428 0 : aLogicClip = mpRefDevice->PixelToLogic( aAreaParam.maClipRect );
4429 : else
4430 0 : aLogicClip = aAreaParam.maClipRect;
4431 :
4432 0 : if (bClip) // bei bSimClip nur aClipRect initialisieren
4433 : {
4434 0 : if (bMetaFile)
4435 : {
4436 0 : mpDev->Push();
4437 0 : mpDev->IntersectClipRegion( aLogicClip );
4438 : }
4439 : else
4440 0 : mpDev->SetClipRegion( Region( aLogicClip ) );
4441 : }
4442 : }
4443 :
4444 0 : Point aLogicStart;
4445 0 : if (rParam.mbPixelToLogic)
4446 0 : aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
4447 : else
4448 0 : aLogicStart = Point(nStartX, nStartY);
4449 :
4450 0 : long nAvailWidth = aCellSize.Width();
4451 : // space for AutoFilter is already handled in GetOutputArea
4452 :
4453 : // horizontal alignment
4454 :
4455 0 : if (rParam.meHorJust==SVX_HOR_JUSTIFY_RIGHT)
4456 0 : aLogicStart.X() += nAvailWidth - nEngineWidth;
4457 0 : else if (rParam.meHorJust==SVX_HOR_JUSTIFY_CENTER)
4458 0 : aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
4459 :
4460 : // paper size is subtracted below
4461 0 : aLogicStart.X() += nEngineWidth;
4462 :
4463 : // vertical adjustment is within the EditEngine
4464 0 : if (rParam.mbPixelToLogic)
4465 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic(Size(0,nTopM)).Height();
4466 : else
4467 0 : aLogicStart.Y() += nTopM;
4468 :
4469 0 : Point aURLStart = aLogicStart; // copy before modifying for orientation
4470 :
4471 0 : rParam.adjustForRTL();
4472 :
4473 : // bMoveClipped handling has been replaced by complete alignment
4474 : // handling (also extending to the left).
4475 :
4476 : // with SetVertical, the start position is top left of
4477 : // the whole output area, not the text itself
4478 0 : aLogicStart.X() -= rParam.mpEngine->GetPaperSize().Width();
4479 :
4480 0 : rParam.mpEngine->Draw(mpDev, aLogicStart, 0);
4481 :
4482 0 : if (bClip)
4483 : {
4484 0 : if (bMetaFile)
4485 0 : mpDev->Pop();
4486 : else
4487 0 : mpDev->SetClipRegion();
4488 : }
4489 :
4490 0 : rParam.adjustForHyperlinkInPDF(aURLStart, mpDev);
4491 : }
4492 :
4493 1179 : void ScOutputData::DrawEdit(sal_Bool bPixelToLogic)
4494 : {
4495 1179 : ScFieldEditEngine* pEngine = NULL;
4496 1179 : bool bHyphenatorSet = false;
4497 1179 : const ScPatternAttr* pOldPattern = NULL;
4498 1179 : const SfxItemSet* pOldCondSet = NULL;
4499 1179 : ScRefCellValue aCell;
4500 :
4501 1179 : long nInitPosX = nScrX;
4502 1179 : if ( bLayoutRTL )
4503 : {
4504 1 : nInitPosX += nMirrorW - 1;
4505 : }
4506 1179 : long nLayoutSign = bLayoutRTL ? -1 : 1;
4507 :
4508 : //! store nLastContentCol as member!
4509 1179 : SCCOL nLastContentCol = MAXCOL;
4510 1179 : if ( nX2 < MAXCOL )
4511 : nLastContentCol = sal::static_int_cast<SCCOL>(
4512 1178 : nLastContentCol - mpDoc->GetEmptyLinesInBlock( nX2+1, nY1, nTab, MAXCOL, nY2, nTab, DIR_RIGHT ) );
4513 :
4514 1179 : long nRowPosY = nScrY;
4515 21037 : for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten
4516 : {
4517 19858 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
4518 :
4519 19858 : if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet
4520 :
4521 19858 : if ( pThisRowInfo->bChanged || nArrY==0 )
4522 : {
4523 19858 : long nPosX = 0;
4524 252104 : for (SCCOL nX=0; nX<=nX2; nX++) // wegen Ueberhaengen
4525 : {
4526 232246 : if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually
4527 :
4528 232246 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
4529 232246 : if (pInfo->bEditEngine)
4530 : {
4531 550 : SCROW nY = pThisRowInfo->nRowNo;
4532 :
4533 550 : SCCOL nCellX = nX; // position where the cell really starts
4534 550 : SCROW nCellY = nY;
4535 550 : sal_Bool bDoCell = false;
4536 :
4537 550 : long nPosY = nRowPosY;
4538 550 : if ( nArrY == 0 )
4539 : {
4540 0 : nPosY = nScrY;
4541 0 : nY = pRowInfo[1].nRowNo;
4542 : SCCOL nOverX; // start of the merged cells
4543 : SCROW nOverY;
4544 0 : if (GetMergeOrigin( nX,nY, 1, nOverX,nOverY, sal_True ))
4545 : {
4546 0 : nCellX = nOverX;
4547 0 : nCellY = nOverY;
4548 0 : bDoCell = sal_True;
4549 : }
4550 : }
4551 550 : else if ( nX == nX2 && pThisRowInfo->pCellInfo[nX+1].maCell.isEmpty() )
4552 : {
4553 : // Rest of a long text further to the right?
4554 :
4555 0 : SCCOL nTempX=nX;
4556 0 : while (nTempX < nLastContentCol && IsEmptyCellText( pThisRowInfo, nTempX, nY ))
4557 0 : ++nTempX;
4558 :
4559 0 : if ( nTempX > nX &&
4560 0 : !IsEmptyCellText( pThisRowInfo, nTempX, nY ) &&
4561 0 : !mpDoc->HasAttrib( nTempX,nY,nTab, nX,nY,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4562 : {
4563 0 : nCellX = nTempX;
4564 0 : bDoCell = sal_True;
4565 : }
4566 : }
4567 : else
4568 : {
4569 550 : bDoCell = sal_True;
4570 : }
4571 :
4572 550 : if ( bDoCell && bEditMode && nCellX == nEditCol && nCellY == nEditRow )
4573 0 : bDoCell = false;
4574 :
4575 550 : const ScPatternAttr* pPattern = NULL;
4576 550 : const SfxItemSet* pCondSet = NULL;
4577 550 : if (bDoCell)
4578 : {
4579 1100 : if ( nCellY == nY && nCellX >= nX1 && nCellX <= nX2 &&
4580 550 : !mpDoc->ColHidden(nCellX, nTab) )
4581 : {
4582 550 : CellInfo& rCellInfo = pThisRowInfo->pCellInfo[nCellX+1];
4583 550 : pPattern = rCellInfo.pPatternAttr;
4584 550 : pCondSet = rCellInfo.pConditionSet;
4585 550 : aCell = rCellInfo.maCell;
4586 : }
4587 : else // get from document
4588 : {
4589 0 : pPattern = mpDoc->GetPattern( nCellX, nCellY, nTab );
4590 0 : pCondSet = mpDoc->GetCondResult( nCellX, nCellY, nTab );
4591 0 : GetVisibleCell( nCellX, nCellY, nTab, aCell );
4592 : }
4593 550 : if (aCell.isEmpty())
4594 0 : bDoCell = false;
4595 : }
4596 550 : if (bDoCell)
4597 : {
4598 550 : SfxItemSet* pPreviewFontSet = mpDoc->GetPreviewFont( nCellX, nCellY, nTab );
4599 550 : if (!pEngine)
4600 182 : pEngine = CreateOutputEditEngine();
4601 : else
4602 368 : lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(sal_False)
4603 :
4604 : // fdo#32530: Check if the first character is RTL.
4605 550 : OUString aStr = mpDoc->GetString(nCellX, nCellY, nTab);
4606 :
4607 1100 : DrawEditParam aParam(pPattern, pCondSet, lcl_SafeIsValue(aCell));
4608 550 : aParam.mbPixelToLogic = bPixelToLogic;
4609 550 : aParam.mbHyphenatorSet = bHyphenatorSet;
4610 550 : aParam.mbRTL = beginsWithRTLCharacter(aStr);
4611 550 : aParam.mpEngine = pEngine;
4612 550 : aParam.maCell = aCell;
4613 550 : aParam.mnArrY = nArrY;
4614 550 : aParam.mnX = nX;
4615 550 : aParam.mnY = nY;
4616 550 : aParam.mnCellX = nCellX;
4617 550 : aParam.mnCellY = nCellY;
4618 550 : aParam.mnPosX = nPosX;
4619 550 : aParam.mnPosY = nPosY;
4620 550 : aParam.mnInitPosX = nInitPosX;
4621 550 : aParam.mpPreviewFontSet = pPreviewFontSet;
4622 550 : aParam.mpOldPattern = pOldPattern;
4623 550 : aParam.mpOldCondSet = pOldCondSet;
4624 550 : aParam.mpThisRowInfo = pThisRowInfo;
4625 550 : if (aParam.meHorJust == SVX_HOR_JUSTIFY_REPEAT)
4626 : {
4627 : // ignore orientation/rotation if "repeat" is active
4628 0 : aParam.meOrient = SVX_ORIENTATION_STANDARD;
4629 : }
4630 550 : switch (aParam.meOrient)
4631 : {
4632 : case SVX_ORIENTATION_BOTTOMTOP:
4633 0 : DrawEditBottomTop(aParam);
4634 0 : break;
4635 : case SVX_ORIENTATION_TOPBOTTOM:
4636 69 : DrawEditTopBottom(aParam);
4637 69 : break;
4638 : case SVX_ORIENTATION_STACKED:
4639 : // this can be vertically stacked or asian vertical.
4640 0 : DrawEditStacked(aParam);
4641 0 : break;
4642 : default:
4643 481 : DrawEditStandard(aParam);
4644 : }
4645 :
4646 : // Retrieve parameters for next iteration.
4647 550 : pOldPattern = aParam.mpOldPattern;
4648 550 : pOldCondSet = aParam.mpOldCondSet;
4649 1100 : bHyphenatorSet = aParam.mbHyphenatorSet;
4650 : }
4651 : }
4652 232246 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
4653 : }
4654 : }
4655 19858 : nRowPosY += pRowInfo[nArrY].nHeight;
4656 : }
4657 :
4658 1179 : delete pEngine;
4659 :
4660 1179 : if (bAnyRotated)
4661 69 : DrawRotated(bPixelToLogic); //! von aussen rufen ?
4662 1179 : }
4663 :
4664 : // -------------------------------------------------------------------------------
4665 :
4666 69 : void ScOutputData::DrawRotated(sal_Bool bPixelToLogic)
4667 : {
4668 : //! nRotMax speichern
4669 69 : SCCOL nRotMax = nX2;
4670 499 : for (SCSIZE nRotY=0; nRotY<nArrCount; nRotY++)
4671 430 : if (pRowInfo[nRotY].nRotMaxCol != SC_ROTMAX_NONE && pRowInfo[nRotY].nRotMaxCol > nRotMax)
4672 0 : nRotMax = pRowInfo[nRotY].nRotMaxCol;
4673 :
4674 :
4675 69 : ScModule* pScMod = SC_MOD();
4676 69 : sal_Int32 nConfBackColor = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
4677 138 : sal_Bool bCellContrast = mbUseStyleColor &&
4678 138 : Application::GetSettings().GetStyleSettings().GetHighContrastMode();
4679 :
4680 69 : ScFieldEditEngine* pEngine = NULL;
4681 69 : sal_Bool bHyphenatorSet = false;
4682 : const ScPatternAttr* pPattern;
4683 : const SfxItemSet* pCondSet;
4684 69 : const ScPatternAttr* pOldPattern = NULL;
4685 69 : const SfxItemSet* pOldCondSet = NULL;
4686 69 : ScRefCellValue aCell;
4687 :
4688 69 : long nInitPosX = nScrX;
4689 69 : if ( bLayoutRTL )
4690 : {
4691 0 : nInitPosX += nMirrorW - 1;
4692 : }
4693 69 : long nLayoutSign = bLayoutRTL ? -1 : 1;
4694 :
4695 69 : long nRowPosY = nScrY;
4696 430 : for (SCSIZE nArrY=0; nArrY+1<nArrCount; nArrY++) // 0 fuer Reste von zusammengefassten
4697 : {
4698 361 : RowInfo* pThisRowInfo = &pRowInfo[nArrY];
4699 361 : long nCellHeight = (long) pThisRowInfo->nHeight;
4700 361 : if (nArrY==1) nRowPosY = nScrY; // vorher wird einzeln berechnet
4701 :
4702 361 : if ( ( pThisRowInfo->bChanged || nArrY==0 ) && pThisRowInfo->nRotMaxCol != SC_ROTMAX_NONE )
4703 : {
4704 259 : long nPosX = 0;
4705 2849 : for (SCCOL nX=0; nX<=nRotMax; nX++)
4706 : {
4707 2590 : if (nX==nX1) nPosX = nInitPosX; // positions before nX1 are calculated individually
4708 :
4709 2590 : CellInfo* pInfo = &pThisRowInfo->pCellInfo[nX+1];
4710 2590 : if ( pInfo->nRotateDir != SC_ROTDIR_NONE )
4711 : {
4712 1030 : SCROW nY = pThisRowInfo->nRowNo;
4713 :
4714 1030 : sal_Bool bHidden = false;
4715 1030 : if (bEditMode)
4716 0 : if ( nX == nEditCol && nY == nEditRow )
4717 0 : bHidden = sal_True;
4718 :
4719 1030 : if (!bHidden)
4720 : {
4721 1030 : if (!pEngine)
4722 69 : pEngine = CreateOutputEditEngine();
4723 : else
4724 961 : lcl_ClearEdit( *pEngine ); // also calls SetUpdateMode(sal_False)
4725 :
4726 1030 : long nPosY = nRowPosY;
4727 1030 : sal_Bool bVisChanged = false;
4728 :
4729 : //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
4730 :
4731 1030 : sal_Bool bFromDoc = false;
4732 1030 : pPattern = pInfo->pPatternAttr;
4733 1030 : pCondSet = pInfo->pConditionSet;
4734 1030 : if (!pPattern)
4735 : {
4736 0 : pPattern = mpDoc->GetPattern( nX, nY, nTab );
4737 0 : bFromDoc = sal_True;
4738 : }
4739 1030 : aCell = pInfo->maCell;
4740 1030 : if (bFromDoc)
4741 0 : pCondSet = mpDoc->GetCondResult( nX, nY, nTab );
4742 :
4743 1030 : if (aCell.isEmpty() && nX>nX2)
4744 0 : GetVisibleCell( nX, nY, nTab, aCell );
4745 :
4746 1030 : if (aCell.isEmpty() || IsEmptyCellText(pThisRowInfo, nX, nY))
4747 652 : bHidden = true; // nRotateDir is also set without a cell
4748 :
4749 1030 : long nCellWidth = (long) pRowInfo[0].pCellInfo[nX+1].nWidth;
4750 :
4751 : SvxCellHorJustify eHorJust = (SvxCellHorJustify)((const SvxHorJustifyItem&)
4752 1030 : pPattern->GetItem(ATTR_HOR_JUSTIFY, pCondSet)).GetValue();
4753 1960 : sal_Bool bBreak = ( eHorJust == SVX_HOR_JUSTIFY_BLOCK ) ||
4754 1960 : ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue();
4755 1030 : sal_Bool bRepeat = ( eHorJust == SVX_HOR_JUSTIFY_REPEAT && !bBreak );
4756 1354 : sal_Bool bShrink = !bBreak && !bRepeat && static_cast<const SfxBoolItem&>
4757 1354 : (pPattern->GetItem( ATTR_SHRINKTOFIT, pCondSet )).GetValue();
4758 1030 : SvxCellOrientation eOrient = pPattern->GetCellOrientation( pCondSet );
4759 :
4760 : const ScMergeAttr* pMerge =
4761 1030 : (ScMergeAttr*)&pPattern->GetItem(ATTR_MERGE);
4762 1030 : sal_Bool bMerged = pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1;
4763 :
4764 1030 : long nStartX = nPosX;
4765 1030 : long nStartY = nPosY;
4766 1030 : if (nX<nX1)
4767 : {
4768 0 : if ((bBreak || eOrient!=SVX_ORIENTATION_STANDARD) && !bMerged)
4769 0 : bHidden = sal_True;
4770 : else
4771 : {
4772 0 : nStartX = nInitPosX;
4773 0 : SCCOL nCol = nX1;
4774 0 : while (nCol > nX)
4775 : {
4776 0 : --nCol;
4777 0 : nStartX -= nLayoutSign * (long) pRowInfo[0].pCellInfo[nCol+1].nWidth;
4778 : }
4779 : }
4780 : }
4781 1030 : long nCellStartX = nStartX;
4782 :
4783 : // Ersatzdarstellung fuer zu kleinen Text weggelassen
4784 :
4785 1030 : if (!bHidden)
4786 : {
4787 378 : long nOutWidth = nCellWidth - 1;
4788 378 : long nOutHeight = nCellHeight;
4789 :
4790 378 : if ( bMerged ) // Zusammengefasst
4791 : {
4792 0 : SCCOL nCountX = pMerge->GetColMerge();
4793 0 : for (SCCOL i=1; i<nCountX; i++)
4794 0 : nOutWidth += (long) ( mpDoc->GetColWidth(nX+i,nTab) * mnPPTX );
4795 0 : SCROW nCountY = pMerge->GetRowMerge();
4796 0 : nOutHeight += (long) mpDoc->GetScaledRowHeight( nY+1, nY+nCountY-1, nTab, mnPPTY);
4797 : }
4798 :
4799 : SvxCellVerJustify eVerJust = (SvxCellVerJustify)((const SvxVerJustifyItem&)
4800 378 : pPattern->GetItem(ATTR_VER_JUSTIFY, pCondSet)).GetValue();
4801 :
4802 : // Syntax-Modus wird hier ignoriert...
4803 :
4804 : // StringDiffer doesn't look at hyphenate, language items
4805 378 : if ( pPattern != pOldPattern || pCondSet != pOldCondSet )
4806 : {
4807 69 : SfxItemSet* pSet = new SfxItemSet( pEngine->GetEmptyItemSet() );
4808 69 : pPattern->FillEditItemSet( pSet, pCondSet );
4809 :
4810 : // Ausrichtung fuer EditEngine
4811 69 : SvxAdjust eSvxAdjust = SVX_ADJUST_LEFT;
4812 69 : if (eOrient==SVX_ORIENTATION_STACKED)
4813 0 : eSvxAdjust = SVX_ADJUST_CENTER;
4814 : // Adjustment fuer bBreak ist hier weggelassen
4815 69 : pSet->Put( SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
4816 :
4817 69 : pEngine->SetDefaults( pSet );
4818 69 : pOldPattern = pPattern;
4819 69 : pOldCondSet = pCondSet;
4820 :
4821 69 : sal_uLong nControl = pEngine->GetControlWord();
4822 69 : if (eOrient==SVX_ORIENTATION_STACKED)
4823 0 : nControl |= EE_CNTRL_ONECHARPERLINE;
4824 : else
4825 69 : nControl &= ~EE_CNTRL_ONECHARPERLINE;
4826 69 : pEngine->SetControlWord( nControl );
4827 :
4828 69 : if ( !bHyphenatorSet && ((const SfxBoolItem&)pSet->Get(EE_PARA_HYPHENATE)).GetValue() )
4829 : {
4830 : // set hyphenator the first time it is needed
4831 40 : com::sun::star::uno::Reference<com::sun::star::linguistic2::XHyphenator> xXHyphenator( LinguMgr::GetHyphenator() );
4832 40 : pEngine->SetHyphenator( xXHyphenator );
4833 40 : bHyphenatorSet = sal_True;
4834 : }
4835 :
4836 : Color aBackCol = ((const SvxBrushItem&)
4837 69 : pPattern->GetItem( ATTR_BACKGROUND, pCondSet )).GetColor();
4838 69 : if ( mbUseStyleColor && ( aBackCol.GetTransparency() > 0 || bCellContrast ) )
4839 26 : aBackCol.SetColor( nConfBackColor );
4840 69 : pEngine->SetBackgroundColor( aBackCol );
4841 : }
4842 :
4843 : // Raender
4844 :
4845 : //! Position und Papersize auf EditUtil umstellen !!!
4846 :
4847 : const SvxMarginItem* pMargin = (const SvxMarginItem*)
4848 378 : &pPattern->GetItem(ATTR_MARGIN, pCondSet);
4849 378 : sal_uInt16 nIndent = 0;
4850 378 : if ( eHorJust == SVX_HOR_JUSTIFY_LEFT )
4851 : nIndent = ((const SfxUInt16Item&)pPattern->
4852 116 : GetItem(ATTR_INDENT, pCondSet)).GetValue();
4853 :
4854 378 : long nTotalHeight = nOutHeight; // ohne Rand abzuziehen
4855 378 : if ( bPixelToLogic )
4856 378 : nTotalHeight = mpRefDevice->PixelToLogic(Size(0,nTotalHeight)).Height();
4857 :
4858 378 : long nLeftM = (long) ( (pMargin->GetLeftMargin() + nIndent) * mnPPTX );
4859 378 : long nTopM = (long) ( pMargin->GetTopMargin() * mnPPTY );
4860 378 : long nRightM = (long) ( pMargin->GetRightMargin() * mnPPTX );
4861 378 : long nBottomM = (long) ( pMargin->GetBottomMargin() * mnPPTY );
4862 378 : nStartX += nLeftM;
4863 378 : nStartY += nTopM;
4864 378 : nOutWidth -= nLeftM + nRightM;
4865 378 : nOutHeight -= nTopM + nBottomM;
4866 :
4867 : // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
4868 378 : long nAttrRotate = 0;
4869 378 : double nSin = 0.0;
4870 378 : double nCos = 1.0;
4871 378 : SvxRotateMode eRotMode = SVX_ROTATE_MODE_STANDARD;
4872 378 : if ( eOrient == SVX_ORIENTATION_STANDARD )
4873 : {
4874 : nAttrRotate = ((const SfxInt32Item&)pPattern->
4875 378 : GetItem(ATTR_ROTATE_VALUE, pCondSet)).GetValue();
4876 378 : if ( nAttrRotate )
4877 : {
4878 : eRotMode = (SvxRotateMode)((const SvxRotateModeItem&)
4879 378 : pPattern->GetItem(ATTR_ROTATE_MODE, pCondSet)).GetValue();
4880 :
4881 378 : if ( nAttrRotate == 18000 )
4882 0 : eRotMode = SVX_ROTATE_MODE_STANDARD; // keinen Ueberlauf
4883 :
4884 378 : if ( bLayoutRTL )
4885 0 : nAttrRotate = -nAttrRotate;
4886 :
4887 378 : double nRealOrient = nAttrRotate * F_PI18000; // 1/100 Grad
4888 378 : nCos = cos( nRealOrient );
4889 378 : nSin = sin( nRealOrient );
4890 : }
4891 : }
4892 :
4893 378 : Size aPaperSize = Size( 1000000, 1000000 );
4894 378 : if (eOrient==SVX_ORIENTATION_STACKED)
4895 0 : aPaperSize.Width() = nOutWidth; // zum Zentrieren
4896 378 : else if (bBreak)
4897 : {
4898 238 : if (nAttrRotate)
4899 : {
4900 : //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
4901 : //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
4902 : //! werden koennen -> darum unbegrenzt, also kein Umbruch.
4903 : //! Mit versetzten Zeilen waere das folgende richtig:
4904 238 : aPaperSize.Width() = (long)(nOutHeight / fabs(nSin));
4905 : }
4906 0 : else if (eOrient == SVX_ORIENTATION_STANDARD)
4907 0 : aPaperSize.Width() = nOutWidth;
4908 : else
4909 0 : aPaperSize.Width() = nOutHeight - 1;
4910 : }
4911 378 : if (bPixelToLogic)
4912 378 : pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
4913 : else
4914 0 : pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1
4915 :
4916 : // Daten aus Zelle lesen
4917 :
4918 378 : if (aCell.meType == CELLTYPE_EDIT)
4919 : {
4920 2 : if (aCell.mpEditText)
4921 2 : pEngine->SetText(*aCell.mpEditText);
4922 : else
4923 : {
4924 : OSL_FAIL("pData == 0");
4925 : }
4926 : }
4927 : else
4928 : {
4929 : sal_uLong nFormat = pPattern->GetNumberFormat(
4930 376 : mpDoc->GetFormatTable(), pCondSet );
4931 376 : OUString aString;
4932 : Color* pColor;
4933 : ScCellFormat::GetString( aCell,
4934 : nFormat,aString, &pColor,
4935 376 : *mpDoc->GetFormatTable(),
4936 : mbShowNullValues,
4937 : mbShowFormulas,
4938 752 : ftCheck );
4939 :
4940 376 : pEngine->SetText(aString);
4941 376 : if ( pColor && !mbSyntaxMode && !( mbUseStyleColor && mbForceAutoColor ) )
4942 0 : lcl_SetEditColor( *pEngine, *pColor );
4943 : }
4944 :
4945 378 : if ( mbSyntaxMode )
4946 : {
4947 0 : SetEditSyntaxColor(*pEngine, aCell);
4948 : }
4949 378 : else if ( mbUseStyleColor && mbForceAutoColor )
4950 0 : lcl_SetEditColor( *pEngine, COL_AUTO ); //! or have a flag at EditEngine
4951 :
4952 378 : pEngine->SetUpdateMode( sal_True ); // after SetText, before CalcTextWidth/GetTextHeight
4953 :
4954 378 : long nEngineWidth = (long) pEngine->CalcTextWidth();
4955 378 : long nEngineHeight = pEngine->GetTextHeight();
4956 :
4957 378 : if (nAttrRotate && bBreak)
4958 : {
4959 238 : double nAbsCos = fabs( nCos );
4960 238 : double nAbsSin = fabs( nSin );
4961 :
4962 : // adjust witdh of papersize for height of text
4963 238 : int nSteps = 5;
4964 844 : while (nSteps > 0)
4965 : {
4966 : // everything is in pixels
4967 : long nEnginePixel = mpRefDevice->LogicToPixel(
4968 368 : Size(0,nEngineHeight)).Height();
4969 368 : long nEffHeight = nOutHeight - (long)(nEnginePixel * nAbsCos) + 2;
4970 368 : long nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
4971 368 : sal_Bool bFits = ( nNewWidth >= aPaperSize.Width() );
4972 368 : if ( bFits )
4973 238 : nSteps = 0;
4974 : else
4975 : {
4976 130 : if ( nNewWidth < 4 )
4977 : {
4978 : // can't fit -> fall back to using half height
4979 0 : nEffHeight = nOutHeight / 2;
4980 0 : nNewWidth = (long)(nEffHeight / nAbsSin) + 2;
4981 0 : nSteps = 0;
4982 : }
4983 : else
4984 130 : --nSteps;
4985 :
4986 : // set paper width and get new text height
4987 130 : aPaperSize.Width() = nNewWidth;
4988 130 : if (bPixelToLogic)
4989 130 : pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
4990 : else
4991 0 : pEngine->SetPaperSize(aPaperSize); // Scale ist immer 1
4992 : //pEngine->QuickFormatDoc( sal_True );
4993 130 : nEngineWidth = (long) pEngine->CalcTextWidth();
4994 130 : nEngineHeight = pEngine->GetTextHeight();
4995 : }
4996 : }
4997 : }
4998 :
4999 378 : long nRealWidth = nEngineWidth;
5000 378 : long nRealHeight = nEngineHeight;
5001 :
5002 : // wenn gedreht, Groesse anpassen
5003 378 : if (nAttrRotate)
5004 : {
5005 378 : double nAbsCos = fabs( nCos );
5006 378 : double nAbsSin = fabs( nSin );
5007 :
5008 378 : if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
5009 756 : nEngineWidth = (long) ( nRealWidth * nAbsCos +
5010 756 : nRealHeight * nAbsSin );
5011 : else
5012 0 : nEngineWidth = (long) ( nRealHeight / nAbsSin );
5013 : //! begrenzen !!!
5014 :
5015 756 : nEngineHeight = (long) ( nRealHeight * nAbsCos +
5016 756 : nRealWidth * nAbsSin );
5017 : }
5018 :
5019 378 : if (!nAttrRotate) // hier nur gedrehter Text
5020 0 : bHidden = sal_True; //! vorher abfragen !!!
5021 :
5022 : //! weglassen, was nicht hereinragt
5023 :
5024 378 : if (!bHidden)
5025 : {
5026 378 : sal_Bool bClip = false;
5027 378 : Size aClipSize = Size( nScrX+nScrW-nStartX, nScrY+nScrH-nStartY );
5028 :
5029 : // weiterschreiben
5030 :
5031 378 : Size aCellSize;
5032 378 : if (bPixelToLogic)
5033 378 : aCellSize = mpRefDevice->PixelToLogic( Size( nOutWidth, nOutHeight ) );
5034 : else
5035 0 : aCellSize = Size( nOutWidth, nOutHeight ); // Scale ist 1
5036 :
5037 378 : long nGridWidth = nEngineWidth;
5038 378 : sal_Bool bNegative = false;
5039 378 : if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
5040 : {
5041 0 : nGridWidth = aCellSize.Width() +
5042 0 : std::abs((long) ( aCellSize.Height() * nCos / nSin ));
5043 0 : bNegative = ( pInfo->nRotateDir == SC_ROTDIR_LEFT );
5044 0 : if ( bLayoutRTL )
5045 0 : bNegative = !bNegative;
5046 : }
5047 :
5048 : // use GetOutputArea to hide the grid
5049 : // (clip region is done manually below)
5050 378 : OutputAreaParam aAreaParam;
5051 :
5052 378 : SCCOL nCellX = nX;
5053 378 : SCROW nCellY = nY;
5054 378 : SvxCellHorJustify eOutHorJust = eHorJust;
5055 378 : if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
5056 0 : eOutHorJust = bNegative ? SVX_HOR_JUSTIFY_RIGHT : SVX_HOR_JUSTIFY_LEFT;
5057 378 : long nNeededWidth = nGridWidth; // in pixel for GetOutputArea
5058 378 : if ( bPixelToLogic )
5059 378 : nNeededWidth = mpRefDevice->LogicToPixel(Size(nNeededWidth,0)).Width();
5060 :
5061 : GetOutputArea( nX, nArrY, nCellStartX, nPosY, nCellX, nCellY, nNeededWidth,
5062 378 : *pPattern, sal::static_int_cast<sal_uInt16>(eOutHorJust),
5063 378 : false, false, sal_True, aAreaParam );
5064 :
5065 378 : if ( bShrink )
5066 : {
5067 : long nPixelWidth = bPixelToLogic ?
5068 78 : mpRefDevice->LogicToPixel(Size(nEngineWidth,0)).Width() : nEngineWidth;
5069 78 : long nNeededPixel = nPixelWidth + nLeftM + nRightM;
5070 :
5071 78 : aAreaParam.mbLeftClip = aAreaParam.mbRightClip = sal_True;
5072 :
5073 : // always do height
5074 : ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
5075 78 : false, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
5076 156 : nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
5077 :
5078 78 : if ( eRotMode == SVX_ROTATE_MODE_STANDARD )
5079 : {
5080 : // do width only if rotating within the cell (standard mode)
5081 : ShrinkEditEngine( *pEngine, aAreaParam.maAlignRect, nLeftM, nTopM, nRightM, nBottomM,
5082 78 : sal_True, sal::static_int_cast<sal_uInt16>(eOrient), nAttrRotate, bPixelToLogic,
5083 156 : nEngineWidth, nEngineHeight, nNeededPixel, aAreaParam.mbLeftClip, aAreaParam.mbRightClip );
5084 : }
5085 :
5086 : // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
5087 : // (but width is only valid for standard mode)
5088 78 : nRealWidth = (long) pEngine->CalcTextWidth();
5089 78 : nRealHeight = pEngine->GetTextHeight();
5090 :
5091 78 : if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
5092 0 : nEngineWidth = (long) ( nRealHeight / fabs( nSin ) );
5093 : }
5094 :
5095 378 : long nClipStartX = nStartX;
5096 378 : if (nX<nX1)
5097 : {
5098 : //! Clipping unnoetig, wenn links am Fenster
5099 :
5100 0 : bClip = sal_True; // nur Rest ausgeben!
5101 0 : if (nStartX<nScrX)
5102 : {
5103 0 : long nDif = nScrX - nStartX;
5104 0 : nClipStartX = nScrX;
5105 0 : aClipSize.Width() -= nDif;
5106 : }
5107 : }
5108 :
5109 378 : long nClipStartY = nStartY;
5110 378 : if (nArrY==0 || bVisChanged)
5111 : {
5112 0 : if ( nClipStartY < nRowPosY )
5113 : {
5114 0 : long nDif = nRowPosY - nClipStartY;
5115 0 : bClip = sal_True;
5116 0 : nClipStartY = nRowPosY;
5117 0 : aClipSize.Height() -= nDif;
5118 : }
5119 : }
5120 :
5121 378 : bClip = sal_True; // always clip at the window/page border
5122 :
5123 : //Rectangle aClipRect;
5124 378 : if (bClip)
5125 : {
5126 378 : if ( nAttrRotate /* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
5127 : {
5128 : // gedrehten, ausgerichteten Text nur an den
5129 : // Seitengrenzen clippen
5130 378 : nClipStartX = nScrX;
5131 378 : aClipSize.Width() = nScrW;
5132 : }
5133 :
5134 378 : if (bPixelToLogic)
5135 : aAreaParam.maClipRect = mpRefDevice->PixelToLogic( Rectangle(
5136 378 : Point(nClipStartX,nClipStartY), aClipSize ) );
5137 : else
5138 : aAreaParam.maClipRect = Rectangle(Point(nClipStartX, nClipStartY),
5139 0 : aClipSize ); // Scale = 1
5140 :
5141 378 : if (bMetaFile)
5142 : {
5143 0 : mpDev->Push();
5144 0 : mpDev->IntersectClipRegion( aAreaParam.maClipRect );
5145 : }
5146 : else
5147 378 : mpDev->SetClipRegion( Region( aAreaParam.maClipRect ) );
5148 : }
5149 :
5150 378 : Point aLogicStart;
5151 378 : if (bPixelToLogic)
5152 378 : aLogicStart = mpRefDevice->PixelToLogic( Point(nStartX,nStartY) );
5153 : else
5154 0 : aLogicStart = Point(nStartX, nStartY);
5155 378 : if ( eOrient!=SVX_ORIENTATION_STANDARD || !bBreak )
5156 : {
5157 140 : long nAvailWidth = aCellSize.Width();
5158 140 : if (eType==OUTTYPE_WINDOW &&
5159 140 : eOrient!=SVX_ORIENTATION_STACKED &&
5160 140 : pInfo && pInfo->bAutoFilter)
5161 : {
5162 : // filter drop-down width is now independent from row height
5163 0 : if (bPixelToLogic)
5164 0 : nAvailWidth -= mpRefDevice->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE)).Height();
5165 : else
5166 0 : nAvailWidth -= DROPDOWN_BITMAP_SIZE;
5167 0 : long nComp = nEngineWidth;
5168 0 : if (nAvailWidth<nComp) nAvailWidth=nComp;
5169 : }
5170 :
5171 : // horizontale Ausrichtung
5172 :
5173 140 : if (eOrient==SVX_ORIENTATION_STANDARD && !nAttrRotate)
5174 : {
5175 0 : if (eHorJust==SVX_HOR_JUSTIFY_RIGHT ||
5176 : eHorJust==SVX_HOR_JUSTIFY_CENTER)
5177 : {
5178 0 : pEngine->SetUpdateMode( false );
5179 :
5180 : SvxAdjust eSvxAdjust =
5181 : (eHorJust==SVX_HOR_JUSTIFY_RIGHT) ?
5182 0 : SVX_ADJUST_RIGHT : SVX_ADJUST_CENTER;
5183 : pEngine->SetDefaultItem(
5184 0 : SvxAdjustItem( eSvxAdjust, EE_PARA_JUST ) );
5185 :
5186 0 : aPaperSize.Width() = nOutWidth;
5187 0 : if (bPixelToLogic)
5188 0 : pEngine->SetPaperSize(mpRefDevice->PixelToLogic(aPaperSize));
5189 : else
5190 0 : pEngine->SetPaperSize(aPaperSize);
5191 :
5192 0 : pEngine->SetUpdateMode( sal_True );
5193 0 : }
5194 : }
5195 : else
5196 : {
5197 : // bei gedrehtem Text ist Standard zentriert
5198 140 : if (eHorJust==SVX_HOR_JUSTIFY_RIGHT)
5199 24 : aLogicStart.X() += nAvailWidth - nEngineWidth;
5200 116 : else if (eHorJust==SVX_HOR_JUSTIFY_CENTER ||
5201 : eHorJust==SVX_HOR_JUSTIFY_STANDARD)
5202 0 : aLogicStart.X() += (nAvailWidth - nEngineWidth) / 2;
5203 : }
5204 : }
5205 :
5206 378 : if ( bLayoutRTL )
5207 : {
5208 0 : if (bPixelToLogic)
5209 0 : aLogicStart.X() -= mpRefDevice->PixelToLogic(
5210 0 : Size( nCellWidth, 0 ) ).Width();
5211 : else
5212 0 : aLogicStart.X() -= nCellWidth;
5213 : }
5214 :
5215 378 : if ( eOrient==SVX_ORIENTATION_STANDARD ||
5216 0 : eOrient==SVX_ORIENTATION_STACKED || !bBreak )
5217 : {
5218 378 : if (eVerJust==SVX_VER_JUSTIFY_BOTTOM ||
5219 : eVerJust==SVX_VER_JUSTIFY_STANDARD)
5220 : {
5221 756 : if (bPixelToLogic)
5222 378 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0,
5223 756 : mpRefDevice->LogicToPixel(aCellSize).Height() -
5224 756 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height()
5225 1134 : )).Height();
5226 : else
5227 0 : aLogicStart.Y() += aCellSize.Height() - nEngineHeight;
5228 : }
5229 :
5230 0 : else if (eVerJust==SVX_VER_JUSTIFY_CENTER)
5231 : {
5232 0 : if (bPixelToLogic)
5233 0 : aLogicStart.Y() += mpRefDevice->PixelToLogic( Size(0,(
5234 0 : mpRefDevice->LogicToPixel(aCellSize).Height() -
5235 0 : mpRefDevice->LogicToPixel(Size(0,nEngineHeight)).Height())
5236 0 : / 2)).Height();
5237 : else
5238 0 : aLogicStart.Y() += (aCellSize.Height() - nEngineHeight) / 2;
5239 : }
5240 : }
5241 :
5242 : // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
5243 : OSL_ENSURE( eOrient == SVX_ORIENTATION_STANDARD && nAttrRotate,
5244 : "DrawRotated: no rotation" );
5245 :
5246 378 : long nOriVal = 0;
5247 378 : if ( nAttrRotate )
5248 : {
5249 : // Attribut ist 1/100, Font 1/10 Grad
5250 378 : nOriVal = nAttrRotate / 10;
5251 :
5252 378 : double nAddX = 0.0;
5253 378 : double nAddY = 0.0;
5254 378 : if ( nCos > 0.0 && eRotMode != SVX_ROTATE_MODE_STANDARD )
5255 : {
5256 : //! begrenzen !!!
5257 0 : double nH = nRealHeight * nCos;
5258 0 : nAddX += nH * ( nCos / fabs(nSin) );
5259 : }
5260 378 : if ( nCos < 0.0 && eRotMode == SVX_ROTATE_MODE_STANDARD )
5261 0 : nAddX -= nRealWidth * nCos;
5262 378 : if ( nSin < 0.0 )
5263 248 : nAddX -= nRealHeight * nSin;
5264 378 : if ( nSin > 0.0 )
5265 130 : nAddY += nRealWidth * nSin;
5266 378 : if ( nCos < 0.0 )
5267 0 : nAddY -= nRealHeight * nCos;
5268 :
5269 378 : if ( eRotMode != SVX_ROTATE_MODE_STANDARD )
5270 : {
5271 : //! begrenzen !!!
5272 0 : double nSkew = nTotalHeight * nCos / fabs(nSin);
5273 0 : if ( eRotMode == SVX_ROTATE_MODE_CENTER )
5274 0 : nAddX -= nSkew * 0.5;
5275 0 : if ( ( eRotMode == SVX_ROTATE_MODE_TOP && nSin > 0.0 ) ||
5276 0 : ( eRotMode == SVX_ROTATE_MODE_BOTTOM && nSin < 0.0 ) )
5277 0 : nAddX -= nSkew;
5278 :
5279 0 : long nUp = 0;
5280 0 : if ( eVerJust == SVX_VER_JUSTIFY_CENTER )
5281 0 : nUp = ( aCellSize.Height() - nEngineHeight ) / 2;
5282 0 : else if ( eVerJust == SVX_VER_JUSTIFY_TOP )
5283 : {
5284 0 : if ( nSin > 0.0 )
5285 0 : nUp = aCellSize.Height() - nEngineHeight;
5286 : }
5287 : else // BOTTOM / STANDARD
5288 : {
5289 0 : if ( nSin < 0.0 )
5290 0 : nUp = aCellSize.Height() - nEngineHeight;
5291 : }
5292 0 : if ( nUp )
5293 0 : nAddX += ( nUp * nCos / fabs(nSin) );
5294 : }
5295 :
5296 378 : aLogicStart.X() += (long) nAddX;
5297 378 : aLogicStart.Y() += (long) nAddY;
5298 : }
5299 :
5300 : // bSimClip is not used here (because nOriVal is set)
5301 :
5302 378 : if ( pEngine->IsRightToLeft( 0 ) )
5303 : {
5304 : // For right-to-left, EditEngine always calculates its lines
5305 : // beginning from the right edge, but EditLine::nStartPosX is
5306 : // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
5307 0 : Size aLogicPaper = pEngine->GetPaperSize();
5308 0 : if ( aLogicPaper.Width() > USHRT_MAX )
5309 : {
5310 0 : aLogicPaper.Width() = USHRT_MAX;
5311 0 : pEngine->SetPaperSize(aLogicPaper);
5312 : }
5313 : }
5314 :
5315 378 : pEngine->Draw( mpDev, aLogicStart, (short)nOriVal );
5316 :
5317 378 : if (bClip)
5318 : {
5319 378 : if (bMetaFile)
5320 0 : mpDev->Pop();
5321 : else
5322 378 : mpDev->SetClipRegion();
5323 : }
5324 : }
5325 : }
5326 : }
5327 : }
5328 2590 : nPosX += pRowInfo[0].pCellInfo[nX+1].nWidth * nLayoutSign;
5329 : }
5330 : }
5331 361 : nRowPosY += pRowInfo[nArrY].nHeight;
5332 : }
5333 :
5334 69 : delete pEngine;
5335 162 : }
5336 :
5337 :
5338 :
5339 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|