1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "scitems.hxx"
21 #include <editeng/eeitem.hxx>
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 #include <vcl/settings.hxx>
49 #include "document.hxx"
50 #include "formulacell.hxx"
52 #include "patattr.hxx"
53 #include "cellform.hxx"
54 #include "editutil.hxx"
55 #include "progress.hxx"
57 #include "fillinfo.hxx"
58 #include "viewdata.hxx"
59 #include "tabvwsh.hxx"
61 #include "markdata.hxx"
62 #include "stlsheet.hxx"
63 #include "spellcheckcontext.hxx"
64 #include <scopetools.hxx>
66 #include <com/sun/star/i18n/DirectionProperty.hpp>
67 #include <comphelper/string.hxx>
69 #include <boost/ptr_container/ptr_vector.hpp>
70 #include <boost/scoped_ptr.hpp>
74 using namespace com::sun::star
;
76 //! Autofilter-Breite mit column.cxx zusammenfassen
77 #define DROPDOWN_BITMAP_SIZE 18
79 #define DRAWTEXT_MAX 32767
81 const sal_uInt16 SC_SHRINKAGAIN_MAX
= 7;
83 // STATIC DATA -----------------------------------------------------------
86 class ScDrawStringsVars
88 ScOutputData
* pOutput
; // Verbindung
90 const ScPatternAttr
* pPattern
; // Attribute
91 const SfxItemSet
* pCondSet
; // aus bedingter Formatierung
93 Font aFont
; // aus Attributen erzeugt
95 long nAscentPixel
; // always pixels
96 SvxCellOrientation eAttrOrient
;
97 SvxCellHorJustify eAttrHorJust
;
98 SvxCellVerJustify eAttrVerJust
;
99 SvxCellJustifyMethod eAttrHorJustMethod
;
100 SvxCellJustifyMethod eAttrVerJustMethod
;
101 const SvxMarginItem
* pMargin
;
105 OUString aString
; // contents
113 ScRefCellValue maLastCell
;
114 sal_uLong nValueFormat
;
122 Color aBackConfigColor
; // used for ScPatternAttr::GetFont calls
123 Color aTextConfigColor
;
128 ScDrawStringsVars(ScOutputData
* pData
, bool bPTL
);
129 ~ScDrawStringsVars();
131 // SetPattern = ex-SetVars
132 // SetPatternSimple: ohne Font
135 const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
, const ScRefCellValue
& rCell
,
138 void SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
);
140 bool SetText( ScRefCellValue
& rCell
); // TRUE -> pOldPattern vergessen
142 void SetTextToWidthOrHash( ScRefCellValue
& rCell
, long nWidth
);
143 void SetAutoText( const OUString
& rAutoText
);
145 SvxCellOrientation
GetOrient() const { return eAttrOrient
; }
146 SvxCellHorJustify
GetHorJust() const { return eAttrHorJust
; }
147 SvxCellVerJustify
GetVerJust() const { return eAttrVerJust
; }
148 SvxCellJustifyMethod
GetHorJustMethod() const { return eAttrHorJustMethod
; }
149 const SvxMarginItem
* GetMargin() const { return pMargin
; }
151 sal_uInt16
GetLeftTotal() const { return pMargin
->GetLeftMargin() + nIndent
; }
152 sal_uInt16
GetRightTotal() const { return pMargin
->GetRightMargin() + nIndent
; }
154 const OUString
& GetString() const { return aString
; }
155 const Size
& GetTextSize() const { return aTextSize
; }
156 long GetOriginalWidth() const { return nOriginalWidth
; }
158 sal_uLong
GetResultValueFormat() const;
160 sal_uLong
GetValueFormat() const { return nValueFormat
; }
161 bool GetLineBreak() const { return bLineBreak
; }
162 bool IsRepeat() const { return bRepeat
; }
163 bool IsShrink() const { return bShrink
; }
164 void RepeatToFill( long colWidth
);
166 long GetAscent() const { return nAscentPixel
; }
167 bool IsRotated() const { return bRotated
; }
169 void SetShrinkScale( long nScale
, sal_uInt8 nScript
);
171 bool HasCondHeight() const { return pCondSet
&& SFX_ITEM_SET
==
172 pCondSet
->GetItemState( ATTR_FONT_HEIGHT
, true ); }
174 bool HasEditCharacters() const;
177 long GetMaxDigitWidth(); // in logic units
184 ScDrawStringsVars::ScDrawStringsVars(ScOutputData
* pData
, bool bPTL
) :
189 eAttrOrient ( SVX_ORIENTATION_STANDARD
),
190 eAttrHorJust( SVX_HOR_JUSTIFY_STANDARD
),
191 eAttrVerJust( SVX_VER_JUSTIFY_BOTTOM
),
192 eAttrHorJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
193 eAttrVerJustMethod( SVX_JUSTIFY_METHOD_AUTO
),
203 bLineBreak ( false ),
206 bPixelToLogic( bPTL
),
210 ScModule
* pScMod
= SC_MOD();
211 bCellContrast
= pOutput
->mbUseStyleColor
&&
212 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
214 const svtools::ColorConfig
& rColorConfig
= pScMod
->GetColorConfig();
215 aBackConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::DOCCOLOR
).nColor
);
216 aTextConfigColor
.SetColor( rColorConfig
.GetColorValue(svtools::FONTCOLOR
).nColor
);
219 ScDrawStringsVars::~ScDrawStringsVars()
223 void ScDrawStringsVars::SetShrinkScale( long nScale
, sal_uInt8 nScript
)
225 // text remains valid, size is updated
227 OutputDevice
* pDev
= pOutput
->mpDev
;
228 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
229 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
231 // call GetFont with a modified fraction, use only the height
233 Fraction
aFraction( nScale
, 100 );
234 if ( !bPixelToLogic
)
235 aFraction
*= pOutput
->aZoomY
;
237 pPattern
->GetFont( aTmpFont
, SC_AUTOCOL_RAW
, pFmtDevice
, &aFraction
, pCondSet
, nScript
);
238 long nNewHeight
= aTmpFont
.GetHeight();
239 if ( nNewHeight
> 0 )
240 aFont
.SetHeight( nNewHeight
);
242 // set font and dependent variables as in SetPattern
244 pDev
->SetFont( aFont
);
245 if ( pFmtDevice
!= pDev
)
246 pFmtDevice
->SetFont( aFont
);
248 aMetric
= pFmtDevice
->GetFontMetric();
249 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
251 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
252 MapMode aOld
= pDefaultDev
->GetMapMode();
253 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
254 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
255 pDefaultDev
->SetMapMode( aOld
);
258 nAscentPixel
= aMetric
.GetAscent();
260 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
262 SetAutoText( aString
); // same text again, to get text size
267 template<typename _ItemType
, typename _EnumType
>
268 _EnumType
lcl_GetValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
270 const _ItemType
& rItem
= static_cast<const _ItemType
&>(rPattern
.GetItem(nWhich
, pCondSet
));
271 return static_cast<_EnumType
>(rItem
.GetValue());
274 bool lcl_GetBoolValue(const ScPatternAttr
& rPattern
, sal_uInt16 nWhich
, const SfxItemSet
* pCondSet
)
276 return lcl_GetValue
<SfxBoolItem
, bool>(rPattern
, nWhich
, pCondSet
);
281 void ScDrawStringsVars::SetPattern(
282 const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
, const ScRefCellValue
& rCell
,
293 // pPattern auswerten
295 OutputDevice
* pDev
= pOutput
->mpDev
;
296 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
297 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
301 ScAutoFontColorMode eColorMode
;
302 if ( pOutput
->mbUseStyleColor
)
304 if ( pOutput
->mbForceAutoColor
)
305 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREALL
: SC_AUTOCOL_IGNOREFONT
;
307 eColorMode
= bCellContrast
? SC_AUTOCOL_IGNOREBACK
: SC_AUTOCOL_DISPLAY
;
310 eColorMode
= SC_AUTOCOL_PRINT
;
313 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, NULL
, pCondSet
, nScript
,
314 &aBackConfigColor
, &aTextConfigColor
);
316 pPattern
->GetFont( aFont
, eColorMode
, pFmtDevice
, &pOutput
->aZoomY
, pCondSet
, nScript
,
317 &aBackConfigColor
, &aTextConfigColor
);
318 aFont
.SetAlign(ALIGN_BASELINE
);
322 eAttrOrient
= pPattern
->GetCellOrientation( pCondSet
);
326 eAttrHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)pPattern
->GetItem( ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
328 eAttrVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)pPattern
->GetItem( ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
329 if ( eAttrVerJust
== SVX_VER_JUSTIFY_STANDARD
)
330 eAttrVerJust
= SVX_VER_JUSTIFY_BOTTOM
;
332 // justification method
334 eAttrHorJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
);
335 eAttrVerJustMethod
= lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
);
339 bLineBreak
= ((const SfxBoolItem
&)pPattern
->GetItem( ATTR_LINEBREAK
, pCondSet
)).GetValue();
341 // handle "repeat" alignment
343 bRepeat
= ( eAttrHorJust
== SVX_HOR_JUSTIFY_REPEAT
);
346 // "repeat" disables rotation (before constructing the font)
347 eAttrOrient
= SVX_ORIENTATION_STANDARD
;
349 // #i31843# "repeat" with "line breaks" is treated as default alignment (but rotation is still disabled)
351 eAttrHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
357 case SVX_ORIENTATION_STANDARD
:
359 bRotated
= (((const SfxInt32Item
&)pPattern
->GetItem( ATTR_ROTATE_VALUE
, pCondSet
)).GetValue() != 0) &&
362 case SVX_ORIENTATION_STACKED
:
366 case SVX_ORIENTATION_TOPBOTTOM
:
370 case SVX_ORIENTATION_BOTTOMTOP
:
375 OSL_FAIL("Falscher SvxCellOrientation Wert");
380 aFont
.SetOrientation( nRot
);
384 if (pOutput
->mbSyntaxMode
)
385 pOutput
->SetSyntaxColor(&aFont
, rCell
);
387 pDev
->SetFont( aFont
);
388 if ( pFmtDevice
!= pDev
)
389 pFmtDevice
->SetFont( aFont
);
391 aMetric
= pFmtDevice
->GetFontMetric();
394 // Wenn auf dem Drucker das Leading 0 ist, gibt es Probleme
395 // -> Metric vom Bildschirm nehmen (wie EditEngine!)
398 if ( pFmtDevice
->GetOutDevType() == OUTDEV_PRINTER
&& aMetric
.GetIntLeading() == 0 )
400 OutputDevice
* pDefaultDev
= Application::GetDefaultDevice();
401 MapMode aOld
= pDefaultDev
->GetMapMode();
402 pDefaultDev
->SetMapMode( pFmtDevice
->GetMapMode() );
403 aMetric
= pDefaultDev
->GetFontMetric( aFont
);
404 pDefaultDev
->SetMapMode( aOld
);
407 nAscentPixel
= aMetric
.GetAscent();
409 nAscentPixel
= pRefDevice
->LogicToPixel( Size( 0, nAscentPixel
) ).Height();
411 Color
aULineColor( ((const SvxUnderlineItem
&)pPattern
->GetItem( ATTR_FONT_UNDERLINE
, pCondSet
)).GetColor() );
412 pDev
->SetTextLineColor( aULineColor
);
414 Color
aOLineColor( ((const SvxOverlineItem
&)pPattern
->GetItem( ATTR_FONT_OVERLINE
, pCondSet
)).GetColor() );
415 pDev
->SetOverlineColor( aOLineColor
);
419 nValueFormat
= pPattern
->GetNumberFormat( pOutput
->mpDoc
->GetFormatTable(), pCondSet
);
423 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
424 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
|| eAttrHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
425 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
431 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
433 // zumindest die Text-Groesse muss neu geholt werden
434 //! unterscheiden, und den Text nicht neu vom Numberformatter holen?
439 void ScDrawStringsVars::SetPatternSimple( const ScPatternAttr
* pNew
, const SfxItemSet
* pSet
)
445 // wird gerufen, wenn sich die Font-Variablen nicht aendern (!StringDiffer)
448 pCondSet
= pSet
; //! noetig ???
452 sal_uLong nOld
= nValueFormat
;
453 const SfxPoolItem
* pFormItem
;
454 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_VALUE_FORMAT
,true,&pFormItem
) != SFX_ITEM_SET
)
455 pFormItem
= &pPattern
->GetItem(ATTR_VALUE_FORMAT
);
456 const SfxPoolItem
* pLangItem
;
457 if ( !pCondSet
|| pCondSet
->GetItemState(ATTR_LANGUAGE_FORMAT
,true,&pLangItem
) != SFX_ITEM_SET
)
458 pLangItem
= &pPattern
->GetItem(ATTR_LANGUAGE_FORMAT
);
459 nValueFormat
= pOutput
->mpDoc
->GetFormatTable()->GetFormatForLanguageIfBuiltIn(
460 ((SfxUInt32Item
*)pFormItem
)->GetValue(),
461 ((SvxLanguageItem
*)pLangItem
)->GetLanguage() );
463 if (nValueFormat
!= nOld
)
464 maLastCell
.clear(); // immer neu formatieren
468 pMargin
= (const SvxMarginItem
*)&pPattern
->GetItem( ATTR_MARGIN
, pCondSet
);
470 if ( eAttrHorJust
== SVX_HOR_JUSTIFY_LEFT
)
471 nIndent
= ((const SfxUInt16Item
&)pPattern
->GetItem( ATTR_INDENT
, pCondSet
)).GetValue();
477 bShrink
= static_cast<const SfxBoolItem
&>(pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
480 inline bool SameValue( const ScRefCellValue
& rCell
, const ScRefCellValue
& rOldCell
)
482 return rOldCell
.meType
== CELLTYPE_VALUE
&& rCell
.meType
== CELLTYPE_VALUE
&&
483 rCell
.mfValue
== rOldCell
.mfValue
;
486 bool ScDrawStringsVars::SetText( ScRefCellValue
& rCell
)
488 bool bChanged
= false;
490 if (!rCell
.isEmpty())
492 if (!SameValue(rCell
, maLastCell
))
494 maLastCell
= rCell
; // Zelle merken
497 sal_uLong nFormat
= GetValueFormat();
498 ScCellFormat::GetString( rCell
,
499 nFormat
, aString
, &pColor
,
500 *pOutput
->mpDoc
->GetFormatTable(),
502 pOutput
->mbShowNullValues
,
503 pOutput
->mbShowFormulas
,
507 nPos
= aString
.indexOf( 0x1B );
510 nChar
= aString
[ nPos
+ 1 ];
511 // delete placeholder and char to repeat
512 aString
= aString
.replaceAt( nPos
, 2, "" );
520 if (aString
.getLength() > DRAWTEXT_MAX
)
521 aString
= aString
.copy(0, DRAWTEXT_MAX
);
523 if ( pColor
&& !pOutput
->mbSyntaxMode
&& !( pOutput
->mbUseStyleColor
&& pOutput
->mbForceAutoColor
) )
525 OutputDevice
* pDev
= pOutput
->mpDev
;
526 aFont
.SetColor(*pColor
);
527 pDev
->SetFont( aFont
); // nur fuer Ausgabe
529 maLastCell
.clear(); // naechstes Mal wieder hierherkommen
534 // sonst String/Groesse behalten
538 aString
= OUString();
540 aTextSize
= Size(0,0);
547 void ScDrawStringsVars::SetHashText()
549 SetAutoText(OUString("###"));
552 void ScDrawStringsVars::RepeatToFill( long colWidth
)
554 if ( nPos
== -1 || nPos
> aString
.getLength() )
557 long charWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString(nChar
));
558 if ( charWidth
< 1) return;
560 colWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(colWidth
,0)).Width();
561 // Are there restrictions on the cell type we should filter out here ?
562 long aSpaceToFill
= ( colWidth
- aTextSize
.Width() );
564 if ( aSpaceToFill
<= charWidth
)
567 long nCharsToInsert
= aSpaceToFill
/ charWidth
;
568 OUStringBuffer aFill
;
569 comphelper::string::padToLength(aFill
, nCharsToInsert
, nChar
);
570 aString
= aString
.replaceAt( nPos
, 0, aFill
.makeStringAndClear() );
574 void ScDrawStringsVars::SetTextToWidthOrHash( ScRefCellValue
& rCell
, long nWidth
)
576 // #i113045# do the single-character width calculations in logic units
578 nWidth
= pOutput
->mpRefDevice
->PixelToLogic(Size(nWidth
,0)).Width();
580 CellType eType
= rCell
.meType
;
581 if (eType
!= CELLTYPE_VALUE
&& eType
!= CELLTYPE_FORMULA
)
582 // must be a value or formula cell.
585 if (eType
== CELLTYPE_FORMULA
)
587 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
588 if (pFCell
->GetErrCode() != 0 || pOutput
->mbShowFormulas
)
590 SetHashText(); // If the error string doesn't fit, always use "###". Also for "display formulas" (#i116691#)
593 // If it's formula, the result must be a value.
594 if (!pFCell
->IsValue())
598 sal_uLong nFormat
= GetResultValueFormat();
599 if ((nFormat
% SV_COUNTRY_LANGUAGE_OFFSET
) != 0)
601 // Not 'General' number format. Set hash text and bail out.
606 double fVal
= rCell
.getValue();
608 const SvNumberformat
* pNumFormat
= pOutput
->mpDoc
->GetFormatTable()->GetEntry(nFormat
);
612 long nMaxDigit
= GetMaxDigitWidth();
613 sal_uInt16 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
615 OUString
sTempOut(aString
);
616 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
619 // Failed to get output string. Bail out.
624 sal_uInt8 nSignCount
= 0, nDecimalCount
= 0, nExpCount
= 0;
625 sal_Int32 nLen
= aString
.getLength();
626 sal_Unicode cDecSep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
[0];
627 for( sal_Int32 i
= 0; i
< nLen
; ++i
)
629 sal_Unicode c
= aString
[i
];
632 else if (c
== cDecSep
)
638 // #i112250# A small value might be formatted as "0" when only counting the digits,
639 // but fit into the column when considering the smaller width of the decimal separator.
640 if (aString
== "0" && fVal
!= 0.0)
644 nWidth
+= (nMaxDigit
- GetDotWidth()) * nDecimalCount
;
646 nWidth
+= (nMaxDigit
- GetSignWidth()) * nSignCount
;
648 nWidth
+= (nMaxDigit
- GetExpWidth()) * nExpCount
;
650 if (nDecimalCount
|| nSignCount
|| nExpCount
)
653 nNumDigits
= static_cast<sal_uInt16
>(nWidth
/ nMaxDigit
);
654 OUString
sTempOut(aString
);
655 if (!pNumFormat
->GetOutputString(fVal
, nNumDigits
, sTempOut
))
658 // Failed to get output string. Bail out.
664 long nActualTextWidth
= pOutput
->pFmtDevice
->GetTextWidth(aString
);
665 if (nActualTextWidth
> nWidth
)
667 // Even after the decimal adjustment the text doesn't fit. Give up.
673 maLastCell
.clear(); // #i113022# equal cell and format in another column may give different string
676 void ScDrawStringsVars::SetAutoText( const OUString
& rAutoText
)
680 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
681 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
682 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
683 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
685 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
687 double fMul
= pOutput
->GetStretch();
688 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
691 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
692 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
694 long nTemp
= aTextSize
.Height();
695 aTextSize
.Height() = aTextSize
.Width();
696 aTextSize
.Width() = nTemp
;
699 nOriginalWidth
= aTextSize
.Width();
701 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
703 maLastCell
.clear(); // derselbe Text kann in der naechsten Zelle wieder passen
706 long ScDrawStringsVars::GetMaxDigitWidth()
708 if (nMaxDigitWidth
> 0)
709 return nMaxDigitWidth
;
711 sal_Char cZero
= '0';
712 for (sal_Char i
= 0; i
< 10; ++i
)
714 sal_Char cDigit
= cZero
+ i
;
715 long n
= pOutput
->pFmtDevice
->GetTextWidth(OUString(cDigit
));
716 nMaxDigitWidth
= ::std::max(nMaxDigitWidth
, n
);
718 return nMaxDigitWidth
;
721 long ScDrawStringsVars::GetSignWidth()
726 nSignWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString('-'));
730 long ScDrawStringsVars::GetDotWidth()
735 const OUString
& sep
= ScGlobal::GetpLocaleData()->getLocaleItem().decimalSeparator
;
736 nDotWidth
= pOutput
->pFmtDevice
->GetTextWidth(sep
);
740 long ScDrawStringsVars::GetExpWidth()
745 nExpWidth
= pOutput
->pFmtDevice
->GetTextWidth(OUString('E'));
749 void ScDrawStringsVars::TextChanged()
751 OutputDevice
* pRefDevice
= pOutput
->mpRefDevice
;
752 OutputDevice
* pFmtDevice
= pOutput
->pFmtDevice
;
753 aTextSize
.Width() = pFmtDevice
->GetTextWidth( aString
);
754 aTextSize
.Height() = pFmtDevice
->GetTextHeight();
756 if ( !pRefDevice
->GetConnectMetaFile() || pRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
758 double fMul
= pOutput
->GetStretch();
759 aTextSize
.Width() = (long)(aTextSize
.Width() / fMul
+ 0.5);
762 aTextSize
.Height() = aMetric
.GetAscent() + aMetric
.GetDescent();
763 if ( GetOrient() != SVX_ORIENTATION_STANDARD
)
765 long nTemp
= aTextSize
.Height();
766 aTextSize
.Height() = aTextSize
.Width();
767 aTextSize
.Width() = nTemp
;
770 nOriginalWidth
= aTextSize
.Width();
772 aTextSize
= pRefDevice
->LogicToPixel( aTextSize
);
775 bool ScDrawStringsVars::HasEditCharacters() const
777 for (sal_Int32 nIdx
= 0; nIdx
< aString
.getLength(); ++nIdx
)
779 switch(aString
[nIdx
])
797 sal_uLong
ScDrawStringsVars::GetResultValueFormat() const
799 // Get the effective number format, including formula result types.
800 // This assumes that a formula cell has already been calculated.
805 double ScOutputData::GetStretch()
807 if ( mpRefDevice
->IsMapMode() )
809 // If a non-trivial MapMode is set, its scale is now already
810 // taken into account in the OutputDevice's font handling
811 // (OutputDevice::ImplNewFont, see #95414#).
812 // The old handling below is only needed for pixel output.
816 // calculation in double is faster than Fraction multiplication
817 // and doesn't overflow
819 if ( mpRefDevice
== pFmtDevice
)
821 MapMode aOld
= mpRefDevice
->GetMapMode();
822 return ((double)aOld
.GetScaleY()) / ((double)aOld
.GetScaleX()) * ((double)aZoomY
) / ((double)aZoomX
);
826 // when formatting for printer, device map mode has already been taken care of
827 return ((double)aZoomY
) / ((double)aZoomX
);
835 static void lcl_DoHyperlinkResult( OutputDevice
* pDev
, const Rectangle
& rRect
, ScRefCellValue
& rCell
)
837 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
841 if (rCell
.meType
== CELLTYPE_FORMULA
)
843 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
844 if ( pFCell
->IsHyperLinkCell() )
845 pFCell
->GetURLResult( aURL
, aCellText
);
848 if ( !aURL
.isEmpty() && pPDFData
)
850 vcl::PDFExtOutDevBookmarkEntry aBookmark
;
851 aBookmark
.nLinkId
= pPDFData
->CreateLink( rRect
);
852 aBookmark
.aBookmark
= aURL
;
853 std::vector
< vcl::PDFExtOutDevBookmarkEntry
>& rBookmarks
= pPDFData
->GetBookmarks();
854 rBookmarks
.push_back( aBookmark
);
858 void ScOutputData::SetSyntaxColor( Font
* pFont
, const ScRefCellValue
& rCell
)
860 switch (rCell
.meType
)
863 pFont
->SetColor(*pValueColor
);
865 case CELLTYPE_STRING
:
866 pFont
->SetColor(*pTextColor
);
868 case CELLTYPE_FORMULA
:
869 pFont
->SetColor(*pFormulaColor
);
873 // added to avoid warnings
878 static void lcl_SetEditColor( EditEngine
& rEngine
, const Color
& rColor
)
880 ESelection
aSel( 0, 0, rEngine
.GetParagraphCount(), 0 );
881 SfxItemSet
aSet( rEngine
.GetEmptyItemSet() );
882 aSet
.Put( SvxColorItem( rColor
, EE_CHAR_COLOR
) );
883 rEngine
.QuickSetAttribs( aSet
, aSel
);
884 // function is called with update mode set to FALSE
887 void ScOutputData::SetEditSyntaxColor( EditEngine
& rEngine
, ScRefCellValue
& rCell
)
890 switch (rCell
.meType
)
893 aColor
= *pValueColor
;
895 case CELLTYPE_STRING
:
896 aColor
= *pTextColor
;
898 case CELLTYPE_FORMULA
:
899 aColor
= *pFormulaColor
;
903 // added to avoid warnings
906 lcl_SetEditColor( rEngine
, aColor
);
909 bool ScOutputData::GetMergeOrigin( SCCOL nX
, SCROW nY
, SCSIZE nArrY
,
910 SCCOL
& rOverX
, SCROW
& rOverY
,
911 bool bVisRowChanged
)
913 bool bDoMerge
= false;
914 bool bIsLeft
= ( nX
== nVisX1
);
915 bool bIsTop
= ( nY
== nVisY1
) || bVisRowChanged
;
917 CellInfo
* pInfo
= &pRowInfo
[nArrY
].pCellInfo
[nX
+1];
918 if ( pInfo
->bHOverlapped
&& pInfo
->bVOverlapped
)
919 bDoMerge
= bIsLeft
&& bIsTop
;
920 else if ( pInfo
->bHOverlapped
)
922 else if ( pInfo
->bVOverlapped
)
927 bool bHOver
= pInfo
->bHOverlapped
;
928 bool bVOver
= pInfo
->bVOverlapped
;
931 while (bHOver
) // nY konstant
934 bHidden
= mpDoc
->ColHidden(rOverX
, nTab
);
935 if ( !bDoMerge
&& !bHidden
)
938 if (rOverX
>= nX1
&& !bHidden
)
940 bHOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bHOverlapped
;
941 bVOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bVOverlapped
;
945 sal_uInt16 nOverlap
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
946 rOverX
, rOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue();
947 bHOver
= ((nOverlap
& SC_MF_HOR
) != 0);
948 bVOver
= ((nOverlap
& SC_MF_VER
) != 0);
955 bHidden
= mpDoc
->RowHidden(rOverY
, nTab
);
956 if ( !bDoMerge
&& !bHidden
)
960 --nArrY
; // lokale Kopie !
962 if (rOverX
>= nX1
&& rOverY
>= nY1
&&
963 !mpDoc
->ColHidden(rOverX
, nTab
) &&
964 !mpDoc
->RowHidden(rOverY
, nTab
) &&
965 pRowInfo
[nArrY
].nRowNo
== rOverY
)
967 bHOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bHOverlapped
;
968 bVOver
= pRowInfo
[nArrY
].pCellInfo
[rOverX
+1].bVOverlapped
;
972 sal_uInt16 nOverlap
= ((ScMergeFlagAttr
*)mpDoc
->GetAttr(
973 rOverX
, rOverY
, nTab
, ATTR_MERGE_FLAG
))->GetValue();
974 bHOver
= ((nOverlap
& SC_MF_HOR
) != 0);
975 bVOver
= ((nOverlap
& SC_MF_VER
) != 0);
982 inline bool StringDiffer( const ScPatternAttr
*& rpOldPattern
, const ScPatternAttr
*& rpNewPattern
)
984 OSL_ENSURE( rpNewPattern
, "pNewPattern" );
986 if ( rpNewPattern
== rpOldPattern
)
988 else if ( !rpOldPattern
)
990 else if ( &rpNewPattern
->GetItem( ATTR_FONT
) != &rpOldPattern
->GetItem( ATTR_FONT
) )
992 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT
) )
994 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT
) )
996 else if ( &rpNewPattern
->GetItem( ATTR_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_HEIGHT
) )
998 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_HEIGHT
) )
1000 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_HEIGHT
) )
1002 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_FONT_WEIGHT
) )
1004 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_WEIGHT
) )
1006 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_WEIGHT
) )
1008 else if ( &rpNewPattern
->GetItem( ATTR_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_FONT_POSTURE
) )
1010 else if ( &rpNewPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CJK_FONT_POSTURE
) )
1012 else if ( &rpNewPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) != &rpOldPattern
->GetItem( ATTR_CTL_FONT_POSTURE
) )
1014 else if ( &rpNewPattern
->GetItem( ATTR_FONT_UNDERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_UNDERLINE
) )
1016 else if ( &rpNewPattern
->GetItem( ATTR_FONT_OVERLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_OVERLINE
) )
1018 else if ( &rpNewPattern
->GetItem( ATTR_FONT_WORDLINE
) != &rpOldPattern
->GetItem( ATTR_FONT_WORDLINE
) )
1020 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) != &rpOldPattern
->GetItem( ATTR_FONT_CROSSEDOUT
) )
1022 else if ( &rpNewPattern
->GetItem( ATTR_FONT_CONTOUR
) != &rpOldPattern
->GetItem( ATTR_FONT_CONTOUR
) )
1024 else if ( &rpNewPattern
->GetItem( ATTR_FONT_SHADOWED
) != &rpOldPattern
->GetItem( ATTR_FONT_SHADOWED
) )
1026 else if ( &rpNewPattern
->GetItem( ATTR_FONT_COLOR
) != &rpOldPattern
->GetItem( ATTR_FONT_COLOR
) )
1028 else if ( &rpNewPattern
->GetItem( ATTR_HOR_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_HOR_JUSTIFY
) )
1030 else if ( &rpNewPattern
->GetItem( ATTR_HOR_JUSTIFY_METHOD
) != &rpOldPattern
->GetItem( ATTR_HOR_JUSTIFY_METHOD
) )
1032 else if ( &rpNewPattern
->GetItem( ATTR_VER_JUSTIFY
) != &rpOldPattern
->GetItem( ATTR_VER_JUSTIFY
) )
1034 else if ( &rpNewPattern
->GetItem( ATTR_VER_JUSTIFY_METHOD
) != &rpOldPattern
->GetItem( ATTR_VER_JUSTIFY_METHOD
) )
1036 else if ( &rpNewPattern
->GetItem( ATTR_STACKED
) != &rpOldPattern
->GetItem( ATTR_STACKED
) )
1038 else if ( &rpNewPattern
->GetItem( ATTR_LINEBREAK
) != &rpOldPattern
->GetItem( ATTR_LINEBREAK
) )
1040 else if ( &rpNewPattern
->GetItem( ATTR_MARGIN
) != &rpOldPattern
->GetItem( ATTR_MARGIN
) )
1042 else if ( &rpNewPattern
->GetItem( ATTR_ROTATE_VALUE
) != &rpOldPattern
->GetItem( ATTR_ROTATE_VALUE
) )
1044 else if ( &rpNewPattern
->GetItem( ATTR_FORBIDDEN_RULES
) != &rpOldPattern
->GetItem( ATTR_FORBIDDEN_RULES
) )
1046 else if ( &rpNewPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) != &rpOldPattern
->GetItem( ATTR_FONT_EMPHASISMARK
) )
1048 else if ( &rpNewPattern
->GetItem( ATTR_FONT_RELIEF
) != &rpOldPattern
->GetItem( ATTR_FONT_RELIEF
) )
1050 else if ( &rpNewPattern
->GetItem( ATTR_BACKGROUND
) != &rpOldPattern
->GetItem( ATTR_BACKGROUND
) )
1051 return true; // needed with automatic text color
1054 rpOldPattern
= rpNewPattern
;
1059 static inline void lcl_CreateInterpretProgress( bool& bProgress
, ScDocument
* pDoc
,
1060 ScFormulaCell
* pFCell
)
1062 if ( !bProgress
&& pFCell
->GetDirty() )
1064 ScProgress::CreateInterpretProgress( pDoc
, true );
1069 inline bool IsAmbiguousScript( sal_uInt8 nScript
)
1071 return ( nScript
!= SCRIPTTYPE_LATIN
&&
1072 nScript
!= SCRIPTTYPE_ASIAN
&&
1073 nScript
!= SCRIPTTYPE_COMPLEX
);
1076 bool ScOutputData::IsEmptyCellText( RowInfo
* pThisRowInfo
, SCCOL nX
, SCROW nY
)
1078 // pThisRowInfo may be NULL
1081 if ( pThisRowInfo
&& nX
<= nX2
)
1082 bEmpty
= pThisRowInfo
->pCellInfo
[nX
+1].bEmptyCellText
;
1085 ScRefCellValue aCell
;
1086 aCell
.assign(*mpDoc
, ScAddress(nX
, nY
, nTab
));
1087 bEmpty
= aCell
.isEmpty();
1090 if ( !bEmpty
&& ( nX
< nX1
|| nX
> nX2
|| !pThisRowInfo
) )
1092 // for the range nX1..nX2 in RowInfo, cell protection attribute is already evaluated
1093 // into bEmptyCellText in ScDocument::FillInfo / lcl_HidePrint (printfun)
1095 bool bIsPrint
= ( eType
== OUTTYPE_PRINTER
);
1097 if ( bIsPrint
|| bTabProtected
)
1099 const ScProtectionAttr
* pAttr
= (const ScProtectionAttr
*)
1100 mpDoc
->GetEffItem( nX
, nY
, nTab
, ATTR_PROTECTION
);
1101 if ( bIsPrint
&& pAttr
->GetHidePrint() )
1103 else if ( bTabProtected
)
1105 if ( pAttr
->GetHideCell() )
1107 else if ( mbShowFormulas
&& pAttr
->GetHideFormula() )
1109 if (mpDoc
->GetCellType(ScAddress(nX
, nY
, nTab
)) == CELLTYPE_FORMULA
)
1118 void ScOutputData::GetVisibleCell( SCCOL nCol
, SCROW nRow
, SCTAB nTabP
, ScRefCellValue
& rCell
)
1120 rCell
.assign(*mpDoc
, ScAddress(nCol
, nRow
, nTabP
));
1121 if (!rCell
.isEmpty() && IsEmptyCellText(NULL
, nCol
, nRow
))
1125 bool ScOutputData::IsAvailable( SCCOL nX
, SCROW nY
)
1127 // apply the same logic here as in DrawStrings/DrawEdit:
1128 // Stop at non-empty or merged or overlapped cell,
1129 // where a note is empty as well as a cell that's hidden by protection settings
1131 ScRefCellValue aCell
;
1132 aCell
.assign(*mpDoc
, ScAddress(nX
, nY
, nTab
));
1133 if (!aCell
.isEmpty() && !IsEmptyCellText(NULL
, nX
, nY
))
1136 const ScPatternAttr
* pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
1137 if ( ((const ScMergeAttr
&)pPattern
->GetItem(ATTR_MERGE
)).IsMerged() ||
1138 ((const ScMergeFlagAttr
&)pPattern
->GetItem(ATTR_MERGE_FLAG
)).IsOverlapped() )
1146 // nX, nArrY: loop variables from DrawStrings / DrawEdit
1147 // nPosX, nPosY: corresponding positions for nX, nArrY
1148 // nCellX, nCellY: position of the cell that contains the text
1149 // nNeeded: Text width, including margin
1150 // rPattern: cell format at nCellX, nCellY
1151 // nHorJustify: horizontal alignment (visual) to determine which cells to use for long strings
1152 // bCellIsValue: if set, don't extend into empty cells
1153 // bBreak: if set, don't extend, and don't set clip marks (but rLeftClip/rRightClip is set)
1154 // bOverwrite: if set, also extend into non-empty cells (for rotated text)
1155 // rParam output: various area parameters.
1157 void ScOutputData::GetOutputArea( SCCOL nX
, SCSIZE nArrY
, long nPosX
, long nPosY
,
1158 SCCOL nCellX
, SCROW nCellY
, long nNeeded
,
1159 const ScPatternAttr
& rPattern
,
1160 sal_uInt16 nHorJustify
, bool bCellIsValue
,
1161 bool bBreak
, bool bOverwrite
,
1162 OutputAreaParam
& rParam
)
1164 // rThisRowInfo may be for a different row than nCellY, is still used for clip marks
1165 RowInfo
& rThisRowInfo
= pRowInfo
[nArrY
];
1167 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1169 long nCellPosX
= nPosX
; // find nCellX position, starting at nX/nPosX
1170 SCCOL nCompCol
= nX
;
1171 while ( nCellX
> nCompCol
)
1173 //! extra member function for width?
1174 long nColWidth
= ( nCompCol
<= nX2
) ?
1175 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1176 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1177 nCellPosX
+= nColWidth
* nLayoutSign
;
1180 while ( nCellX
< nCompCol
)
1183 long nColWidth
= ( nCompCol
<= nX2
) ?
1184 pRowInfo
[0].pCellInfo
[nCompCol
+1].nWidth
:
1185 (long) ( mpDoc
->GetColWidth( nCompCol
, nTab
) * mnPPTX
);
1186 nCellPosX
-= nColWidth
* nLayoutSign
;
1189 long nCellPosY
= nPosY
; // find nCellY position, starting at nArrY/nPosY
1190 SCSIZE nCompArr
= nArrY
;
1191 SCROW nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1192 while ( nCellY
> nCompRow
)
1194 if ( nCompArr
+ 1 < nArrCount
)
1196 nCellPosY
+= pRowInfo
[nCompArr
].nHeight
;
1198 nCompRow
= pRowInfo
[nCompArr
].nRowNo
;
1202 sal_uInt16 nDocHeight
= mpDoc
->GetRowHeight( nCompRow
, nTab
);
1204 nCellPosY
+= (long) ( nDocHeight
* mnPPTY
);
1208 nCellPosY
-= (long) mpDoc
->GetScaledRowHeight( nCellY
, nCompRow
-1, nTab
, mnPPTY
);
1210 const ScMergeAttr
* pMerge
= (const ScMergeAttr
*)&rPattern
.GetItem( ATTR_MERGE
);
1211 bool bMerged
= pMerge
->IsMerged();
1212 long nMergeCols
= pMerge
->GetColMerge();
1213 if ( nMergeCols
== 0 )
1215 long nMergeRows
= pMerge
->GetRowMerge();
1216 if ( nMergeRows
== 0 )
1219 long nMergeSizeX
= 0;
1220 for ( long i
=0; i
<nMergeCols
; i
++ )
1222 long nColWidth
= ( nCellX
+i
<= nX2
) ?
1223 pRowInfo
[0].pCellInfo
[nCellX
+i
+1].nWidth
:
1224 (long) ( mpDoc
->GetColWidth( sal::static_int_cast
<SCCOL
>(nCellX
+i
), nTab
) * mnPPTX
);
1225 nMergeSizeX
+= nColWidth
;
1227 long nMergeSizeY
= 0;
1229 if ( rThisRowInfo
.nRowNo
== nCellY
)
1231 // take first row's height from row info
1232 nMergeSizeY
+= rThisRowInfo
.nHeight
;
1233 nDirect
= 1; // skip in loop
1235 // following rows always from document
1236 nMergeSizeY
+= (long) mpDoc
->GetScaledRowHeight( nCellY
+nDirect
, nCellY
+nMergeRows
-1, nTab
, mnPPTY
);
1238 --nMergeSizeX
; // leave out the grid horizontally, also for alignment (align between grid lines)
1240 rParam
.mnColWidth
= nMergeSizeX
; // store the actual column width.
1241 rParam
.mnLeftClipLength
= rParam
.mnRightClipLength
= 0;
1243 // construct the rectangles using logical left/right values (justify is called at the end)
1246 // rAlignRect is the single cell or merged area, used for alignment.
1248 rParam
.maAlignRect
.Left() = nCellPosX
;
1249 rParam
.maAlignRect
.Right() = nCellPosX
+ ( nMergeSizeX
- 1 ) * nLayoutSign
;
1250 rParam
.maAlignRect
.Top() = nCellPosY
;
1251 rParam
.maAlignRect
.Bottom() = nCellPosY
+ nMergeSizeY
- 1;
1253 // rClipRect is all cells that are used for output.
1254 // For merged cells this is the same as rAlignRect, otherwise neighboring cells can also be used.
1256 rParam
.maClipRect
= rParam
.maAlignRect
;
1257 if ( nNeeded
> nMergeSizeX
)
1259 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)nHorJustify
;
1261 long nMissing
= nNeeded
- nMergeSizeX
;
1262 long nLeftMissing
= 0;
1263 long nRightMissing
= 0;
1266 case SVX_HOR_JUSTIFY_LEFT
:
1267 nRightMissing
= nMissing
;
1269 case SVX_HOR_JUSTIFY_RIGHT
:
1270 nLeftMissing
= nMissing
;
1272 case SVX_HOR_JUSTIFY_CENTER
:
1273 nLeftMissing
= nMissing
/ 2;
1274 nRightMissing
= nMissing
- nLeftMissing
;
1278 // added to avoid warnings
1282 // nLeftMissing, nRightMissing are logical, eHorJust values are visual
1284 ::std::swap( nLeftMissing
, nRightMissing
);
1286 SCCOL nRightX
= nCellX
;
1287 SCCOL nLeftX
= nCellX
;
1288 if ( !bMerged
&& !bCellIsValue
&& !bBreak
)
1290 // look for empty cells into which the text can be extended
1292 while ( nRightMissing
> 0 && nRightX
< MAXCOL
&& ( bOverwrite
|| IsAvailable( nRightX
+1, nCellY
) ) )
1295 long nAdd
= (long) ( mpDoc
->GetColWidth( nRightX
, nTab
) * mnPPTX
);
1296 nRightMissing
-= nAdd
;
1297 rParam
.maClipRect
.Right() += nAdd
* nLayoutSign
;
1299 if ( rThisRowInfo
.nRowNo
== nCellY
&& nRightX
>= nX1
&& nRightX
<= nX2
)
1300 rThisRowInfo
.pCellInfo
[nRightX
].bHideGrid
= true;
1303 while ( nLeftMissing
> 0 && nLeftX
> 0 && ( bOverwrite
|| IsAvailable( nLeftX
-1, nCellY
) ) )
1305 if ( rThisRowInfo
.nRowNo
== nCellY
&& nLeftX
>= nX1
&& nLeftX
<= nX2
)
1306 rThisRowInfo
.pCellInfo
[nLeftX
].bHideGrid
= true;
1309 long nAdd
= (long) ( mpDoc
->GetColWidth( nLeftX
, nTab
) * mnPPTX
);
1310 nLeftMissing
-= nAdd
;
1311 rParam
.maClipRect
.Left() -= nAdd
* nLayoutSign
;
1315 // Set flag and reserve space for clipping mark triangle,
1316 // even if rThisRowInfo isn't for nCellY (merged cells).
1317 if ( nRightMissing
> 0 && bMarkClipped
&& nRightX
>= nX1
&& nRightX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1319 rThisRowInfo
.pCellInfo
[nRightX
+1].nClipMark
|= SC_CLIPMARK_RIGHT
;
1321 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1322 rParam
.maClipRect
.Right() -= nMarkPixel
* nLayoutSign
;
1324 if ( nLeftMissing
> 0 && bMarkClipped
&& nLeftX
>= nX1
&& nLeftX
<= nX2
&& !bBreak
&& !bCellIsValue
)
1326 rThisRowInfo
.pCellInfo
[nLeftX
+1].nClipMark
|= SC_CLIPMARK_LEFT
;
1328 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
1329 rParam
.maClipRect
.Left() += nMarkPixel
* nLayoutSign
;
1332 rParam
.mbLeftClip
= ( nLeftMissing
> 0 );
1333 rParam
.mbRightClip
= ( nRightMissing
> 0 );
1334 rParam
.mnLeftClipLength
= nLeftMissing
;
1335 rParam
.mnRightClipLength
= nRightMissing
;
1339 rParam
.mbLeftClip
= rParam
.mbRightClip
= false;
1341 // leave space for AutoFilter on screen
1342 // (for automatic line break: only if not formatting for printer, as in ScColumn::GetNeededSize)
1344 if ( eType
==OUTTYPE_WINDOW
&&
1345 ( static_cast<const ScMergeFlagAttr
&>(rPattern
.GetItem(ATTR_MERGE_FLAG
)).GetValue() & (SC_MF_AUTO
|SC_MF_BUTTON
|SC_MF_BUTTON_POPUP
) ) &&
1346 ( !bBreak
|| mpRefDevice
== pFmtDevice
) )
1348 // filter drop-down width is now independent from row height
1349 const long nFilter
= DROPDOWN_BITMAP_SIZE
;
1350 bool bFit
= ( nNeeded
+ nFilter
<= nMergeSizeX
);
1351 if ( bFit
|| bCellIsValue
)
1353 // content fits even in the remaining area without the filter button
1354 // -> align within that remaining area
1356 rParam
.maAlignRect
.Right() -= nFilter
* nLayoutSign
;
1357 rParam
.maClipRect
.Right() -= nFilter
* nLayoutSign
;
1359 // if a number doesn't fit, don't hide part of the number behind the button
1360 // -> set clip flags, so "###" replacement is used (but also within the smaller area)
1363 rParam
.mbLeftClip
= rParam
.mbRightClip
= true;
1368 // justify both rectangles for alignment calculation, use with DrawText etc.
1370 rParam
.maAlignRect
.Justify();
1371 rParam
.maClipRect
.Justify();
1376 bool beginsWithRTLCharacter(const OUString
& rStr
)
1381 switch (ScGlobal::pCharClass
->getCharacterDirection(rStr
, 0))
1383 case i18n::DirectionProperty_RIGHT_TO_LEFT
:
1384 case i18n::DirectionProperty_RIGHT_TO_LEFT_ARABIC
:
1385 case i18n::DirectionProperty_RIGHT_TO_LEFT_EMBEDDING
:
1386 case i18n::DirectionProperty_RIGHT_TO_LEFT_OVERRIDE
:
1397 /** Get left, right or centered alignment from RTL context.
1399 Does not return standard, block or repeat, for these the contextual left or
1400 right alignment is returned.
1402 static SvxCellHorJustify
getAlignmentFromContext( SvxCellHorJustify eInHorJust
,
1403 bool bCellIsValue
, const OUString
& rText
,
1404 const ScPatternAttr
& rPattern
, const SfxItemSet
* pCondSet
,
1405 const ScDocument
* pDoc
, SCTAB nTab
)
1407 SvxCellHorJustify eHorJustContext
= eInHorJust
;
1408 bool bUseWritingDirection
= false;
1409 if (eInHorJust
== SVX_HOR_JUSTIFY_STANDARD
)
1411 // fdo#32530: Default alignment depends on value vs
1412 // string, and the direction of the 1st letter.
1413 if (beginsWithRTLCharacter( rText
))
1414 eHorJustContext
= bCellIsValue
? SVX_HOR_JUSTIFY_LEFT
: SVX_HOR_JUSTIFY_RIGHT
;
1415 else if (bCellIsValue
)
1416 eHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
1418 bUseWritingDirection
= true;
1421 if (bUseWritingDirection
||
1422 eInHorJust
== SVX_HOR_JUSTIFY_BLOCK
|| eInHorJust
== SVX_HOR_JUSTIFY_REPEAT
)
1424 sal_uInt16 nDirection
= lcl_GetValue
<SvxFrameDirectionItem
, sal_uInt16
>( rPattern
, ATTR_WRITINGDIR
, pCondSet
);
1425 if (nDirection
== FRMDIR_HORI_LEFT_TOP
|| nDirection
== FRMDIR_VERT_TOP_LEFT
)
1426 eHorJustContext
= SVX_HOR_JUSTIFY_LEFT
;
1427 else if (nDirection
== FRMDIR_ENVIRONMENT
)
1429 SAL_WARN_IF( !pDoc
, "sc.ui", "getAlignmentFromContext - pDoc==NULL");
1430 // fdo#73588: The content of the cell must also
1431 // begin with a RTL character to be right
1432 // aligned; otherwise, it should be left aligned.
1433 eHorJustContext
= (pDoc
&& pDoc
->IsLayoutRTL(nTab
) && (beginsWithRTLCharacter( rText
))) ? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
1436 eHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
1438 return eHorJustContext
;
1441 void ScOutputData::DrawStrings( bool bPixelToLogic
)
1443 OSL_ENSURE( mpDev
== mpRefDevice
||
1444 mpDev
->GetMapMode().GetMapUnit() == mpRefDevice
->GetMapMode().GetMapUnit(),
1445 "DrawStrings: unterschiedliche MapUnits ?!?!" );
1447 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, mpDev
->GetExtOutDevData() );
1449 sc::IdleSwitch
aIdleSwitch(*mpDoc
, false);
1450 ScDrawStringsVars
aVars( this, bPixelToLogic
);
1452 bool bProgress
= false;
1454 long nInitPosX
= nScrX
;
1456 nInitPosX
+= nMirrorW
- 1; // pixels
1457 long nLayoutSign
= bLayoutRTL
? -1 : 1;
1459 SCCOL nLastContentCol
= MAXCOL
;
1461 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
1462 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
1463 SCCOL nLoopStartX
= nX1
;
1465 --nLoopStartX
; // start before nX1 for rest of long text to the left
1467 // variables for GetOutputArea
1468 OutputAreaParam aAreaParam
;
1469 bool bCellIsValue
= false;
1470 long nNeededWidth
= 0;
1471 const ScPatternAttr
* pPattern
= NULL
;
1472 const SfxItemSet
* pCondSet
= NULL
;
1473 const ScPatternAttr
* pOldPattern
= NULL
;
1474 const SfxItemSet
* pOldCondSet
= NULL
;
1475 sal_uInt8 nOldScript
= 0;
1477 // alternative pattern instances in case we need to modify the pattern
1478 // before processing the cell value.
1479 ::boost::ptr_vector
<ScPatternAttr
> aAltPatterns
;
1481 std::vector
<sal_Int32
> aDX
;
1483 for (SCSIZE nArrY
=1; nArrY
+1<nArrCount
; nArrY
++)
1485 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
1486 if ( pThisRowInfo
->bChanged
)
1488 SCROW nY
= pThisRowInfo
->nRowNo
;
1489 long nPosX
= nInitPosX
;
1490 if ( nLoopStartX
< nX1
)
1491 nPosX
-= pRowInfo
[0].pCellInfo
[nLoopStartX
+1].nWidth
* nLayoutSign
;
1492 for (SCCOL nX
=nLoopStartX
; nX
<=nX2
; nX
++)
1494 bool bMergeEmpty
= false;
1495 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
1496 bool bEmpty
= nX
< nX1
|| pInfo
->bEmptyCellText
;
1498 SCCOL nCellX
= nX
; // position where the cell really starts
1500 bool bDoCell
= false;
1501 bool bNeedEdit
= false;
1504 // Part of a merged cell?
1507 bool bOverlapped
= (pInfo
->bHOverlapped
|| pInfo
->bVOverlapped
);
1512 SCCOL nOverX
; // start of the merged cells
1514 bool bVisChanged
= !pRowInfo
[nArrY
-1].bChanged
;
1515 if (GetMergeOrigin( nX
,nY
, nArrY
, nOverX
,nOverY
, bVisChanged
))
1526 // Rest of a long text further to the left?
1529 if ( bEmpty
&& !bMergeEmpty
&& nX
< nX1
&& !bOverlapped
)
1532 while (nTempX
> 0 && IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1535 if ( nTempX
< nX1
&&
1536 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1537 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX1
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1545 // Rest of a long text further to the right?
1548 if ( bEmpty
&& !bMergeEmpty
&& nX
== nX2
&& !bOverlapped
)
1550 // don't have to look further than nLastContentCol
1553 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
1557 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
1558 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
1566 // normal visible cell
1573 // don't output the cell that's being edited
1576 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
1579 // skip text in cell if data bar/icon set is set and only value selected
1582 if(pInfo
->pDataBar
&& !pInfo
->pDataBar
->mbShowValue
)
1584 if(pInfo
->pIconSet
&& !pInfo
->pIconSet
->mbShowValue
)
1589 // output the cell text
1592 ScRefCellValue aCell
;
1595 if ( nCellY
== nY
&& nCellX
== nX
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1596 aCell
= pThisRowInfo
->pCellInfo
[nCellX
+1].maCell
;
1598 GetVisibleCell( nCellX
, nCellY
, nTab
, aCell
); // get from document
1599 if (aCell
.isEmpty())
1601 else if (aCell
.meType
== CELLTYPE_EDIT
)
1605 // Check if this cell is mis-spelled.
1606 if (bDoCell
&& !bNeedEdit
&& aCell
.meType
== CELLTYPE_STRING
)
1608 if (mpSpellCheckCxt
&& mpSpellCheckCxt
->isMisspelled(nCellX
, nCellY
))
1612 if (bDoCell
&& !bNeedEdit
)
1614 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
)
1616 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
1617 pPattern
= rCellInfo
.pPatternAttr
;
1618 pCondSet
= rCellInfo
.pConditionSet
;
1622 // #i68085# pattern from cell info for hidden columns is null,
1623 // test for null is quicker than using column flags
1624 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1625 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1628 else // get from document
1630 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
1631 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
1633 if ( mpDoc
->GetPreviewFont() || mpDoc
->GetPreviewCellStyle() )
1635 aAltPatterns
.push_back(new ScPatternAttr(*pPattern
));
1636 ScPatternAttr
* pAltPattern
= &aAltPatterns
.back();
1637 if ( ScStyleSheet
* pPreviewStyle
= mpDoc
->GetPreviewCellStyle( nCellX
, nCellY
, nTab
) )
1639 pAltPattern
->SetStyleSheet(pPreviewStyle
);
1641 else if ( SfxItemSet
* pFontSet
= mpDoc
->GetPreviewFont( nCellX
, nCellY
, nTab
) )
1643 const SfxPoolItem
* pItem
;
1644 if ( pFontSet
->GetItemState( ATTR_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1645 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1646 if ( pFontSet
->GetItemState( ATTR_CJK_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1647 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1648 if ( pFontSet
->GetItemState( ATTR_CTL_FONT
, true, &pItem
) == SFX_ITEM_SET
)
1649 pAltPattern
->GetItemSet().Put( (const SvxFontItem
&)*pItem
);
1651 pPattern
= pAltPattern
;
1654 if (aCell
.hasNumeric() &&
1655 static_cast<const SfxBoolItem
&>(
1656 pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue())
1658 // Disable line break when the cell content is numeric.
1659 aAltPatterns
.push_back(new ScPatternAttr(*pPattern
));
1660 ScPatternAttr
* pAltPattern
= &aAltPatterns
.back();
1661 SfxBoolItem
aLineBreak(ATTR_LINEBREAK
, false);
1662 pAltPattern
->GetItemSet().Put(aLineBreak
);
1663 pPattern
= pAltPattern
;
1666 sal_uInt8 nScript
= mpDoc
->GetCellScriptType(
1667 ScAddress(nCellX
, nCellY
, nTab
),
1668 pPattern
->GetNumberFormat(mpDoc
->GetFormatTable(), pCondSet
));
1671 nScript
= ScGlobal::GetDefaultScriptType();
1673 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
||
1674 nScript
!= nOldScript
|| mbSyntaxMode
)
1676 if ( StringDiffer(pOldPattern
,pPattern
) ||
1677 pCondSet
!= pOldCondSet
|| nScript
!= nOldScript
|| mbSyntaxMode
)
1679 aVars
.SetPattern(pPattern
, pCondSet
, aCell
, nScript
);
1682 aVars
.SetPatternSimple( pPattern
, pCondSet
);
1683 pOldPattern
= pPattern
;
1684 pOldCondSet
= pCondSet
;
1685 nOldScript
= nScript
;
1688 // use edit engine for rotated, stacked or mixed-script text
1689 if ( aVars
.GetOrient() == SVX_ORIENTATION_STACKED
||
1690 aVars
.IsRotated() || IsAmbiguousScript(nScript
) )
1693 if (bDoCell
&& !bNeedEdit
)
1695 bool bFormulaCell
= (aCell
.meType
== CELLTYPE_FORMULA
);
1697 lcl_CreateInterpretProgress(bProgress
, mpDoc
, aCell
.mpFormula
);
1698 if ( aVars
.SetText(aCell
) )
1700 bNeedEdit
= aVars
.HasEditCharacters() || (bFormulaCell
&& aCell
.mpFormula
->IsMultilineResult());
1702 long nTotalMargin
= 0;
1703 SvxCellHorJustify eOutHorJust
= SVX_HOR_JUSTIFY_STANDARD
;
1704 if (bDoCell
&& !bNeedEdit
)
1706 CellType eCellType
= aCell
.meType
;
1707 bCellIsValue
= ( eCellType
== CELLTYPE_VALUE
);
1708 if ( eCellType
== CELLTYPE_FORMULA
)
1710 ScFormulaCell
* pFCell
= aCell
.mpFormula
;
1711 bCellIsValue
= pFCell
->IsRunning() || pFCell
->IsValue();
1714 eOutHorJust
= getAlignmentFromContext( aVars
.GetHorJust(), bCellIsValue
, aVars
.GetString(),
1715 *pPattern
, pCondSet
, mpDoc
, nTab
);
1717 bool bBreak
= ( aVars
.GetLineBreak() || aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
);
1718 // #i111387# #o11817313# disable automatic line breaks only for "General" number format
1719 if (bBreak
&& bCellIsValue
&& (aVars
.GetResultValueFormat() % SV_COUNTRY_LANGUAGE_OFFSET
) == 0)
1722 bool bRepeat
= aVars
.IsRepeat() && !bBreak
;
1723 bool bShrink
= aVars
.IsShrink() && !bBreak
&& !bRepeat
;
1726 static_cast<long>(aVars
.GetLeftTotal() * mnPPTX
) +
1727 static_cast<long>(aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1729 nNeededWidth
= aVars
.GetTextSize().Width() + nTotalMargin
;
1731 // GetOutputArea gives justfied rectangles
1732 GetOutputArea( nX
, nArrY
, nPosX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
1733 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
1734 bCellIsValue
|| bRepeat
|| bShrink
, bBreak
, false,
1737 aVars
.RepeatToFill( aAreaParam
.mnColWidth
- nTotalMargin
);
1740 if ( aVars
.GetOrient() != SVX_ORIENTATION_STANDARD
)
1742 // Only horizontal scaling is handled here.
1743 // DrawEdit is used to vertically scale 90 deg rotated text.
1746 else if ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) // horizontal
1748 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1749 long nScaleSize
= aVars
.GetTextSize().Width(); // without margin
1751 if ( nScaleSize
> 0 ) // 0 if the text is empty (formulas, number formats)
1753 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
1755 aVars
.SetShrinkScale( nScale
, nOldScript
);
1756 long nNewSize
= aVars
.GetTextSize().Width();
1758 sal_uInt16 nShrinkAgain
= 0;
1759 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
1761 // If the text is still too large, reduce the scale again by 10%, until it fits,
1762 // at most 7 times (it's less than 50% of the calculated scale then).
1764 nScale
= ( nScale
* 9 ) / 10;
1765 aVars
.SetShrinkScale( nScale
, nOldScript
);
1766 nNewSize
= aVars
.GetTextSize().Width();
1769 // If even at half the size the font still isn't rendered smaller,
1770 // fall back to normal clipping (showing ### for numbers).
1771 if ( nNewSize
<= nAvailable
)
1772 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1779 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
)
1781 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nTotalMargin
;
1782 long nRepeatSize
= aVars
.GetTextSize().Width(); // without margin
1783 // When formatting for the printer, the text sizes don't always add up.
1784 // Round down (too few repetitions) rather than exceeding the cell size then:
1785 if ( pFmtDevice
!= mpRefDevice
)
1787 if ( nRepeatSize
> 0 )
1789 long nRepeatCount
= nAvailable
/ nRepeatSize
;
1790 if ( nRepeatCount
> 1 )
1792 OUString aCellStr
= aVars
.GetString();
1793 OUString aRepeated
= aCellStr
;
1794 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
1795 aRepeated
+= aCellStr
;
1796 aVars
.SetAutoText( aRepeated
);
1801 // use edit engine if automatic line breaks are needed
1804 if ( aVars
.GetOrient() == SVX_ORIENTATION_STANDARD
)
1805 bNeedEdit
= ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
);
1808 long nHeight
= aVars
.GetTextSize().Height() +
1809 (long)(aVars
.GetMargin()->GetTopMargin()*mnPPTY
) +
1810 (long)(aVars
.GetMargin()->GetBottomMargin()*mnPPTY
);
1811 bNeedEdit
= ( nHeight
> aAreaParam
.maClipRect
.GetHeight() );
1817 aVars
.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK
&&
1818 aVars
.GetHorJustMethod() == SVX_JUSTIFY_METHOD_DISTRIBUTE
;
1823 // mark the cell in CellInfo to be drawn in DrawEdit:
1824 // Cells to the left are marked directly, cells to the
1825 // right are handled by the flag for nX2
1826 SCCOL nMarkX
= ( nCellX
<= nX2
) ? nCellX
: nX2
;
1827 RowInfo
* pMarkRowInfo
= ( nCellY
== nY
) ? pThisRowInfo
: &pRowInfo
[0];
1828 pMarkRowInfo
->pCellInfo
[nMarkX
+1].bEditEngine
= true;
1829 bDoCell
= false; // don't draw here
1833 if ( bCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
1836 aVars
.SetHashText();
1838 // Adjust the decimals to fit the available column width.
1839 aVars
.SetTextToWidthOrHash(aCell
, aAreaParam
.mnColWidth
- nTotalMargin
);
1841 nNeededWidth
= aVars
.GetTextSize().Width() +
1842 (long) ( aVars
.GetLeftTotal() * mnPPTX
) +
1843 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
);
1844 if ( nNeededWidth
<= aAreaParam
.maClipRect
.GetWidth() )
1846 // Cell value is no longer clipped. Reset relevant parameters.
1847 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= false;
1848 aAreaParam
.mnLeftClipLength
= aAreaParam
.mnRightClipLength
= 0;
1851 // If the "###" replacement doesn't fit into the cells, no clip marks
1852 // are shown, as the "###" already denotes too little space.
1853 // The rectangles from the first GetOutputArea call remain valid.
1856 long nJustPosX
= aAreaParam
.maAlignRect
.Left(); // "justified" - effect of alignment will be added
1857 long nJustPosY
= aAreaParam
.maAlignRect
.Top();
1858 long nAvailWidth
= aAreaParam
.maAlignRect
.GetWidth();
1859 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight();
1861 bool bOutside
= ( aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
1862 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
1864 aAreaParam
.maClipRect
.Left() = nScrX
;
1865 aAreaParam
.mbLeftClip
= true;
1867 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
1869 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
1870 aAreaParam
.mbRightClip
= true;
1873 bool bHClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
1874 bool bVClip
= false;
1876 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
1878 aAreaParam
.maClipRect
.Top() = nScrY
;
1881 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
1883 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
1888 // horizontalen Platz testen
1891 bool bRightAdjusted
= false; // to correct text width calculation later
1892 bool bNeedEditEngine
= false;
1893 if ( !bNeedEditEngine
&& !bOutside
)
1895 switch (eOutHorJust
)
1897 case SVX_HOR_JUSTIFY_LEFT
:
1898 nJustPosX
+= (long) ( aVars
.GetLeftTotal() * mnPPTX
);
1900 case SVX_HOR_JUSTIFY_RIGHT
:
1901 nJustPosX
+= nAvailWidth
- aVars
.GetTextSize().Width() -
1902 (long) ( aVars
.GetRightTotal() * mnPPTX
);
1903 bRightAdjusted
= true;
1905 case SVX_HOR_JUSTIFY_CENTER
:
1906 nJustPosX
+= ( nAvailWidth
- aVars
.GetTextSize().Width() +
1907 (long) ( aVars
.GetLeftTotal() * mnPPTX
) -
1908 (long) ( aVars
.GetMargin()->GetRightMargin() * mnPPTX
) ) / 2;
1912 // added to avoid warnings
1916 long nTestClipHeight
= aVars
.GetTextSize().Height();
1917 switch (aVars
.GetVerJust())
1919 case SVX_VER_JUSTIFY_TOP
:
1920 case SVX_VER_JUSTIFY_BLOCK
:
1922 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1924 nTestClipHeight
+= nTop
;
1927 case SVX_VER_JUSTIFY_BOTTOM
:
1929 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1930 nJustPosY
+= nOutHeight
- aVars
.GetTextSize().Height() - nBot
;
1931 nTestClipHeight
+= nBot
;
1934 case SVX_VER_JUSTIFY_CENTER
:
1936 long nTop
= (long)( aVars
.GetMargin()->GetTopMargin() * mnPPTY
);
1937 long nBot
= (long)( aVars
.GetMargin()->GetBottomMargin() * mnPPTY
);
1938 nJustPosY
+= ( nOutHeight
+ nTop
-
1939 aVars
.GetTextSize().Height() - nBot
) / 2;
1940 nTestClipHeight
+= std::abs( nTop
- nBot
);
1945 // added to avoid warnings
1949 if ( nTestClipHeight
> nOutHeight
)
1951 // kein vertikales Clipping beim Drucken von Zellen mit
1952 // optimaler Hoehe, ausser bei Groesse in bedingter Formatierung
1953 if ( eType
!= OUTTYPE_PRINTER
||
1954 ( mpDoc
->GetRowFlags( nCellY
, nTab
) & CR_MANUALSIZE
) ||
1955 ( aVars
.HasCondHeight() ) )
1959 if ( bHClip
|| bVClip
)
1961 // nur die betroffene Dimension clippen,
1962 // damit bei nicht-proportionalem Resize nicht alle
1963 // rechtsbuendigen Zahlen abgeschnitten werden:
1967 aAreaParam
.maClipRect
.Left() = nScrX
;
1968 aAreaParam
.maClipRect
.Right() = nScrX
+nScrW
;
1972 aAreaParam
.maClipRect
.Top() = nScrY
;
1973 aAreaParam
.maClipRect
.Bottom() = nScrY
+nScrH
;
1976 // aClipRect is not used after SetClipRegion/IntersectClipRegion,
1977 // so it can be modified here
1979 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
1984 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
1987 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
1990 Point
aURLStart( nJustPosX
, nJustPosY
); // copy before modifying for orientation
1992 switch (aVars
.GetOrient())
1994 case SVX_ORIENTATION_STANDARD
:
1995 nJustPosY
+= aVars
.GetAscent();
1997 case SVX_ORIENTATION_TOPBOTTOM
:
1998 nJustPosX
+= aVars
.GetTextSize().Width() - aVars
.GetAscent();
2000 case SVX_ORIENTATION_BOTTOMTOP
:
2001 nJustPosY
+= aVars
.GetTextSize().Height();
2002 nJustPosX
+= aVars
.GetAscent();
2006 // added to avoid warnings
2010 // When clipping, the visible part is now completely defined by the alignment,
2011 // there's no more special handling to show the right part of RTL text.
2013 Point
aDrawTextPos( nJustPosX
, nJustPosY
);
2014 if ( bPixelToLogic
)
2016 // undo text width adjustment in pixels
2018 aDrawTextPos
.X() += aVars
.GetTextSize().Width();
2020 aDrawTextPos
= mpRefDevice
->PixelToLogic( aDrawTextPos
);
2022 // redo text width adjustment in logic units
2024 aDrawTextPos
.X() -= aVars
.GetOriginalWidth();
2027 // in Metafiles immer DrawTextArray, damit die Positionen mit
2028 // aufgezeichnet werden (fuer nicht-proportionales Resize):
2030 OUString aString
= aVars
.GetString();
2031 if (!aString
.isEmpty())
2033 // If the string is clipped, make it shorter for
2034 // better performance since drawing by HarfBuzz is
2035 // quite expensive especiall for long string.
2037 OUString aShort
= aString
;
2039 double fVisibleRatio
= 1.0;
2040 double fTextWidth
= aVars
.GetTextSize().Width();
2041 sal_Int32 nTextLen
= aString
.getLength();
2042 if (eOutHorJust
== SVX_HOR_JUSTIFY_LEFT
&& aAreaParam
.mnRightClipLength
> 0)
2044 fVisibleRatio
= (fTextWidth
- aAreaParam
.mnRightClipLength
) / fTextWidth
;
2045 if (0.0 < fVisibleRatio
&& fVisibleRatio
< 1.0)
2047 // Only show the left-end segment.
2048 sal_Int32 nShortLen
= fVisibleRatio
*nTextLen
+ 1;
2049 aShort
= aShort
.copy(0, nShortLen
);
2052 else if (eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
&& aAreaParam
.mnLeftClipLength
> 0)
2054 fVisibleRatio
= (fTextWidth
- aAreaParam
.mnLeftClipLength
) / fTextWidth
;
2055 if (0.0 < fVisibleRatio
&& fVisibleRatio
< 1.0)
2057 // Only show the right-end segment.
2058 sal_Int32 nShortLen
= fVisibleRatio
*nTextLen
+ 1;
2059 aShort
= aShort
.copy(nTextLen
-nShortLen
);
2061 // Adjust the text position after shortening of the string.
2062 double fShortWidth
= pFmtDevice
->GetTextWidth(aShort
);
2063 double fOffset
= fTextWidth
- fShortWidth
;
2064 aDrawTextPos
.Move(fOffset
, 0);
2068 if (bMetaFile
|| pFmtDevice
!= mpDev
|| aZoomX
!= aZoomY
)
2070 size_t nLen
= aShort
.getLength();
2071 if (aDX
.size() < nLen
)
2072 aDX
.resize(nLen
, 0);
2074 pFmtDevice
->GetTextArray(aShort
, &aDX
[0]);
2076 if ( !mpRefDevice
->GetConnectMetaFile() ||
2077 mpRefDevice
->GetOutDevType() == OUTDEV_PRINTER
)
2079 double fMul
= GetStretch();
2080 for (size_t i
= 0; i
< nLen
; ++i
)
2081 aDX
[i
] = static_cast<sal_Int32
>(aDX
[i
] / fMul
+ 0.5);
2084 mpDev
->DrawTextArray(aDrawTextPos
, aShort
, &aDX
[0]);
2087 mpDev
->DrawText(aDrawTextPos
, aShort
);
2090 if ( bHClip
|| bVClip
)
2095 mpDev
->SetClipRegion();
2098 // PDF: whole-cell hyperlink from formula?
2099 bool bHasURL
= pPDFData
&& aCell
.meType
== CELLTYPE_FORMULA
&& aCell
.mpFormula
->IsHyperLinkCell();
2102 Rectangle
aURLRect( aURLStart
, aVars
.GetTextSize() );
2103 lcl_DoHyperlinkResult(mpDev
, aURLRect
, aCell
);
2107 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
2110 nPosY
+= pRowInfo
[nArrY
].nHeight
;
2113 ScProgress::DeleteInterpretProgress();
2116 ScFieldEditEngine
* ScOutputData::CreateOutputEditEngine()
2118 ScFieldEditEngine
* pEngine
= new ScFieldEditEngine(mpDoc
, mpDoc
->GetEnginePool());
2119 pEngine
->SetUpdateMode( false );
2120 // a RefDevice always has to be set, otherwise EditEngine would create a VirtualDevice
2121 pEngine
->SetRefDevice( pFmtDevice
);
2122 sal_uLong nCtrl
= pEngine
->GetControlWord();
2123 if ( bShowSpellErrors
)
2124 nCtrl
|= EE_CNTRL_ONLINESPELLING
;
2125 if ( eType
== OUTTYPE_PRINTER
)
2126 nCtrl
&= ~EE_CNTRL_MARKFIELDS
;
2127 if ( eType
== OUTTYPE_WINDOW
&& mpRefDevice
== pFmtDevice
)
2128 nCtrl
&= ~EE_CNTRL_FORMAT100
; // use the actual MapMode
2129 pEngine
->SetControlWord( nCtrl
);
2130 mpDoc
->ApplyAsianEditSettings( *pEngine
);
2131 pEngine
->EnableAutoColor( mbUseStyleColor
);
2132 pEngine
->SetDefaultHorizontalTextDirection( (EEHorizontalTextDirection
)mpDoc
->GetEditTextDirection( nTab
) );
2136 static void lcl_ClearEdit( EditEngine
& rEngine
) // Text und Attribute
2138 rEngine
.SetUpdateMode( false );
2140 rEngine
.SetText(EMPTY_OUSTRING
);
2141 // keine Para-Attribute uebrigbehalten...
2142 const SfxItemSet
& rPara
= rEngine
.GetParaAttribs(0);
2144 rEngine
.SetParaAttribs( 0,
2145 SfxItemSet( *rPara
.GetPool(), rPara
.GetRanges() ) );
2148 static bool lcl_SafeIsValue( ScRefCellValue
& rCell
)
2150 switch (rCell
.meType
)
2152 case CELLTYPE_VALUE
:
2154 case CELLTYPE_FORMULA
:
2156 ScFormulaCell
* pFCell
= rCell
.mpFormula
;
2157 if (pFCell
->IsRunning() || pFCell
->IsValue())
2163 // added to avoid warnings
2169 static void lcl_ScaleFonts( EditEngine
& rEngine
, long nPercent
)
2171 bool bUpdateMode
= rEngine
.GetUpdateMode();
2173 rEngine
.SetUpdateMode( false );
2175 sal_Int32 nParCount
= rEngine
.GetParagraphCount();
2176 for (sal_Int32 nPar
=0; nPar
<nParCount
; nPar
++)
2178 std::vector
<sal_Int32
> aPortions
;
2179 rEngine
.GetPortions( nPar
, aPortions
);
2181 sal_Int32 nStart
= 0;
2182 for ( std::vector
<sal_Int32
>::const_iterator
it(aPortions
.begin()); it
!= aPortions
.end(); ++it
)
2184 sal_Int32 nEnd
= *it
;
2185 ESelection
aSel( nPar
, nStart
, nPar
, nEnd
);
2186 SfxItemSet aAttribs
= rEngine
.GetAttribs( aSel
);
2188 long nWestern
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT
)).GetHeight();
2189 long nCJK
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CJK
)).GetHeight();
2190 long nCTL
= static_cast<const SvxFontHeightItem
&>(aAttribs
.Get(EE_CHAR_FONTHEIGHT_CTL
)).GetHeight();
2192 nWestern
= ( nWestern
* nPercent
) / 100;
2193 nCJK
= ( nCJK
* nPercent
) / 100;
2194 nCTL
= ( nCTL
* nPercent
) / 100;
2196 aAttribs
.Put( SvxFontHeightItem( nWestern
, 100, EE_CHAR_FONTHEIGHT
) );
2197 aAttribs
.Put( SvxFontHeightItem( nCJK
, 100, EE_CHAR_FONTHEIGHT_CJK
) );
2198 aAttribs
.Put( SvxFontHeightItem( nCTL
, 100, EE_CHAR_FONTHEIGHT_CTL
) );
2200 rEngine
.QuickSetAttribs( aAttribs
, aSel
); //! remove paragraph attributes from aAttribs?
2207 rEngine
.SetUpdateMode( true );
2210 static long lcl_GetEditSize( EditEngine
& rEngine
, bool bWidth
, bool bSwap
, long nAttrRotate
)
2217 long nRealWidth
= (long) rEngine
.CalcTextWidth();
2218 long nRealHeight
= rEngine
.GetTextHeight();
2220 // assuming standard mode, otherwise width isn't used
2222 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100th degrees
2223 double nAbsCos
= fabs( cos( nRealOrient
) );
2224 double nAbsSin
= fabs( sin( nRealOrient
) );
2226 return (long) ( nRealWidth
* nAbsCos
+ nRealHeight
* nAbsSin
);
2228 return (long) ( nRealHeight
* nAbsCos
+ nRealWidth
* nAbsSin
);
2231 return (long) rEngine
.CalcTextWidth();
2233 return rEngine
.GetTextHeight();
2237 void ScOutputData::ShrinkEditEngine( EditEngine
& rEngine
, const Rectangle
& rAlignRect
,
2238 long nLeftM
, long nTopM
, long nRightM
, long nBottomM
,
2239 bool bWidth
, sal_uInt16 nOrient
, long nAttrRotate
, bool bPixelToLogic
,
2240 long& rEngineWidth
, long& rEngineHeight
, long& rNeededPixel
, bool& rLeftClip
, bool& rRightClip
)
2246 long nScaleSize
= bPixelToLogic
?
2247 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2249 // Don't scale if it fits already.
2250 // Allowing to extend into the margin, to avoid scaling at optimal height.
2251 if ( nScaleSize
<= rAlignRect
.GetHeight() )
2254 bool bSwap
= ( nOrient
== SVX_ORIENTATION_TOPBOTTOM
|| nOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2255 long nAvailable
= rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2256 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2258 lcl_ScaleFonts( rEngine
, nScale
);
2259 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2260 long nNewSize
= bPixelToLogic
?
2261 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2263 sal_uInt16 nShrinkAgain
= 0;
2264 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2266 // further reduce, like in DrawStrings
2267 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2268 rEngineHeight
= lcl_GetEditSize( rEngine
, false, bSwap
, nAttrRotate
);
2269 nNewSize
= bPixelToLogic
?
2270 mpRefDevice
->LogicToPixel(Size(0,rEngineHeight
)).Height() : rEngineHeight
;
2274 // sizes for further processing (alignment etc):
2275 rEngineWidth
= lcl_GetEditSize( rEngine
, true, bSwap
, nAttrRotate
);
2276 long nPixelWidth
= bPixelToLogic
?
2277 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2278 rNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
2280 else if ( rLeftClip
|| rRightClip
)
2284 long nAvailable
= rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2285 long nScaleSize
= rNeededPixel
- nLeftM
- nRightM
; // without margin
2287 if ( nScaleSize
<= nAvailable
)
2290 long nScale
= ( nAvailable
* 100 ) / nScaleSize
;
2292 lcl_ScaleFonts( rEngine
, nScale
);
2293 rEngineWidth
= lcl_GetEditSize( rEngine
, true, false, nAttrRotate
);
2294 long nNewSize
= bPixelToLogic
?
2295 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2297 sal_uInt16 nShrinkAgain
= 0;
2298 while ( nNewSize
> nAvailable
&& nShrinkAgain
< SC_SHRINKAGAIN_MAX
)
2300 // further reduce, like in DrawStrings
2301 lcl_ScaleFonts( rEngine
, 90 ); // reduce by 10%
2302 rEngineWidth
= lcl_GetEditSize( rEngine
, true, false, nAttrRotate
);
2303 nNewSize
= bPixelToLogic
?
2304 mpRefDevice
->LogicToPixel(Size(rEngineWidth
,0)).Width() : rEngineWidth
;
2307 if ( nNewSize
<= nAvailable
)
2308 rLeftClip
= rRightClip
= false;
2310 // sizes for further processing (alignment etc):
2311 rNeededPixel
= nNewSize
+ nLeftM
+ nRightM
;
2312 rEngineHeight
= lcl_GetEditSize( rEngine
, false, false, nAttrRotate
);
2316 ScOutputData::DrawEditParam::DrawEditParam(const ScPatternAttr
* pPattern
, const SfxItemSet
* pCondSet
, bool bCellIsValue
) :
2317 meHorJustAttr( lcl_GetValue
<SvxHorJustifyItem
, SvxCellHorJustify
>(*pPattern
, ATTR_HOR_JUSTIFY
, pCondSet
) ),
2318 meHorJustContext( meHorJustAttr
),
2319 meHorJustResult( meHorJustAttr
),
2320 meVerJust( lcl_GetValue
<SvxVerJustifyItem
, SvxCellVerJustify
>(*pPattern
, ATTR_VER_JUSTIFY
, pCondSet
) ),
2321 meHorJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_HOR_JUSTIFY_METHOD
, pCondSet
) ),
2322 meVerJustMethod( lcl_GetValue
<SvxJustifyMethodItem
, SvxCellJustifyMethod
>(*pPattern
, ATTR_VER_JUSTIFY_METHOD
, pCondSet
) ),
2323 meOrient( pPattern
->GetCellOrientation(pCondSet
) ),
2325 mnX(0), mnY(0), mnCellX(0), mnCellY(0), mnTab(0),
2326 mnPosX(0), mnPosY(0), mnInitPosX(0),
2327 mbBreak( (meHorJustAttr
== SVX_HOR_JUSTIFY_BLOCK
) || lcl_GetBoolValue(*pPattern
, ATTR_LINEBREAK
, pCondSet
) ),
2328 mbCellIsValue(bCellIsValue
),
2329 mbAsianVertical(false),
2330 mbPixelToLogic(false),
2331 mbHyphenatorSet(false),
2333 mpPattern(pPattern
),
2334 mpCondSet(pCondSet
),
2335 mpPreviewFontSet(NULL
),
2338 mpOldPreviewFontSet(NULL
),
2339 mpThisRowInfo(NULL
),
2340 mpMisspellRanges(NULL
)
2343 bool ScOutputData::DrawEditParam::readCellContent(
2344 ScDocument
* pDoc
, bool bShowNullValues
, bool bShowFormulas
, bool bSyntaxMode
, bool bUseStyleColor
, bool bForceAutoColor
, bool& rWrapFields
)
2346 if (maCell
.meType
== CELLTYPE_EDIT
)
2348 const EditTextObject
* pData
= maCell
.mpEditText
;
2351 mpEngine
->SetText(*pData
);
2353 if ( mbBreak
&& !mbAsianVertical
&& pData
->HasField() )
2355 // Fields aren't wrapped, so clipping is enabled to prevent
2356 // a field from being drawn beyond the cell size
2363 OSL_FAIL("pData == 0");
2369 sal_uLong nFormat
= mpPattern
->GetNumberFormat(
2370 pDoc
->GetFormatTable(), mpCondSet
);
2373 ScCellFormat::GetString( maCell
,
2374 nFormat
,aString
, &pColor
,
2375 *pDoc
->GetFormatTable(),
2381 mpEngine
->SetText(aString
);
2382 if ( pColor
&& !bSyntaxMode
&& !( bUseStyleColor
&& bForceAutoColor
) )
2383 lcl_SetEditColor( *mpEngine
, *pColor
);
2386 if (mpMisspellRanges
)
2387 mpEngine
->SetAllMisspellRanges(*mpMisspellRanges
);
2392 void ScOutputData::DrawEditParam::setPatternToEngine(bool bUseStyleColor
)
2394 // syntax highlighting mode is ignored here
2395 // StringDiffer doesn't look at hyphenate, language items
2397 if (mpPattern
== mpOldPattern
&& mpCondSet
== mpOldCondSet
&& mpPreviewFontSet
== mpOldPreviewFontSet
)
2400 sal_Int32 nConfBackColor
= SC_MOD()->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
2401 bool bCellContrast
= bUseStyleColor
&&
2402 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
2404 SfxItemSet
* pSet
= new SfxItemSet( mpEngine
->GetEmptyItemSet() );
2405 mpPattern
->FillEditItemSet( pSet
, mpCondSet
);
2406 if ( mpPreviewFontSet
)
2408 const SfxPoolItem
* pItem
;
2409 if ( mpPreviewFontSet
->GetItemState( ATTR_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2411 SvxFontItem
aFontItem(EE_CHAR_FONTINFO
);
2412 aFontItem
= (const SvxFontItem
&)*pItem
;
2413 pSet
->Put( aFontItem
);
2415 if ( mpPreviewFontSet
->GetItemState( ATTR_CJK_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2417 SvxFontItem
aCjkFontItem(EE_CHAR_FONTINFO_CJK
);
2418 aCjkFontItem
= (const SvxFontItem
&)*pItem
;
2419 pSet
->Put( aCjkFontItem
);
2421 if ( mpPreviewFontSet
->GetItemState( ATTR_CTL_FONT
, true, &pItem
) == SFX_ITEM_SET
)
2423 SvxFontItem
aCtlFontItem(EE_CHAR_FONTINFO_CTL
);
2424 aCtlFontItem
= (const SvxFontItem
&)*pItem
;
2425 pSet
->Put( aCtlFontItem
);
2428 mpEngine
->SetDefaults( pSet
);
2429 mpOldPattern
= mpPattern
;
2430 mpOldCondSet
= mpCondSet
;
2431 mpOldPreviewFontSet
= mpPreviewFontSet
;
2433 sal_uLong nControl
= mpEngine
->GetControlWord();
2434 if (meOrient
== SVX_ORIENTATION_STACKED
)
2435 nControl
|= EE_CNTRL_ONECHARPERLINE
;
2437 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
2438 mpEngine
->SetControlWord( nControl
);
2440 if ( !mbHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
2442 // set hyphenator the first time it is needed
2443 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
2444 mpEngine
->SetHyphenator( xXHyphenator
);
2445 mbHyphenatorSet
= true;
2448 Color aBackCol
= ((const SvxBrushItem
&)mpPattern
->GetItem( ATTR_BACKGROUND
, mpCondSet
)).GetColor();
2449 if ( bUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
2450 aBackCol
.SetColor( nConfBackColor
);
2451 mpEngine
->SetBackgroundColor( aBackCol
);
2454 void ScOutputData::DrawEditParam::calcMargins(long& rTopM
, long& rLeftM
, long& rBottomM
, long& rRightM
, double nPPTX
, double nPPTY
) const
2456 const SvxMarginItem
& rMargin
=
2457 static_cast<const SvxMarginItem
&>(mpPattern
->GetItem(ATTR_MARGIN
, mpCondSet
));
2459 sal_uInt16 nIndent
= 0;
2460 if (meHorJustAttr
== SVX_HOR_JUSTIFY_LEFT
|| meHorJustAttr
== SVX_HOR_JUSTIFY_RIGHT
)
2461 nIndent
= lcl_GetValue
<SfxUInt16Item
, sal_uInt16
>(*mpPattern
, ATTR_INDENT
, mpCondSet
);
2463 rLeftM
= static_cast<long>(((rMargin
.GetLeftMargin() + nIndent
) * nPPTX
));
2464 rTopM
= static_cast<long>((rMargin
.GetTopMargin() * nPPTY
));
2465 rRightM
= static_cast<long>((rMargin
.GetRightMargin() * nPPTX
));
2466 rBottomM
= static_cast<long>((rMargin
.GetBottomMargin() * nPPTY
));
2467 if(meHorJustAttr
== SVX_HOR_JUSTIFY_RIGHT
)
2469 rLeftM
= static_cast<long>((rMargin
.GetLeftMargin() * nPPTX
));
2470 rRightM
= static_cast<long>(((rMargin
.GetRightMargin() + nIndent
) * nPPTX
));
2474 void ScOutputData::DrawEditParam::calcPaperSize(
2475 Size
& rPaperSize
, const Rectangle
& rAlignRect
, double nPPTX
, double nPPTY
) const
2477 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2478 calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, nPPTX
, nPPTY
);
2480 if (isVerticallyOriented())
2482 rPaperSize
.Width() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2483 rPaperSize
.Height() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2487 rPaperSize
.Width() = rAlignRect
.GetWidth() - nLeftM
- nRightM
;
2488 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2491 if (mbAsianVertical
)
2493 rPaperSize
.Height() = rAlignRect
.GetHeight() - nTopM
- nBottomM
;
2494 // Subtract some extra value from the height or else the text would go
2495 // outside the cell area. The value of 5 is arbitrary, and is based
2496 // entirely on heuristics.
2497 rPaperSize
.Height() -= 5;
2501 void ScOutputData::DrawEditParam::getEngineSize(ScFieldEditEngine
* pEngine
, long& rWidth
, long& rHeight
) const
2503 long nEngineWidth
= 0;
2504 if (!mbBreak
|| meOrient
== SVX_ORIENTATION_STACKED
|| mbAsianVertical
)
2505 nEngineWidth
= static_cast<long>(pEngine
->CalcTextWidth());
2507 long nEngineHeight
= pEngine
->GetTextHeight();
2509 if (isVerticallyOriented())
2511 long nTemp
= nEngineWidth
;
2512 nEngineWidth
= nEngineHeight
;
2513 nEngineHeight
= nTemp
;
2516 if (meOrient
== SVX_ORIENTATION_STACKED
)
2517 nEngineWidth
= nEngineWidth
* 11 / 10;
2519 rWidth
= nEngineWidth
;
2520 rHeight
= nEngineHeight
;
2523 bool ScOutputData::DrawEditParam::hasLineBreak() const
2525 return (mbBreak
|| (meOrient
== SVX_ORIENTATION_STACKED
) || mbAsianVertical
);
2528 bool ScOutputData::DrawEditParam::isHyperlinkCell() const
2530 if (maCell
.meType
!= CELLTYPE_FORMULA
)
2533 return maCell
.mpFormula
->IsHyperLinkCell();
2536 bool ScOutputData::DrawEditParam::isVerticallyOriented() const
2538 return (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| meOrient
== SVX_ORIENTATION_BOTTOMTOP
);
2541 void ScOutputData::DrawEditParam::calcStartPosForVertical(
2542 Point
& rLogicStart
, long nCellWidth
, long nEngineWidth
, long nTopM
, OutputDevice
* pRefDevice
)
2544 OSL_ENSURE(isVerticallyOriented(), "Use this only for vertically oriented cell!");
2547 rLogicStart
= pRefDevice
->PixelToLogic(rLogicStart
);
2551 // vertical adjustment is within the EditEngine
2553 rLogicStart
.Y() += pRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
2555 rLogicStart
.Y() += nTopM
;
2557 switch (meHorJustResult
)
2559 case SVX_HOR_JUSTIFY_CENTER
:
2560 rLogicStart
.X() += (nCellWidth
- nEngineWidth
) / 2;
2562 case SVX_HOR_JUSTIFY_RIGHT
:
2563 rLogicStart
.X() += nCellWidth
- nEngineWidth
;
2571 void ScOutputData::DrawEditParam::setAlignmentToEngine()
2573 if (isVerticallyOriented() || mbAsianVertical
)
2575 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2578 case SVX_VER_JUSTIFY_TOP
:
2579 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2580 SVX_ADJUST_LEFT
: SVX_ADJUST_RIGHT
;
2582 case SVX_VER_JUSTIFY_CENTER
:
2583 eSvxAdjust
= SVX_ADJUST_CENTER
;
2585 case SVX_VER_JUSTIFY_BOTTOM
:
2586 case SVX_VER_JUSTIFY_STANDARD
:
2587 eSvxAdjust
= (meOrient
== SVX_ORIENTATION_TOPBOTTOM
|| mbAsianVertical
) ?
2588 SVX_ADJUST_RIGHT
: SVX_ADJUST_LEFT
;
2590 case SVX_VER_JUSTIFY_BLOCK
:
2591 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2595 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2596 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2598 if (meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
2599 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2603 // horizontal alignment now may depend on cell content
2604 // (for values with number formats with mixed script types)
2605 // -> always set adjustment
2607 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
2608 if (meOrient
== SVX_ORIENTATION_STACKED
)
2609 eSvxAdjust
= SVX_ADJUST_CENTER
;
2612 if (meOrient
== SVX_ORIENTATION_STANDARD
)
2613 switch (meHorJustResult
)
2615 case SVX_HOR_JUSTIFY_REPEAT
: // repeat is not yet implemented
2616 case SVX_HOR_JUSTIFY_STANDARD
:
2617 assert(!"meHorJustResult does not match getAlignmentFromContext()");
2619 case SVX_HOR_JUSTIFY_LEFT
:
2620 eSvxAdjust
= SVX_ADJUST_LEFT
;
2622 case SVX_HOR_JUSTIFY_CENTER
:
2623 eSvxAdjust
= SVX_ADJUST_CENTER
;
2625 case SVX_HOR_JUSTIFY_RIGHT
:
2626 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2628 case SVX_HOR_JUSTIFY_BLOCK
:
2629 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2635 case SVX_VER_JUSTIFY_TOP
:
2636 eSvxAdjust
= SVX_ADJUST_RIGHT
;
2638 case SVX_VER_JUSTIFY_CENTER
:
2639 eSvxAdjust
= SVX_ADJUST_CENTER
;
2641 case SVX_VER_JUSTIFY_BOTTOM
:
2642 case SVX_VER_JUSTIFY_STANDARD
:
2643 eSvxAdjust
= SVX_ADJUST_LEFT
;
2645 case SVX_VER_JUSTIFY_BLOCK
:
2646 eSvxAdjust
= SVX_ADJUST_BLOCK
;
2651 mpEngine
->SetDefaultItem( SvxAdjustItem(eSvxAdjust
, EE_PARA_JUST
) );
2653 if (mbAsianVertical
)
2655 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meVerJustMethod
, EE_PARA_JUST_METHOD
) );
2656 if (meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
2657 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2661 mpEngine
->SetDefaultItem( SvxJustifyMethodItem(meHorJustMethod
, EE_PARA_JUST_METHOD
) );
2662 if (meVerJust
== SVX_VER_JUSTIFY_BLOCK
)
2663 mpEngine
->SetDefaultItem( SvxVerJustifyItem(SVX_VER_JUSTIFY_BLOCK
, EE_PARA_VER_JUST
) );
2667 mpEngine
->SetVertical(mbAsianVertical
);
2668 if (maCell
.meType
== CELLTYPE_EDIT
)
2670 // We need to synchronize the vertical mode in the EditTextObject
2671 // instance too. No idea why we keep this state in two separate
2673 const EditTextObject
* pData
= maCell
.mpEditText
;
2675 const_cast<EditTextObject
*>(pData
)->SetVertical(mbAsianVertical
);
2679 bool ScOutputData::DrawEditParam::adjustHorAlignment(ScFieldEditEngine
* pEngine
)
2681 if (meHorJustResult
== SVX_HOR_JUSTIFY_RIGHT
|| meHorJustResult
== SVX_HOR_JUSTIFY_CENTER
)
2683 SvxAdjust eEditAdjust
= (meHorJustResult
== SVX_HOR_JUSTIFY_CENTER
) ?
2684 SVX_ADJUST_CENTER
: SVX_ADJUST_RIGHT
;
2686 pEngine
->SetUpdateMode(false);
2687 pEngine
->SetDefaultItem( SvxAdjustItem(eEditAdjust
, EE_PARA_JUST
) );
2688 pEngine
->SetUpdateMode(true);
2694 void ScOutputData::DrawEditParam::adjustForRTL()
2696 if (!mpEngine
->IsRightToLeft(0))
2700 // For right-to-left, EditEngine always calculates its lines
2701 // beginning from the right edge, but EditLine::nStartPosX is
2702 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
2703 Size aLogicPaper
= mpEngine
->GetPaperSize();
2704 if ( aLogicPaper
.Width() > USHRT_MAX
)
2706 aLogicPaper
.Width() = USHRT_MAX
;
2707 mpEngine
->SetPaperSize(aLogicPaper
);
2711 void ScOutputData::DrawEditParam::adjustForHyperlinkInPDF(Point aURLStart
, OutputDevice
* pDev
)
2713 // PDF: whole-cell hyperlink from formula?
2714 vcl::PDFExtOutDevData
* pPDFData
= PTR_CAST( vcl::PDFExtOutDevData
, pDev
->GetExtOutDevData() );
2715 bool bHasURL
= pPDFData
&& isHyperlinkCell();
2719 long nURLWidth
= (long) mpEngine
->CalcTextWidth();
2720 long nURLHeight
= mpEngine
->GetTextHeight();
2723 Size aPaper
= mpEngine
->GetPaperSize();
2724 if ( mbAsianVertical
)
2725 nURLHeight
= aPaper
.Height();
2727 nURLWidth
= aPaper
.Width();
2729 if (isVerticallyOriented())
2730 std::swap( nURLWidth
, nURLHeight
);
2731 else if (mbAsianVertical
)
2732 aURLStart
.X() -= nURLWidth
;
2734 Rectangle
aURLRect( aURLStart
, Size( nURLWidth
, nURLHeight
) );
2735 lcl_DoHyperlinkResult(pDev
, aURLRect
, maCell
);
2738 void ScOutputData::DrawEditStandard(DrawEditParam
& rParam
)
2740 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
2741 OSL_ASSERT(!rParam
.mbAsianVertical
);
2743 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
2745 bool bHidden
= false;
2746 bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
2747 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
2748 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
2750 if ( rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
)
2752 // ignore orientation/rotation if "repeat" is active
2753 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
2756 // #i31843# "repeat" with "line breaks" is treated as default alignment
2757 // (but rotation is still disabled).
2758 // Default again leads to context dependent alignment instead of
2759 // SVX_HOR_JUSTIFY_STANDARD.
2760 if ( rParam
.mbBreak
)
2761 rParam
.meHorJustResult
= rParam
.meHorJustContext
;
2766 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
2767 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
2768 bHidden
= true; // gedreht wird getrennt ausgegeben
2774 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
2776 //! mirror margin values for RTL?
2777 //! move margin down to after final GetOutputArea call
2778 long nTopM
, nLeftM
, nBottomM
, nRightM
;
2779 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
2781 SCCOL nXForPos
= rParam
.mnX
;
2782 if ( nXForPos
< nX1
)
2785 rParam
.mnPosX
= rParam
.mnInitPosX
;
2787 SCSIZE nArrYForPos
= rParam
.mnArrY
;
2788 if ( nArrYForPos
< 1 )
2791 rParam
.mnPosY
= nScrY
;
2794 OutputAreaParam aAreaParam
;
2797 // Initial page size - large for normal text, cell size for automatic line breaks
2800 Size aPaperSize
= Size( 1000000, 1000000 );
2803 // call GetOutputArea with nNeeded=0, to get only the cell width
2805 //! handle nArrY == 0
2806 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
2807 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2808 rParam
.mbCellIsValue
, true, false, aAreaParam
);
2810 //! special ScEditUtil handling if formatting for printer
2811 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
2813 if (rParam
.mbPixelToLogic
)
2815 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
2816 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
2818 // #i85342# screen display and formatting for printer,
2819 // use same GetEditArea call as in ScViewData::SetEditEngine
2821 Fraction
aFract(1,1);
2822 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
2823 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
2824 aLogicSize
.Width() = aUtilRect
.GetWidth();
2826 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
2829 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2832 // Fill the EditEngine (cell attributes and text)
2835 // default alignment for asian vertical mode is top-right
2836 if ( rParam
.mbAsianVertical
&& rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
2837 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
2839 rParam
.setPatternToEngine(mbUseStyleColor
);
2840 rParam
.setAlignmentToEngine();
2842 // Read content from cell
2844 bool bWrapFields
= false;
2845 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
2846 // Failed to read cell content. Bail out.
2850 SetEditSyntaxColor(*rParam
.mpEngine
, rParam
.maCell
);
2851 else if ( mbUseStyleColor
&& mbForceAutoColor
)
2852 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
2854 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
2857 // Get final output area using the calculated width
2860 long nEngineWidth
, nEngineHeight
;
2861 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
2863 long nNeededPixel
= nEngineWidth
;
2864 if (rParam
.mbPixelToLogic
)
2865 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
2866 nNeededPixel
+= nLeftM
+ nRightM
;
2868 if (!rParam
.mbBreak
|| bShrink
)
2870 // for break, the first GetOutputArea call is sufficient
2871 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
2872 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
2873 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
2877 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
2878 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
2879 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
2880 nEngineWidth
, nEngineHeight
, nNeededPixel
,
2881 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
2883 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
2885 // First check if twice the space for the formatted text is available
2886 // (otherwise just keep it unchanged).
2888 long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
2889 long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
2890 if ( nAvailable
>= 2 * nFormatted
)
2892 // "repeat" is handled with unformatted text (for performance reasons)
2893 OUString aCellStr
= rParam
.mpEngine
->GetText();
2894 rParam
.mpEngine
->SetText( aCellStr
);
2896 long nRepeatSize
= (long) rParam
.mpEngine
->CalcTextWidth();
2897 if (rParam
.mbPixelToLogic
)
2898 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
2899 if ( pFmtDevice
!= mpRefDevice
)
2901 if ( nRepeatSize
> 0 )
2903 long nRepeatCount
= nAvailable
/ nRepeatSize
;
2904 if ( nRepeatCount
> 1 )
2906 OUString aRepeated
= aCellStr
;
2907 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
2908 aRepeated
+= aCellStr
;
2909 rParam
.mpEngine
->SetText( aRepeated
);
2911 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
2912 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2913 if (rParam
.mbPixelToLogic
)
2914 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2916 nNeededPixel
= nEngineWidth
;
2917 nNeededPixel
+= nLeftM
+ nRightM
;
2923 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
2925 rParam
.mpEngine
->SetText(OUString("###"));
2926 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
2927 if (rParam
.mbPixelToLogic
)
2928 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
2930 nNeededPixel
= nEngineWidth
;
2931 nNeededPixel
+= nLeftM
+ nRightM
;
2933 // No clip marks if "###" doesn't fit (same as in DrawStrings)
2936 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
2938 aPaperSize
.Width() = nNeededPixel
+ 1;
2939 if (rParam
.mbPixelToLogic
)
2940 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
2942 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
2946 long nStartX
= aAreaParam
.maAlignRect
.Left();
2947 long nStartY
= aAreaParam
.maAlignRect
.Top();
2948 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
2949 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
2950 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
2954 // text with automatic breaks is aligned only within the
2955 // edit engine's paper size, the output of the whole area
2956 // is always left-aligned
2962 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
2963 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
2964 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
2965 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
2970 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
2974 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
2976 aAreaParam
.maClipRect
.Left() = nScrX
;
2977 aAreaParam
.mbLeftClip
= true;
2979 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
2981 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
2982 aAreaParam
.mbRightClip
= true;
2985 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
2986 bool bSimClip
= false;
2990 // Fields in a cell with automatic breaks: clip to cell width
2994 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
2996 aAreaParam
.maClipRect
.Top() = nScrY
;
2999 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3001 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3005 Size aCellSize
; // output area, excluding margins, in logical units
3006 if (rParam
.mbPixelToLogic
)
3007 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
3009 aCellSize
= Size( nOutWidth
, nOutHeight
);
3011 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
3013 const ScMergeAttr
* pMerge
=
3014 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
3015 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
3017 // Don't clip for text height when printing rows with optimal height,
3018 // except when font size is from conditional formatting.
3019 //! Allow clipping when vertically merged?
3020 if ( eType
!= OUTTYPE_PRINTER
||
3021 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
3022 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
3023 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
3028 // Show clip marks if height is at least 5pt too small and
3029 // there are several lines of text.
3030 // Not for asian vertical text, because that would interfere
3031 // with the default right position of the text.
3032 // Only with automatic line breaks, to avoid having to find
3033 // the cells with the horizontal end of the text again.
3034 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
3035 rParam
.mbBreak
&& bMarkClipped
&&
3036 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3038 CellInfo
* pClipMarkCell
= NULL
;
3041 // anywhere in the merged area...
3042 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3043 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3046 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3048 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3051 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
3052 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3053 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3057 Rectangle aLogicClip
;
3058 if (bClip
|| bSimClip
)
3060 // Clip marks are already handled in GetOutputArea
3062 if (rParam
.mbPixelToLogic
)
3063 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3065 aLogicClip
= aAreaParam
.maClipRect
;
3067 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3072 mpDev
->IntersectClipRegion( aLogicClip
);
3075 mpDev
->SetClipRegion( Region( aLogicClip
) );
3080 if (rParam
.mbPixelToLogic
)
3081 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
3083 aLogicStart
= Point(nStartX
, nStartY
);
3085 if (!rParam
.mbBreak
)
3087 // horizontal alignment
3088 if (rParam
.adjustHorAlignment(rParam
.mpEngine
))
3089 // reset adjustment for the next cell
3090 rParam
.mpOldPattern
= NULL
;
3093 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
3094 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
3096 //! if pRefDevice != pFmtDevice, keep heights in logic units,
3097 //! only converting margin?
3099 if (rParam
.mbPixelToLogic
)
3100 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
3101 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3102 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
3105 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
3107 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
3109 if (rParam
.mbPixelToLogic
)
3110 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
3111 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
3112 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
3115 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
3119 if (rParam
.mbPixelToLogic
)
3120 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3122 aLogicStart
.Y() += nTopM
;
3125 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3127 rParam
.adjustForRTL();
3129 // bMoveClipped handling has been replaced by complete alignment
3130 // handling (also extending to the left).
3134 // kein hartes Clipping, aber nur die betroffenen
3137 Point aDocStart
= aLogicClip
.TopLeft();
3138 aDocStart
-= aLogicStart
;
3139 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
3143 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
3151 mpDev
->SetClipRegion();
3154 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3157 void ScOutputData::ShowClipMarks( DrawEditParam
& rParam
, long nEngineHeight
, const Size
& aCellSize
,
3158 bool bMerged
, OutputAreaParam
& aAreaParam
)
3160 // Show clip marks if height is at least 5pt too small and
3161 // there are several lines of text.
3162 // Not for asian vertical text, because that would interfere
3163 // with the default right position of the text.
3164 // Only with automatic line breaks, to avoid having to find
3165 // the cells with the horizontal end of the text again.
3166 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
3167 rParam
.mbBreak
&& bMarkClipped
&&
3168 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
3170 CellInfo
* pClipMarkCell
= NULL
;
3173 // anywhere in the merged area...
3174 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
3175 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
3178 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
3180 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
3183 const long nMarkPixel
= static_cast<long>( SC_CLIPMARK_SIZE
* mnPPTX
);
3184 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
3185 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
3189 bool ScOutputData::Clip( DrawEditParam
& rParam
, const Size
& aCellSize
,
3190 OutputAreaParam
& aAreaParam
, long nEngineHeight
,
3193 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3195 aAreaParam
.maClipRect
.Left() = nScrX
;
3196 aAreaParam
.mbLeftClip
= true;
3198 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3200 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3201 aAreaParam
.mbRightClip
= true;
3204 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3205 bool bSimClip
= false;
3209 // Fields in a cell with automatic breaks: clip to cell width
3213 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3215 aAreaParam
.maClipRect
.Top() = nScrY
;
3218 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3220 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3224 const Size
& aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3225 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
3227 const ScMergeAttr
* pMerge
=
3228 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
3229 const bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
3231 // Don't clip for text height when printing rows with optimal height,
3232 // except when font size is from conditional formatting.
3233 //! Allow clipping when vertically merged?
3234 if ( eType
!= OUTTYPE_PRINTER
||
3235 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
3236 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
3237 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
3242 ShowClipMarks( rParam
, nEngineHeight
, aCellSize
, bMerged
, aAreaParam
);
3245 Rectangle aLogicClip
;
3246 if (bClip
|| bSimClip
)
3248 // Clip marks are already handled in GetOutputArea
3250 if (rParam
.mbPixelToLogic
)
3251 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
3253 aLogicClip
= aAreaParam
.maClipRect
;
3255 if (bClip
) // bei bSimClip nur aClipRect initialisieren
3260 mpDev
->IntersectClipRegion( aLogicClip
);
3263 mpDev
->SetClipRegion( Region( aLogicClip
) );
3270 void ScOutputData::DrawEditBottomTop(DrawEditParam
& rParam
)
3272 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3274 const bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3275 const bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3277 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3279 //! mirror margin values for RTL?
3280 //! move margin down to after final GetOutputArea call
3281 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3282 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3284 SCCOL nXForPos
= rParam
.mnX
;
3285 if ( nXForPos
< nX1
)
3288 rParam
.mnPosX
= rParam
.mnInitPosX
;
3290 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3291 if ( nArrYForPos
< 1 )
3294 rParam
.mnPosY
= nScrY
;
3297 OutputAreaParam aAreaParam
;
3300 // Initial page size - large for normal text, cell size for automatic line breaks
3303 Size aPaperSize
= Size( 1000000, 1000000 );
3306 // call GetOutputArea with nNeeded=0, to get only the cell width
3308 //! handle nArrY == 0
3309 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3310 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3311 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3313 //! special ScEditUtil handling if formatting for printer
3314 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3316 if (rParam
.mbPixelToLogic
)
3318 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3319 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3322 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3325 // Fill the EditEngine (cell attributes and text)
3328 rParam
.setPatternToEngine(mbUseStyleColor
);
3329 rParam
.setAlignmentToEngine();
3331 // Read content from cell
3333 bool bWrapFields
= false;
3334 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3335 // Failed to read cell content. Bail out.
3339 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3340 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3341 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3343 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3346 // Get final output area using the calculated width
3349 long nEngineWidth
, nEngineHeight
;
3350 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3352 long nNeededPixel
= nEngineWidth
;
3353 if (rParam
.mbPixelToLogic
)
3354 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3355 nNeededPixel
+= nLeftM
+ nRightM
;
3357 if (!rParam
.mbBreak
|| bShrink
)
3359 // for break, the first GetOutputArea call is sufficient
3360 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3361 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3362 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3366 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3367 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3368 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3369 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3370 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3372 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3374 // First check if twice the space for the formatted text is available
3375 // (otherwise just keep it unchanged).
3377 const long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3378 const long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3379 if ( nAvailable
>= 2 * nFormatted
)
3381 // "repeat" is handled with unformatted text (for performance reasons)
3382 OUString aCellStr
= rParam
.mpEngine
->GetText();
3383 rParam
.mpEngine
->SetText( aCellStr
);
3385 long nRepeatSize
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3386 if (rParam
.mbPixelToLogic
)
3387 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3388 if ( pFmtDevice
!= mpRefDevice
)
3390 if ( nRepeatSize
> 0 )
3392 const long nRepeatCount
= nAvailable
/ nRepeatSize
;
3393 if ( nRepeatCount
> 1 )
3395 OUString aRepeated
= aCellStr
;
3396 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3397 aRepeated
+= aCellStr
;
3398 rParam
.mpEngine
->SetText( aRepeated
);
3400 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3401 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3402 if (rParam
.mbPixelToLogic
)
3403 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3405 nNeededPixel
= nEngineWidth
;
3406 nNeededPixel
+= nLeftM
+ nRightM
;
3412 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3414 rParam
.mpEngine
->SetText(OUString("###"));
3415 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3416 if (rParam
.mbPixelToLogic
)
3417 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3419 nNeededPixel
= nEngineWidth
;
3420 nNeededPixel
+= nLeftM
+ nRightM
;
3422 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3426 long nStartX
= aAreaParam
.maAlignRect
.Left();
3427 const long nStartY
= aAreaParam
.maAlignRect
.Top();
3428 const long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3429 const long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3430 const long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3434 // text with automatic breaks is aligned only within the
3435 // edit engine's paper size, the output of the whole area
3436 // is always left-aligned
3442 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3443 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3444 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3445 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3450 const bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3454 // output area, excluding margins, in logical units
3455 const Size
& aCellSize
= rParam
.mbPixelToLogic
3456 ? mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) )
3457 : Size( nOutWidth
, nOutHeight
);
3459 const bool bClip
= Clip( rParam
, aCellSize
, aAreaParam
, nEngineHeight
, bWrapFields
);
3461 Point
aLogicStart(nStartX
, nStartY
);
3462 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3464 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3466 if (rParam
.meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
|| rParam
.mbBreak
)
3468 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3469 aPSize
.Width() = aCellSize
.Height();
3470 rParam
.mpEngine
->SetPaperSize(aPSize
);
3472 rParam
.mbBreak
? aPSize
.Width() : nEngineHeight
;
3476 // Note that the "paper" is rotated 90 degrees to the left, so
3477 // paper's width is in vertical direction. Also, the whole text
3478 // is on a single line, as text wrap is not in effect.
3480 // Set the paper width to be the width of the text.
3481 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3482 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3483 rParam
.mpEngine
->SetPaperSize(aPSize
);
3486 long nTopOffset
= 0;
3487 if (rParam
.mbPixelToLogic
)
3489 nGap
= mpRefDevice
->LogicToPixel(aCellSize
).Height() - mpRefDevice
->LogicToPixel(aPSize
).Width();
3490 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3491 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3495 nGap
= aCellSize
.Height() - aPSize
.Width();
3499 // First, align text to bottom.
3500 aLogicStart
.Y() += aCellSize
.Height();
3501 aLogicStart
.Y() += nTopOffset
;
3503 switch (rParam
.meVerJust
)
3505 case SVX_VER_JUSTIFY_STANDARD
:
3506 case SVX_VER_JUSTIFY_BOTTOM
:
3507 // align to bottom (do nothing).
3509 case SVX_VER_JUSTIFY_CENTER
:
3511 aLogicStart
.Y() -= nGap
/ 2;
3513 case SVX_VER_JUSTIFY_BLOCK
:
3514 case SVX_VER_JUSTIFY_TOP
:
3516 aLogicStart
.Y() -= nGap
;
3522 rParam
.adjustForRTL();
3523 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 900);
3530 mpDev
->SetClipRegion();
3533 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3536 void ScOutputData::DrawEditTopBottom(DrawEditParam
& rParam
)
3538 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3540 const bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3541 const bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3543 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3545 //! mirror margin values for RTL?
3546 //! move margin down to after final GetOutputArea call
3547 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3548 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3550 SCCOL nXForPos
= rParam
.mnX
;
3551 if ( nXForPos
< nX1
)
3554 rParam
.mnPosX
= rParam
.mnInitPosX
;
3556 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3557 if ( nArrYForPos
< 1 )
3560 rParam
.mnPosY
= nScrY
;
3563 OutputAreaParam aAreaParam
;
3566 // Initial page size - large for normal text, cell size for automatic line breaks
3569 Size aPaperSize
= Size( 1000000, 1000000 );
3570 if (rParam
.hasLineBreak())
3572 // call GetOutputArea with nNeeded=0, to get only the cell width
3574 //! handle nArrY == 0
3575 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3576 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3577 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3579 //! special ScEditUtil handling if formatting for printer
3580 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3582 if (rParam
.mbPixelToLogic
)
3584 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3585 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3588 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3591 // Fill the EditEngine (cell attributes and text)
3594 rParam
.setPatternToEngine(mbUseStyleColor
);
3595 rParam
.setAlignmentToEngine();
3597 // Read content from cell
3599 bool bWrapFields
= false;
3600 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3601 // Failed to read cell content. Bail out.
3605 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3606 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3607 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3609 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3612 // Get final output area using the calculated width
3615 long nEngineWidth
, nEngineHeight
;
3616 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3618 long nNeededPixel
= nEngineWidth
;
3619 if (rParam
.mbPixelToLogic
)
3620 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3621 nNeededPixel
+= nLeftM
+ nRightM
;
3623 if (!rParam
.mbBreak
|| bShrink
)
3625 // for break, the first GetOutputArea call is sufficient
3626 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3627 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3628 rParam
.mbCellIsValue
|| bRepeat
|| bShrink
, false, false, aAreaParam
);
3632 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3633 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
3634 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3635 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3636 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3638 if ( bRepeat
&& !aAreaParam
.mbLeftClip
&& !aAreaParam
.mbRightClip
&& rParam
.mpEngine
->GetParagraphCount() == 1 )
3640 // First check if twice the space for the formatted text is available
3641 // (otherwise just keep it unchanged).
3643 const long nFormatted
= nNeededPixel
- nLeftM
- nRightM
; // without margin
3644 const long nAvailable
= aAreaParam
.maAlignRect
.GetWidth() - nLeftM
- nRightM
;
3645 if ( nAvailable
>= 2 * nFormatted
)
3647 // "repeat" is handled with unformatted text (for performance reasons)
3648 OUString aCellStr
= rParam
.mpEngine
->GetText();
3649 rParam
.mpEngine
->SetText( aCellStr
);
3651 long nRepeatSize
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3652 if (rParam
.mbPixelToLogic
)
3653 nRepeatSize
= mpRefDevice
->LogicToPixel(Size(nRepeatSize
,0)).Width();
3654 if ( pFmtDevice
!= mpRefDevice
)
3656 if ( nRepeatSize
> 0 )
3658 const long nRepeatCount
= nAvailable
/ nRepeatSize
;
3659 if ( nRepeatCount
> 1 )
3661 OUString aRepeated
= aCellStr
;
3662 for ( long nRepeat
= 1; nRepeat
< nRepeatCount
; nRepeat
++ )
3663 aRepeated
+= aCellStr
;
3664 rParam
.mpEngine
->SetText( aRepeated
);
3666 nEngineHeight
= rParam
.mpEngine
->GetTextHeight();
3667 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3668 if (rParam
.mbPixelToLogic
)
3669 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3671 nNeededPixel
= nEngineWidth
;
3672 nNeededPixel
+= nLeftM
+ nRightM
;
3678 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3680 rParam
.mpEngine
->SetText(OUString("###"));
3681 nEngineWidth
= static_cast<long>( rParam
.mpEngine
->CalcTextWidth() );
3682 if (rParam
.mbPixelToLogic
)
3683 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3685 nNeededPixel
= nEngineWidth
;
3686 nNeededPixel
+= nLeftM
+ nRightM
;
3688 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3692 long nStartX
= aAreaParam
.maAlignRect
.Left();
3693 const long nStartY
= aAreaParam
.maAlignRect
.Top();
3694 const long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3695 const long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3696 const long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3700 // text with automatic breaks is aligned only within the
3701 // edit engine's paper size, the output of the whole area
3702 // is always left-aligned
3705 if (rParam
.meHorJustResult
== SVX_HOR_JUSTIFY_BLOCK
)
3706 nStartX
+= aPaperSize
.Height();
3710 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3711 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3712 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3713 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3718 const bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3722 // output area, excluding margins, in logical units
3723 const Size
& aCellSize
= rParam
.mbPixelToLogic
3724 ? mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) )
3725 : Size( nOutWidth
, nOutHeight
);
3727 const bool bClip
= Clip( rParam
, aCellSize
, aAreaParam
, nEngineHeight
, bWrapFields
);
3729 Point
aLogicStart(nStartX
, nStartY
);
3730 rParam
.calcStartPosForVertical(aLogicStart
, aCellSize
.Width(), nEngineWidth
, nTopM
, mpRefDevice
);
3732 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
3734 if (rParam
.meHorJustResult
!= SVX_HOR_JUSTIFY_BLOCK
)
3736 aLogicStart
.X() += nEngineWidth
;
3737 if (!rParam
.mbBreak
)
3739 // Set the paper width to text size.
3740 Size aPSize
= rParam
.mpEngine
->GetPaperSize();
3741 aPSize
.Width() = rParam
.mpEngine
->CalcTextWidth();
3742 rParam
.mpEngine
->SetPaperSize(aPSize
);
3745 long nTopOffset
= 0; // offset by top margin
3746 if (rParam
.mbPixelToLogic
)
3748 nGap
= mpRefDevice
->LogicToPixel(aPSize
).Width() - mpRefDevice
->LogicToPixel(aCellSize
).Height();
3749 nGap
= mpRefDevice
->PixelToLogic(Size(0, nGap
)).Height();
3750 nTopOffset
= mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
3754 nGap
= aPSize
.Width() - aCellSize
.Height();
3757 aLogicStart
.Y() += nTopOffset
;
3759 switch (rParam
.meVerJust
)
3761 case SVX_VER_JUSTIFY_STANDARD
:
3762 case SVX_VER_JUSTIFY_BOTTOM
:
3764 aLogicStart
.Y() -= nGap
;
3766 case SVX_VER_JUSTIFY_CENTER
:
3768 aLogicStart
.Y() -= nGap
/ 2;
3770 case SVX_VER_JUSTIFY_BLOCK
:
3771 case SVX_VER_JUSTIFY_TOP
:
3772 // align to top (do nothing)
3779 rParam
.adjustForRTL();
3781 // bMoveClipped handling has been replaced by complete alignment
3782 // handling (also extending to the left).
3784 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 2700);
3791 mpDev
->SetClipRegion();
3794 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
3797 void ScOutputData::DrawEditStacked(DrawEditParam
& rParam
)
3799 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
3800 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
3802 bool bRepeat
= (rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
&& !rParam
.mbBreak
);
3803 bool bShrink
= !rParam
.mbBreak
&& !bRepeat
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
3805 rParam
.mbAsianVertical
=
3806 lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_VERTICAL_ASIAN
, rParam
.mpCondSet
);
3808 if ( rParam
.mbAsianVertical
)
3810 // in asian mode, use EditEngine::SetVertical instead of EE_CNTRL_ONECHARPERLINE
3811 rParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
3812 DrawEditAsianVertical(rParam
);
3816 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
3818 //! mirror margin values for RTL?
3819 //! move margin down to after final GetOutputArea call
3820 long nTopM
, nLeftM
, nBottomM
, nRightM
;
3821 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
3823 SCCOL nXForPos
= rParam
.mnX
;
3824 if ( nXForPos
< nX1
)
3827 rParam
.mnPosX
= rParam
.mnInitPosX
;
3829 SCSIZE nArrYForPos
= rParam
.mnArrY
;
3830 if ( nArrYForPos
< 1 )
3833 rParam
.mnPosY
= nScrY
;
3836 OutputAreaParam aAreaParam
;
3839 // Initial page size - large for normal text, cell size for automatic line breaks
3842 Size aPaperSize
= Size( 1000000, 1000000 );
3843 // call GetOutputArea with nNeeded=0, to get only the cell width
3845 //! handle nArrY == 0
3846 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
3847 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3848 rParam
.mbCellIsValue
, true, false, aAreaParam
);
3850 //! special ScEditUtil handling if formatting for printer
3851 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
3853 if (rParam
.mbPixelToLogic
)
3855 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
3856 if ( rParam
.mbBreak
&& mpRefDevice
!= pFmtDevice
)
3858 // #i85342# screen display and formatting for printer,
3859 // use same GetEditArea call as in ScViewData::SetEditEngine
3861 Fraction
aFract(1,1);
3862 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
3863 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
3864 aLogicSize
.Width() = aUtilRect
.GetWidth();
3866 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
3869 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3872 // Fill the EditEngine (cell attributes and text)
3875 rParam
.setPatternToEngine(mbUseStyleColor
);
3876 rParam
.setAlignmentToEngine();
3878 // Read content from cell
3880 bool bWrapFields
= false;
3881 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
3882 // Failed to read cell content. Bail out.
3886 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
3887 else if ( mbUseStyleColor
&& mbForceAutoColor
)
3888 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
3890 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
3893 // Get final output area using the calculated width
3896 long nEngineWidth
, nEngineHeight
;
3897 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
3899 long nNeededPixel
= nEngineWidth
;
3900 if (rParam
.mbPixelToLogic
)
3901 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
3902 nNeededPixel
+= nLeftM
+ nRightM
;
3906 // for break, the first GetOutputArea call is sufficient
3907 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
3908 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
3909 true, false, false, aAreaParam
);
3911 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
3912 nLeftM
, nTopM
, nRightM
, nBottomM
, true,
3913 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
3914 nEngineWidth
, nEngineHeight
, nNeededPixel
,
3915 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
3917 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
3919 rParam
.mpEngine
->SetText(OUString("###"));
3920 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
3921 if (rParam
.mbPixelToLogic
)
3922 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
3924 nNeededPixel
= nEngineWidth
;
3925 nNeededPixel
+= nLeftM
+ nRightM
;
3927 // No clip marks if "###" doesn't fit (same as in DrawStrings)
3930 if ( eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
3932 aPaperSize
.Width() = nNeededPixel
+ 1;
3933 if (rParam
.mbPixelToLogic
)
3934 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
3936 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
3940 long nStartX
= aAreaParam
.maAlignRect
.Left();
3941 long nStartY
= aAreaParam
.maAlignRect
.Top();
3942 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
3943 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
3944 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
3948 // text with automatic breaks is aligned only within the
3949 // edit engine's paper size, the output of the whole area
3950 // is always left-aligned
3956 if ( eOutHorJust
== SVX_HOR_JUSTIFY_RIGHT
)
3957 nStartX
-= nNeededPixel
- nCellWidth
+ nRightM
+ 1;
3958 else if ( eOutHorJust
== SVX_HOR_JUSTIFY_CENTER
)
3959 nStartX
-= ( nNeededPixel
- nCellWidth
+ nRightM
+ 1 - nLeftM
) / 2;
3964 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
3968 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
3970 aAreaParam
.maClipRect
.Left() = nScrX
;
3971 aAreaParam
.mbLeftClip
= true;
3973 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
3975 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
3976 aAreaParam
.mbRightClip
= true;
3979 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
3980 bool bSimClip
= false;
3984 // Fields in a cell with automatic breaks: clip to cell width
3988 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
3990 aAreaParam
.maClipRect
.Top() = nScrY
;
3993 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
3995 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
3999 Size aCellSize
; // output area, excluding margins, in logical units
4000 if (rParam
.mbPixelToLogic
)
4001 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4003 aCellSize
= Size( nOutWidth
, nOutHeight
);
4005 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4007 const ScMergeAttr
* pMerge
=
4008 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4009 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4011 // Don't clip for text height when printing rows with optimal height,
4012 // except when font size is from conditional formatting.
4013 //! Allow clipping when vertically merged?
4014 if ( eType
!= OUTTYPE_PRINTER
||
4015 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4016 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4017 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4022 // Show clip marks if height is at least 5pt too small and
4023 // there are several lines of text.
4024 // Not for asian vertical text, because that would interfere
4025 // with the default right position of the text.
4026 // Only with automatic line breaks, to avoid having to find
4027 // the cells with the horizontal end of the text again.
4028 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4029 rParam
.mbBreak
&& bMarkClipped
&&
4030 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4032 CellInfo
* pClipMarkCell
= NULL
;
4035 // anywhere in the merged area...
4036 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4037 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4040 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4042 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4045 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4046 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4047 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4051 Rectangle aLogicClip
;
4052 if (bClip
|| bSimClip
)
4054 // Clip marks are already handled in GetOutputArea
4056 if (rParam
.mbPixelToLogic
)
4057 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4059 aLogicClip
= aAreaParam
.maClipRect
;
4061 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4066 mpDev
->IntersectClipRegion( aLogicClip
);
4069 mpDev
->SetClipRegion( Region( aLogicClip
) );
4074 if (rParam
.mbPixelToLogic
)
4075 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4077 aLogicStart
= Point(nStartX
, nStartY
);
4079 if (rParam
.meVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
4080 rParam
.meVerJust
==SVX_VER_JUSTIFY_STANDARD
)
4082 //! if pRefDevice != pFmtDevice, keep heights in logic units,
4083 //! only converting margin?
4085 if (rParam
.mbPixelToLogic
)
4086 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+
4087 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4088 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
4091 aLogicStart
.Y() += nTopM
+ aCellSize
.Height() - nEngineHeight
;
4093 else if (rParam
.meVerJust
==SVX_VER_JUSTIFY_CENTER
)
4095 if (rParam
.mbPixelToLogic
)
4096 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0, nTopM
+ (
4097 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
4098 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height() )
4101 aLogicStart
.Y() += nTopM
+ (aCellSize
.Height() - nEngineHeight
) / 2;
4105 if (rParam
.mbPixelToLogic
)
4106 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4108 aLogicStart
.Y() += nTopM
;
4111 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4113 Size aPaperLogic
= rParam
.mpEngine
->GetPaperSize();
4114 aPaperLogic
.Width() = nEngineWidth
;
4115 rParam
.mpEngine
->SetPaperSize(aPaperLogic
);
4117 rParam
.adjustForRTL();
4119 // bMoveClipped handling has been replaced by complete alignment
4120 // handling (also extending to the left).
4124 // kein hartes Clipping, aber nur die betroffenen
4127 Point aDocStart
= aLogicClip
.TopLeft();
4128 aDocStart
-= aLogicStart
;
4129 rParam
.mpEngine
->Draw( mpDev
, aLogicClip
, aDocStart
, false );
4133 rParam
.mpEngine
->Draw( mpDev
, aLogicStart
, 0 );
4141 mpDev
->SetClipRegion();
4144 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4147 void ScOutputData::DrawEditAsianVertical(DrawEditParam
& rParam
)
4149 // When in asian vertical orientation, the orientation value is STANDARD,
4150 // and the asian vertical boolean is true.
4151 OSL_ASSERT(rParam
.meOrient
== SVX_ORIENTATION_STANDARD
);
4152 OSL_ASSERT(rParam
.mbAsianVertical
);
4153 OSL_ASSERT(rParam
.meHorJustAttr
!= SVX_HOR_JUSTIFY_REPEAT
);
4155 Size aRefOne
= mpRefDevice
->PixelToLogic(Size(1,1));
4157 bool bHidden
= false;
4158 bool bShrink
= !rParam
.mbBreak
&& lcl_GetBoolValue(*rParam
.mpPattern
, ATTR_SHRINKTOFIT
, rParam
.mpCondSet
);
4159 long nAttrRotate
= lcl_GetValue
<SfxInt32Item
, long>(*rParam
.mpPattern
, ATTR_ROTATE_VALUE
, rParam
.mpCondSet
);
4163 //! Flag setzen, um die Zelle in DrawRotated wiederzufinden ?
4164 //! (oder Flag schon bei DrawBackground, dann hier keine Abfrage)
4165 bHidden
= true; // gedreht wird getrennt ausgegeben
4168 // default alignment for asian vertical mode is top-right
4169 /* TODO: is setting meHorJustContext and meHorJustResult unconditionally to
4170 * SVX_HOR_JUSTIFY_RIGHT really wanted? Seems this was done all the time,
4171 * also before context was introduced and everything was attr only. */
4172 if ( rParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_STANDARD
)
4173 rParam
.meHorJustResult
= rParam
.meHorJustContext
= SVX_HOR_JUSTIFY_RIGHT
;
4178 SvxCellHorJustify eOutHorJust
= rParam
.meHorJustContext
;
4180 //! mirror margin values for RTL?
4181 //! move margin down to after final GetOutputArea call
4182 long nTopM
, nLeftM
, nBottomM
, nRightM
;
4183 rParam
.calcMargins(nTopM
, nLeftM
, nBottomM
, nRightM
, mnPPTX
, mnPPTY
);
4185 SCCOL nXForPos
= rParam
.mnX
;
4186 if ( nXForPos
< nX1
)
4189 rParam
.mnPosX
= rParam
.mnInitPosX
;
4191 SCSIZE nArrYForPos
= rParam
.mnArrY
;
4192 if ( nArrYForPos
< 1 )
4195 rParam
.mnPosY
= nScrY
;
4198 OutputAreaParam aAreaParam
;
4201 // Initial page size - large for normal text, cell size for automatic line breaks
4204 Size aPaperSize
= Size( 1000000, 1000000 );
4205 // call GetOutputArea with nNeeded=0, to get only the cell width
4207 //! handle nArrY == 0
4208 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, 0,
4209 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4210 rParam
.mbCellIsValue
, true, false, aAreaParam
);
4212 //! special ScEditUtil handling if formatting for printer
4213 rParam
.calcPaperSize(aPaperSize
, aAreaParam
.maAlignRect
, mnPPTX
, mnPPTY
);
4215 if (rParam
.mbPixelToLogic
)
4217 Size aLogicSize
= mpRefDevice
->PixelToLogic(aPaperSize
);
4218 if ( rParam
.mbBreak
&& !rParam
.mbAsianVertical
&& mpRefDevice
!= pFmtDevice
)
4220 // #i85342# screen display and formatting for printer,
4221 // use same GetEditArea call as in ScViewData::SetEditEngine
4223 Fraction
aFract(1,1);
4224 Rectangle aUtilRect
= ScEditUtil( mpDoc
, rParam
.mnCellX
, rParam
.mnCellY
, nTab
, Point(0,0), pFmtDevice
,
4225 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( rParam
.mpPattern
, false );
4226 aLogicSize
.Width() = aUtilRect
.GetWidth();
4228 rParam
.mpEngine
->SetPaperSize(aLogicSize
);
4231 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4234 // Fill the EditEngine (cell attributes and text)
4237 // default alignment for asian vertical mode is top-right
4238 if ( rParam
.meVerJust
== SVX_VER_JUSTIFY_STANDARD
)
4239 rParam
.meVerJust
= SVX_VER_JUSTIFY_TOP
;
4241 rParam
.setPatternToEngine(mbUseStyleColor
);
4242 rParam
.setAlignmentToEngine();
4244 // Read content from cell
4246 bool bWrapFields
= false;
4247 if (!rParam
.readCellContent(mpDoc
, mbShowNullValues
, mbShowFormulas
, mbSyntaxMode
, mbUseStyleColor
, mbForceAutoColor
, bWrapFields
))
4248 // Failed to read cell content. Bail out.
4252 SetEditSyntaxColor( *rParam
.mpEngine
, rParam
.maCell
);
4253 else if ( mbUseStyleColor
&& mbForceAutoColor
)
4254 lcl_SetEditColor( *rParam
.mpEngine
, COL_AUTO
); //! or have a flag at EditEngine
4256 rParam
.mpEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
4259 // Get final output area using the calculated width
4262 long nEngineWidth
, nEngineHeight
;
4263 rParam
.getEngineSize(rParam
.mpEngine
, nEngineWidth
, nEngineHeight
);
4265 long nNeededPixel
= nEngineWidth
;
4266 if (rParam
.mbPixelToLogic
)
4267 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nNeededPixel
,0)).Width();
4268 nNeededPixel
+= nLeftM
+ nRightM
;
4270 // for break, the first GetOutputArea call is sufficient
4271 GetOutputArea( nXForPos
, nArrYForPos
, rParam
.mnPosX
, rParam
.mnPosY
, rParam
.mnCellX
, rParam
.mnCellY
, nNeededPixel
,
4272 *rParam
.mpPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
4273 rParam
.mbCellIsValue
|| bShrink
, false, false, aAreaParam
);
4277 ShrinkEditEngine( *rParam
.mpEngine
, aAreaParam
.maAlignRect
,
4278 nLeftM
, nTopM
, nRightM
, nBottomM
, false,
4279 sal::static_int_cast
<sal_uInt16
>(rParam
.meOrient
), 0, rParam
.mbPixelToLogic
,
4280 nEngineWidth
, nEngineHeight
, nNeededPixel
,
4281 aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
4284 if ( rParam
.mbCellIsValue
&& ( aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
) )
4286 rParam
.mpEngine
->SetText(OUString("###"));
4287 nEngineWidth
= (long) rParam
.mpEngine
->CalcTextWidth();
4288 if (rParam
.mbPixelToLogic
)
4289 nNeededPixel
= mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width();
4291 nNeededPixel
= nEngineWidth
;
4292 nNeededPixel
+= nLeftM
+ nRightM
;
4294 // No clip marks if "###" doesn't fit (same as in DrawStrings)
4297 if (eOutHorJust
!= SVX_HOR_JUSTIFY_LEFT
)
4299 aPaperSize
.Width() = nNeededPixel
+ 1;
4300 if (rParam
.mbPixelToLogic
)
4301 rParam
.mpEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4303 rParam
.mpEngine
->SetPaperSize(aPaperSize
);
4306 long nStartX
= aAreaParam
.maAlignRect
.Left();
4307 long nStartY
= aAreaParam
.maAlignRect
.Top();
4308 long nCellWidth
= aAreaParam
.maAlignRect
.GetWidth();
4309 long nOutWidth
= nCellWidth
- 1 - nLeftM
- nRightM
;
4310 long nOutHeight
= aAreaParam
.maAlignRect
.GetHeight() - nTopM
- nBottomM
;
4312 // text with automatic breaks is aligned only within the
4313 // edit engine's paper size, the output of the whole area
4314 // is always left-aligned
4318 bool bOutside
= (aAreaParam
.maClipRect
.Right() < nScrX
|| aAreaParam
.maClipRect
.Left() >= nScrX
+ nScrW
);
4322 if ( aAreaParam
.maClipRect
.Left() < nScrX
)
4324 aAreaParam
.maClipRect
.Left() = nScrX
;
4325 aAreaParam
.mbLeftClip
= true;
4327 if ( aAreaParam
.maClipRect
.Right() > nScrX
+ nScrW
)
4329 aAreaParam
.maClipRect
.Right() = nScrX
+ nScrW
; //! minus one?
4330 aAreaParam
.mbRightClip
= true;
4333 bool bClip
= aAreaParam
.mbLeftClip
|| aAreaParam
.mbRightClip
;
4334 bool bSimClip
= false;
4338 // Fields in a cell with automatic breaks: clip to cell width
4342 if ( aAreaParam
.maClipRect
.Top() < nScrY
)
4344 aAreaParam
.maClipRect
.Top() = nScrY
;
4347 if ( aAreaParam
.maClipRect
.Bottom() > nScrY
+ nScrH
)
4349 aAreaParam
.maClipRect
.Bottom() = nScrY
+ nScrH
; //! minus one?
4353 Size aCellSize
; // output area, excluding margins, in logical units
4354 if (rParam
.mbPixelToLogic
)
4355 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
4357 aCellSize
= Size( nOutWidth
, nOutHeight
);
4359 if ( nEngineHeight
>= aCellSize
.Height() + aRefOne
.Height() )
4361 const ScMergeAttr
* pMerge
=
4362 (ScMergeAttr
*)&rParam
.mpPattern
->GetItem(ATTR_MERGE
);
4363 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4365 // Don't clip for text height when printing rows with optimal height,
4366 // except when font size is from conditional formatting.
4367 //! Allow clipping when vertically merged?
4368 if ( eType
!= OUTTYPE_PRINTER
||
4369 ( mpDoc
->GetRowFlags( rParam
.mnCellY
, nTab
) & CR_MANUALSIZE
) ||
4370 ( rParam
.mpCondSet
&& SFX_ITEM_SET
==
4371 rParam
.mpCondSet
->GetItemState(ATTR_FONT_HEIGHT
, true) ) )
4376 // Show clip marks if height is at least 5pt too small and
4377 // there are several lines of text.
4378 // Not for asian vertical text, because that would interfere
4379 // with the default right position of the text.
4380 // Only with automatic line breaks, to avoid having to find
4381 // the cells with the horizontal end of the text again.
4382 if ( nEngineHeight
- aCellSize
.Height() > 100 &&
4383 ( rParam
.mbBreak
|| rParam
.meOrient
== SVX_ORIENTATION_STACKED
) &&
4384 !rParam
.mbAsianVertical
&& bMarkClipped
&&
4385 ( rParam
.mpEngine
->GetParagraphCount() > 1 || rParam
.mpEngine
->GetLineCount(0) > 1 ) )
4387 CellInfo
* pClipMarkCell
= NULL
;
4390 // anywhere in the merged area...
4391 SCCOL nClipX
= ( rParam
.mnX
< nX1
) ? nX1
: rParam
.mnX
;
4392 pClipMarkCell
= &pRowInfo
[(rParam
.mnArrY
!= 0) ? rParam
.mnArrY
: 1].pCellInfo
[nClipX
+1];
4395 pClipMarkCell
= &rParam
.mpThisRowInfo
->pCellInfo
[rParam
.mnX
+1];
4397 pClipMarkCell
->nClipMark
|= SC_CLIPMARK_RIGHT
; //! also allow left?
4400 long nMarkPixel
= (long)( SC_CLIPMARK_SIZE
* mnPPTX
);
4401 if ( aAreaParam
.maClipRect
.Right() - nMarkPixel
> aAreaParam
.maClipRect
.Left() )
4402 aAreaParam
.maClipRect
.Right() -= nMarkPixel
;
4406 Rectangle aLogicClip
;
4407 if (bClip
|| bSimClip
)
4409 // Clip marks are already handled in GetOutputArea
4411 if (rParam
.mbPixelToLogic
)
4412 aLogicClip
= mpRefDevice
->PixelToLogic( aAreaParam
.maClipRect
);
4414 aLogicClip
= aAreaParam
.maClipRect
;
4416 if (bClip
) // bei bSimClip nur aClipRect initialisieren
4421 mpDev
->IntersectClipRegion( aLogicClip
);
4424 mpDev
->SetClipRegion( Region( aLogicClip
) );
4429 if (rParam
.mbPixelToLogic
)
4430 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
4432 aLogicStart
= Point(nStartX
, nStartY
);
4434 long nAvailWidth
= aCellSize
.Width();
4435 // space for AutoFilter is already handled in GetOutputArea
4437 // horizontal alignment
4439 if (rParam
.meHorJustResult
==SVX_HOR_JUSTIFY_RIGHT
)
4440 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
4441 else if (rParam
.meHorJustResult
==SVX_HOR_JUSTIFY_CENTER
)
4442 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
4444 // paper size is subtracted below
4445 aLogicStart
.X() += nEngineWidth
;
4447 // vertical adjustment is within the EditEngine
4448 if (rParam
.mbPixelToLogic
)
4449 aLogicStart
.Y() += mpRefDevice
->PixelToLogic(Size(0,nTopM
)).Height();
4451 aLogicStart
.Y() += nTopM
;
4453 Point aURLStart
= aLogicStart
; // copy before modifying for orientation
4455 rParam
.adjustForRTL();
4457 // bMoveClipped handling has been replaced by complete alignment
4458 // handling (also extending to the left).
4460 // with SetVertical, the start position is top left of
4461 // the whole output area, not the text itself
4462 aLogicStart
.X() -= rParam
.mpEngine
->GetPaperSize().Width();
4464 rParam
.mpEngine
->Draw(mpDev
, aLogicStart
, 0);
4471 mpDev
->SetClipRegion();
4474 rParam
.adjustForHyperlinkInPDF(aURLStart
, mpDev
);
4477 void ScOutputData::DrawEdit(bool bPixelToLogic
)
4479 boost::scoped_ptr
<ScFieldEditEngine
> pEngine
;
4480 bool bHyphenatorSet
= false;
4481 const ScPatternAttr
* pOldPattern
= NULL
;
4482 const SfxItemSet
* pOldCondSet
= NULL
;
4483 const SfxItemSet
* pOldPreviewFontSet
= NULL
;
4484 ScRefCellValue aCell
;
4486 long nInitPosX
= nScrX
;
4489 nInitPosX
+= nMirrorW
- 1;
4491 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4493 //! store nLastContentCol as member!
4494 SCCOL nLastContentCol
= MAXCOL
;
4496 nLastContentCol
= sal::static_int_cast
<SCCOL
>(
4497 nLastContentCol
- mpDoc
->GetEmptyLinesInBlock( nX2
+1, nY1
, nTab
, MAXCOL
, nY2
, nTab
, DIR_RIGHT
) );
4499 long nRowPosY
= nScrY
;
4500 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4502 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4504 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4506 if ( pThisRowInfo
->bChanged
|| nArrY
==0 )
4509 for (SCCOL nX
=0; nX
<=nX2
; nX
++) // wegen Ueberhaengen
4511 boost::scoped_ptr
< ScPatternAttr
> pPreviewPattr
;
4512 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4514 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4515 if (pInfo
->bEditEngine
)
4517 SCROW nY
= pThisRowInfo
->nRowNo
;
4519 SCCOL nCellX
= nX
; // position where the cell really starts
4521 bool bDoCell
= false;
4523 long nPosY
= nRowPosY
;
4527 nY
= pRowInfo
[1].nRowNo
;
4528 SCCOL nOverX
; // start of the merged cells
4530 if (GetMergeOrigin( nX
,nY
, 1, nOverX
,nOverY
, true ))
4537 else if ( nX
== nX2
&& pThisRowInfo
->pCellInfo
[nX
+1].maCell
.isEmpty() )
4539 // Rest of a long text further to the right?
4542 while (nTempX
< nLastContentCol
&& IsEmptyCellText( pThisRowInfo
, nTempX
, nY
))
4546 !IsEmptyCellText( pThisRowInfo
, nTempX
, nY
) &&
4547 !mpDoc
->HasAttrib( nTempX
,nY
,nTab
, nX
,nY
,nTab
, HASATTR_MERGED
| HASATTR_OVERLAPPED
) )
4558 if ( bDoCell
&& bEditMode
&& nCellX
== nEditCol
&& nCellY
== nEditRow
)
4561 const ScPatternAttr
* pPattern
= NULL
;
4562 const SfxItemSet
* pCondSet
= NULL
;
4565 if ( nCellY
== nY
&& nCellX
>= nX1
&& nCellX
<= nX2
&&
4566 !mpDoc
->ColHidden(nCellX
, nTab
) )
4568 CellInfo
& rCellInfo
= pThisRowInfo
->pCellInfo
[nCellX
+1];
4569 pPattern
= rCellInfo
.pPatternAttr
;
4570 pCondSet
= rCellInfo
.pConditionSet
;
4571 aCell
= rCellInfo
.maCell
;
4573 else // get from document
4575 pPattern
= mpDoc
->GetPattern( nCellX
, nCellY
, nTab
);
4576 pCondSet
= mpDoc
->GetCondResult( nCellX
, nCellY
, nTab
);
4577 GetVisibleCell( nCellX
, nCellY
, nTab
, aCell
);
4579 if (aCell
.isEmpty())
4584 if ( mpDoc
->GetPreviewCellStyle() )
4586 if ( ScStyleSheet
* pPreviewStyle
= mpDoc
->GetPreviewCellStyle( nCellX
, nCellY
, nTab
) )
4588 pPreviewPattr
.reset( new ScPatternAttr(*pPattern
) );
4589 pPreviewPattr
->SetStyleSheet(pPreviewStyle
);
4590 pPattern
= const_cast<ScPatternAttr
*>(pPreviewPattr
.get());
4593 SfxItemSet
* pPreviewFontSet
= mpDoc
->GetPreviewFont( nCellX
, nCellY
, nTab
);
4595 pEngine
.reset(CreateOutputEditEngine());
4597 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4599 // fdo#32530: Check if the first character is RTL.
4600 OUString aStr
= mpDoc
->GetString(nCellX
, nCellY
, nTab
);
4602 DrawEditParam
aParam(pPattern
, pCondSet
, lcl_SafeIsValue(aCell
));
4603 aParam
.meHorJustContext
= getAlignmentFromContext( aParam
.meHorJustAttr
,
4604 aParam
.mbCellIsValue
, aStr
, *pPattern
, pCondSet
, mpDoc
, nTab
);
4605 aParam
.meHorJustResult
= (aParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_BLOCK
) ?
4606 SVX_HOR_JUSTIFY_BLOCK
: aParam
.meHorJustContext
;
4607 aParam
.mbPixelToLogic
= bPixelToLogic
;
4608 aParam
.mbHyphenatorSet
= bHyphenatorSet
;
4609 aParam
.mpEngine
= pEngine
.get();
4610 aParam
.maCell
= aCell
;
4611 aParam
.mnArrY
= nArrY
;
4614 aParam
.mnCellX
= nCellX
;
4615 aParam
.mnCellY
= nCellY
;
4616 aParam
.mnTab
= nTab
;
4617 aParam
.mnPosX
= nPosX
;
4618 aParam
.mnPosY
= nPosY
;
4619 aParam
.mnInitPosX
= nInitPosX
;
4620 aParam
.mpPreviewFontSet
= pPreviewFontSet
;
4621 aParam
.mpPreviewFontSet
= pPreviewFontSet
;
4622 aParam
.mpOldPattern
= pOldPattern
;
4623 aParam
.mpOldCondSet
= pOldCondSet
;
4624 aParam
.mpOldPreviewFontSet
= pOldPreviewFontSet
;
4625 aParam
.mpThisRowInfo
= pThisRowInfo
;
4626 if (mpSpellCheckCxt
)
4627 aParam
.mpMisspellRanges
= mpSpellCheckCxt
->getMisspellRanges(nCellX
, nCellY
);
4629 if (aParam
.meHorJustAttr
== SVX_HOR_JUSTIFY_REPEAT
)
4631 // ignore orientation/rotation if "repeat" is active
4632 aParam
.meOrient
= SVX_ORIENTATION_STANDARD
;
4634 switch (aParam
.meOrient
)
4636 case SVX_ORIENTATION_BOTTOMTOP
:
4637 DrawEditBottomTop(aParam
);
4639 case SVX_ORIENTATION_TOPBOTTOM
:
4640 DrawEditTopBottom(aParam
);
4642 case SVX_ORIENTATION_STACKED
:
4643 // this can be vertically stacked or asian vertical.
4644 DrawEditStacked(aParam
);
4647 DrawEditStandard(aParam
);
4650 // Retrieve parameters for next iteration.
4651 pOldPattern
= aParam
.mpOldPattern
;
4652 pOldCondSet
= aParam
.mpOldCondSet
;
4653 pOldPreviewFontSet
= aParam
.mpOldPreviewFontSet
;
4654 bHyphenatorSet
= aParam
.mbHyphenatorSet
;
4657 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
4660 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
4666 DrawRotated(bPixelToLogic
); //! von aussen rufen ?
4669 void ScOutputData::DrawRotated(bool bPixelToLogic
)
4671 //! nRotMax speichern
4672 SCCOL nRotMax
= nX2
;
4673 for (SCSIZE nRotY
=0; nRotY
<nArrCount
; nRotY
++)
4674 if (pRowInfo
[nRotY
].nRotMaxCol
!= SC_ROTMAX_NONE
&& pRowInfo
[nRotY
].nRotMaxCol
> nRotMax
)
4675 nRotMax
= pRowInfo
[nRotY
].nRotMaxCol
;
4678 ScModule
* pScMod
= SC_MOD();
4679 sal_Int32 nConfBackColor
= pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
4680 bool bCellContrast
= mbUseStyleColor
&&
4681 Application::GetSettings().GetStyleSettings().GetHighContrastMode();
4683 boost::scoped_ptr
<ScFieldEditEngine
> pEngine
;
4684 bool bHyphenatorSet
= false;
4685 const ScPatternAttr
* pPattern
;
4686 const SfxItemSet
* pCondSet
;
4687 const ScPatternAttr
* pOldPattern
= NULL
;
4688 const SfxItemSet
* pOldCondSet
= NULL
;
4689 ScRefCellValue aCell
;
4691 long nInitPosX
= nScrX
;
4694 nInitPosX
+= nMirrorW
- 1;
4696 long nLayoutSign
= bLayoutRTL
? -1 : 1;
4698 long nRowPosY
= nScrY
;
4699 for (SCSIZE nArrY
=0; nArrY
+1<nArrCount
; nArrY
++) // 0 fuer Reste von zusammengefassten
4701 RowInfo
* pThisRowInfo
= &pRowInfo
[nArrY
];
4702 long nCellHeight
= (long) pThisRowInfo
->nHeight
;
4703 if (nArrY
==1) nRowPosY
= nScrY
; // vorher wird einzeln berechnet
4705 if ( ( pThisRowInfo
->bChanged
|| nArrY
==0 ) && pThisRowInfo
->nRotMaxCol
!= SC_ROTMAX_NONE
)
4708 for (SCCOL nX
=0; nX
<=nRotMax
; nX
++)
4710 if (nX
==nX1
) nPosX
= nInitPosX
; // positions before nX1 are calculated individually
4712 CellInfo
* pInfo
= &pThisRowInfo
->pCellInfo
[nX
+1];
4713 if ( pInfo
->nRotateDir
!= SC_ROTDIR_NONE
)
4715 SCROW nY
= pThisRowInfo
->nRowNo
;
4717 bool bHidden
= false;
4719 if ( nX
== nEditCol
&& nY
== nEditRow
)
4725 pEngine
.reset(CreateOutputEditEngine());
4727 lcl_ClearEdit( *pEngine
); // also calls SetUpdateMode(sal_False)
4729 long nPosY
= nRowPosY
;
4730 bool bVisChanged
= false;
4732 //! Rest von zusammengefasster Zelle weiter oben funktioniert nicht!
4734 bool bFromDoc
= false;
4735 pPattern
= pInfo
->pPatternAttr
;
4736 pCondSet
= pInfo
->pConditionSet
;
4739 pPattern
= mpDoc
->GetPattern( nX
, nY
, nTab
);
4742 aCell
= pInfo
->maCell
;
4744 pCondSet
= mpDoc
->GetCondResult( nX
, nY
, nTab
);
4746 if (aCell
.isEmpty() && nX
>nX2
)
4747 GetVisibleCell( nX
, nY
, nTab
, aCell
);
4749 if (aCell
.isEmpty() || IsEmptyCellText(pThisRowInfo
, nX
, nY
))
4750 bHidden
= true; // nRotateDir is also set without a cell
4752 long nCellWidth
= (long) pRowInfo
[0].pCellInfo
[nX
+1].nWidth
;
4754 SvxCellHorJustify eHorJust
= (SvxCellHorJustify
)((const SvxHorJustifyItem
&)
4755 pPattern
->GetItem(ATTR_HOR_JUSTIFY
, pCondSet
)).GetValue();
4756 bool bBreak
= ( eHorJust
== SVX_HOR_JUSTIFY_BLOCK
) ||
4757 ((const SfxBoolItem
&)pPattern
->GetItem(ATTR_LINEBREAK
, pCondSet
)).GetValue();
4758 bool bRepeat
= ( eHorJust
== SVX_HOR_JUSTIFY_REPEAT
&& !bBreak
);
4759 bool bShrink
= !bBreak
&& !bRepeat
&& static_cast<const SfxBoolItem
&>
4760 (pPattern
->GetItem( ATTR_SHRINKTOFIT
, pCondSet
)).GetValue();
4761 SvxCellOrientation eOrient
= pPattern
->GetCellOrientation( pCondSet
);
4763 const ScMergeAttr
* pMerge
=
4764 (ScMergeAttr
*)&pPattern
->GetItem(ATTR_MERGE
);
4765 bool bMerged
= pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1;
4767 long nStartX
= nPosX
;
4768 long nStartY
= nPosY
;
4771 if ((bBreak
|| eOrient
!=SVX_ORIENTATION_STANDARD
) && !bMerged
)
4775 nStartX
= nInitPosX
;
4780 nStartX
-= nLayoutSign
* (long) pRowInfo
[0].pCellInfo
[nCol
+1].nWidth
;
4784 long nCellStartX
= nStartX
;
4786 // Ersatzdarstellung fuer zu kleinen Text weggelassen
4790 long nOutWidth
= nCellWidth
- 1;
4791 long nOutHeight
= nCellHeight
;
4793 if ( bMerged
) // Zusammengefasst
4795 SCCOL nCountX
= pMerge
->GetColMerge();
4796 for (SCCOL i
=1; i
<nCountX
; i
++)
4797 nOutWidth
+= (long) ( mpDoc
->GetColWidth(nX
+i
,nTab
) * mnPPTX
);
4798 SCROW nCountY
= pMerge
->GetRowMerge();
4799 nOutHeight
+= (long) mpDoc
->GetScaledRowHeight( nY
+1, nY
+nCountY
-1, nTab
, mnPPTY
);
4802 SvxCellVerJustify eVerJust
= (SvxCellVerJustify
)((const SvxVerJustifyItem
&)
4803 pPattern
->GetItem(ATTR_VER_JUSTIFY
, pCondSet
)).GetValue();
4805 // Syntax-Modus wird hier ignoriert...
4807 // StringDiffer doesn't look at hyphenate, language items
4808 if ( pPattern
!= pOldPattern
|| pCondSet
!= pOldCondSet
)
4810 SfxItemSet
* pSet
= new SfxItemSet( pEngine
->GetEmptyItemSet() );
4811 pPattern
->FillEditItemSet( pSet
, pCondSet
);
4813 // Ausrichtung fuer EditEngine
4814 SvxAdjust eSvxAdjust
= SVX_ADJUST_LEFT
;
4815 if (eOrient
==SVX_ORIENTATION_STACKED
)
4816 eSvxAdjust
= SVX_ADJUST_CENTER
;
4817 // Adjustment fuer bBreak ist hier weggelassen
4818 pSet
->Put( SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
4820 pEngine
->SetDefaults( pSet
);
4821 pOldPattern
= pPattern
;
4822 pOldCondSet
= pCondSet
;
4824 sal_uLong nControl
= pEngine
->GetControlWord();
4825 if (eOrient
==SVX_ORIENTATION_STACKED
)
4826 nControl
|= EE_CNTRL_ONECHARPERLINE
;
4828 nControl
&= ~EE_CNTRL_ONECHARPERLINE
;
4829 pEngine
->SetControlWord( nControl
);
4831 if ( !bHyphenatorSet
&& ((const SfxBoolItem
&)pSet
->Get(EE_PARA_HYPHENATE
)).GetValue() )
4833 // set hyphenator the first time it is needed
4834 com::sun::star::uno::Reference
<com::sun::star::linguistic2::XHyphenator
> xXHyphenator( LinguMgr::GetHyphenator() );
4835 pEngine
->SetHyphenator( xXHyphenator
);
4836 bHyphenatorSet
= true;
4839 Color aBackCol
= ((const SvxBrushItem
&)
4840 pPattern
->GetItem( ATTR_BACKGROUND
, pCondSet
)).GetColor();
4841 if ( mbUseStyleColor
&& ( aBackCol
.GetTransparency() > 0 || bCellContrast
) )
4842 aBackCol
.SetColor( nConfBackColor
);
4843 pEngine
->SetBackgroundColor( aBackCol
);
4848 //! Position und Papersize auf EditUtil umstellen !!!
4850 const SvxMarginItem
* pMargin
= (const SvxMarginItem
*)
4851 &pPattern
->GetItem(ATTR_MARGIN
, pCondSet
);
4852 sal_uInt16 nIndent
= 0;
4853 if ( eHorJust
== SVX_HOR_JUSTIFY_LEFT
)
4854 nIndent
= ((const SfxUInt16Item
&)pPattern
->
4855 GetItem(ATTR_INDENT
, pCondSet
)).GetValue();
4857 long nTotalHeight
= nOutHeight
; // ohne Rand abzuziehen
4858 if ( bPixelToLogic
)
4859 nTotalHeight
= mpRefDevice
->PixelToLogic(Size(0,nTotalHeight
)).Height();
4861 long nLeftM
= (long) ( (pMargin
->GetLeftMargin() + nIndent
) * mnPPTX
);
4862 long nTopM
= (long) ( pMargin
->GetTopMargin() * mnPPTY
);
4863 long nRightM
= (long) ( pMargin
->GetRightMargin() * mnPPTX
);
4864 long nBottomM
= (long) ( pMargin
->GetBottomMargin() * mnPPTY
);
4867 nOutWidth
-= nLeftM
+ nRightM
;
4868 nOutHeight
-= nTopM
+ nBottomM
;
4870 // Rotation schon hier, um bei Umbruch auch PaperSize anzupassen
4871 long nAttrRotate
= 0;
4874 SvxRotateMode eRotMode
= SVX_ROTATE_MODE_STANDARD
;
4875 if ( eOrient
== SVX_ORIENTATION_STANDARD
)
4877 nAttrRotate
= ((const SfxInt32Item
&)pPattern
->
4878 GetItem(ATTR_ROTATE_VALUE
, pCondSet
)).GetValue();
4881 eRotMode
= (SvxRotateMode
)((const SvxRotateModeItem
&)
4882 pPattern
->GetItem(ATTR_ROTATE_MODE
, pCondSet
)).GetValue();
4884 if ( nAttrRotate
== 18000 )
4885 eRotMode
= SVX_ROTATE_MODE_STANDARD
; // keinen Ueberlauf
4888 nAttrRotate
= -nAttrRotate
;
4890 double nRealOrient
= nAttrRotate
* F_PI18000
; // 1/100 Grad
4891 nCos
= cos( nRealOrient
);
4892 nSin
= sin( nRealOrient
);
4896 Size aPaperSize
= Size( 1000000, 1000000 );
4897 if (eOrient
==SVX_ORIENTATION_STACKED
)
4898 aPaperSize
.Width() = nOutWidth
; // zum Zentrieren
4903 //! richtige PaperSize fuer Umbruch haengt von der Zeilenzahl
4904 //! ab, solange die Zeilen nicht einzeln versetzt ausgegeben
4905 //! werden koennen -> darum unbegrenzt, also kein Umbruch.
4906 //! Mit versetzten Zeilen waere das folgende richtig:
4907 aPaperSize
.Width() = (long)(nOutHeight
/ fabs(nSin
));
4909 else if (eOrient
== SVX_ORIENTATION_STANDARD
)
4910 aPaperSize
.Width() = nOutWidth
;
4912 aPaperSize
.Width() = nOutHeight
- 1;
4915 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4917 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
4919 // Daten aus Zelle lesen
4921 if (aCell
.meType
== CELLTYPE_EDIT
)
4923 if (aCell
.mpEditText
)
4924 pEngine
->SetText(*aCell
.mpEditText
);
4927 OSL_FAIL("pData == 0");
4932 sal_uLong nFormat
= pPattern
->GetNumberFormat(
4933 mpDoc
->GetFormatTable(), pCondSet
);
4936 ScCellFormat::GetString( aCell
,
4937 nFormat
,aString
, &pColor
,
4938 *mpDoc
->GetFormatTable(),
4944 pEngine
->SetText(aString
);
4945 if ( pColor
&& !mbSyntaxMode
&& !( mbUseStyleColor
&& mbForceAutoColor
) )
4946 lcl_SetEditColor( *pEngine
, *pColor
);
4951 SetEditSyntaxColor(*pEngine
, aCell
);
4953 else if ( mbUseStyleColor
&& mbForceAutoColor
)
4954 lcl_SetEditColor( *pEngine
, COL_AUTO
); //! or have a flag at EditEngine
4956 pEngine
->SetUpdateMode( true ); // after SetText, before CalcTextWidth/GetTextHeight
4958 long nEngineWidth
= (long) pEngine
->CalcTextWidth();
4959 long nEngineHeight
= pEngine
->GetTextHeight();
4961 if (nAttrRotate
&& bBreak
)
4963 double nAbsCos
= fabs( nCos
);
4964 double nAbsSin
= fabs( nSin
);
4966 // adjust witdh of papersize for height of text
4970 // everything is in pixels
4971 long nEnginePixel
= mpRefDevice
->LogicToPixel(
4972 Size(0,nEngineHeight
)).Height();
4973 long nEffHeight
= nOutHeight
- (long)(nEnginePixel
* nAbsCos
) + 2;
4974 long nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
4975 bool bFits
= ( nNewWidth
>= aPaperSize
.Width() );
4980 if ( nNewWidth
< 4 )
4982 // can't fit -> fall back to using half height
4983 nEffHeight
= nOutHeight
/ 2;
4984 nNewWidth
= (long)(nEffHeight
/ nAbsSin
) + 2;
4990 // set paper width and get new text height
4991 aPaperSize
.Width() = nNewWidth
;
4993 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
4995 pEngine
->SetPaperSize(aPaperSize
); // Scale ist immer 1
4996 //pEngine->QuickFormatDoc( sal_True );
4997 nEngineWidth
= (long) pEngine
->CalcTextWidth();
4998 nEngineHeight
= pEngine
->GetTextHeight();
5003 long nRealWidth
= nEngineWidth
;
5004 long nRealHeight
= nEngineHeight
;
5006 // wenn gedreht, Groesse anpassen
5009 double nAbsCos
= fabs( nCos
);
5010 double nAbsSin
= fabs( nSin
);
5012 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5013 nEngineWidth
= (long) ( nRealWidth
* nAbsCos
+
5014 nRealHeight
* nAbsSin
);
5016 nEngineWidth
= (long) ( nRealHeight
/ nAbsSin
);
5019 nEngineHeight
= (long) ( nRealHeight
* nAbsCos
+
5020 nRealWidth
* nAbsSin
);
5023 if (!nAttrRotate
) // hier nur gedrehter Text
5024 bHidden
= true; //! vorher abfragen !!!
5026 //! weglassen, was nicht hereinragt
5031 Size aClipSize
= Size( nScrX
+nScrW
-nStartX
, nScrY
+nScrH
-nStartY
);
5037 aCellSize
= mpRefDevice
->PixelToLogic( Size( nOutWidth
, nOutHeight
) );
5039 aCellSize
= Size( nOutWidth
, nOutHeight
); // Scale ist 1
5041 long nGridWidth
= nEngineWidth
;
5042 bool bNegative
= false;
5043 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5045 nGridWidth
= aCellSize
.Width() +
5046 std::abs((long) ( aCellSize
.Height() * nCos
/ nSin
));
5047 bNegative
= ( pInfo
->nRotateDir
== SC_ROTDIR_LEFT
);
5049 bNegative
= !bNegative
;
5052 // use GetOutputArea to hide the grid
5053 // (clip region is done manually below)
5054 OutputAreaParam aAreaParam
;
5058 SvxCellHorJustify eOutHorJust
= eHorJust
;
5059 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5060 eOutHorJust
= bNegative
? SVX_HOR_JUSTIFY_RIGHT
: SVX_HOR_JUSTIFY_LEFT
;
5061 long nNeededWidth
= nGridWidth
; // in pixel for GetOutputArea
5062 if ( bPixelToLogic
)
5063 nNeededWidth
= mpRefDevice
->LogicToPixel(Size(nNeededWidth
,0)).Width();
5065 GetOutputArea( nX
, nArrY
, nCellStartX
, nPosY
, nCellX
, nCellY
, nNeededWidth
,
5066 *pPattern
, sal::static_int_cast
<sal_uInt16
>(eOutHorJust
),
5067 false, false, true, aAreaParam
);
5071 long nPixelWidth
= bPixelToLogic
?
5072 mpRefDevice
->LogicToPixel(Size(nEngineWidth
,0)).Width() : nEngineWidth
;
5073 long nNeededPixel
= nPixelWidth
+ nLeftM
+ nRightM
;
5075 aAreaParam
.mbLeftClip
= aAreaParam
.mbRightClip
= true;
5078 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5079 false, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5080 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5082 if ( eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5084 // do width only if rotating within the cell (standard mode)
5085 ShrinkEditEngine( *pEngine
, aAreaParam
.maAlignRect
, nLeftM
, nTopM
, nRightM
, nBottomM
,
5086 true, sal::static_int_cast
<sal_uInt16
>(eOrient
), nAttrRotate
, bPixelToLogic
,
5087 nEngineWidth
, nEngineHeight
, nNeededPixel
, aAreaParam
.mbLeftClip
, aAreaParam
.mbRightClip
);
5090 // nEngineWidth/nEngineHeight is updated in ShrinkEditEngine
5091 // (but width is only valid for standard mode)
5092 nRealWidth
= (long) pEngine
->CalcTextWidth();
5093 nRealHeight
= pEngine
->GetTextHeight();
5095 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5096 nEngineWidth
= (long) ( nRealHeight
/ fabs( nSin
) );
5099 long nClipStartX
= nStartX
;
5102 //! Clipping unnoetig, wenn links am Fenster
5104 bClip
= true; // nur Rest ausgeben!
5107 long nDif
= nScrX
- nStartX
;
5108 nClipStartX
= nScrX
;
5109 aClipSize
.Width() -= nDif
;
5113 long nClipStartY
= nStartY
;
5114 if (nArrY
==0 || bVisChanged
)
5116 if ( nClipStartY
< nRowPosY
)
5118 long nDif
= nRowPosY
- nClipStartY
;
5120 nClipStartY
= nRowPosY
;
5121 aClipSize
.Height() -= nDif
;
5125 bClip
= true; // always clip at the window/page border
5127 //Rectangle aClipRect;
5130 if ( nAttrRotate
/* && eRotMode != SVX_ROTATE_MODE_STANDARD */ )
5132 // gedrehten, ausgerichteten Text nur an den
5133 // Seitengrenzen clippen
5134 nClipStartX
= nScrX
;
5135 aClipSize
.Width() = nScrW
;
5139 aAreaParam
.maClipRect
= mpRefDevice
->PixelToLogic( Rectangle(
5140 Point(nClipStartX
,nClipStartY
), aClipSize
) );
5142 aAreaParam
.maClipRect
= Rectangle(Point(nClipStartX
, nClipStartY
),
5143 aClipSize
); // Scale = 1
5148 mpDev
->IntersectClipRegion( aAreaParam
.maClipRect
);
5151 mpDev
->SetClipRegion( Region( aAreaParam
.maClipRect
) );
5156 aLogicStart
= mpRefDevice
->PixelToLogic( Point(nStartX
,nStartY
) );
5158 aLogicStart
= Point(nStartX
, nStartY
);
5159 if ( eOrient
!=SVX_ORIENTATION_STANDARD
|| !bBreak
)
5161 long nAvailWidth
= aCellSize
.Width();
5162 if (eType
==OUTTYPE_WINDOW
&&
5163 eOrient
!=SVX_ORIENTATION_STACKED
&&
5166 // filter drop-down width is now independent from row height
5168 nAvailWidth
-= mpRefDevice
->PixelToLogic(Size(0,DROPDOWN_BITMAP_SIZE
)).Height();
5170 nAvailWidth
-= DROPDOWN_BITMAP_SIZE
;
5171 long nComp
= nEngineWidth
;
5172 if (nAvailWidth
<nComp
) nAvailWidth
=nComp
;
5175 // horizontale Ausrichtung
5177 if (eOrient
==SVX_ORIENTATION_STANDARD
&& !nAttrRotate
)
5179 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
||
5180 eHorJust
==SVX_HOR_JUSTIFY_CENTER
)
5182 pEngine
->SetUpdateMode( false );
5184 SvxAdjust eSvxAdjust
=
5185 (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
) ?
5186 SVX_ADJUST_RIGHT
: SVX_ADJUST_CENTER
;
5187 pEngine
->SetDefaultItem(
5188 SvxAdjustItem( eSvxAdjust
, EE_PARA_JUST
) );
5190 aPaperSize
.Width() = nOutWidth
;
5192 pEngine
->SetPaperSize(mpRefDevice
->PixelToLogic(aPaperSize
));
5194 pEngine
->SetPaperSize(aPaperSize
);
5196 pEngine
->SetUpdateMode( true );
5201 // bei gedrehtem Text ist Standard zentriert
5202 if (eHorJust
==SVX_HOR_JUSTIFY_RIGHT
)
5203 aLogicStart
.X() += nAvailWidth
- nEngineWidth
;
5204 else if (eHorJust
==SVX_HOR_JUSTIFY_CENTER
||
5205 eHorJust
==SVX_HOR_JUSTIFY_STANDARD
)
5206 aLogicStart
.X() += (nAvailWidth
- nEngineWidth
) / 2;
5213 aLogicStart
.X() -= mpRefDevice
->PixelToLogic(
5214 Size( nCellWidth
, 0 ) ).Width();
5216 aLogicStart
.X() -= nCellWidth
;
5219 if ( eOrient
==SVX_ORIENTATION_STANDARD
||
5220 eOrient
==SVX_ORIENTATION_STACKED
|| !bBreak
)
5222 if (eVerJust
==SVX_VER_JUSTIFY_BOTTOM
||
5223 eVerJust
==SVX_VER_JUSTIFY_STANDARD
)
5226 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,
5227 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5228 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height()
5231 aLogicStart
.Y() += aCellSize
.Height() - nEngineHeight
;
5234 else if (eVerJust
==SVX_VER_JUSTIFY_CENTER
)
5237 aLogicStart
.Y() += mpRefDevice
->PixelToLogic( Size(0,(
5238 mpRefDevice
->LogicToPixel(aCellSize
).Height() -
5239 mpRefDevice
->LogicToPixel(Size(0,nEngineHeight
)).Height())
5242 aLogicStart
.Y() += (aCellSize
.Height() - nEngineHeight
) / 2;
5246 // TOPBOTTON and BOTTOMTOP are handled in DrawStrings/DrawEdit
5247 OSL_ENSURE( eOrient
== SVX_ORIENTATION_STANDARD
&& nAttrRotate
,
5248 "DrawRotated: no rotation" );
5253 // Attribut ist 1/100, Font 1/10 Grad
5254 nOriVal
= nAttrRotate
/ 10;
5258 if ( nCos
> 0.0 && eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5261 double nH
= nRealHeight
* nCos
;
5262 nAddX
+= nH
* ( nCos
/ fabs(nSin
) );
5264 if ( nCos
< 0.0 && eRotMode
== SVX_ROTATE_MODE_STANDARD
)
5265 nAddX
-= nRealWidth
* nCos
;
5267 nAddX
-= nRealHeight
* nSin
;
5269 nAddY
+= nRealWidth
* nSin
;
5271 nAddY
-= nRealHeight
* nCos
;
5273 if ( eRotMode
!= SVX_ROTATE_MODE_STANDARD
)
5276 double nSkew
= nTotalHeight
* nCos
/ fabs(nSin
);
5277 if ( eRotMode
== SVX_ROTATE_MODE_CENTER
)
5278 nAddX
-= nSkew
* 0.5;
5279 if ( ( eRotMode
== SVX_ROTATE_MODE_TOP
&& nSin
> 0.0 ) ||
5280 ( eRotMode
== SVX_ROTATE_MODE_BOTTOM
&& nSin
< 0.0 ) )
5284 if ( eVerJust
== SVX_VER_JUSTIFY_CENTER
)
5285 nUp
= ( aCellSize
.Height() - nEngineHeight
) / 2;
5286 else if ( eVerJust
== SVX_VER_JUSTIFY_TOP
)
5289 nUp
= aCellSize
.Height() - nEngineHeight
;
5291 else // BOTTOM / STANDARD
5294 nUp
= aCellSize
.Height() - nEngineHeight
;
5297 nAddX
+= ( nUp
* nCos
/ fabs(nSin
) );
5300 aLogicStart
.X() += (long) nAddX
;
5301 aLogicStart
.Y() += (long) nAddY
;
5304 // bSimClip is not used here (because nOriVal is set)
5306 if ( pEngine
->IsRightToLeft( 0 ) )
5308 // For right-to-left, EditEngine always calculates its lines
5309 // beginning from the right edge, but EditLine::nStartPosX is
5310 // of sal_uInt16 type, so the PaperSize must be limited to USHRT_MAX.
5311 Size aLogicPaper
= pEngine
->GetPaperSize();
5312 if ( aLogicPaper
.Width() > USHRT_MAX
)
5314 aLogicPaper
.Width() = USHRT_MAX
;
5315 pEngine
->SetPaperSize(aLogicPaper
);
5319 pEngine
->Draw( mpDev
, aLogicStart
, (short)nOriVal
);
5326 mpDev
->SetClipRegion();
5332 nPosX
+= pRowInfo
[0].pCellInfo
[nX
+1].nWidth
* nLayoutSign
;
5335 nRowPosY
+= pRowInfo
[nArrY
].nHeight
;
5339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */