LCOV - code coverage report
Current view: top level - svx/source/dialog - framelink.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 113 475 23.8 %
Date: 2014-04-11 Functions: 18 76 23.7 %
Legend: Lines: hit not hit

          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 <sal/config.h>
      21             : 
      22             : #include <cstdlib>
      23             : 
      24             : #include <svx/framelink.hxx>
      25             : 
      26             : #include <math.h>
      27             : #include <vcl/outdev.hxx>
      28             : #include <tools/gen.hxx>
      29             : #include <editeng/borderline.hxx>
      30             : #include <svtools/borderhelper.hxx>
      31             : 
      32             : #include <basegfx/polygon/b2dpolygon.hxx>
      33             : #include <basegfx/polygon/b2dpolygontools.hxx>
      34             : 
      35             : #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
      36             : #include <drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx>
      37             : 
      38             : 
      39             : using namespace ::com::sun::star;
      40             : using namespace editeng;
      41             : 
      42             : namespace svx {
      43             : namespace frame {
      44             : 
      45             : 
      46             : 
      47             : namespace {
      48             : 
      49             : typedef std::vector< Point > PointVec;
      50             : 
      51             : 
      52             : // Link result structs for horizontal and vertical lines and borders.
      53             : 
      54             : /** Result struct used by the horizontal/vertical frame link functions.
      55             : 
      56             :     This struct is used to return coordinate offsets for one end of a single
      57             :     line in a frame border, i.e. the left end of the primary line of a
      58             :     horizontal frame border.
      59             : 
      60             :     1) Usage for horizontal lines
      61             : 
      62             :     If this struct is returned by the lclLinkHorFrameBorder() function, each
      63             :     member refers to the X coordinate of one edge of a single line end in a
      64             :     horizontal frame border. They specify an offset to modify this coordinate
      65             :     when the line is painted. The values in this struct may change a
      66             :     rectangular line shape into a line with slanted left or right border, which
      67             :     is used to connect the line with diagonal lines.
      68             : 
      69             :     Usage for a left line end:          Usage for a right line end:
      70             :                 mnOffs1                         mnOffs1
      71             :                 <------->                       <------->
      72             :                     +-------------------------------+
      73             :                     | the original horizontal line  |
      74             :                     +-------------------------------+
      75             :                 <------->                       <------->
      76             :                 mnOffs2                         mnOffs2
      77             : 
      78             :     2) Usage for vertical lines
      79             : 
      80             :     If this struct is returned by the lclLinkVerFrameBorder() function, each
      81             :     member refers to the Y coordinate of one edge of a single line end in a
      82             :     vertical frame border. They specify an offset to modify this coordinate
      83             :     when the line is painted. The values in this struct may change a
      84             :     rectangular line shape into a line with slanted top or bottom border, which
      85             :     is used to connect the line with diagonal lines.
      86             : 
      87             :     Usage for a top line end:       mnOffs1 ^               ^ mnOffs2
      88             :                                             |   +-------+   |
      89             :                                             v   |       |   v
      90             :                                                 |       |
      91             :                                                 |       |
      92             :                 the original vertical line ---> |       |
      93             :                                                 |       |
      94             :                                                 |       |
      95             :                                             ^   |       |   ^
      96             :                                             |   +-------+   |
      97             :     Usage for a bottom line end:    mnOffs1 v               v mnOffs2
      98             :  */
      99             : struct LineEndResult
     100             : {
     101             :     long                mnOffs1;    /// Offset for top or left edge, dependent of context.
     102             :     long                mnOffs2;    /// Offset for bottom or right edge, dependent of context
     103             : 
     104           0 :     inline explicit     LineEndResult() : mnOffs1( 0 ), mnOffs2( 0 ) {}
     105             : 
     106           0 :     inline void         Swap() { std::swap( mnOffs1, mnOffs2 ); }
     107           0 :     inline void         Negate() { mnOffs1 = -mnOffs1; mnOffs2 = -mnOffs2; }
     108             : };
     109             : 
     110             : /** Result struct used by the horizontal/vertical frame link functions.
     111             : 
     112             :     This struct contains the linking results for one end of a frame border,
     113             :     including both the primary and secondary line ends.
     114             :  */
     115           0 : struct BorderEndResult
     116             : {
     117             :     LineEndResult       maPrim;     /// Result for primary line.
     118             :     LineEndResult       maSecn;     /// Result for secondary line.
     119             :     LineEndResult       maGap;      /// Result for gap line.
     120             : 
     121           0 :     inline void         Negate() { maPrim.Negate(); maSecn.Negate(); maGap.Negate(); }
     122             : };
     123             : 
     124             : /** Result struct used by the horizontal/vertical frame link functions.
     125             : 
     126             :     This struct contains the linking results for both frame border ends, and
     127             :     therefore for the complete frame border.
     128             :  */
     129           0 : struct BorderResult
     130             : {
     131             :     BorderEndResult     maBeg;      /// Result for begin of border line (left or top end).
     132             :     BorderEndResult     maEnd;      /// Result for end of border line (right or bottom end).
     133             : };
     134             : 
     135             : 
     136             : // Link result structs for diagonal lines and borders.
     137             : 
     138             : /** Result struct used by the diagonal frame link functions.
     139             : 
     140             :     This struct contains the linking results for one line of a diagonal frame
     141             :     border.
     142             :  */
     143             : struct DiagLineResult
     144             : {
     145             :     long                mnLClip;    /// Offset for left border of clipping rectangle.
     146             :     long                mnRClip;    /// Offset for right border of clipping rectangle.
     147             :     long                mnTClip;    /// Offset for top border of clipping rectangle.
     148             :     long                mnBClip;    /// Offset for bottom border of clipping rectangle.
     149             : 
     150           0 :     inline explicit     DiagLineResult() : mnLClip( 0 ), mnRClip( 0 ), mnTClip( 0 ), mnBClip( 0 ) {}
     151             : };
     152             : 
     153             : /** Result struct used by the diagonal frame link functions.
     154             : 
     155             :     This struct contains the linking results for one diagonal frame border.
     156             :  */
     157           0 : struct DiagBorderResult
     158             : {
     159             :     DiagLineResult      maPrim;     /// Result for primary line.
     160             :     DiagLineResult      maSecn;     /// Result for secondary line.
     161             : };
     162             : 
     163             : /** Result struct used by the diagonal frame link functions.
     164             : 
     165             :     This struct contains the linking results for both diagonal frame borders.
     166             :  */
     167           0 : struct DiagBordersResult
     168             : {
     169             :     DiagBorderResult    maTLBR;     /// Result for top-left to bottom-right frame border.
     170             :     DiagBorderResult    maBLTR;     /// Result for bottom-left to top-right frame border.
     171             : };
     172             : 
     173             : 
     174             : 
     175             : /** A helper struct containing two points of a line.
     176             :  */
     177             : struct LinePoints
     178             : {
     179             :     Point               maBeg;      /// Start position of the line.
     180             :     Point               maEnd;      /// End position of the line.
     181             : 
     182           0 :     explicit            LinePoints( const Point& rBeg, const Point& rEnd ) :
     183           0 :                             maBeg( rBeg ), maEnd( rEnd ) {}
     184           0 :     explicit            LinePoints( const Rectangle& rRect, bool bTLBR ) :
     185             :                             maBeg( bTLBR ? rRect.TopLeft() : rRect.TopRight() ),
     186           0 :                             maEnd( bTLBR ? rRect.BottomRight() : rRect.BottomLeft() ) {}
     187             : };
     188             : 
     189             : 
     190             : 
     191             : /** Rounds and casts a double value to a long value. */
     192           0 : inline long lclD2L( double fValue )
     193             : {
     194           0 :     return static_cast< long >( (fValue < 0.0) ? (fValue - 0.5) : (fValue + 0.5) );
     195             : }
     196             : 
     197             : /** Converts a width in twips to a width in another map unit (specified by fScale). */
     198     1074343 : double lclScaleValue( double nValue, double fScale, sal_uInt16 nMaxWidth )
     199             : {
     200     1074343 :     return std::min<double>(nValue * fScale, nMaxWidth);
     201             : }
     202             : 
     203             : 
     204             : // Line width offset calculation.
     205             : 
     206             : /** Returns the start offset of the single/primary line across the frame border.
     207             : 
     208             :     All following lclGet*Beg() and lclGet*End() functions return sub units to
     209             :     increase the computational accuracy, where 256 sub units are equal to
     210             :     1 map unit of the used OutputDevice.
     211             : 
     212             :     The following pictures show the upper end of a vertical frame border and
     213             :     illustrates the return values of all following lclGet*Beg() and lclGet*End()
     214             :     functions. The first picture shows a single frame border, the second picture
     215             :     shows a double frame border.
     216             : 
     217             :     The functions regard the reference point handling mode of the passed border
     218             :     style.
     219             :     REFMODE_CENTERED:
     220             :         All returned offsets are relative to the middle position of the frame
     221             :         border (offsets left of the middle are returned negative, offsets right
     222             :         of the middle are returned positive).
     223             :     REFMODE_BEGIN:
     224             :         All returned offsets are relative to the begin of the frame border
     225             :         (lclGetBeg() always returns 0).
     226             :     REFMODE_END:
     227             :         All returned offsets are relative to the end of the frame border
     228             :         (lclGetEnd() always returns 0).
     229             : 
     230             :                                                         |<- lclGetEnd()
     231             :                        |<- lclGetBeforeBeg()            |<- lclGetPrimEnd()
     232             :                        |                                |
     233             :                        ||<- lclGetBeg()                 ||<- lclGetBehindEnd()
     234             :                        ||                               ||
     235             :                        |#################################|
     236             :        direction of |   #################################
     237             :           the frame |   #################################
     238             :           border is |   #################################
     239             :            vertical |   #################################
     240             :                     v   #################################
     241             :                                         |
     242             :                                         |<- middle of the frame border
     243             : 
     244             :                                          lclGetDistEnd() ->||<- lclGetSecnBeg()
     245             :                                                            ||
     246             :           lclGetBeg() ->|   lclGetDistBeg() ->|            ||           |<- lclGetEnd()
     247             :                         |                     |            ||           |
     248             :     lclGetBeforeBeg()->||  lclGetPrimEnd() ->||            ||           ||<- lclGetBehindEnd()
     249             :                        ||                    ||            ||           ||
     250             :                        |######################|            |#############|
     251             :        direction of |   ######################              #############
     252             :           the frame |   ######################              #############
     253             :           border is |   ######################              #############
     254             :            vertical |   ######################  |           #############
     255             :                     v   ######################  |           #############
     256             :                         primary line            |           secondary line
     257             :                                                 |
     258             :                                                 |<- middle of the frame border
     259             : 
     260             :     @return
     261             :         The start offset of the single/primary line relative to the reference
     262             :         position of the frame border (sub units; 0 for invisible or one pixel
     263             :         wide single frame styles).
     264             :  */
     265           0 : long lclGetBeg( const Style& rBorder )
     266             : {
     267           0 :     long nPos = 0;
     268           0 :     switch( rBorder.GetRefMode() )
     269             :     {
     270           0 :         case REFMODE_CENTERED:  if( rBorder.Prim() ) nPos = -128 * (rBorder.GetWidth() - 1); break;
     271           0 :         case REFMODE_END:       if( rBorder.Prim() ) nPos = -256 * (rBorder.GetWidth() - 1); break;
     272           0 :         case REFMODE_BEGIN:     break;
     273             :     }
     274           0 :     return nPos;
     275             : }
     276             : 
     277             : /** Returns the end offset of the single/secondary line across the frame border.
     278             :     @descr  See description of lclGetBeg() for an illustration.
     279             :     @return  The end offset of the single/secondary line relative to the
     280             :     reference position of the frame border (sub units; 0 for invisible or one
     281             :     pixel wide single frame styles). */
     282           0 : long lclGetEnd( const Style& rBorder )
     283             : {
     284           0 :     long nPos = 0;
     285           0 :     switch( rBorder.GetRefMode() )
     286             :     {
     287           0 :         case REFMODE_CENTERED:  if( rBorder.Prim() ) nPos = 128 * (rBorder.GetWidth() - 1); break;
     288           0 :         case REFMODE_BEGIN:     if( rBorder.Prim() ) nPos = 256 * (rBorder.GetWidth() - 1); break;
     289           0 :         case REFMODE_END:     break;
     290             :     }
     291           0 :     return nPos;
     292             : }
     293             : 
     294             : /** Returns the end offset of the primary line across the frame border.
     295             :     @descr  See description of lclGetBeg() for an illustration.
     296             :     @return  The end offset of the primary line relative to the reference
     297             :     position of the frame border (sub units; the end of the primary line in a
     298             :     double frame style, otherwise the same as lclGetEnd()). */
     299           0 : inline long lclGetPrimEnd( const Style& rBorder )
     300           0 : { return rBorder.Prim() ? (lclGetBeg( rBorder ) + 256 * (rBorder.Prim() - 1)) : 0; }
     301             : 
     302             : /** Returns the start offset of the secondary line across the frame border.
     303             :     @descr  See description of lclGetBeg() for an illustration.
     304             :     @return  The start offset of the secondary line relative to the reference
     305             :     position of the frame border (sub units; 0 for single/invisible border
     306             :     styles). */
     307           0 : inline long lclGetSecnBeg( const Style& rBorder )
     308           0 : { return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * (rBorder.Secn() - 1)) : 0; }
     309             : 
     310             : /** Returns the start offset of the distance space across the frame border.
     311             :     @descr  See description of lclGetBeg() for an illustration.
     312             :     @return  The start offset of the distance space relative to the reference
     313             :     position of the frame border (sub units; 0 for single/invisible border
     314             :     styles). */
     315           0 : inline long lclGetDistBeg( const Style& rBorder )
     316           0 : { return rBorder.Secn() ? (lclGetBeg( rBorder ) + 256 * rBorder.Prim()) : 0; }
     317             : 
     318             : /** Returns the end offset of the distance space across the frame border.
     319             :     @descr  See description of lclGetBeg() for an illustration.
     320             :     @return  The end offset of the distance space relative to the reference
     321             :     position of the frame border (sub units; 0 for single/invisible border
     322             :     styles). */
     323           0 : inline long lclGetDistEnd( const Style& rBorder )
     324           0 : { return rBorder.Secn() ? (lclGetEnd( rBorder ) - 256 * rBorder.Secn()) : 0; }
     325             : 
     326             : /** Returns the offset before start of single/primary line across the frame border.
     327             :     @descr  See description of lclGetBeg() for an illustration.
     328             :     @return  The offset directly before start of single/primary line relative
     329             :     to the reference position of the frame border (sub units; a value one less
     330             :     than lclGetBeg() for visible frame styles, or 0 for invisible frame style). */
     331           0 : inline long lclGetBeforeBeg( const Style& rBorder )
     332           0 : { return rBorder.Prim() ? (lclGetBeg( rBorder ) - 256) : 0; }
     333             : 
     334             : /** Returns the offset behind end of single/secondary line across the frame border.
     335             :     @descr  See description of lclGetBeg() for an illustration.
     336             :     @return  The offset directly behind end of single/secondary line relative
     337             :     to the reference position of the frame border (sub units; a value one
     338             :     greater than lclGetEnd() for visible frame styles, or 0 for invisible frame
     339             :     style). */
     340           0 : inline long lclGetBehindEnd( const Style& rBorder )
     341           0 : { return rBorder.Prim() ? (lclGetEnd( rBorder ) + 256) : 0; }
     342             : 
     343             : 
     344             : // Linking functions
     345             : 
     346             : 
     347             : 
     348             : // Linking of single horizontal line ends.
     349             : 
     350             : /** Calculates X offsets for the left end of a single horizontal frame border.
     351             : 
     352             :     See DrawHorFrameBorder() function for a description of all parameters.
     353             : 
     354             :     @param rResult
     355             :         (out-param) The contained values (sub units) specify offsets for the
     356             :         X coordinates of the left line end.
     357             :  */
     358           0 : void lclLinkLeftEnd_Single(
     359             :         LineEndResult& rResult, const Style& rBorder,
     360             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
     361             : {
     362             :     // both vertical and diagonal frame borders are double
     363           0 :     if( rLFromT.Secn() && rLFromB.Secn() && rLFromTR.Secn() && rLFromBR.Secn() )
     364             :     {
     365             :         // take left position of upper and lower secondary start
     366           0 :         rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
     367           0 :         rResult.mnOffs2 = GetTLDiagOffset( lclGetEnd( rBorder ), lclGetSecnBeg( rLFromBR ), rLFromBR.GetAngle() );
     368             :     }
     369             :     else
     370             :     {
     371             :         // both vertical frame borders are double
     372           0 :         if( rLFromT.Secn() && rLFromB.Secn() )
     373             :         {
     374           0 :             rResult.mnOffs1 = (!rLFromTR.Secn() && !rLFromBR.Secn() && (rLFromT.GetWidth() == rLFromB.GetWidth())) ?
     375             :                 // don't overdraw vertical borders with equal width
     376             :                 lclGetBehindEnd( rLFromT ) :
     377             :                 // take leftmost start of both secondary lines (#46488#)
     378           0 :                 std::min( lclGetSecnBeg( rLFromT ), lclGetSecnBeg( rLFromB ) );
     379             :         }
     380             : 
     381             :         // single border with equal width coming from left
     382           0 :         else if( !rLFromL.Secn() && (rLFromL.Prim() == rBorder.Prim()) )
     383             :             // draw to connection point
     384           0 :             rResult.mnOffs1 = 0;
     385             : 
     386             :         // single border coming from left
     387           0 :         else if( !rLFromL.Secn() && rLFromL.Prim() )
     388             :         {
     389           0 :             if( rLFromL.Prim() == rBorder.Prim() )
     390             :                 // draw to reference position, if from left has equal width
     391           0 :                 rResult.mnOffs1 = 0;
     392             :             else
     393           0 :                 rResult.mnOffs1 = (rLFromL < rBorder) ?
     394             :                     // take leftmost start of both frame borders, if from left is thinner
     395           0 :                     std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) :
     396             :                     // do not overdraw vertical, if from left is thicker
     397           0 :                     std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
     398             :         }
     399             : 
     400             :         // no border coming from left
     401           0 :         else if( !rLFromL.Prim() )
     402             :             // don't overdraw vertical borders with equal width
     403           0 :             rResult.mnOffs1 = (rLFromT.GetWidth() == rLFromB.GetWidth()) ?
     404             :                 lclGetBehindEnd( rLFromT ) :
     405           0 :                 std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) );
     406             : 
     407             :         // double frame border coming from left and from top
     408           0 :         else if( rLFromT.Secn() )
     409             :             // do not overdraw the vertical double frame border
     410           0 :             rResult.mnOffs1 = lclGetBehindEnd( rLFromT );
     411             : 
     412             :         // double frame border coming from left and from bottom
     413           0 :         else if( rLFromB.Secn() )
     414             :             // do not overdraw the vertical double frame border
     415           0 :             rResult.mnOffs1 = lclGetBehindEnd( rLFromB );
     416             : 
     417             :         // double frame border coming from left, both vertical frame borders are single or off
     418             :         else
     419             :             // draw from leftmost start of both frame borders, if from left is not thicker
     420           0 :             rResult.mnOffs1 = (rLFromL <= rBorder) ?
     421           0 :                 std::min( lclGetBeg( rLFromT ), lclGetBeg( rLFromB ) ) :
     422           0 :                 std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
     423             : 
     424             :         // bottom-left point is equal to top-left point (results in rectangle)
     425           0 :         rResult.mnOffs2 = rResult.mnOffs1;
     426             :     }
     427           0 : }
     428             : 
     429             : /** Calculates X offsets for the left end of a primary horizontal line.
     430             : 
     431             :     See DrawHorFrameBorder() function for a description of all parameters.
     432             : 
     433             :     @param rResult
     434             :         (out-param) The contained values (sub units) specify offsets for the
     435             :         X coordinates of the left end of the primary line.
     436             :  */
     437           0 : void lclLinkLeftEnd_Prim(
     438             :         LineEndResult& rResult, const Style& rBorder,
     439             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& /*rLFromBR*/ )
     440             : {
     441             :     // double diagonal frame border coming from top right
     442           0 :     if( rLFromTR.Secn() )
     443             :     {
     444             :         // draw from where secondary diagonal line meets the own primary
     445           0 :         rResult.mnOffs1 = GetBLDiagOffset( lclGetBeg( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
     446           0 :         rResult.mnOffs2 = GetBLDiagOffset( lclGetPrimEnd( rBorder ), lclGetSecnBeg( rLFromTR ), rLFromTR.GetAngle() );
     447             :     }
     448             : 
     449             :     // no or single diagonal frame border - ignore it
     450             :     else
     451             :     {
     452             :         // double frame border coming from top
     453           0 :         if( rLFromT.Secn() )
     454             :             // draw from left edge of secondary vertical
     455           0 :             rResult.mnOffs1 = lclGetSecnBeg( rLFromT );
     456             : 
     457             :         // double frame border coming from left (from top is not double)
     458           0 :         else if( rLFromL.Secn() )
     459             :             // do not overdraw single frame border coming from top
     460           0 :             rResult.mnOffs1 = (rLFromL.GetWidth() == rBorder.GetWidth()) ?
     461           0 :                 0 : lclGetBehindEnd( rLFromT );
     462             : 
     463             :         // double frame border coming from bottom (from top and from left are not double)
     464           0 :         else if( rLFromB.Secn() )
     465             :             // draw from left edge of primary vertical from bottom
     466           0 :             rResult.mnOffs1 = lclGetBeg( rLFromB );
     467             : 
     468             :         // no other frame border is double
     469             :         else
     470             :             // do not overdraw vertical frame borders
     471           0 :             rResult.mnOffs1 = std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
     472             : 
     473             :         // bottom-left point is equal to top-left point (results in rectangle)
     474           0 :         rResult.mnOffs2 = rResult.mnOffs1;
     475             :     }
     476           0 : }
     477             : 
     478             : /** Calculates X offsets for the left end of a secondary horizontal line.
     479             : 
     480             :     See DrawHorFrameBorder() function for a description of all parameters.
     481             : 
     482             :     @param rResult
     483             :         (out-param) The contained values (sub units) specify offsets for the
     484             :         X coordinates of the left end of the secondary line.
     485             :  */
     486           0 : void lclLinkLeftEnd_Secn(
     487             :         LineEndResult& rResult, const Style& rBorder,
     488             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
     489             : {
     490             :     /*  Recycle lclLinkLeftEnd_Prim() function with mirrored horizontal borders. */
     491           0 :     lclLinkLeftEnd_Prim( rResult, rBorder.Mirror(), rLFromBR, rLFromB, rLFromL.Mirror(), rLFromT, rLFromTR );
     492           0 :     rResult.Swap();
     493           0 : }
     494             : 
     495           0 : void lclLinkLeftEnd_Gap(
     496             :         LineEndResult& rResult, const Style& rBorder,
     497             :         const DiagStyle& /*rLFromTR*/, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& /*rLFromBR*/ )
     498             : 
     499             : {
     500           0 :     if ( rLFromT.Secn() )
     501           0 :         rResult.mnOffs1 = lclGetDistBeg( rLFromT );
     502           0 :     else if ( rLFromL.Secn( ) )
     503           0 :         rResult.mnOffs1 = ( rLFromL.GetWidth() == rBorder.GetWidth() )?
     504           0 :             0 : lclGetBehindEnd( rLFromT );
     505           0 :     else if ( rLFromB.Secn( ) )
     506           0 :         rResult.mnOffs1 = lclGetDistBeg( rLFromB );
     507             :     else
     508           0 :         rResult.mnOffs1 = std::max( lclGetBehindEnd( rLFromT ), lclGetBehindEnd( rLFromB ) );
     509             : 
     510           0 :     rResult.mnOffs2 = rResult.mnOffs1;
     511           0 : }
     512             : 
     513             : // Linking of horizontal frame border ends.
     514             : 
     515             : /** Calculates X offsets for the left end of a horizontal frame border.
     516             : 
     517             :     This function can be used for single and double frame borders.
     518             :     See DrawHorFrameBorder() function for a description of all parameters.
     519             : 
     520             :     @param rResult
     521             :         (out-param) The contained values (sub units) specify offsets for the
     522             :         X coordinates of the left end of the line(s) in the frame border.
     523             :  */
     524           0 : void lclLinkLeftEnd(
     525             :         BorderEndResult& rResult, const Style& rBorder,
     526             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR )
     527             : {
     528           0 :     if( rBorder.Secn() )
     529             :     {
     530             :         // current frame border is double
     531           0 :         lclLinkLeftEnd_Prim( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
     532           0 :         lclLinkLeftEnd_Secn( rResult.maSecn, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
     533           0 :         lclLinkLeftEnd_Gap( rResult.maGap, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
     534             :     }
     535           0 :     else if( rBorder.Prim() )
     536             :     {
     537             :         // current frame border is single
     538           0 :         lclLinkLeftEnd_Single( rResult.maPrim, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
     539             :     }
     540             :     else
     541             :     {
     542             :         SAL_WARN( "svx.dialog", "lclLinkLeftEnd - called for invisible frame style" );
     543             :     }
     544           0 : }
     545             : 
     546             : /** Calculates X offsets for the right end of a horizontal frame border.
     547             : 
     548             :     This function can be used for single and double frame borders.
     549             :     See DrawHorFrameBorder() function for a description of all parameters.
     550             : 
     551             :     @param rResult
     552             :         (out-param) The contained values (sub units) specify offsets for the
     553             :         X coordinates of the right end of the line(s) in the frame border.
     554             :  */
     555           0 : void lclLinkRightEnd(
     556             :         BorderEndResult& rResult, const Style& rBorder,
     557             :         const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL )
     558             : {
     559             :     /*  Recycle lclLinkLeftEnd() function with mirrored vertical borders. */
     560           0 :     lclLinkLeftEnd( rResult, rBorder, rRFromTL.Mirror(), rRFromT.Mirror(), rRFromR, rRFromB.Mirror(), rRFromBL.Mirror() );
     561           0 :     rResult.Negate();
     562           0 : }
     563             : 
     564             : 
     565             : // Linking of horizontal and vertical frame borders.
     566             : 
     567             : /** Calculates X offsets for all line ends of a horizontal frame border.
     568             : 
     569             :     This function can be used for single and double frame borders.
     570             :     See DrawHorFrameBorder() function for a description of all parameters.
     571             : 
     572             :     @param rResult
     573             :         (out-param) The contained values (sub units) specify offsets for the
     574             :         X coordinates of both ends of the line(s) in the frame border. To get
     575             :         the actual X coordinates to draw the lines, these offsets have to be
     576             :         added to the X coordinates of the reference points of the frame border
     577             :         (the offsets may be negative).
     578             :  */
     579           0 : void lclLinkHorFrameBorder(
     580             :         BorderResult& rResult, const Style& rBorder,
     581             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR,
     582             :         const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL )
     583             : {
     584           0 :     lclLinkLeftEnd( rResult.maBeg, rBorder, rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR );
     585           0 :     lclLinkRightEnd( rResult.maEnd, rBorder, rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL );
     586           0 : }
     587             : 
     588             : /** Calculates Y offsets for all line ends of a vertical frame border.
     589             : 
     590             :     This function can be used for single and double frame borders.
     591             :     See DrawVerFrameBorder() function for a description of all parameters.
     592             : 
     593             :     @param rResult
     594             :         (out-param) The contained values (sub units) specify offsets for the
     595             :         Y coordinates of both ends of the line(s) in the frame border. To get
     596             :         the actual Y coordinates to draw the lines, these offsets have to be
     597             :         added to the Y coordinates of the reference points of the frame border
     598             :         (the offsets may be negative).
     599             :  */
     600           0 : void lclLinkVerFrameBorder(
     601             :         BorderResult& rResult, const Style& rBorder,
     602             :         const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR,
     603             :         const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR )
     604             : {
     605             :     /*  Recycle lclLinkHorFrameBorder() function with correct parameters. The
     606             :         frame border is virtually mirrored at the top-left to bottom-right
     607             :         diagonal. rTFromBR and rBFromTL are mirrored to process their primary
     608             :         and secondary lines correctly. */
     609             :     lclLinkHorFrameBorder( rResult, rBorder,
     610             :         rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR.Mirror(),
     611           0 :         rBFromTL.Mirror(), rBFromL, rBFromB, rBFromR, rBFromTR );
     612           0 : }
     613             : 
     614             : 
     615             : 
     616             : 
     617             : // Linking of diagonal frame borders.
     618             : 
     619             : /** Calculates clipping offsets for a top-left to bottom-right frame border.
     620             : 
     621             :     This function can be used for single and double frame borders.
     622             :     See DrawDiagFrameBorders() function for a description of all parameters.
     623             : 
     624             :     @param rResult
     625             :         (out-param) The contained values (sub units) specify offsets for all
     626             :         borders of the reference rectangle containing the diagonal frame border.
     627             :  */
     628           0 : void lclLinkTLBRFrameBorder(
     629             :         DiagBorderResult& rResult, const Style& rBorder,
     630             :         const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL )
     631             : {
     632           0 :     bool bIsDbl = rBorder.Secn() != 0;
     633             : 
     634           0 :     rResult.maPrim.mnLClip = lclGetBehindEnd( rTLFromB );
     635           0 :     rResult.maPrim.mnRClip = (bIsDbl && rBRFromT.Secn()) ? lclGetEnd( rBRFromT ) : lclGetBeforeBeg( rBRFromT );
     636           0 :     rResult.maPrim.mnTClip = (bIsDbl && rTLFromR.Secn()) ? lclGetBeg( rTLFromR ) : lclGetBehindEnd( rTLFromR );
     637           0 :     rResult.maPrim.mnBClip = lclGetBeforeBeg( rBRFromL );
     638             : 
     639           0 :     if( bIsDbl )
     640             :     {
     641           0 :         rResult.maSecn.mnLClip = rTLFromB.Secn() ? lclGetBeg( rTLFromB ) : lclGetBehindEnd( rTLFromB );
     642           0 :         rResult.maSecn.mnRClip = lclGetBeforeBeg( rBRFromT );
     643           0 :         rResult.maSecn.mnTClip = lclGetBehindEnd( rTLFromR );
     644           0 :         rResult.maSecn.mnBClip = rBRFromL.Secn() ? lclGetEnd( rBRFromL ) : lclGetBeforeBeg( rBRFromL );
     645             :     }
     646           0 : }
     647             : 
     648             : /** Calculates clipping offsets for a bottom-left to top-right frame border.
     649             : 
     650             :     This function can be used for single and double frame borders.
     651             :     See DrawDiagFrameBorders() function for a description of all parameters.
     652             : 
     653             :     @param rResult
     654             :         (out-param) The contained values (sub units) specify offsets for all
     655             :         borders of the reference rectangle containing the diagonal frame border.
     656             :  */
     657           0 : void lclLinkBLTRFrameBorder(
     658             :         DiagBorderResult& rResult, const Style& rBorder,
     659             :         const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL )
     660             : {
     661           0 :     bool bIsDbl = rBorder.Secn() != 0;
     662             : 
     663           0 :     rResult.maPrim.mnLClip = lclGetBehindEnd( rBLFromT );
     664           0 :     rResult.maPrim.mnRClip = (bIsDbl && rTRFromB.Secn()) ? lclGetEnd( rTRFromB ) : lclGetBeforeBeg( rTRFromB );
     665           0 :     rResult.maPrim.mnTClip = lclGetBehindEnd( rTRFromL );
     666           0 :     rResult.maPrim.mnBClip = (bIsDbl && rBLFromR.Secn()) ? lclGetEnd( rBLFromR ) : lclGetBeforeBeg( rBLFromR );
     667             : 
     668           0 :     if( bIsDbl )
     669             :     {
     670           0 :         rResult.maSecn.mnLClip = rBLFromT.Secn() ? lclGetBeg( rBLFromT ) : lclGetBehindEnd( rBLFromT );
     671           0 :         rResult.maSecn.mnRClip = lclGetBeforeBeg( rTRFromB );
     672           0 :         rResult.maSecn.mnTClip = rTRFromL.Secn() ? lclGetBeg( rTRFromL ) : lclGetBehindEnd( rTRFromL );
     673           0 :         rResult.maSecn.mnBClip = lclGetBeforeBeg( rBLFromR );
     674             :     }
     675           0 : }
     676             : 
     677             : /** Calculates clipping offsets for both diagonal frame borders.
     678             : 
     679             :     This function can be used for single and double frame borders.
     680             :     See DrawDiagFrameBorders() function for a description of all parameters.
     681             : 
     682             :     @param rResult
     683             :         (out-param) The contained values (sub units) specify offsets for all
     684             :         borders of the reference rectangle containing the diagonal frame
     685             :         borders.
     686             :  */
     687           0 : void lclLinkDiagFrameBorders(
     688             :         DiagBordersResult& rResult, const Style& rTLBR, const Style& rBLTR,
     689             :         const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL,
     690             :         const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL )
     691             : {
     692           0 :     lclLinkTLBRFrameBorder( rResult.maTLBR, rTLBR, rTLFromB, rTLFromR, rBRFromT, rBRFromL );
     693           0 :     lclLinkBLTRFrameBorder( rResult.maBLTR, rBLTR, rBLFromT, rBLFromR, rTRFromB, rTRFromL );
     694           0 : }
     695             : 
     696             : 
     697             : // Drawing functions
     698             : 
     699             : 
     700             : 
     701             : // Simple helper functions
     702             : 
     703             : /** Converts sub units to OutputDevice map units. */
     704           0 : inline long lclToMapUnit( long nSubUnits )
     705             : {
     706           0 :     return ((nSubUnits < 0) ? (nSubUnits - 127) : (nSubUnits + 128)) / 256;
     707             : }
     708             : 
     709             : /** Converts a point in sub units to an OutputDevice point. */
     710           0 : inline Point lclToMapUnit( long nSubXPos, long nSubYPos )
     711             : {
     712           0 :     return Point( lclToMapUnit( nSubXPos ), lclToMapUnit( nSubYPos ) );
     713             : }
     714             : 
     715             : /** Returns a polygon constructed from a vector of points. */
     716           0 : inline Polygon lclCreatePolygon( const PointVec& rPoints )
     717             : {
     718           0 :     return Polygon( static_cast< sal_uInt16 >( rPoints.size() ), &rPoints[ 0 ] );
     719             : }
     720             : 
     721             : /** Returns a polygon constructed from the five passed points. */
     722           0 : Region lclCreatePolygon( const Point& rP1, const Point& rP2, const Point& rP3, const Point& rP4, const Point& rP5 )
     723             : {
     724           0 :     PointVec aPoints;
     725           0 :     aPoints.reserve( 5 );
     726           0 :     aPoints.push_back( rP1 );
     727           0 :     aPoints.push_back( rP2 );
     728           0 :     aPoints.push_back( rP3 );
     729           0 :     aPoints.push_back( rP4 );
     730           0 :     aPoints.push_back( rP5 );
     731           0 :     return Region(lclCreatePolygon(aPoints));
     732             : }
     733             : 
     734             : /** Sets the color of the passed frame style to the output device.
     735             : 
     736             :     Sets the line color and fill color in the output device.
     737             : 
     738             :     @param rDev
     739             :         The output device the color has to be set to. The old colors are pushed
     740             :         onto the device's stack and can be restored with a call to
     741             :         OutputDevice::Pop(). Please take care about the correct calling order
     742             :         of Pop() if this function is used with other functions pushing
     743             :         something onto the stack.
     744             :     @param rStyle
     745             :         The border style that contains the line color to be set to the device.
     746             :  */
     747           0 : void lclSetColorToOutDev( OutputDevice& rDev, const Color& rColor, const Color* pForceColor )
     748             : {
     749           0 :     rDev.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
     750           0 :     rDev.SetLineColor( pForceColor ? *pForceColor : rColor );
     751           0 :     rDev.SetFillColor( pForceColor ? *pForceColor : rColor );
     752           0 : }
     753             : 
     754             : 
     755             : 
     756             : // Drawing of horizontal frame borders.
     757             : 
     758             : /** Draws a horizontal thin or thick line into the passed output device.
     759             : 
     760             :     The X coordinates of the edges of the line are adjusted according to the
     761             :     passed LineEndResult structs. A one pixel wide line can be drawn dotted.
     762             :  */
     763           0 : void lclDrawHorLine(
     764             :         OutputDevice& rDev,
     765             :         const Point& rLPos, const LineEndResult& rLRes,
     766             :         const Point& rRPos, const LineEndResult& rRRes,
     767             :         long nTOffs, long nBOffs, SvxBorderStyle nDashing )
     768             : {
     769           0 :     LinePoints aTPoints( rLPos + lclToMapUnit( rLRes.mnOffs1, nTOffs ), rRPos + lclToMapUnit( rRRes.mnOffs1, nTOffs ) );
     770           0 :     LinePoints aBPoints( rLPos + lclToMapUnit( rLRes.mnOffs2, nBOffs ), rRPos + lclToMapUnit( rRRes.mnOffs2, nBOffs ) );
     771             : 
     772           0 :     sal_uInt32 nWidth = lclToMapUnit( std::abs( nTOffs ) ) + lclToMapUnit( std::abs( nBOffs ) );
     773           0 :     if ( ( nTOffs >= 0 && nBOffs >= 0 ) || ( nTOffs <= 0 && nBOffs <= 0 ) )
     774           0 :         nWidth = std::abs( lclToMapUnit( nTOffs ) - lclToMapUnit( nBOffs ) ) + 1;
     775           0 :     Point rLMid = ( aTPoints.maBeg + aBPoints.maBeg ) / 2;
     776           0 :     Point rRMid = ( aTPoints.maEnd + aBPoints.maEnd ) / 2;
     777             : 
     778           0 :     ::svtools::DrawLine( rDev, rLMid, rRMid, nWidth, nDashing );
     779           0 : }
     780             : 
     781             : /** Draws a horizontal frame border into the passed output device.
     782             : 
     783             :     @param rLPos
     784             :         The top-left or bottom-left reference point of the diagonal frame border.
     785             :     @param rRPos
     786             :         The top-right or bottom-right reference point of the diagonal frame border.
     787             :     @param rBorder
     788             :         The frame style used to draw the border.
     789             :     @param rResult
     790             :         The X coordinates of the edges of all lines of the frame border are
     791             :         adjusted according to the offsets contained here.
     792             :  */
     793           0 : void lclDrawHorFrameBorder(
     794             :         OutputDevice& rDev, const Point& rLPos, const Point& rRPos,
     795             :         const Style& rBorder, const BorderResult& rResult, const Color* pForceColor )
     796             : {
     797             :     DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawHorFrameBorder - line not visible" );
     798             :     DBG_ASSERT( rLPos.X() <= rRPos.X(), "svx::frame::lclDrawHorFrameBorder - wrong order of line ends" );
     799             :     DBG_ASSERT( rLPos.Y() == rRPos.Y(), "svx::frame::lclDrawHorFrameBorder - line not horizontal" );
     800           0 :     if( rLPos.X() <= rRPos.X() )
     801             :     {
     802           0 :         if ( rBorder.UseGapColor( ) )
     803             :         {
     804           0 :             lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
     805             :             lclDrawHorLine( rDev, rLPos, rResult.maBeg.maGap, rRPos, rResult.maEnd.maGap,
     806           0 :                    lclGetPrimEnd( rBorder ), lclGetSecnBeg( rBorder ), rBorder.Type() );
     807           0 :             rDev.Pop(); // Gap color
     808             :         }
     809             : 
     810           0 :         lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
     811             :         lclDrawHorLine( rDev, rLPos, rResult.maBeg.maPrim, rRPos, rResult.maEnd.maPrim,
     812           0 :             lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
     813           0 :         rDev.Pop(); // colors
     814             : 
     815           0 :         if( rBorder.Secn() )
     816             :         {
     817           0 :             lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
     818             :             lclDrawHorLine( rDev, rLPos, rResult.maBeg.maSecn, rRPos, rResult.maEnd.maSecn,
     819           0 :                 lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
     820           0 :             rDev.Pop(); // colors
     821             :         }
     822             :     }
     823           0 : }
     824             : 
     825             : 
     826             : // Drawing of vertical frame borders.
     827             : 
     828             : /** Draws a vertical thin or thick line into the passed output device.
     829             : 
     830             :     The Y coordinates of the edges of the line are adjusted according to the
     831             :     passed LineEndResult structs. A one pixel wide line can be drawn dotted.
     832             :  */
     833           0 : void lclDrawVerLine(
     834             :         OutputDevice& rDev,
     835             :         const Point& rTPos, const LineEndResult& rTRes,
     836             :         const Point& rBPos, const LineEndResult& rBRes,
     837             :         long nLOffs, long nROffs, SvxBorderStyle nDashing )
     838             : {
     839           0 :     LinePoints aLPoints( rTPos + lclToMapUnit( nLOffs, rTRes.mnOffs1 ), rBPos + lclToMapUnit( nLOffs, rBRes.mnOffs1 ) );
     840           0 :     LinePoints aRPoints( rTPos + lclToMapUnit( nROffs, rTRes.mnOffs2 ), rBPos + lclToMapUnit( nROffs, rBRes.mnOffs2 ) );
     841             : 
     842           0 :     sal_uInt32 nWidth = lclToMapUnit( std::abs( nLOffs ) ) + lclToMapUnit( std::abs( nROffs ) );
     843           0 :     if ( ( nLOffs >= 0 && nROffs >= 0 ) || ( nLOffs <= 0 && nROffs <= 0 ) )
     844           0 :         nWidth = std::abs( lclToMapUnit( nLOffs ) - lclToMapUnit( nROffs ) ) + 1;
     845           0 :     Point rTMid = ( aLPoints.maBeg + aRPoints.maBeg ) / 2;
     846           0 :     Point rBMid = ( aLPoints.maEnd + aRPoints.maEnd ) / 2;
     847             : 
     848           0 :     ::svtools::DrawLine( rDev, rTMid, rBMid, nWidth, nDashing );
     849           0 : }
     850             : 
     851             : /** Draws a vertical frame border into the passed output device.
     852             : 
     853             :     @param rTPos
     854             :         The top-left or top-right reference point of the diagonal frame border.
     855             :     @param rBPos
     856             :         The bottom-left or bottom-right reference point of the diagonal frame border.
     857             :     @param rBorder
     858             :         The frame style used to draw the border.
     859             :     @param rResult
     860             :         The Y coordinates of the edges of all lines of the frame border are
     861             :         adjusted according to the offsets contained here.
     862             :  */
     863           0 : void lclDrawVerFrameBorder(
     864             :         OutputDevice& rDev, const Point& rTPos, const Point& rBPos,
     865             :         const Style& rBorder, const BorderResult& rResult, const Color* pForceColor )
     866             : {
     867             :     DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawVerFrameBorder - line not visible" );
     868             :     DBG_ASSERT( rTPos.Y() <= rBPos.Y(), "svx::frame::lclDrawVerFrameBorder - wrong order of line ends" );
     869             :     DBG_ASSERT( rTPos.X() == rBPos.X(), "svx::frame::lclDrawVerFrameBorder - line not vertical" );
     870           0 :     if( rTPos.Y() <= rBPos.Y() )
     871             :     {
     872           0 :         if ( rBorder.UseGapColor( ) )
     873             :         {
     874           0 :             lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
     875             :             lclDrawVerLine( rDev, rTPos, rResult.maBeg.maGap, rBPos, rResult.maEnd.maGap,
     876           0 :                    lclGetPrimEnd( rBorder ), lclGetSecnBeg( rBorder ), rBorder.Type() );
     877           0 :             rDev.Pop(); // Gap color
     878             :         }
     879             : 
     880           0 :         lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
     881             :         lclDrawVerLine( rDev, rTPos, rResult.maBeg.maPrim, rBPos, rResult.maEnd.maPrim,
     882           0 :             lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
     883           0 :         rDev.Pop(); // colors
     884           0 :         if( rBorder.Secn() )
     885             :         {
     886           0 :             lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
     887             :             lclDrawVerLine( rDev, rTPos, rResult.maBeg.maSecn, rBPos, rResult.maEnd.maSecn,
     888           0 :                 lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
     889           0 :             rDev.Pop(); // colors
     890             :         }
     891             :     }
     892           0 : }
     893             : 
     894             : 
     895             : // Drawing of diagonal frame borders, incudes clipping functions.
     896             : 
     897             : /** Returns the drawing coordinates for a diagonal thin line.
     898             : 
     899             :     This function can be used for top-left to bottom-right and for bottom-left
     900             :     to top-right lines.
     901             : 
     902             :     @param rRect
     903             :         The reference rectangle of the diagonal frame border.
     904             :     @param bTLBR
     905             :         true = top-left to bottom-right; false = bottom-left to top-right.
     906             :     @param nDiagOffs
     907             :         Width offset (sub units) across the diagonal frame border.
     908             :     @return
     909             :         A struct containg start and end position of the diagonal line.
     910             :  */
     911           0 : LinePoints lclGetDiagLineEnds( const Rectangle& rRect, bool bTLBR, long nDiagOffs )
     912             : {
     913           0 :     LinePoints aPoints( rRect, bTLBR );
     914           0 :     bool bVert = rRect.GetWidth() < rRect.GetHeight();
     915           0 :     double fAngle = bVert ? GetVerDiagAngle( rRect ) : GetHorDiagAngle( rRect );
     916             :     // vertical top-left to bottom-right borders are handled mirrored
     917           0 :     if( bVert && bTLBR )
     918           0 :         nDiagOffs = -nDiagOffs;
     919           0 :     long nTOffs = bTLBR ? GetTLDiagOffset( 0, nDiagOffs, fAngle ) : GetTRDiagOffset( 0, nDiagOffs, fAngle );
     920           0 :     long nBOffs = bTLBR ? GetBRDiagOffset( 0, nDiagOffs, fAngle ) : GetBLDiagOffset( 0, nDiagOffs, fAngle );
     921             :     // vertical bottom-left to top-right borders are handled with exchanged end points
     922           0 :     if( bVert && !bTLBR )
     923           0 :         std::swap( nTOffs, nBOffs );
     924           0 :     (bVert ? aPoints.maBeg.Y() : aPoints.maBeg.X()) += lclToMapUnit( nTOffs );
     925           0 :     (bVert ? aPoints.maEnd.Y() : aPoints.maEnd.X()) += lclToMapUnit( nBOffs );
     926           0 :     return aPoints;
     927             : }
     928             : 
     929             : 
     930             : // Clipping functions for diagonal frame borders.
     931             : 
     932             : /** Limits the clipping region to the inner area of a rectange.
     933             : 
     934             :     Takes the values from the passed DiagLineResult struct into account. They
     935             :     may specify to not clip one or more borders of a rectangle.
     936             : 
     937             :     @param rDev
     938             :         The output device with the clipping region to be modified. The old
     939             :         clipping region is pushed onto the device's stack and can be restored
     940             :         with a call to OutputDevice::Pop(). Please take care about the correct
     941             :         calling order of Pop() if this function is used with other functions
     942             :         pushing something onto the stack.
     943             :     @param rRect
     944             :         The reference rectangle of the diagonal frame borders.
     945             :     @param rResult
     946             :         The result struct containing modifies for each border of the reference
     947             :         rectangle.
     948             :  */
     949           0 : void lclPushDiagClipRect( OutputDevice& rDev, const Rectangle& rRect, const DiagLineResult& rResult )
     950             : {
     951             :     // PixelToLogic() regards internal offset of the output device
     952           0 :     Rectangle aClipRect( rRect );
     953           0 :     aClipRect.Left()   += lclToMapUnit( rResult.mnLClip );
     954           0 :     aClipRect.Top()    += lclToMapUnit( rResult.mnTClip );
     955           0 :     aClipRect.Right()  += lclToMapUnit( rResult.mnRClip );
     956           0 :     aClipRect.Bottom() += lclToMapUnit( rResult.mnBClip );
     957             :     // output device would adjust the rectangle -> invalidate it before
     958           0 :     if( (aClipRect.GetWidth() < 1) ||(aClipRect.GetHeight() < 1) )
     959           0 :         aClipRect.SetEmpty();
     960             : 
     961           0 :     rDev.Push( PUSH_CLIPREGION );
     962           0 :     rDev.IntersectClipRegion( aClipRect );
     963           0 : }
     964             : 
     965             : /** Excludes inner area of a crossing double frame border from clipping region.
     966             : 
     967             :     This function is used to modify the clipping region so that it excludes the
     968             :     inner free area of a double diagonal frame border. This makes it possible
     969             :     to draw a diagonal frame border in one step without taking care of the
     970             :     crossing double frame border.
     971             : 
     972             :     @param rDev
     973             :         The output device with the clipping region to be modified. The old
     974             :         clipping region is pushed onto the device's stack and can be restored
     975             :         with a call to OutputDevice::Pop(). Please take care about the correct
     976             :         calling order of Pop() if this function is used with other functions
     977             :         pushing something onto the stack.
     978             :     @param rRect
     979             :         The reference rectangle of the diagonal frame borders.
     980             :     @param bTLBR
     981             :         The orientation of the processed frame border (not the orientation of
     982             :         the crossing frame border).
     983             :     @param bCrossStyle
     984             :         The style of the crossing frame border. Must be a double frame style.
     985             :  */
     986           0 : void lclPushCrossingClipRegion( OutputDevice& rDev, const Rectangle& rRect, bool bTLBR, const Style& rCrossStyle )
     987             : {
     988             :     DBG_ASSERT( rCrossStyle.Secn(), "lclGetCrossingClipRegion - use only for double styles" );
     989           0 :     LinePoints aLPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetPrimEnd( rCrossStyle ) ) );
     990           0 :     LinePoints aRPoints( lclGetDiagLineEnds( rRect, !bTLBR, lclGetSecnBeg( rCrossStyle ) ) );
     991             : 
     992           0 :     Region aClipReg;
     993           0 :     if( bTLBR )
     994             :     {
     995           0 :         aClipReg = lclCreatePolygon(
     996           0 :             aLPoints.maBeg, aLPoints.maEnd, rRect.BottomRight(), rRect.BottomLeft(), rRect.TopLeft() );
     997             :         aClipReg.Union( lclCreatePolygon(
     998           0 :             aRPoints.maBeg, aRPoints.maEnd, rRect.BottomRight(), rRect.TopRight(), rRect.TopLeft() ) );
     999             :     }
    1000             :     else
    1001             :     {
    1002           0 :         aClipReg = lclCreatePolygon(
    1003           0 :             aLPoints.maBeg, aLPoints.maEnd, rRect.BottomLeft(), rRect.TopLeft(), rRect.TopRight() );
    1004             :         aClipReg.Union( lclCreatePolygon(
    1005           0 :             aRPoints.maBeg, aRPoints.maEnd, rRect.BottomLeft(), rRect.BottomRight(), rRect.TopRight() ) );
    1006             :     }
    1007             : 
    1008           0 :     rDev.Push( PUSH_CLIPREGION );
    1009           0 :     rDev.IntersectClipRegion( aClipReg );
    1010           0 : }
    1011             : 
    1012             : 
    1013             : // Drawing functions for diagonal frame borders.
    1014             : 
    1015             : /** Draws a diagonal thin or thick line into the passed output device.
    1016             : 
    1017             :     The clipping region of the output device is modified according to the
    1018             :     passed DiagLineResult struct. A one pixel wide line can be drawn dotted.
    1019             :  */
    1020           0 : void lclDrawDiagLine(
    1021             :         OutputDevice& rDev, const Rectangle& rRect, bool bTLBR,
    1022             :         const DiagLineResult& rResult, long nDiagOffs1, long nDiagOffs2, SvxBorderStyle nDashing )
    1023             : {
    1024           0 :     lclPushDiagClipRect( rDev, rRect, rResult );
    1025           0 :     LinePoints aLPoints( lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs1 ) );
    1026           0 :     LinePoints aL2Points( lclGetDiagLineEnds( rRect, bTLBR, nDiagOffs2 ) );
    1027           0 :     Point aSMid( ( aLPoints.maBeg + aL2Points.maBeg ) / 2 );
    1028           0 :     Point aEMid( ( aLPoints.maEnd + aL2Points.maEnd ) / 2 );
    1029             : 
    1030           0 :     sal_uInt32 nWidth = lclToMapUnit( std::abs( nDiagOffs1 ) ) + lclToMapUnit( std::abs( nDiagOffs2 ) );
    1031           0 :     if ( ( nDiagOffs1 <= 0 && nDiagOffs2 <= 0 ) || ( nDiagOffs1 >=0 && nDiagOffs2 >=0 ) )
    1032           0 :         nWidth = lclToMapUnit( std::abs( nDiagOffs1 - nDiagOffs2 ) );
    1033             : 
    1034           0 :     svtools::DrawLine( rDev, aSMid, aEMid, nWidth, nDashing );
    1035           0 :     rDev.Pop(); // clipping region
    1036           0 : }
    1037             : 
    1038             : /** Draws a diagonal frame border into the passed output device.
    1039             : 
    1040             :     The lines of the frame border are drawn interrupted, if the style of the
    1041             :     crossing frame border is double.
    1042             : 
    1043             :     @param rRect
    1044             :         The reference rectangle of the diagonal frame border.
    1045             :     @param bTLBR
    1046             :         The orientation of the diagonal frame border.
    1047             :     @param rBorder
    1048             :         The frame style used to draw the border.
    1049             :     @param rResult
    1050             :         Offsets (sub units) to modify the clipping region of the output device.
    1051             :     @param rCrossStyle
    1052             :         Style of the crossing diagonal frame border.
    1053             :  */
    1054           0 : void lclDrawDiagFrameBorder(
    1055             :         OutputDevice& rDev, const Rectangle& rRect, bool bTLBR,
    1056             :         const Style& rBorder, const DiagBorderResult& rResult, const Style& rCrossStyle,
    1057             :         const Color* pForceColor, bool bDiagDblClip )
    1058             : {
    1059             :     DBG_ASSERT( rBorder.Prim(), "svx::frame::lclDrawDiagFrameBorder - line not visible" );
    1060             : 
    1061           0 :     bool bClip = bDiagDblClip && rCrossStyle.Secn();
    1062           0 :     if( bClip )
    1063           0 :         lclPushCrossingClipRegion( rDev, rRect, bTLBR, rCrossStyle );
    1064             : 
    1065           0 :     lclSetColorToOutDev( rDev, rBorder.GetColorPrim(), pForceColor );
    1066           0 :     lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maPrim, lclGetBeg( rBorder ), lclGetPrimEnd( rBorder ), rBorder.Type() );
    1067           0 :     rDev.Pop(); // colors
    1068           0 :     if( rBorder.Secn() )
    1069             :     {
    1070           0 :         if ( rBorder.UseGapColor( ) )
    1071             :         {
    1072           0 :             lclSetColorToOutDev( rDev, rBorder.GetColorGap(), pForceColor );
    1073           0 :             lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maSecn, lclGetDistBeg( rBorder ), lclGetDistEnd( rBorder ), rBorder.Type() );
    1074           0 :             rDev.Pop(); // colors
    1075             :         }
    1076             : 
    1077           0 :         lclSetColorToOutDev( rDev, rBorder.GetColorSecn(), pForceColor );
    1078           0 :         lclDrawDiagLine( rDev, rRect, bTLBR, rResult.maSecn, lclGetSecnBeg( rBorder ), lclGetEnd( rBorder ), rBorder.Type() );
    1079           0 :         rDev.Pop(); // colors
    1080             :     }
    1081             : 
    1082           0 :     if( bClip )
    1083           0 :         rDev.Pop(); // clipping region
    1084           0 : }
    1085             : 
    1086             : /** Draws both diagonal frame borders into the passed output device.
    1087             : 
    1088             :     The lines of each frame border is drawn interrupted, if the style of the
    1089             :     other crossing frame border is double.
    1090             : 
    1091             :     @param rRect
    1092             :         The reference rectangle of the diagonal frame borders.
    1093             :     @param rTLBR
    1094             :         The frame style of the top-left to bottom-right frame border.
    1095             :     @param rBLTR
    1096             :         The frame style of the bottom-left to top-right frame border.
    1097             :     @param rResult
    1098             :         Offsets (sub units) to modify the clipping region of the output device.
    1099             :  */
    1100           0 : void lclDrawDiagFrameBorders(
    1101             :         OutputDevice& rDev, const Rectangle& rRect,
    1102             :         const Style& rTLBR, const Style& rBLTR, const DiagBordersResult& rResult,
    1103             :         const Color* pForceColor, bool bDiagDblClip )
    1104             : {
    1105             :     DBG_ASSERT( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1), "svx::frame::lclDrawDiagFrameBorders - rectangle too small" );
    1106           0 :     if( (rRect.GetWidth() > 1) && (rRect.GetHeight() > 1) )
    1107             :     {
    1108           0 :         bool bDrawTLBR = rTLBR.Prim() != 0;
    1109           0 :         bool bDrawBLTR = rBLTR.Prim() != 0;
    1110           0 :         bool bFirstDrawBLTR = rTLBR.Secn() != 0;
    1111             : 
    1112           0 :         if( bDrawBLTR && bFirstDrawBLTR )
    1113           0 :             lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip );
    1114           0 :         if( bDrawTLBR )
    1115           0 :             lclDrawDiagFrameBorder( rDev, rRect, true, rTLBR, rResult.maTLBR, rBLTR, pForceColor, bDiagDblClip );
    1116           0 :         if( bDrawBLTR && !bFirstDrawBLTR )
    1117           0 :             lclDrawDiagFrameBorder( rDev, rRect, false, rBLTR, rResult.maBLTR, rTLBR, pForceColor, bDiagDblClip );
    1118             :     }
    1119           0 : }
    1120             : 
    1121             : 
    1122             : 
    1123             : } // namespace
    1124             : 
    1125             : 
    1126             : // Classes
    1127             : 
    1128             : 
    1129             : #define SCALEVALUE( value ) lclScaleValue( value, fScale, nMaxWidth )
    1130             : 
    1131    17488530 : Style::Style() :
    1132             :     meRefMode(REFMODE_CENTERED),
    1133             :     mfPatternScale(1.0),
    1134    17488530 :     mnType(table::BorderLineStyle::SOLID)
    1135             : {
    1136    17488530 :     Clear();
    1137    17488530 : }
    1138             : 
    1139           0 : Style::Style( double nP, double nD, double nS, editeng::SvxBorderStyle nType ) :
    1140             :     meRefMode(REFMODE_CENTERED),
    1141             :     mfPatternScale(1.0),
    1142           0 :     mnType(nType)
    1143             : {
    1144           0 :     Clear();
    1145           0 :     Set( nP, nD, nS );
    1146           0 : }
    1147             : 
    1148           0 : Style::Style( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor,
    1149             :               double nP, double nD, double nS, editeng::SvxBorderStyle nType ) :
    1150             :     meRefMode(REFMODE_CENTERED),
    1151             :     mfPatternScale(1.0),
    1152           0 :     mnType(nType)
    1153             : {
    1154           0 :     Set( rColorPrim, rColorSecn, rColorGap, bUseGapColor, nP, nD, nS );
    1155           0 : }
    1156             : 
    1157    15382848 : Style::Style( const editeng::SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth ) :
    1158             :     meRefMode(REFMODE_CENTERED),
    1159    15382848 :     mfPatternScale(fScale)
    1160             : {
    1161    15382848 :     Set( pBorder, fScale, nMaxWidth );
    1162    15382848 : }
    1163             : 
    1164        8196 : double Style::PatternScale() const
    1165             : {
    1166        8196 :     return mfPatternScale;
    1167             : }
    1168             : 
    1169       17076 : void Style::SetPatternScale( double fScale )
    1170             : {
    1171       17076 :     mfPatternScale = fScale;
    1172       17076 : }
    1173             : 
    1174    31802318 : void Style::Clear()
    1175             : {
    1176    31802318 :     Set( Color(), Color(), Color(), false, 0, 0, 0 );
    1177    31802318 : }
    1178             : 
    1179    32871719 : void Style::Set( double nP, double nD, double nS )
    1180             : {
    1181             :     /*  nP  nD  nS  ->  mfPrim  mfDist  mfSecn
    1182             :         --------------------------------------
    1183             :         any any 0       nP      0       0
    1184             :         0   any >0      nS      0       0
    1185             :         >0  0   >0      nP      0       0
    1186             :         >0  >0  >0      nP      nD      nS
    1187             :      */
    1188    32871719 :     mfPrim = rtl::math::round(nP ? nP : nS, 2);
    1189    32871719 :     mfDist = rtl::math::round((nP && nS) ? nD : 0, 2);
    1190    32871719 :     mfSecn = rtl::math::round((nP && nD) ? nS : 0, 2);
    1191    32871719 : }
    1192             : 
    1193    31802659 : void Style::Set( const Color& rColorPrim, const Color& rColorSecn, const Color& rColorGap, bool bUseGapColor, double nP, double nD, double nS )
    1194             : {
    1195    31802659 :     maColorPrim = rColorPrim;
    1196    31802659 :     maColorSecn = rColorSecn;
    1197    31802659 :     maColorGap = rColorGap;
    1198    31802659 :     mbUseGapColor = bUseGapColor;
    1199    31802659 :     Set( nP, nD, nS );
    1200    31802659 : }
    1201             : 
    1202     1069060 : void Style::Set( const SvxBorderLine& rBorder, double fScale, sal_uInt16 nMaxWidth )
    1203             : {
    1204     1069060 :     maColorPrim = rBorder.GetColorOut();
    1205     1069060 :     maColorSecn = rBorder.GetColorIn();
    1206     1069060 :     maColorGap = rBorder.GetColorGap();
    1207     1069060 :     mbUseGapColor = rBorder.HasGapColor();
    1208             : 
    1209     1069060 :     sal_uInt16 nPrim = rBorder.GetOutWidth();
    1210     1069060 :     sal_uInt16 nDist = rBorder.GetDistance();
    1211     1069060 :     sal_uInt16 nSecn = rBorder.GetInWidth();
    1212             : 
    1213     1069060 :     mnType = rBorder.GetBorderLineStyle();
    1214     1069060 :     if( !nSecn )    // no or single frame border
    1215             :     {
    1216     1067299 :         Set( SCALEVALUE( nPrim ), 0, 0 );
    1217             :     }
    1218             :     else
    1219             :     {
    1220        1761 :         Set( SCALEVALUE( nPrim ), SCALEVALUE( nDist ), SCALEVALUE( nSecn ) );
    1221             :         // Enlarge the style if distance is too small due to rounding losses.
    1222        1761 :         double nPixWidth = SCALEVALUE( nPrim + nDist + nSecn );
    1223        1761 :         if( nPixWidth > GetWidth() )
    1224        1712 :             mfDist = nPixWidth - mfPrim - mfSecn;
    1225             :         // Shrink the style if it is too thick for the control.
    1226        3522 :         while( GetWidth() > nMaxWidth )
    1227             :         {
    1228             :             // First decrease space between lines.
    1229           0 :             if (mfDist)
    1230           0 :                 --mfDist;
    1231             :             // Still too thick? Decrease the line widths.
    1232           0 :             if( GetWidth() > nMaxWidth )
    1233             :             {
    1234           0 :                 if (!rtl::math::approxEqual(mfPrim, 0.0) && rtl::math::approxEqual(mfPrim, mfSecn))
    1235             :                 {
    1236             :                     // Both lines equal - decrease both to keep symmetry.
    1237           0 :                     --mfPrim;
    1238           0 :                     --mfSecn;
    1239             :                 }
    1240             :                 else
    1241             :                 {
    1242             :                     // Decrease each line for itself
    1243           0 :                     if (mfPrim)
    1244           0 :                         --mfPrim;
    1245           0 :                     if ((GetWidth() > nMaxWidth) && !rtl::math::approxEqual(mfSecn, 0.0))
    1246           0 :                         --mfSecn;
    1247             :                 }
    1248             :             }
    1249             :         }
    1250             :     }
    1251     1069060 : }
    1252             : 
    1253    15382848 : void Style::Set( const SvxBorderLine* pBorder, double fScale, sal_uInt16 nMaxWidth )
    1254             : {
    1255    15382848 :     if( pBorder )
    1256     1069060 :         Set( *pBorder, fScale, nMaxWidth );
    1257             :     else
    1258             :     {
    1259    14313788 :         Clear();
    1260    14313788 :         mnType = table::BorderLineStyle::SOLID;
    1261             :     }
    1262    15382848 : }
    1263             : 
    1264        9930 : Style& Style::MirrorSelf()
    1265             : {
    1266        9930 :     if (mfSecn)
    1267          26 :         std::swap( mfPrim, mfSecn );
    1268        9930 :     if( meRefMode != REFMODE_CENTERED )
    1269           0 :         meRefMode = (meRefMode == REFMODE_BEGIN) ? REFMODE_END : REFMODE_BEGIN;
    1270        9930 :     return *this;
    1271             : }
    1272             : 
    1273           0 : Style Style::Mirror() const
    1274             : {
    1275           0 :     return Style( *this ).MirrorSelf();
    1276             : }
    1277             : 
    1278      333462 : bool operator==( const Style& rL, const Style& rR )
    1279             : {
    1280      997476 :     return (rL.Prim() == rR.Prim()) && (rL.Dist() == rR.Dist()) && (rL.Secn() == rR.Secn()) &&
    1281      996021 :         (rL.GetColorPrim() == rR.GetColorPrim()) && (rL.GetColorSecn() == rR.GetColorSecn()) &&
    1282      996021 :         (rL.GetColorGap() == rR.GetColorGap()) && (rL.GetRefMode() == rR.GetRefMode()) &&
    1283      997476 :         (rL.UseGapColor() == rR.UseGapColor() ) && (rL.Type() == rR.Type());
    1284             : }
    1285             : 
    1286     1280799 : bool operator<( const Style& rL, const Style& rR )
    1287             : {
    1288             :     // different total widths -> rL<rR, if rL is thinner
    1289     1280799 :     double nLW = rL.GetWidth();
    1290     1280799 :     double nRW = rR.GetWidth();
    1291     1280799 :     if( nLW != nRW ) return nLW < nRW;
    1292             : 
    1293             :     // one line double, the other single -> rL<rR, if rL is single
    1294     1256130 :     if( (rL.Secn() == 0) != (rR.Secn() == 0) ) return rL.Secn() == 0;
    1295             : 
    1296             :     // both lines double with different distances -> rL<rR, if distance of rL greater
    1297     1256130 :     if( (rL.Secn() && rR.Secn()) && (rL.Dist() != rR.Dist()) ) return rL.Dist() > rR.Dist();
    1298             : 
    1299             :     // both lines single and 1 unit thick, only one is dotted -> rL<rR, if rL is dotted
    1300     1256130 :     if( (nLW == 1) && (rL.Type() != rR.Type()) ) return rL.Type();
    1301             : 
    1302             :     // seem to be equal
    1303     1256130 :     return false;
    1304             : }
    1305             : 
    1306             : #undef SCALEVALUE
    1307             : 
    1308             : 
    1309             : // Various helper functions
    1310             : 
    1311             : 
    1312      737090 : double GetHorDiagAngle( long nWidth, long nHeight )
    1313             : {
    1314      737090 :     return atan2( static_cast< double >( std::abs( nHeight ) ), static_cast< double >( std::abs( nWidth ) ) );
    1315             : }
    1316             : 
    1317             : 
    1318             : 
    1319           0 : long GetTLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
    1320             : {
    1321           0 :     return lclD2L( nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) );
    1322             : }
    1323             : 
    1324           0 : long GetBLDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
    1325             : {
    1326           0 :     return lclD2L( -nVerOffs / tan( fAngle ) + nDiagOffs / sin( fAngle ) );
    1327             : }
    1328             : 
    1329           0 : long GetBRDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
    1330             : {
    1331           0 :     return -lclD2L( -nVerOffs / tan( fAngle ) - nDiagOffs / sin( fAngle ) );
    1332             : }
    1333             : 
    1334           0 : long GetTRDiagOffset( long nVerOffs, long nDiagOffs, double fAngle )
    1335             : {
    1336           0 :     return -lclD2L( nVerOffs / tan( fAngle ) - nDiagOffs / sin( fAngle ) );
    1337             : }
    1338             : 
    1339             : 
    1340             : 
    1341      333462 : bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder,
    1342             :         const Style& rTFromTL, const Style& rTFromT, const Style& rTFromTR,
    1343             :         const Style& rBFromBL, const Style& rBFromB, const Style& rBFromBR )
    1344             : {
    1345             :     return      // returns 1 AND (2a OR 2b)
    1346             :         // 1) only, if both frame borders are equal
    1347      333462 :         (rLBorder == rRBorder)
    1348      997476 :         &&
    1349             :         (
    1350             :             (
    1351             :                 // 2a) if the borders are not double, at least one of the vertical must not be double
    1352      664014 :                 !rLBorder.Secn() && (!rTFromT.Secn() || !rBFromB.Secn())
    1353             :             )
    1354           0 :             ||
    1355             :             (
    1356             :                 // 2b) if the borders are double, all other borders must not be double
    1357           0 :                 rLBorder.Secn() &&
    1358           0 :                 !rTFromTL.Secn() && !rTFromT.Secn() && !rTFromTR.Secn() &&
    1359           0 :                 !rBFromBL.Secn() && !rBFromB.Secn() && !rBFromBR.Secn()
    1360             :             )
    1361      333462 :         );
    1362             : }
    1363             : 
    1364             : 
    1365             : // Drawing functions
    1366             : 
    1367             : 
    1368       32784 : double lcl_GetExtent( const Style& rBorder, const Style& rSide, const Style& rOpposite,
    1369             :                       long nAngleSide = 9000, long nAngleOpposite = 9000 )
    1370             : {
    1371       32784 :     Style aOtherBorder = const_cast< Style& >( rSide );
    1372       32784 :     long nOtherAngle = nAngleSide;
    1373       32784 :     if ( rSide.GetWidth() == 0 && rOpposite.GetWidth() > 0 )
    1374             :     {
    1375        4346 :         nOtherAngle = nAngleOpposite;
    1376        4346 :         aOtherBorder = const_cast< Style& >( rOpposite );
    1377             :     }
    1378       28438 :     else if ( rSide.GetWidth() == 0 && rOpposite.GetWidth() == 0 )
    1379             :     {
    1380        2120 :         if ( ( nAngleOpposite % 18000 ) == 0 )
    1381           0 :             nOtherAngle = nAngleSide;
    1382        2120 :         else if ( ( nAngleSide % 18000 ) == 0 )
    1383           0 :             nOtherAngle = nAngleOpposite;
    1384             :     }
    1385             : 
    1386             :     // Let's assume the border we are drawing is horizontal and compute all the angles / distances from this
    1387       32784 :     basegfx::B2DVector aBaseVector( 1.0, 0.0 );
    1388       65568 :     basegfx::B2DPoint aBasePoint( 0.0, static_cast<double>( rBorder.GetWidth() / 2 ) );
    1389             : 
    1390       65568 :     basegfx::B2DHomMatrix aRotation;
    1391       32784 :     aRotation.rotate( double( nOtherAngle ) * M_PI / 18000.0 );
    1392             : 
    1393       65568 :     basegfx::B2DVector aOtherVector = aRotation * aBaseVector;
    1394             :     // Compute a line shifted by half the width of the other border
    1395       65568 :     basegfx::B2DVector aPerpendicular = basegfx::getNormalizedPerpendicular( aOtherVector );
    1396       65568 :     basegfx::B2DPoint aOtherPoint = basegfx::B2DPoint() + aPerpendicular * aOtherBorder.GetWidth() / 2;
    1397             : 
    1398             :     // Find the cut between the two lines
    1399       32784 :     double nCut = 0.0;
    1400             :     basegfx::tools::findCut(
    1401             :             aBasePoint, aBaseVector, aOtherPoint, aOtherVector,
    1402       32784 :             CUTFLAG_ALL, &nCut );
    1403             : 
    1404       65568 :     return nCut;
    1405             : }
    1406             : 
    1407           0 : basegfx::B2DPoint lcl_PointToB2DPoint( const Point aPoint )
    1408             : {
    1409           0 :     return basegfx::B2DPoint( aPoint.getX(), aPoint.getY() );
    1410             : }
    1411             : 
    1412           0 : drawinglayer::primitive2d::Primitive2DSequence CreateClippedBorderPrimitives (
    1413             :         const Point& rStart, const Point& rEnd, const Style& rBorder,
    1414             :         const Rectangle& rClipRect )
    1415             : {
    1416           0 :     drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
    1417           0 :     basegfx::B2DPolygon aPolygon;
    1418           0 :     aPolygon.append( lcl_PointToB2DPoint( rClipRect.TopLeft( ) ) );
    1419           0 :     aPolygon.append( lcl_PointToB2DPoint( rClipRect.TopRight( ) ) );
    1420           0 :     aPolygon.append( lcl_PointToB2DPoint( rClipRect.BottomRight( ) ) );
    1421           0 :     aPolygon.append( lcl_PointToB2DPoint( rClipRect.BottomLeft( ) ) );
    1422           0 :     aPolygon.setClosed( true );
    1423             : 
    1424           0 :     aSequence[0] = new drawinglayer::primitive2d::ClippedBorderLinePrimitive2D(
    1425             :         lcl_PointToB2DPoint( rStart ),
    1426             :         lcl_PointToB2DPoint( rEnd ),
    1427             :         rBorder.Prim(),
    1428             :         rBorder.Dist(),
    1429             :         rBorder.Secn(),
    1430             :         aPolygon,
    1431           0 :         rBorder.GetColorSecn().getBColor(),
    1432           0 :         rBorder.GetColorPrim().getBColor(),
    1433           0 :         rBorder.GetColorGap().getBColor(),
    1434           0 :         rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale() );
    1435             : 
    1436           0 :     return aSequence;
    1437             : }
    1438             : 
    1439        8196 : drawinglayer::primitive2d::Primitive2DSequence CreateBorderPrimitives(
    1440             :         const Point& rLPos, const Point& rRPos, const Style& rBorder,
    1441             :         const DiagStyle& /*rLFromTR*/, const Style& rLFromT, const Style& /*rLFromL*/, const Style& rLFromB, const DiagStyle& /*rLFromBR*/,
    1442             :         const DiagStyle& /*rRFromTL*/, const Style& rRFromT, const Style& /*rRFromR*/, const Style& rRFromB, const DiagStyle& /*rRFromBL*/,
    1443             :         const Color* /*pForceColor*/, const long& nRotateT, const long& nRotateB )
    1444             : {
    1445        8196 :     drawinglayer::primitive2d::Primitive2DSequence aSequence( 1 );
    1446             : 
    1447       16392 :     basegfx::B2DPoint aStart( rLPos.getX(), rLPos.getY() );
    1448       16392 :     basegfx::B2DPoint aEnd( rRPos.getX(), rRPos.getY() );
    1449             : 
    1450       98352 :     aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D(
    1451             :         aStart, aEnd,
    1452             :         rBorder.Prim(),
    1453             :         rBorder.Dist(),
    1454             :         rBorder.Secn(),
    1455        8196 :         lcl_GetExtent( rBorder, rLFromT, rLFromB, nRotateT, - nRotateB ),
    1456        8196 :         lcl_GetExtent( rBorder, rRFromT, rRFromB, 18000 - nRotateT, nRotateB - 18000 ),
    1457        8196 :         lcl_GetExtent( rBorder, rLFromB, rLFromT, nRotateB, - nRotateT ),
    1458        8196 :         lcl_GetExtent( rBorder, rRFromB, rRFromT, 18000 - nRotateB, nRotateT - 18000 ),
    1459        8196 :         rBorder.GetColorSecn().getBColor(),
    1460        8196 :         rBorder.GetColorPrim().getBColor(),
    1461        8196 :         rBorder.GetColorGap().getBColor(),
    1462       32784 :         rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale() );
    1463             : 
    1464       16392 :     return aSequence;
    1465             : }
    1466             : 
    1467        5588 : drawinglayer::primitive2d::Primitive2DSequence CreateBorderPrimitives(
    1468             :         const Point& rLPos, const Point& rRPos, const Style& rBorder,
    1469             :         const Style& rLFromT, const Style& rLFromL, const Style& rLFromB,
    1470             :         const Style& rRFromT, const Style& rRFromR, const Style& rRFromB,
    1471             :         const Color* pForceColor, const long& nRotateT, const long& nRotateB )
    1472             : {
    1473             :     return CreateBorderPrimitives( rLPos, rRPos, rBorder,
    1474             :             DiagStyle(), rLFromT, rLFromL, rLFromB, DiagStyle(),
    1475             :             DiagStyle(), rRFromT, rRFromR, rRFromB, DiagStyle(),
    1476        5588 :             pForceColor, nRotateT, nRotateB );
    1477             : }
    1478             : 
    1479           0 : void DrawHorFrameBorder( OutputDevice& rDev,
    1480             :         const Point& rLPos, const Point& rRPos, const Style& rBorder,
    1481             :         const DiagStyle& rLFromTR, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const DiagStyle& rLFromBR,
    1482             :         const DiagStyle& rRFromTL, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, const DiagStyle& rRFromBL,
    1483             :         const Color* pForceColor )
    1484             : {
    1485           0 :     if( rBorder.Prim() )
    1486             :     {
    1487           0 :         BorderResult aResult;
    1488             :         lclLinkHorFrameBorder( aResult, rBorder,
    1489             :             rLFromTR, rLFromT, rLFromL, rLFromB, rLFromBR,
    1490           0 :             rRFromTL, rRFromT, rRFromR, rRFromB, rRFromBL );
    1491           0 :         lclDrawHorFrameBorder( rDev, rLPos, rRPos, rBorder, aResult, pForceColor );
    1492             :     }
    1493           0 : }
    1494             : 
    1495             : 
    1496             : 
    1497           0 : void DrawVerFrameBorder( OutputDevice& rDev,
    1498             :         const Point& rTPos, const Point& rBPos, const Style& rBorder,
    1499             :         const DiagStyle& rTFromBL, const Style& rTFromL, const Style& rTFromT, const Style& rTFromR, const DiagStyle& rTFromBR,
    1500             :         const DiagStyle& rBFromTL, const Style& rBFromL, const Style& rBFromB, const Style& rBFromR, const DiagStyle& rBFromTR,
    1501             :         const Color* pForceColor )
    1502             : {
    1503           0 :     if( rBorder.Prim() )
    1504             :     {
    1505           0 :         BorderResult aResult;
    1506             :         lclLinkVerFrameBorder( aResult, rBorder,
    1507             :             rTFromBL, rTFromL, rTFromT, rTFromR, rTFromBR,
    1508           0 :             rBFromTL, rBFromL, rBFromB, rBFromR, rBFromTR );
    1509           0 :         lclDrawVerFrameBorder( rDev, rTPos, rBPos, rBorder, aResult, pForceColor );
    1510             :     }
    1511           0 : }
    1512             : 
    1513             : 
    1514             : 
    1515           0 : void DrawDiagFrameBorders(
    1516             :         OutputDevice& rDev, const Rectangle& rRect, const Style& rTLBR, const Style& rBLTR,
    1517             :         const Style& rTLFromB, const Style& rTLFromR, const Style& rBRFromT, const Style& rBRFromL,
    1518             :         const Style& rBLFromT, const Style& rBLFromR, const Style& rTRFromB, const Style& rTRFromL,
    1519             :         const Color* pForceColor, bool bDiagDblClip )
    1520             : {
    1521           0 :     if( rTLBR.Prim() || rBLTR.Prim() )
    1522             :     {
    1523           0 :         DiagBordersResult aResult;
    1524             :         lclLinkDiagFrameBorders( aResult, rTLBR, rBLTR,
    1525           0 :             rTLFromB, rTLFromR, rBRFromT, rBRFromL, rBLFromT, rBLFromR, rTRFromB, rTRFromL );
    1526           0 :         lclDrawDiagFrameBorders( rDev, rRect, rTLBR, rBLTR, aResult, pForceColor, bDiagDblClip );
    1527             :     }
    1528           0 : }
    1529             : 
    1530             : 
    1531             : 
    1532             : } // namespace frame
    1533             : } // namespace svx
    1534             : 
    1535             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10