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

Generated by: LCOV version 1.10