LCOV - code coverage report
Current view: top level - starmath/source - rect.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 287 327 87.8 %
Date: 2012-08-25 Functions: 19 23 82.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 173 300 57.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : #include <osl/diagnose.h>
      21                 :            : #include <vcl/svapp.hxx>
      22                 :            : #include <vcl/wrkwin.hxx>
      23                 :            : #include <vcl/virdev.hxx>
      24                 :            : 
      25                 :            : 
      26                 :            : #include "rect.hxx"
      27                 :            : #include "types.hxx"
      28                 :            : #include "utility.hxx"
      29                 :            : #include "smmod.hxx"
      30                 :            : 
      31                 :            : 
      32                 :            : ////////////////////////////////////////////////////////////////////////////////
      33                 :            : 
      34                 :            : 
      35                 :            : // '\0' terminated Array with symbol, which should be treat as letters in
      36                 :            : // StarMath Font, (to get a normal (non-clipped) SmRect in contrast to the
      37                 :            : // other operators and symbols).
      38                 :            : static xub_Unicode const aMathAlpha[] =
      39                 :            : {
      40                 :            :     MS_ALEPH,               MS_IM,                  MS_RE,
      41                 :            :     MS_WP,                  xub_Unicode(0xE070),    MS_EMPTYSET,
      42                 :            :     xub_Unicode(0x2113),    xub_Unicode(0xE0D6),    xub_Unicode(0x2107),
      43                 :            :     xub_Unicode(0x2127),    xub_Unicode(0x210A),    MS_HBAR,
      44                 :            :     MS_LAMBDABAR,           MS_SETN,                MS_SETZ,
      45                 :            :     MS_SETQ,                MS_SETR,                MS_SETC,
      46                 :            :     xub_Unicode(0x2373),    xub_Unicode(0xE0A5),    xub_Unicode(0x2112),
      47                 :            :     xub_Unicode(0x2130),    xub_Unicode(0x2131),
      48                 :            :     xub_Unicode('\0')
      49                 :            : };
      50                 :            : 
      51                 :       6388 : bool SmIsMathAlpha(const rtl::OUString &rText)
      52                 :            :     // true iff symbol (from StarMath Font) should be treated as letter
      53                 :            : {
      54         [ +  + ]:       6388 :     if (rText.isEmpty())
      55                 :         18 :         return false;
      56                 :            : 
      57                 :            :     OSL_ENSURE(rText.getLength() == 1, "Sm : string must be exactly one character long");
      58                 :       6370 :     xub_Unicode cChar = rText[0];
      59                 :            : 
      60                 :            :     // is it a greek symbol?
      61 [ #  # ][ -  + ]:       6370 :     if (xub_Unicode(0xE0AC) <= cChar  &&  cChar <= xub_Unicode(0xE0D4))
      62                 :          0 :         return true;
      63                 :            :     else
      64                 :            :     {
      65                 :            :         // appears it in 'aMathAlpha'?
      66                 :       6370 :         const xub_Unicode *pChar = aMathAlpha;
      67 [ +  + ][ +  - ]:     152880 :         while (*pChar  &&  *pChar != cChar)
                 [ +  + ]
      68                 :     146510 :             pChar++;
      69                 :       6388 :         return *pChar != xub_Unicode('\0');
      70                 :            :     }
      71                 :            : }
      72                 :            : 
      73                 :            : 
      74                 :            : ////////////////////////////////////////
      75                 :            : //
      76                 :            : // SmRect members
      77                 :            : //
      78                 :            : 
      79                 :            : 
      80                 :      28088 : SmRect::SmRect()
      81                 :            :     // constructs empty rectangle at (0, 0) with width and height 0.
      82                 :            : {
      83                 :            :     OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: ooops...");
      84                 :            :     OSL_ENSURE(aSize == Size(0, 0), "Sm: ooops...");
      85                 :            : 
      86                 :      28088 :     bHasBaseline = bHasAlignInfo = false;
      87                 :            :     nBaseline = nAlignT = nAlignM = nAlignB =
      88                 :            :     nGlyphTop = nGlyphBottom =
      89                 :            :     nItalicLeftSpace = nItalicRightSpace =
      90                 :      28088 :     nLoAttrFence = nHiAttrFence = 0;
      91                 :      28088 :     nBorderWidth = 0;
      92                 :      28088 : }
      93                 :            : 
      94                 :            : 
      95                 :      31546 : SmRect::SmRect(const SmRect &rRect)
      96                 :            : :   aTopLeft(rRect.aTopLeft),
      97                 :      31546 :     aSize(rRect.aSize)
      98                 :            : {
      99                 :      31546 :     bHasBaseline  = rRect.bHasBaseline;
     100                 :      31546 :     nBaseline     = rRect.nBaseline;
     101                 :      31546 :     nAlignT       = rRect.nAlignT;
     102                 :      31546 :     nAlignM       = rRect.nAlignM;
     103                 :      31546 :     nAlignB       = rRect.nAlignB;
     104                 :      31546 :     nGlyphTop     = rRect.nGlyphTop;
     105                 :      31546 :     nGlyphBottom  = rRect.nGlyphBottom;
     106                 :      31546 :     nHiAttrFence  = rRect.nHiAttrFence;
     107                 :      31546 :     nLoAttrFence  = rRect.nLoAttrFence;
     108                 :      31546 :     bHasAlignInfo = rRect.bHasAlignInfo;
     109                 :      31546 :     nItalicLeftSpace  = rRect.nItalicLeftSpace;
     110                 :      31546 :     nItalicRightSpace = rRect.nItalicRightSpace;
     111                 :      31546 :     nBorderWidth  = rRect.nBorderWidth;
     112                 :      31546 : }
     113                 :            : 
     114                 :            : 
     115                 :        180 : void SmRect::CopyAlignInfo(const SmRect &rRect)
     116                 :            : {
     117                 :        180 :     nBaseline     = rRect.nBaseline;
     118                 :        180 :     bHasBaseline  = rRect.bHasBaseline;
     119                 :        180 :     nAlignT       = rRect.nAlignT;
     120                 :        180 :     nAlignM       = rRect.nAlignM;
     121                 :        180 :     nAlignB       = rRect.nAlignB;
     122                 :        180 :     bHasAlignInfo = rRect.bHasAlignInfo;
     123                 :        180 :     nLoAttrFence  = rRect.nLoAttrFence;
     124                 :        180 :     nHiAttrFence  = rRect.nHiAttrFence;
     125                 :        180 : }
     126                 :            : 
     127                 :            : 
     128                 :      14130 : void SmRect::BuildRect(const OutputDevice &rDev, const SmFormat *pFormat,
     129                 :            :                        const rtl::OUString &rText, sal_uInt16 nBorder)
     130                 :            : {
     131                 :            :     OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: Ooops...");
     132                 :            : 
     133 [ +  - ][ +  - ]:      14130 :     aSize = Size(rDev.GetTextWidth(rText), rDev.GetTextHeight());
         [ +  - ][ +  - ]
     134                 :            : 
     135         [ +  - ]:      14130 :     const FontMetric  aFM (rDev.GetFontMetric());
     136 [ +  - ][ +  - ]:      14130 :     bool              bIsMath  = aFM.GetName().EqualsIgnoreCaseAscii( FONTNAME_MATH );
     137 [ +  + ][ +  - ]:      14130 :     bool              bAllowSmaller = bIsMath && !SmIsMathAlpha(rText);
     138         [ +  - ]:      14130 :     const long        nFontHeight = rDev.GetFont().GetSize().Height();
     139                 :            : 
     140                 :      14130 :     nBorderWidth  = nBorder;
     141                 :      14130 :     bHasAlignInfo = true;
     142                 :      14130 :     bHasBaseline  = true;
     143         [ +  - ]:      14130 :     nBaseline     = aFM.GetAscent();
     144                 :      14130 :     nAlignT       = nBaseline - nFontHeight * 750L / 1000L;
     145                 :      14130 :     nAlignM       = nBaseline - nFontHeight * 121L / 422L;
     146                 :            :         // that's where the horizontal bars of '+', '-', ... are
     147                 :            :         // (1/3 of ascent over baseline)
     148                 :            :         // (121 = 1/3 of 12pt ascent, 422 = 12pt fontheight)
     149                 :      14130 :     nAlignB       = nBaseline;
     150                 :            : 
     151                 :            :     // workaround for printer fonts with very small (possible 0 or even
     152                 :            :     // negative(!)) leading
     153 [ +  - ][ +  + ]:      14130 :     if (aFM.GetIntLeading() < 5  &&  rDev.GetOutDevType() == OUTDEV_PRINTER)
         [ +  - ][ +  + ]
     154                 :            :     {
     155         [ +  - ]:         16 :         OutputDevice    *pWindow = Application::GetDefaultDevice();
     156                 :            : 
     157         [ +  - ]:         16 :         pWindow->Push(PUSH_MAPMODE | PUSH_FONT);
     158                 :            : 
     159         [ +  - ]:         16 :         pWindow->SetMapMode(rDev.GetMapMode());
     160 [ +  - ][ +  - ]:         16 :         pWindow->SetFont(rDev.GetFontMetric());
                 [ +  - ]
     161                 :            : 
     162 [ +  - ][ +  - ]:         16 :         long  nDelta = pWindow->GetFontMetric().GetIntLeading();
                 [ +  - ]
     163         [ +  - ]:         16 :         if (nDelta == 0)
     164                 :            :         {   // this value approx. fits a Leading of 80 at a
     165                 :            :             // Fontheight of 422 (12pt)
     166                 :         16 :             nDelta = nFontHeight * 8L / 43;
     167                 :            :         }
     168         [ +  - ]:         16 :         SetTop(GetTop() - nDelta);
     169                 :            : 
     170         [ +  - ]:         16 :         pWindow->Pop();
     171                 :            :     }
     172                 :            : 
     173                 :            :     // get GlyphBoundRect
     174         [ +  - ]:      14130 :     Rectangle  aGlyphRect;
     175                 :            : #if OSL_DEBUG_LEVEL > 1
     176                 :            :     bool bSuccess =
     177                 :            : #endif
     178         [ +  - ]:      14130 :                 SmGetGlyphBoundRect(rDev, rText, aGlyphRect);
     179                 :            : #if OSL_DEBUG_LEVEL > 1
     180                 :            :     if (!bSuccess)
     181                 :            :     {
     182                 :            :         OSL_FAIL( "Sm : Ooops... (fehlt evtl. der Font?)");
     183                 :            :     }
     184                 :            : #endif
     185                 :            : 
     186                 :      14130 :     nItalicLeftSpace  = GetLeft() - aGlyphRect.Left() + nBorderWidth;
     187         [ +  - ]:      14130 :     nItalicRightSpace = aGlyphRect.Right() - GetRight() + nBorderWidth;
     188 [ +  + ][ +  + ]:      14130 :     if (nItalicLeftSpace  < 0  &&  !bAllowSmaller)
     189                 :       1118 :         nItalicLeftSpace  = 0;
     190 [ +  + ][ +  + ]:      14130 :     if (nItalicRightSpace < 0  &&  !bAllowSmaller)
     191                 :       1824 :         nItalicRightSpace = 0;
     192                 :            : 
     193                 :      14130 :     long  nDist = 0;
     194         [ +  + ]:      14130 :     if (pFormat)
     195         [ +  - ]:      12150 :         nDist = (rDev.GetFont().GetSize().Height()
     196                 :      12150 :                 * pFormat->GetDistance(DIS_ORNAMENTSIZE)) / 100L;
     197                 :            : 
     198                 :      14130 :     nHiAttrFence = aGlyphRect.TopLeft().Y() - 1 - nBorderWidth - nDist;
     199         [ +  - ]:      14130 :     nLoAttrFence = SmFromTo(GetAlignB(), GetBottom(), 0.0);
     200                 :            : 
     201                 :      14130 :     nGlyphTop    = aGlyphRect.Top() - nBorderWidth;
     202                 :      14130 :     nGlyphBottom = aGlyphRect.Bottom() + nBorderWidth;
     203                 :            : 
     204         [ +  + ]:      14130 :     if (bAllowSmaller)
     205                 :            :     {
     206                 :            :         // for symbols and operators from the StarMath Font
     207                 :            :         // we adjust upper and lower margin of the symbol
     208         [ +  - ]:       6388 :         SetTop(nGlyphTop);
     209                 :       6388 :         SetBottom(nGlyphBottom);
     210                 :            :     }
     211                 :            : 
     212         [ +  + ]:      14130 :     if (nHiAttrFence < GetTop())
     213                 :       6424 :         nHiAttrFence = GetTop();
     214                 :            : 
     215 [ +  - ][ +  + ]:      14130 :     if (nLoAttrFence > GetBottom())
     216         [ +  - ]:       1756 :         nLoAttrFence = GetBottom();
     217                 :            : 
     218                 :            :     OSL_ENSURE(rText.isEmpty() || !IsEmpty(),
     219         [ +  - ]:      14130 :                "Sm: empty rectangle created");
     220                 :      14130 : }
     221                 :            : 
     222                 :            : 
     223                 :      14130 : void SmRect::Init(const OutputDevice &rDev, const SmFormat *pFormat,
     224                 :            :                   const rtl::OUString &rText, sal_uInt16 nEBorderWidth)
     225                 :            :     // get rectangle fitting for drawing 'rText' on OutputDevice 'rDev'
     226                 :            : {
     227                 :      14130 :     BuildRect(rDev, pFormat, rText, nEBorderWidth);
     228                 :      14130 : }
     229                 :            : 
     230                 :            : 
     231                 :      14130 : SmRect::SmRect(const OutputDevice &rDev, const SmFormat *pFormat,
     232                 :      14130 :                const rtl::OUString &rText, long nEBorderWidth)
     233                 :            : {
     234                 :            :     OSL_ENSURE( nEBorderWidth >= 0, "BorderWidth is negative" );
     235         [ -  + ]:      14130 :     if (nEBorderWidth < 0)
     236                 :          0 :         nEBorderWidth = 0;
     237                 :      14130 :     Init(rDev, pFormat, rText, (sal_uInt16) nEBorderWidth);
     238                 :      14130 : }
     239                 :            : 
     240                 :            : 
     241                 :       2174 : SmRect::SmRect(long nWidth, long nHeight)
     242                 :            :     // this constructor should never be used for anything textlike because
     243                 :            :     // it will not provide useful values for baseline, AlignT and AlignB!
     244                 :            :     // It's purpose is to get a 'SmRect' for the horizontal line in fractions
     245                 :            :     // as used in 'SmBinVerNode'.
     246                 :       2174 : :   aSize(nWidth, nHeight)
     247                 :            : {
     248                 :            :     OSL_ENSURE(aTopLeft == Point(0, 0), "Sm: ooops...");
     249                 :            : 
     250                 :       2174 :     bHasBaseline  = false;
     251                 :       2174 :     bHasAlignInfo = true;
     252                 :       2174 :     nBaseline     = 0;
     253                 :       2174 :     nAlignT       = GetTop();
     254                 :       2174 :     nAlignB       = GetBottom();
     255                 :       2174 :     nAlignM       = (nAlignT + nAlignB) / 2;        // this is the default
     256                 :       2174 :     nItalicLeftSpace = nItalicRightSpace = 0;
     257                 :       2174 :     nGlyphTop    = nHiAttrFence  = GetTop();
     258                 :       2174 :     nGlyphBottom = nLoAttrFence  = GetBottom();
     259                 :       2174 :     nBorderWidth  = 0;
     260                 :       2174 : }
     261                 :            : 
     262                 :            : 
     263                 :      13190 : void SmRect::SetLeft(long nLeft)
     264                 :            : {
     265         [ +  + ]:      13190 :     if (nLeft <= GetRight())
     266                 :      13082 :     {   aSize.Width() = GetRight() - nLeft + 1;
     267                 :      13082 :         aTopLeft.X()  = nLeft;
     268                 :            :     }
     269                 :      13190 : }
     270                 :            : 
     271                 :            : 
     272                 :      13190 : void SmRect::SetRight(long nRight)
     273                 :            : {
     274         [ +  - ]:      13190 :     if (nRight >= GetLeft())
     275                 :      13190 :         aSize.Width() = nRight - GetLeft() + 1;
     276                 :      13190 : }
     277                 :            : 
     278                 :            : 
     279                 :      19596 : void SmRect::SetBottom(long nBottom)
     280                 :            : {
     281         [ +  + ]:      19596 :     if (nBottom >= GetTop())
     282                 :      19578 :         aSize.Height() = nBottom - GetTop() + 1;
     283                 :      19596 : }
     284                 :            : 
     285                 :            : 
     286                 :      19594 : void SmRect::SetTop(long nTop)
     287                 :            : {
     288         [ +  + ]:      19594 :     if (nTop <= GetBottom())
     289                 :      19558 :     {   aSize.Height()   = GetBottom() - nTop + 1;
     290                 :      19558 :         aTopLeft.Y() = nTop;
     291                 :            :     }
     292                 :      19594 : }
     293                 :            : 
     294                 :            : 
     295                 :      67626 : void SmRect::Move(const Point &rPosition)
     296                 :            :     // move rectangle by position 'rPosition'.
     297                 :            : {
     298                 :      67626 :     aTopLeft  += rPosition;
     299                 :            : 
     300                 :      67626 :     long  nDelta = rPosition.Y();
     301                 :      67626 :     nBaseline += nDelta;
     302                 :      67626 :     nAlignT   += nDelta;
     303                 :      67626 :     nAlignM   += nDelta;
     304                 :      67626 :     nAlignB   += nDelta;
     305                 :      67626 :     nGlyphTop    += nDelta;
     306                 :      67626 :     nGlyphBottom += nDelta;
     307                 :      67626 :     nHiAttrFence += nDelta;
     308                 :      67626 :     nLoAttrFence += nDelta;
     309                 :      67626 : }
     310                 :            : 
     311                 :            : 
     312                 :      13788 : const Point SmRect::AlignTo(const SmRect &rRect, RectPos ePos,
     313                 :            :                             RectHorAlign eHor, RectVerAlign eVer) const
     314                 :      13788 : {   Point  aPos (GetTopLeft());
     315                 :            :         // will become the topleft point of the new rectangle position
     316                 :            : 
     317                 :            :     // set horizontal or vertical new rectangle position depending on
     318                 :            :     // 'ePos' is one of 'RP_LEFT', 'RP_RIGHT' or 'RP_TOP', 'RP_BOTTOM'
     319   [ +  +  +  +  :      13788 :     switch (ePos)
                   +  - ]
     320                 :            :     {   case RP_LEFT :
     321                 :       1338 :             aPos.X() = rRect.GetItalicLeft() - GetItalicRightSpace()
     322                 :       1338 :                        - GetWidth();
     323                 :       1338 :             break;
     324                 :            :         case RP_RIGHT :
     325                 :       8472 :             aPos.X() = rRect.GetItalicRight() + 1 + GetItalicLeftSpace();
     326                 :       8472 :             break;
     327                 :            :         case RP_TOP :
     328                 :        792 :             aPos.Y() = rRect.GetTop() - GetHeight();
     329                 :        792 :             break;
     330                 :            :         case RP_BOTTOM :
     331                 :       2678 :             aPos.Y() = rRect.GetBottom() + 1;
     332                 :       2678 :             break;
     333                 :            :         case RP_ATTRIBUT :
     334                 :        508 :             aPos.X() = rRect.GetItalicCenterX() - GetItalicWidth() / 2
     335                 :        508 :                        + GetItalicLeftSpace();
     336                 :        508 :             break;
     337                 :            :         default :
     338                 :            :             OSL_FAIL("Sm: unknown case");
     339                 :            :     }
     340                 :            : 
     341                 :            :     // check if horizontal position is already set
     342 [ +  + ][ +  + ]:      13788 :     if (ePos == RP_LEFT  ||  ePos == RP_RIGHT  ||  ePos == RP_ATTRIBUT)
                 [ +  + ]
     343                 :            :         // correct error in current vertical position
     344   [ +  +  +  +  :      10318 :         switch (eVer)
             +  +  +  +  
                      - ]
     345                 :            :         {   case RVA_TOP :
     346                 :        738 :                 aPos.Y() += rRect.GetAlignT() - GetAlignT();
     347                 :        738 :                 break;
     348                 :            :             case RVA_MID :
     349                 :        258 :                 aPos.Y() += rRect.GetAlignM() - GetAlignM();
     350                 :        258 :                 break;
     351                 :            :             case RVA_BASELINE :
     352                 :            :                 // align baselines if possible else align mid's
     353 [ +  + ][ +  + ]:       6834 :                 if (HasBaseline() && rRect.HasBaseline())
                 [ +  + ]
     354                 :       5988 :                     aPos.Y() += rRect.GetBaseline() - GetBaseline();
     355                 :            :                 else
     356                 :        846 :                     aPos.Y() += rRect.GetAlignM() - GetAlignM();
     357                 :       6834 :                 break;
     358                 :            :             case RVA_BOTTOM :
     359                 :        288 :                 aPos.Y() += rRect.GetAlignB() - GetAlignB();
     360                 :        288 :                 break;
     361                 :            :             case RVA_CENTERY :
     362                 :       1692 :                 aPos.Y() += rRect.GetCenterY() - GetCenterY();
     363                 :       1692 :                 break;
     364                 :            :             case RVA_ATTRIBUT_HI:
     365                 :        436 :                 aPos.Y() += rRect.GetHiAttrFence() - GetBottom();
     366                 :        436 :                 break;
     367                 :            :             case RVA_ATTRIBUT_MID :
     368                 :         72 :                 aPos.Y() += SmFromTo(rRect.GetAlignB(), rRect.GetAlignT(), 0.4)
     369                 :         36 :                             - GetCenterY();
     370                 :         36 :                 break;
     371                 :            :             case RVA_ATTRIBUT_LO :
     372                 :         36 :                 aPos.Y() += rRect.GetLoAttrFence() - GetTop();
     373                 :         36 :                 break;
     374                 :            :         default :
     375                 :            :                 OSL_FAIL("Sm: unknown case");
     376                 :            :         }
     377                 :            : 
     378                 :            :     // check if vertical position is already set
     379 [ +  + ][ +  + ]:      13788 :     if (ePos == RP_TOP  ||  ePos == RP_BOTTOM)
     380                 :            :         // correct error in current horizontal position
     381   [ -  +  +  - ]:       3470 :         switch (eHor)
     382                 :            :         {   case RHA_LEFT :
     383                 :          0 :                 aPos.X() += rRect.GetItalicLeft() - GetItalicLeft();
     384                 :          0 :                 break;
     385                 :            :             case RHA_CENTER :
     386                 :       3360 :                 aPos.X() += rRect.GetItalicCenterX() - GetItalicCenterX();
     387                 :       3360 :                 break;
     388                 :            :             case RHA_RIGHT :
     389                 :        110 :                 aPos.X() += rRect.GetItalicRight() - GetItalicRight();
     390                 :        110 :                 break;
     391                 :            :             default :
     392                 :            :                 OSL_FAIL("Sm: unknown case");
     393                 :            :         }
     394                 :            : 
     395                 :      13788 :     return aPos;
     396                 :            : }
     397                 :            : 
     398                 :            : 
     399                 :      13608 : SmRect & SmRect::Union(const SmRect &rRect)
     400                 :            :     // rectangle union of current one with 'rRect'. The result is to be the
     401                 :            :     // smallest rectangles that covers the space of both rectangles.
     402                 :            :     // (empty rectangles cover no space)
     403                 :            :     //! Italic correction is NOT taken into account here!
     404                 :            : {
     405         [ +  + ]:      13608 :     if (rRect.IsEmpty())
     406                 :        418 :         return *this;
     407                 :            : 
     408                 :      13190 :     long  nL  = rRect.GetLeft(),
     409                 :      13190 :           nR  = rRect.GetRight(),
     410                 :      13190 :           nT  = rRect.GetTop(),
     411                 :      13190 :           nB  = rRect.GetBottom(),
     412                 :      13190 :           nGT = rRect.nGlyphTop,
     413                 :      13190 :           nGB = rRect.nGlyphBottom;
     414         [ +  + ]:      13190 :     if (!IsEmpty())
     415                 :            :     {   long  nTmp;
     416                 :            : 
     417         [ +  + ]:      13010 :         if ((nTmp = GetLeft()) < nL)
     418                 :      10628 :             nL = nTmp;
     419         [ +  + ]:      13010 :         if ((nTmp = GetRight()) > nR)
     420                 :       3338 :             nR = nTmp;
     421         [ +  + ]:      13010 :         if ((nTmp = GetTop()) < nT)
     422                 :       6538 :             nT = nTmp;
     423         [ +  + ]:      13010 :         if ((nTmp = GetBottom()) > nB)
     424                 :       4562 :             nB = nTmp;
     425         [ +  + ]:      13010 :         if ((nTmp = nGlyphTop) < nGT)
     426                 :       7096 :             nGT = nTmp;
     427         [ +  + ]:      13010 :         if ((nTmp = nGlyphBottom) > nGB)
     428                 :       5264 :             nGB = nTmp;
     429                 :            :     }
     430                 :            : 
     431                 :      13190 :     SetLeft(nL);
     432                 :      13190 :     SetRight(nR);
     433                 :      13190 :     SetTop(nT);
     434                 :      13190 :     SetBottom(nB);
     435                 :      13190 :     nGlyphTop    = nGT;
     436                 :      13190 :     nGlyphBottom = nGB;
     437                 :            : 
     438                 :      13608 :     return *this;
     439                 :            : }
     440                 :            : 
     441                 :            : 
     442                 :      13608 : SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode)
     443                 :            :     // let current rectangle be the union of itself and 'rRect'
     444                 :            :     // (the smallest rectangle surrounding both). Also adapt values for
     445                 :            :     // 'AlignT', 'AlignM', 'AlignB', baseline and italic-spaces.
     446                 :            :     // The baseline is set according to 'eCopyMode'.
     447                 :            :     // If one of the rectangles has no relevant info the other one is copied.
     448                 :            : {
     449                 :            :     // get some values used for (italic) spaces adaption
     450                 :            :     // ! (need to be done before changing current SmRect) !
     451                 :      13608 :     long  nL = Min(GetItalicLeft(),  rRect.GetItalicLeft()),
     452                 :      13608 :           nR = Max(GetItalicRight(), rRect.GetItalicRight());
     453                 :            : 
     454                 :      13608 :     Union(rRect);
     455                 :            : 
     456                 :      13608 :     SetItalicSpaces(GetLeft() - nL, nR - GetRight());
     457                 :            : 
     458         [ +  + ]:      13608 :     if (!HasAlignInfo())
     459                 :        180 :         CopyAlignInfo(rRect);
     460         [ +  + ]:      13428 :     else if (rRect.HasAlignInfo())
     461                 :      13410 :     {   nAlignT = Min(GetAlignT(), rRect.GetAlignT());
     462                 :      13410 :         nAlignB = Max(GetAlignB(), rRect.GetAlignB());
     463                 :      13410 :         nHiAttrFence = Min(GetHiAttrFence(), rRect.GetHiAttrFence());
     464                 :      13410 :         nLoAttrFence = Max(GetLoAttrFence(), rRect.GetLoAttrFence());
     465                 :            :         OSL_ENSURE(HasAlignInfo(), "Sm: ooops...");
     466                 :            : 
     467   [ +  +  +  +  :      13410 :         switch (eCopyMode)
                      - ]
     468                 :            :         {   case RCP_THIS:
     469                 :            :                 // already done
     470                 :       4186 :                 break;
     471                 :            :             case RCP_ARG:
     472                 :       1436 :                 CopyMBL(rRect);
     473                 :       1436 :                 break;
     474                 :            :             case RCP_NONE:
     475                 :       1386 :                 ClearBaseline();
     476                 :       1386 :                 nAlignM = (nAlignT + nAlignB) / 2;
     477                 :       1386 :                 break;
     478                 :            :             case RCP_XOR:
     479         [ +  + ]:       6402 :                 if (!HasBaseline())
     480                 :        270 :                     CopyMBL(rRect);
     481                 :      13410 :                 break;
     482                 :            :             default :
     483                 :            :                 OSL_FAIL("Sm: unknown case");
     484                 :            :         }
     485                 :            :     }
     486                 :            : 
     487                 :      13608 :     return *this;
     488                 :            : }
     489                 :            : 
     490                 :            : 
     491                 :        504 : SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode,
     492                 :            :                           long nNewAlignM)
     493                 :            :     // as 'ExtendBy' but sets AlignM value to 'nNewAlignM'.
     494                 :            :     // (this version will be used in 'SmBinVerNode' to provide means to
     495                 :            :     // align eg "{a over b} over c" correctly where AlignM should not
     496                 :            :     // be (AlignT + AlignB) / 2)
     497                 :            : {
     498                 :            :     OSL_ENSURE(HasAlignInfo(), "Sm: no align info");
     499                 :            : 
     500                 :        504 :     ExtendBy(rRect, eCopyMode);
     501                 :        504 :     nAlignM = nNewAlignM;
     502                 :            : 
     503                 :        504 :     return *this;
     504                 :            : }
     505                 :            : 
     506                 :            : 
     507                 :       2038 : SmRect & SmRect::ExtendBy(const SmRect &rRect, RectCopyMBL eCopyMode,
     508                 :            :                           bool bKeepVerAlignParams)
     509                 :            :     // as 'ExtendBy' but keeps original values for AlignT, -M and -B and
     510                 :            :     // baseline.
     511                 :            :     // (this is used in 'SmSupSubNode' where the sub-/supscripts shouldn't
     512                 :            :     // be allowed to modify these values.)
     513                 :            : {
     514                 :       2038 :     long  nOldAlignT   = GetAlignT(),
     515                 :       2038 :           nOldAlignM   = GetAlignM(),
     516                 :       2038 :           nOldAlignB   = GetAlignB(),
     517                 :       2038 :           nOldBaseline = nBaseline;     //! depends not on 'HasBaseline'
     518                 :       2038 :     bool  bOldHasAlignInfo = HasAlignInfo();
     519                 :            : 
     520                 :       2038 :     ExtendBy(rRect, eCopyMode);
     521                 :            : 
     522         [ +  - ]:       2038 :     if (bKeepVerAlignParams)
     523                 :       2038 :     {   nAlignT   = nOldAlignT;
     524                 :       2038 :         nAlignM   = nOldAlignM;
     525                 :       2038 :         nAlignB   = nOldAlignB;
     526                 :       2038 :         nBaseline = nOldBaseline;
     527                 :       2038 :         bHasAlignInfo = bOldHasAlignInfo;
     528                 :            :     }
     529                 :            : 
     530                 :       2038 :     return *this;
     531                 :            : }
     532                 :            : 
     533                 :            : 
     534                 :          0 : long SmRect::OrientedDist(const Point &rPoint) const
     535                 :            :     // return oriented distance of rPoint to the current rectangle,
     536                 :            :     // especially the return value is <= 0 iff the point is inside the
     537                 :            :     // rectangle.
     538                 :            :     // For simplicity the maximum-norm is used.
     539                 :            : {
     540         [ #  # ]:          0 :     bool  bIsInside = IsInsideItalicRect(rPoint);
     541                 :            : 
     542                 :            :     // build reference point to define the distance
     543                 :          0 :     Point  aRef;
     544         [ #  # ]:          0 :     if (bIsInside)
     545 [ #  # ][ #  # ]:          0 :     {   Point  aIC (GetItalicCenterX(), GetCenterY());
     546                 :            : 
     547 [ #  # ][ #  # ]:          0 :         aRef.X() = rPoint.X() >= aIC.X() ? GetItalicRight() : GetItalicLeft();
     548 [ #  # ][ #  # ]:          0 :         aRef.Y() = rPoint.Y() >= aIC.Y() ? GetBottom() : GetTop();
     549                 :            :     }
     550                 :            :     else
     551                 :            :     {
     552                 :            :         // x-coordinate
     553 [ #  # ][ #  # ]:          0 :         if (rPoint.X() > GetItalicRight())
     554         [ #  # ]:          0 :             aRef.X() = GetItalicRight();
     555         [ #  # ]:          0 :         else if (rPoint.X() < GetItalicLeft())
     556                 :          0 :             aRef.X() = GetItalicLeft();
     557                 :            :         else
     558                 :          0 :             aRef.X() = rPoint.X();
     559                 :            :         // y-coordinate
     560 [ #  # ][ #  # ]:          0 :         if (rPoint.Y() > GetBottom())
     561         [ #  # ]:          0 :             aRef.Y() = GetBottom();
     562         [ #  # ]:          0 :         else if (rPoint.Y() < GetTop())
     563                 :          0 :             aRef.Y() = GetTop();
     564                 :            :         else
     565                 :          0 :             aRef.Y() = rPoint.Y();
     566                 :            :     }
     567                 :            : 
     568                 :            :     // build distance vector
     569                 :          0 :     Point  aDist (aRef - rPoint);
     570                 :            : 
     571                 :          0 :     long nAbsX = labs(aDist.X()),
     572                 :          0 :          nAbsY = labs(aDist.Y());
     573                 :            : 
     574         [ #  # ]:          0 :     return bIsInside ? - Min(nAbsX, nAbsY) : Max (nAbsX, nAbsY);
     575                 :            : }
     576                 :            : 
     577                 :            : 
     578                 :          0 : bool SmRect::IsInsideRect(const Point &rPoint) const
     579                 :            : {
     580                 :          0 :     return     rPoint.Y() >= GetTop()
     581                 :          0 :            &&  rPoint.Y() <= GetBottom()
     582                 :          0 :            &&  rPoint.X() >= GetLeft()
     583 [ #  # ][ #  #  :          0 :            &&  rPoint.X() <= GetRight();
             #  #  #  # ]
     584                 :            : }
     585                 :            : 
     586                 :            : 
     587                 :          0 : bool SmRect::IsInsideItalicRect(const Point &rPoint) const
     588                 :            : {
     589                 :          0 :     return     rPoint.Y() >= GetTop()
     590                 :          0 :            &&  rPoint.Y() <= GetBottom()
     591                 :          0 :            &&  rPoint.X() >= GetItalicLeft()
     592 [ #  # ][ #  #  :          0 :            &&  rPoint.X() <= GetItalicRight();
             #  #  #  # ]
     593                 :            : }
     594                 :            : 
     595                 :          0 : SmRect SmRect::AsGlyphRect() const
     596                 :            : {
     597                 :          0 :     SmRect aRect (*this);
     598                 :          0 :     aRect.SetTop(nGlyphTop);
     599                 :          0 :     aRect.SetBottom(nGlyphBottom);
     600                 :          0 :     return aRect;
     601                 :            : }
     602                 :            : 
     603                 :      14130 : bool SmGetGlyphBoundRect(const OutputDevice &rDev,
     604                 :            :                          const rtl::OUString &rText, Rectangle &rRect)
     605                 :            :     // basically the same as 'GetTextBoundRect' (in class 'OutputDevice')
     606                 :            :     // but with a string as argument.
     607                 :            : {
     608                 :            :     // handle special case first
     609         [ +  + ]:      14130 :     if (rText.isEmpty())
     610                 :            :     {
     611                 :         18 :         rRect.SetEmpty();
     612                 :         18 :         return true;
     613                 :            :     }
     614                 :            : 
     615                 :            :     // get a device where 'OutputDevice::GetTextBoundRect' will be successful
     616                 :            :     OutputDevice *pGlyphDev;
     617         [ +  + ]:      14112 :     if (rDev.GetOutDevType() != OUTDEV_PRINTER)
     618                 :      13932 :         pGlyphDev = (OutputDevice *) &rDev;
     619                 :            :     else
     620                 :            :     {
     621                 :            :         // since we format for the printer (where GetTextBoundRect will fail)
     622                 :            :         // we need a virtual device here.
     623 [ +  - ][ +  - ]:        180 :         pGlyphDev = &SM_MOD()->GetDefaultVirtualDev();
     624                 :            :     }
     625                 :            : 
     626         [ +  - ]:      14112 :     const FontMetric  aDevFM (rDev.GetFontMetric());
     627                 :            : 
     628         [ +  - ]:      14112 :     pGlyphDev->Push(PUSH_FONT | PUSH_MAPMODE);
     629         [ +  - ]:      14112 :     Font aFnt(rDev.GetFont());
     630         [ +  - ]:      14112 :     aFnt.SetAlign(ALIGN_TOP);
     631                 :            : 
     632                 :            :     // use scale factor when calling GetTextBoundRect to counter
     633                 :            :     // negative effects from antialiasing which may otherwise result
     634                 :            :     // in significant incorrect bounding rectangles for some charcters.
     635         [ +  - ]:      14112 :     Size aFntSize = aFnt.GetSize();
     636                 :            : 
     637                 :            :     // Workaround to avoid HUGE font sizes and resulting problems
     638                 :      14112 :     long nScaleFactor = 1;
     639         [ +  + ]:      14238 :     while( aFntSize.Height() > 2000 * nScaleFactor )
     640                 :        126 :         nScaleFactor *= 2;
     641                 :            : 
     642         [ +  - ]:      14112 :     aFnt.SetSize( Size( aFntSize.Width() / nScaleFactor, aFntSize.Height() / nScaleFactor ) );
     643         [ +  - ]:      14112 :     pGlyphDev->SetFont(aFnt);
     644                 :            : 
     645 [ +  - ][ +  - ]:      14112 :     long nTextWidth = rDev.GetTextWidth(rText);
                 [ +  - ]
     646                 :      14112 :     Point aPoint;
     647 [ +  - ][ +  - ]:      14112 :     Rectangle   aResult (aPoint, Size(nTextWidth, rDev.GetTextHeight())),
     648         [ +  - ]:      14112 :                 aTmp;
     649                 :            : 
     650 [ +  - ][ +  - ]:      14112 :     bool bSuccess = pGlyphDev->GetTextBoundRect(aTmp, rText, 0, 0);
                 [ +  - ]
     651                 :            :     OSL_ENSURE( bSuccess, "GetTextBoundRect failed" );
     652                 :            : 
     653                 :            : 
     654 [ +  - ][ +  + ]:      14112 :     if (!aTmp.IsEmpty())
     655                 :            :     {
     656                 :      11700 :         aResult = Rectangle(aTmp.Left() * nScaleFactor, aTmp.Top() * nScaleFactor,
     657         [ +  - ]:      23400 :                             aTmp.Right() * nScaleFactor, aTmp.Bottom() * nScaleFactor);
     658         [ +  + ]:      11700 :         if (&rDev != pGlyphDev) /* only when rDev is a printer... */
     659                 :            :         {
     660 [ +  - ][ +  - ]:        180 :             long nGDTextWidth  = pGlyphDev->GetTextWidth(rText);
                 [ +  - ]
     661 [ +  + ][ +  - ]:        180 :             if (nGDTextWidth != 0  &&
     662                 :            :                 nTextWidth != nGDTextWidth)
     663                 :            :             {
     664                 :        176 :                 aResult.Right() *= nTextWidth;
     665                 :        176 :                 aResult.Right() /= nGDTextWidth * nScaleFactor;
     666                 :            :             }
     667                 :            :         }
     668                 :            :     }
     669                 :            : 
     670                 :            :     // move rectangle to match possibly different baselines
     671                 :            :     // (because of different devices)
     672 [ +  - ][ +  - ]:      14112 :     long nDelta = aDevFM.GetAscent() - pGlyphDev->GetFontMetric().GetAscent() * nScaleFactor;
         [ +  - ][ +  - ]
     673         [ +  - ]:      14112 :     aResult.Move(0, nDelta);
     674                 :            : 
     675         [ +  - ]:      14112 :     pGlyphDev->Pop();
     676                 :            : 
     677                 :      14112 :     rRect = aResult;
     678 [ +  - ][ +  - ]:      14130 :     return bSuccess;
     679                 :            : }
     680                 :            : 
     681                 :            : 
     682                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10