LCOV - code coverage report
Current view: top level - sdext/source/pdfimport/tree - pdfiprocessor.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 377 879 42.9 %
Date: 2012-08-25 Functions: 37 50 74.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 350 802 43.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include "pdfiprocessor.hxx"
      31                 :            : #include "xmlemitter.hxx"
      32                 :            : #include "pdfihelper.hxx"
      33                 :            : #include "imagecontainer.hxx"
      34                 :            : #include "genericelements.hxx"
      35                 :            : #include "style.hxx"
      36                 :            : #include "treevisiting.hxx"
      37                 :            : 
      38                 :            : #include <rtl/string.hxx>
      39                 :            : #include <rtl/strbuf.hxx>
      40                 :            : 
      41                 :            : #include <comphelper/sequence.hxx>
      42                 :            : #include <basegfx/polygon/b2dpolypolygontools.hxx>
      43                 :            : #include <basegfx/polygon/b2dpolygonclipper.hxx>
      44                 :            : #include <basegfx/polygon/b2dpolygontools.hxx>
      45                 :            : #include <basegfx/tools/canvastools.hxx>
      46                 :            : #include <basegfx/matrix/b2dhommatrix.hxx>
      47                 :            : #include <basegfx/range/b2irange.hxx>
      48                 :            : #include <basegfx/range/b2drectangle.hxx>
      49                 :            : #include <basegfx/matrix/b2dhommatrixtools.hxx>
      50                 :            : 
      51                 :            : #include <com/sun/star/rendering/XVolatileBitmap.hpp>
      52                 :            : #include <com/sun/star/geometry/RealSize2D.hpp>
      53                 :            : #include <com/sun/star/geometry/RealPoint2D.hpp>
      54                 :            : #include <com/sun/star/geometry/RealRectangle2D.hpp>
      55                 :            : 
      56                 :            : 
      57                 :            : using namespace com::sun::star;
      58                 :            : 
      59                 :            : 
      60                 :            : namespace pdfi
      61                 :            : {
      62                 :            : 
      63                 :          6 :  PDFIProcessor::PDFIProcessor( const uno::Reference< task::XStatusIndicator >& xStat ,
      64                 :            :             com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >  xContext) :
      65                 :            : 
      66                 :            :     m_xContext(xContext),
      67                 :            :     fYPrevTextPosition(-10000.0),
      68                 :            :     fPrevTextHeight(0.0),
      69                 :            :     fXPrevTextPosition(0.0),
      70                 :            :     fPrevTextWidth(0.0),
      71                 :            :     m_pElFactory( new ElementFactory() ),
      72                 :          6 :     m_pDocument( m_pElFactory->createDocumentElement() ),
      73                 :            :     m_pCurPage(0),
      74                 :            :     m_pCurElement(0),
      75                 :            :     m_nNextFontId( 1 ),
      76                 :            :     m_aIdToFont(),
      77                 :            :     m_aFontToId(),
      78                 :            :     m_aGCStack(),
      79                 :            :     m_nNextGCId( 1 ),
      80                 :            :     m_aIdToGC(),
      81                 :            :     m_aGCToId(),
      82                 :            :     m_aImages(),
      83                 :            :     m_eTextDirection( LrTb ),
      84                 :            :     m_nPages(0),
      85                 :            :     m_nNextZOrder( 1 ),
      86                 :            :     m_fWordSpace(0.0),
      87                 :            :     m_bIsWhiteSpaceInLine( false ),
      88                 :            :     m_xStatusIndicator( xStat ),
      89                 :            :     m_bHaveTextOnDocLevel(false),
      90 [ +  - ][ +  - ]:         12 :     m_bMirrorMapperTried(false)
           [ +  -  +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      91                 :            : {
      92                 :          6 :     FontAttributes aDefFont;
      93         [ +  - ]:          6 :     aDefFont.familyName = USTR("Helvetica");
      94                 :          6 :     aDefFont.isBold     = false;
      95                 :          6 :     aDefFont.isItalic   = false;
      96                 :          6 :     aDefFont.size       = 10*PDFI_OUTDEV_RESOLUTION/72;
      97         [ +  - ]:          6 :     m_aIdToFont[ 0 ]    = aDefFont;
      98         [ +  - ]:          6 :     m_aFontToId[ aDefFont ] = 0;
      99                 :            : 
     100         [ +  - ]:          6 :     GraphicsContext aDefGC;
     101         [ +  - ]:          6 :     m_aGCStack.push_back( aDefGC );
     102 [ +  - ][ +  - ]:          6 :     m_aIdToGC[ 0 ] = aDefGC;
     103 [ +  - ][ +  - ]:          6 :     m_aGCToId[ aDefGC ] = 0;
     104                 :          6 : }
     105                 :            : 
     106                 :          0 : void PDFIProcessor::enableToplevelText()
     107                 :            : {
     108                 :          0 :     m_bHaveTextOnDocLevel = true;
     109                 :          0 : }
     110                 :            : 
     111                 :          6 : void PDFIProcessor::setPageNum( sal_Int32 nPages )
     112                 :            : {
     113                 :          6 :     m_nPages = nPages;
     114                 :          6 : }
     115                 :            : 
     116                 :            : 
     117                 :         96 : void PDFIProcessor::pushState()
     118                 :            : {
     119 [ +  - ][ +  - ]:         96 :     GraphicsContextStack::value_type const a(m_aGCStack.back());
     120 [ +  - ][ +  - ]:         96 :     m_aGCStack.push_back(a);
     121                 :         96 : }
     122                 :            : 
     123                 :         96 : void PDFIProcessor::popState()
     124                 :            : {
     125                 :         96 :     m_aGCStack.pop_back();
     126                 :         96 : }
     127                 :            : 
     128                 :          6 : void PDFIProcessor::setFlatness( double value )
     129                 :            : {
     130                 :          6 :     getCurrentContext().Flatness = value;
     131                 :          6 : }
     132                 :            : 
     133                 :         12 : void PDFIProcessor::setTransformation( const geometry::AffineMatrix2D& rMatrix )
     134                 :            : {
     135                 :            :     basegfx::unotools::homMatrixFromAffineMatrix(
     136                 :         12 :         getCurrentContext().Transformation,
     137                 :         12 :         rMatrix );
     138                 :         12 : }
     139                 :            : 
     140                 :         12 : void PDFIProcessor::setLineDash( const uno::Sequence<double>& dashes,
     141                 :            :                                  double                       /*start*/ )
     142                 :            : {
     143                 :            :     // TODO(F2): factor in start offset
     144                 :         12 :     GraphicsContext& rContext( getCurrentContext() );
     145                 :         12 :     comphelper::sequenceToContainer(rContext.DashArray,dashes);
     146                 :         12 : }
     147                 :            : 
     148                 :         18 : void PDFIProcessor::setLineJoin(sal_Int8 nJoin)
     149                 :            : {
     150                 :         18 :     getCurrentContext().LineJoin = nJoin;
     151                 :         18 : }
     152                 :            : 
     153                 :         18 : void PDFIProcessor::setLineCap(sal_Int8 nCap)
     154                 :            : {
     155                 :         18 :     getCurrentContext().LineCap = nCap;
     156                 :         18 : }
     157                 :            : 
     158                 :          6 : void PDFIProcessor::setMiterLimit(double)
     159                 :            : {
     160                 :            :     OSL_TRACE("PDFIProcessor::setMiterLimit(): not supported by ODF");
     161                 :          6 : }
     162                 :            : 
     163                 :         24 : void PDFIProcessor::setLineWidth(double nWidth)
     164                 :            : {
     165                 :         24 :     getCurrentContext().LineWidth = nWidth;
     166                 :         24 : }
     167                 :            : 
     168                 :         84 : void PDFIProcessor::setFillColor( const rendering::ARGBColor& rColor )
     169                 :            : {
     170                 :         84 :     getCurrentContext().FillColor = rColor;
     171                 :         84 : }
     172                 :            : 
     173                 :         24 : void PDFIProcessor::setStrokeColor( const rendering::ARGBColor& rColor )
     174                 :            : {
     175                 :         24 :     getCurrentContext().LineColor = rColor;
     176                 :         24 : }
     177                 :            : 
     178                 :          0 : void PDFIProcessor::setBlendMode(sal_Int8)
     179                 :            : {
     180                 :            :     OSL_TRACE("PDFIProcessor::setBlendMode(): not supported by ODF");
     181                 :          0 : }
     182                 :            : 
     183                 :         66 : void PDFIProcessor::setFont( const FontAttributes& i_rFont )
     184                 :            : {
     185                 :         66 :     FontAttributes aChangedFont( i_rFont );
     186         [ +  - ]:         66 :     GraphicsContext& rGC=getCurrentContext();
     187                 :            :     // for text render modes, please see PDF reference manual
     188 [ +  - ][ -  + ]:         66 :     aChangedFont.isOutline = ( (rGC.TextRenderMode == 1) || (rGC. TextRenderMode == 2) );
     189         [ +  - ]:         66 :     FontToIdMap::const_iterator it = m_aFontToId.find( aChangedFont );
     190 [ +  + ][ +  - ]:         66 :     if( it != m_aFontToId.end() )
     191         [ +  - ]:         42 :         rGC.FontId = it->second;
     192                 :            :     else
     193                 :            :     {
     194         [ +  - ]:         24 :         m_aFontToId[ aChangedFont ] = m_nNextFontId;
     195         [ +  - ]:         24 :         m_aIdToFont[ m_nNextFontId ] = aChangedFont;
     196                 :         24 :         rGC.FontId = m_nNextFontId;
     197                 :         24 :         m_nNextFontId++;
     198                 :         66 :     }
     199                 :         66 : }
     200                 :            : 
     201                 :          0 : void PDFIProcessor::setTextRenderMode( sal_Int32 i_nMode )
     202                 :            : {
     203         [ #  # ]:          0 :     GraphicsContext& rGC=getCurrentContext();
     204                 :          0 :     rGC.TextRenderMode = i_nMode;
     205         [ #  # ]:          0 :     IdToFontMap::iterator it = m_aIdToFont.find( rGC.FontId );
     206 [ #  # ][ #  # ]:          0 :     if( it != m_aIdToFont.end() )
     207 [ #  # ][ #  # ]:          0 :         setFont( it->second );
     208                 :          0 : }
     209                 :            : 
     210                 :          0 : sal_Int32 PDFIProcessor::getFontId( const FontAttributes& rAttr ) const
     211                 :            : {
     212                 :          0 :     const sal_Int32 nCurFont = getCurrentContext().FontId;
     213                 :          0 :     const_cast<PDFIProcessor*>(this)->setFont( rAttr );
     214                 :          0 :     const sal_Int32 nFont = getCurrentContext().FontId;
     215                 :          0 :     const_cast<PDFIProcessor*>(this)->getCurrentContext().FontId = nCurFont;
     216                 :            : 
     217                 :          0 :     return nFont;
     218                 :            : }
     219                 :            : 
     220                 :            : // line diagnose block - start
     221                 :         66 : void PDFIProcessor::processGlyphLine()
     222                 :            : {
     223         [ -  + ]:         66 :     if( m_GlyphsList.size()<1 )
     224                 :         66 :         return;
     225                 :            : 
     226                 :         66 :     double fPreAvarageSpaceValue= 0.0;
     227                 :         66 :     double fAvarageDiffCharSpaceValue= 0.0;
     228                 :         66 :     double fMinPreSpaceValue= 0.0;
     229                 :         66 :     double fMaxPreSpaceValue= 0.0;
     230                 :         66 :     double fNullSpaceBreakerAvaregeSpaceValue = 0.0;
     231                 :            : 
     232                 :         66 :     unsigned int    nSpaceCount( 0 );
     233                 :         66 :     unsigned int    nDiffSpaceCount( 0 );
     234                 :         66 :     unsigned int    nNullSpaceBreakerCount=0;
     235                 :         66 :     bool preSpaceNull(true);
     236                 :            : 
     237         [ +  + ]:        624 :     for ( unsigned int i=0; i<m_GlyphsList.size()-1; i++ ) // i=1 because the first glyph doesn't have a prevGlyphSpace value
     238                 :            :     {
     239         [ +  + ]:        558 :         if( m_GlyphsList[i].getPrevGlyphsSpace()>0.0 )
     240                 :            :         {
     241         [ -  + ]:        174 :            if( fMinPreSpaceValue>m_GlyphsList[i].getPrevGlyphsSpace() )
     242                 :          0 :                fMinPreSpaceValue=m_GlyphsList[i].getPrevGlyphsSpace();
     243                 :            : 
     244         [ +  + ]:        174 :            if( fMaxPreSpaceValue<m_GlyphsList[i].getPrevGlyphsSpace() )
     245                 :         42 :                fMaxPreSpaceValue=m_GlyphsList[i].getPrevGlyphsSpace();
     246                 :            : 
     247                 :        174 :            fPreAvarageSpaceValue+= m_GlyphsList[i].getPrevGlyphsSpace();
     248                 :        174 :            nSpaceCount++;
     249                 :            :         }
     250                 :            :     }
     251                 :            : 
     252         [ +  + ]:         66 :     if( nSpaceCount!=0 )
     253                 :         42 :      fPreAvarageSpaceValue= fPreAvarageSpaceValue/( nSpaceCount );
     254                 :            : 
     255         [ +  + ]:        624 :     for ( unsigned int i=0; i<m_GlyphsList.size()-1; i++ ) // i=1 because the first glyph doesn't have a prevGlyphSpace value
     256                 :            :     {
     257         [ +  + ]:        558 :        if ( m_GlyphsList[i].getPrevGlyphsSpace()==0.0 )
     258                 :            :        {
     259         [ +  + ]:        504 :             if (
           [ +  +  +  + ]
     260                 :        384 :                  ( m_GlyphsList[i+1].getPrevGlyphsSpace()>0.0)&&
     261                 :        120 :                  ( fPreAvarageSpaceValue>m_GlyphsList[i+1].getPrevGlyphsSpace())
     262                 :            :                )
     263                 :            :             {
     264                 :         78 :               fNullSpaceBreakerAvaregeSpaceValue+=m_GlyphsList[i+1].getPrevGlyphsSpace();
     265                 :         78 :               nNullSpaceBreakerCount++;
     266                 :            :             }
     267                 :            :         }
     268                 :            :     }
     269                 :            : 
     270 [ +  + ][ +  - ]:         66 :     if( ( fNullSpaceBreakerAvaregeSpaceValue!= 0.0 )&&
     271                 :            :         ( fNullSpaceBreakerAvaregeSpaceValue < fPreAvarageSpaceValue )
     272                 :            :       )
     273                 :            :     {
     274                 :         30 :         fPreAvarageSpaceValue = fNullSpaceBreakerAvaregeSpaceValue;
     275                 :            :     }
     276                 :            : 
     277         [ +  + ]:        624 :     for ( unsigned int i=0; i<m_GlyphsList.size()-1; i++ ) // i=1 cose the first Glypth dont have prevGlyphSpace value
     278                 :            :     {
     279         [ +  + ]:        558 :         if  ( ( m_GlyphsList[i].getPrevGlyphsSpace()>0.0 )
     280                 :            :             )
     281                 :            :         {
     282         [ +  + ]:        300 :           if (
           [ +  +  +  + ]
     283                 :        174 :               ( m_GlyphsList[i].getPrevGlyphsSpace()  <= fPreAvarageSpaceValue )&&
     284                 :        126 :               ( m_GlyphsList[i+1].getPrevGlyphsSpace()<= fPreAvarageSpaceValue )
     285                 :            :              )
     286                 :            :           {
     287                 :        120 :                double temp= m_GlyphsList[i].getPrevGlyphsSpace()-m_GlyphsList[i+1].getPrevGlyphsSpace();
     288                 :            : 
     289         [ +  + ]:        120 :                if(temp!=0.0)
     290                 :            :                {
     291         [ -  + ]:        114 :                  if( temp< 0.0)
     292                 :          0 :                   temp= temp* -1.0;
     293                 :            : 
     294                 :        114 :                  fAvarageDiffCharSpaceValue+=temp;
     295                 :        114 :                  nDiffSpaceCount++;
     296                 :            :                }
     297                 :            :           }
     298                 :            :         }
     299                 :            : 
     300                 :            :     }
     301                 :            : 
     302         [ +  + ]:         66 :     if (
     303                 :            :          ( nNullSpaceBreakerCount>0 )
     304                 :            :        )
     305                 :            :     {
     306                 :         30 :        fNullSpaceBreakerAvaregeSpaceValue=fNullSpaceBreakerAvaregeSpaceValue/nNullSpaceBreakerCount;
     307                 :            :     }
     308                 :            : 
     309 [ +  + ][ +  - ]:         66 :     if (
     310                 :            :          ( nDiffSpaceCount>0 )&&(fAvarageDiffCharSpaceValue>0)
     311                 :            :        )
     312                 :            :     {
     313                 :         42 :         fAvarageDiffCharSpaceValue= fAvarageDiffCharSpaceValue/ nDiffSpaceCount;
     314                 :            :     }
     315                 :            : 
     316                 :         66 :     ParagraphElement* pPara= NULL ;
     317                 :         66 :     FrameElement* pFrame= NULL ;
     318                 :            : 
     319         [ +  - ]:         66 :     if(!m_GlyphsList.empty())
     320                 :            :     {
     321                 :         66 :         pFrame = m_pElFactory->createFrameElement( m_GlyphsList[0].getCurElement(), getGCId( getTransformGlyphContext( m_GlyphsList[0])) );
     322                 :         66 :         pFrame->ZOrder = m_nNextZOrder++;
     323                 :         66 :         pPara = m_pElFactory->createParagraphElement( pFrame );
     324                 :            : 
     325                 :            :         processGlyph( 0,
     326                 :         66 :                   m_GlyphsList[0],
     327                 :            :                   pPara,
     328                 :            :                   pFrame,
     329                 :         66 :                   m_bIsWhiteSpaceInLine );
     330                 :            :     }
     331                 :            : 
     332                 :            : 
     333                 :         66 :     preSpaceNull=false;
     334                 :            : 
     335         [ +  + ]:        582 :     for ( unsigned int i=1; i<m_GlyphsList.size()-1; i++ )
     336                 :            :     {
     337                 :        516 :         double fPrevDiffCharSpace= m_GlyphsList[i].getPrevGlyphsSpace()-m_GlyphsList[i-1].getPrevGlyphsSpace();
     338                 :        516 :         double fPostDiffCharSpace= m_GlyphsList[i].getPrevGlyphsSpace()-m_GlyphsList[i+1].getPrevGlyphsSpace();
     339                 :            : 
     340                 :            : 
     341         [ +  + ]:        858 :          if(
           [ +  +  +  + ]
     342                 :        342 :              preSpaceNull && (m_GlyphsList[i].getPrevGlyphsSpace()!= 0.0)
     343                 :            :             )
     344                 :            :          {
     345                 :        114 :                preSpaceNull=false;
     346         [ +  + ]:        114 :               if( fNullSpaceBreakerAvaregeSpaceValue > m_GlyphsList[i].getPrevGlyphsSpace() )
     347                 :            :               {
     348                 :            :                 processGlyph( 0,
     349                 :         24 :                                       m_GlyphsList[i],
     350                 :            :                               pPara,
     351                 :            :                               pFrame,
     352                 :         24 :                               m_bIsWhiteSpaceInLine );
     353                 :            : 
     354                 :            :               }
     355                 :            :               else
     356                 :            :               {
     357                 :            :                 processGlyph( 1,
     358                 :         90 :                               m_GlyphsList[i],
     359                 :            :                               pPara,
     360                 :            :                               pFrame,
     361                 :         90 :                               m_bIsWhiteSpaceInLine );
     362                 :            : 
     363                 :            :               }
     364                 :            : 
     365                 :            :          }
     366                 :            :          else
     367                 :            :          {
     368         [ +  - ]:        426 :             if (
           [ +  +  -  + ]
         [ +  + ][ +  + ]
     369                 :        402 :                 ( ( m_GlyphsList[i].getPrevGlyphsSpace()<= fPreAvarageSpaceValue )&&
     370                 :            :                   ( fPrevDiffCharSpace<=fAvarageDiffCharSpaceValue )&&
     371                 :            :                   ( fPostDiffCharSpace<=fAvarageDiffCharSpaceValue )
     372                 :            :                 ) ||
     373                 :         24 :                 ( m_GlyphsList[i].getPrevGlyphsSpace() == 0.0 )
     374                 :            :             )
     375                 :            :             {
     376                 :        378 :                 preSpaceNull=true;
     377                 :            : 
     378                 :            :             processGlyph( 0,
     379                 :        378 :                         m_GlyphsList[i],
     380                 :            :                         pPara,
     381                 :            :                         pFrame,
     382                 :        378 :                         m_bIsWhiteSpaceInLine );
     383                 :            : 
     384                 :            :             }
     385                 :            :             else
     386                 :            :             {
     387                 :            :                 processGlyph( 1,
     388                 :         24 :                         m_GlyphsList[i],
     389                 :            :                         pPara,
     390                 :            :                         pFrame,
     391                 :         24 :                         m_bIsWhiteSpaceInLine );
     392                 :            : 
     393                 :            :             }
     394                 :            : 
     395                 :            :          }
     396                 :            : 
     397                 :            :     }
     398                 :            : 
     399         [ +  + ]:         66 :     if(m_GlyphsList.size()>1)
     400                 :            :      processGlyph( 0,
     401                 :         42 :                   m_GlyphsList[m_GlyphsList.size()-1],
     402                 :            :                   pPara,
     403                 :            :                   pFrame,
     404                 :         42 :                   m_bIsWhiteSpaceInLine );
     405                 :            : 
     406                 :         66 :     m_GlyphsList.clear();
     407                 :            : }
     408                 :            : 
     409                 :        624 : void PDFIProcessor::processGlyph( double       fPreAvarageSpaceValue,
     410                 :            :                                   CharGlyph&   aGlyph,
     411                 :            :                                   ParagraphElement* pPara,
     412                 :            :                                   FrameElement* pFrame,
     413                 :            :                                   bool         bIsWhiteSpaceInLine
     414                 :            :                                       )
     415                 :            : {
     416         [ -  + ]:        624 :     if( !bIsWhiteSpaceInLine )
     417                 :            :     {
     418                 :          0 :         bool flag=( 0 < fPreAvarageSpaceValue );
     419                 :            : 
     420                 :          0 :         drawCharGlyphs(  aGlyph.getGlyph(),
     421                 :          0 :                          aGlyph.getRect(),
     422                 :          0 :                          aGlyph.getGC(),
     423                 :            :                          pPara,
     424                 :            :                          pFrame,
     425         [ #  # ]:          0 :                          flag);
     426                 :            :     }
     427                 :            :     else
     428                 :            :     {
     429                 :        624 :         drawCharGlyphs( aGlyph.getGlyph(),
     430                 :        624 :                         aGlyph.getRect(),
     431                 :        624 :                         aGlyph.getGC(),
     432                 :            :                         pPara,
     433                 :            :                         pFrame,
     434         [ +  - ]:       1248 :                         false );
     435                 :            :     }
     436                 :        624 : }
     437                 :            : 
     438                 :        624 : void PDFIProcessor::drawGlyphLine( const rtl::OUString&             rGlyphs,
     439                 :            :                                    const geometry::RealRectangle2D& rRect,
     440                 :            :                                    const geometry::Matrix2D&        rFontMatrix )
     441                 :            : {
     442                 :        624 :     double isFirstLine= fYPrevTextPosition+ fXPrevTextPosition+ fPrevTextHeight+ fPrevTextWidth ;
     443 [ +  + ][ +  - ]:        624 :     if(
         [ +  + ][ +  + ]
     444                 :            :         (  ( ( fYPrevTextPosition!= rRect.Y1 ) ) ||
     445                 :            :            ( ( fXPrevTextPosition > rRect.X2 ) ) ||
     446                 :            :            ( ( fXPrevTextPosition+fPrevTextWidth*1.3)<rRect.X1 )
     447                 :            :         )  && ( isFirstLine> 0.0 )
     448                 :            :     )
     449                 :            :     {
     450         [ +  - ]:         60 :         processGlyphLine();
     451                 :            :     }
     452                 :            : 
     453         [ +  - ]:        624 :     CharGlyph aGlyph;
     454                 :            : 
     455                 :        624 :     aGlyph.setGlyph ( rGlyphs );
     456                 :        624 :     aGlyph.setRect  ( rRect );
     457                 :        624 :     aGlyph.setFontMatrix ( rFontMatrix );
     458 [ +  - ][ +  - ]:        624 :     aGlyph.setGraphicsContext ( getCurrentContext() );
     459 [ +  - ][ +  - ]:        624 :     getGCId(getCurrentContext());
     460                 :        624 :     aGlyph.setCurElement( m_pCurElement );
     461                 :            : 
     462                 :        624 :     aGlyph.setYPrevGlyphPosition( fYPrevTextPosition );
     463                 :        624 :     aGlyph.setXPrevGlyphPosition( fXPrevTextPosition );
     464                 :        624 :     aGlyph.setPrevGlyphHeight  ( fPrevTextHeight );
     465                 :        624 :     aGlyph.setPrevGlyphWidth   ( fPrevTextWidth );
     466                 :            : 
     467         [ +  - ]:        624 :     m_GlyphsList.push_back( aGlyph );
     468                 :            : 
     469                 :        624 :     fYPrevTextPosition  = rRect.Y1;
     470                 :        624 :     fXPrevTextPosition  = rRect.X2;
     471                 :        624 :     fPrevTextHeight     = rRect.Y2-rRect.Y1;
     472                 :        624 :     fPrevTextWidth      = rRect.X2-rRect.X1;
     473                 :            : 
     474         [ +  + ]:        624 :     if( !m_bIsWhiteSpaceInLine )
     475                 :            :     {
     476 [ +  + ][ +  - ]:          6 :         static rtl::OUString tempWhiteSpaceStr( 0x20 );
     477 [ +  + ][ +  - ]:          6 :         static rtl::OUString tempWhiteSpaceNonBreakingStr( 0xa0 );
     478 [ -  + ][ #  # ]:          6 :         m_bIsWhiteSpaceInLine=(rGlyphs.equals( tempWhiteSpaceStr ) || rGlyphs.equals( tempWhiteSpaceNonBreakingStr ));
     479         [ +  - ]:        624 :     }
     480                 :        624 : }
     481                 :            : 
     482                 :         66 : GraphicsContext& PDFIProcessor::getTransformGlyphContext( CharGlyph& rGlyph )
     483                 :            : {
     484                 :         66 :     geometry::RealRectangle2D   rRect = rGlyph.getRect();
     485                 :         66 :     geometry::Matrix2D          rFontMatrix = rGlyph.getFontMatrix();
     486                 :            : 
     487                 :         66 :     rtl::OUString tempStr( 32 );
     488                 :            : 
     489         [ +  - ]:         66 :     basegfx::B2DHomMatrix aFontMatrix;
     490                 :            :     basegfx::unotools::homMatrixFromMatrix(
     491                 :            :         aFontMatrix,
     492         [ +  - ]:         66 :         rFontMatrix );
     493                 :            : 
     494         [ +  - ]:         66 :     FontAttributes aFontAttrs = m_aIdToFont[ rGlyph.getGC().FontId ];
     495                 :            : 
     496                 :            :     // add transformation to GC
     497         [ +  - ]:         66 :     basegfx::B2DHomMatrix aFontTransform(basegfx::tools::createTranslateB2DHomMatrix(-rRect.X1, -rRect.Y1));
     498         [ +  - ]:         66 :     aFontTransform *= aFontMatrix;
     499         [ +  - ]:         66 :     aFontTransform.translate( rRect.X1, rRect.Y1 );
     500                 :            : 
     501                 :            : 
     502 [ +  - ][ +  - ]:         66 :     rGlyph.getGC().Transformation = rGlyph.getGC().Transformation * aFontTransform;
                 [ +  - ]
     503         [ +  - ]:         66 :     getGCId(rGlyph.getGC());
     504                 :            : 
     505 [ +  - ][ +  - ]:         66 :   return rGlyph.getGC();
     506                 :            : }
     507                 :        624 : void PDFIProcessor::drawCharGlyphs( rtl::OUString&             rGlyphs,
     508                 :            :                                     geometry::RealRectangle2D& rRect,
     509                 :            :                                     GraphicsContext aGC,
     510                 :            :                                     ParagraphElement* pPara,
     511                 :            :                                     FrameElement* pFrame,
     512                 :            :                                     bool bSpaceFlag )
     513                 :            : {
     514                 :            : 
     515                 :            : 
     516                 :        624 :     rtl::OUString tempStr( 32 );
     517                 :        624 :     geometry::RealRectangle2D aRect(rRect);
     518                 :            : 
     519         [ +  - ]:        624 :     ::basegfx::B2DRange aRect2;
     520                 :            :     calcTransformedRectBounds( aRect2,
     521                 :            :                                               ::basegfx::unotools::b2DRectangleFromRealRectangle2D(aRect),
     522 [ +  - ][ +  - ]:        624 :                                               aGC.Transformation );
     523                 :            :    // check whether there was a previous draw frame
     524                 :            : 
     525                 :        624 :     TextElement* pText = m_pElFactory->createTextElement( pPara,
     526                 :            :                                                           getGCId(aGC),
     527 [ +  - ][ +  - ]:        624 :                                                           aGC.FontId );
     528         [ -  + ]:        624 :     if( bSpaceFlag )
     529         [ #  # ]:          0 :         pText->Text.append( tempStr );
     530                 :            : 
     531         [ +  - ]:        624 :     pText->Text.append( rGlyphs );
     532                 :            : 
     533         [ +  - ]:        624 :     pText->x = aRect2.getMinX() ;
     534         [ +  - ]:        624 :     pText->y = aRect2.getMinY() ;
     535                 :        624 :     pText->w = 0.0;  // ToDO P2: 1.1 is a hack for solving of size auto-grow problem
     536         [ +  - ]:        624 :     pText->h = aRect2.getHeight(); // ToDO P2: 1.1 is a hack for solving of size auto-grow problem
     537                 :            : 
     538         [ +  - ]:        624 :     pPara->updateGeometryWith( pText );
     539                 :            : 
     540         [ +  - ]:        624 :     if( pFrame )
     541         [ +  - ]:        624 :       pFrame->updateGeometryWith( pPara );
     542                 :            : 
     543                 :        624 : }
     544                 :        624 : void PDFIProcessor::drawGlyphs( const rtl::OUString&             rGlyphs,
     545                 :            :                                 const geometry::RealRectangle2D& rRect,
     546                 :            :                                 const geometry::Matrix2D&        rFontMatrix )
     547                 :            : {
     548                 :        624 :      drawGlyphLine( rGlyphs, rRect, rFontMatrix );
     549                 :        624 : }
     550                 :            : 
     551                 :         66 : void PDFIProcessor::endText()
     552                 :            : {
     553         [ -  + ]:         66 :     TextElement* pText = dynamic_cast<TextElement*>(m_pCurElement);
     554         [ -  + ]:         66 :     if( pText )
     555                 :          0 :         m_pCurElement = pText->Parent;
     556                 :         66 : }
     557                 :            : 
     558                 :          0 : void PDFIProcessor::setupImage(ImageId nImage)
     559                 :            : {
     560         [ #  # ]:          0 :     const GraphicsContext& rGC( getCurrentContext() );
     561                 :            : 
     562         [ #  # ]:          0 :     basegfx::B2DHomMatrix aTrans( rGC.Transformation );
     563                 :            : 
     564                 :            :     // check for rotation, which is the other way around in ODF
     565                 :          0 :     basegfx::B2DTuple aScale, aTranslation;
     566                 :            :     double fRotate, fShearX;
     567         [ #  # ]:          0 :     rGC.Transformation.decompose( aScale, aTranslation, fRotate, fShearX );
     568                 :            :     // TODDO(F4): correcting rotation when fShearX != 0 ?
     569         [ #  # ]:          0 :     if( fRotate != 0.0 )
     570                 :            :     {
     571                 :            : 
     572                 :            :         // try to create a Transformation that corrects for the wrong rotation
     573         [ #  # ]:          0 :         aTrans.identity();
     574         [ #  # ]:          0 :         aTrans.scale( aScale.getX(), aScale.getY() );
     575         [ #  # ]:          0 :         aTrans.rotate( -fRotate );
     576                 :            : 
     577         [ #  # ]:          0 :         basegfx::B2DRange aRect( 0, 0, 1, 1 );
     578         [ #  # ]:          0 :         aRect.transform( aTrans );
     579                 :            : 
     580                 :            :         // TODO(F3) treat translation correctly
     581                 :            :         // the corrections below work for multiples of 90 degree
     582                 :            :         // which is a common case (landscape/portrait/seascape)
     583                 :            :         // we need a general solution here; however this needs to
     584                 :            :         // work in sync with DrawXmlEmitter::fillFrameProps and WriterXmlEmitter::fillFrameProps
     585                 :            :         // admittedly this is a lame workaround and fails for arbitrary rotation
     586                 :          0 :         double fQuadrant = fmod( fRotate, 2.0*M_PI ) / M_PI_2;
     587                 :          0 :         int nQuadrant = (int)fQuadrant;
     588         [ #  # ]:          0 :         if( nQuadrant < 0 )
     589                 :          0 :             nQuadrant += 4;
     590         [ #  # ]:          0 :         if( nQuadrant == 1 )
     591                 :            :         {
     592 [ #  # ][ #  # ]:          0 :             aTranslation.setX( aTranslation.getX() + aRect.getHeight() + aRect.getWidth());
     593         [ #  # ]:          0 :             aTranslation.setY( aTranslation.getY() + aRect.getHeight() );
     594                 :            :         }
     595         [ #  # ]:          0 :         if( nQuadrant == 3 )
     596         [ #  # ]:          0 :             aTranslation.setX( aTranslation.getX() - aRect.getHeight() );
     597                 :            : 
     598                 :            :         aTrans.translate( aTranslation.getX(),
     599         [ #  # ]:          0 :                           aTranslation.getY() );
     600                 :            :     }
     601                 :            : 
     602                 :          0 :     bool bMirrorVertical = aScale.getY() > 0;
     603                 :            : 
     604                 :            :     // transform unit rect to determine view box
     605         [ #  # ]:          0 :     basegfx::B2DRange aRect( 0, 0, 1, 1 );
     606         [ #  # ]:          0 :     aRect.transform( aTrans );
     607                 :            : 
     608                 :            :     // TODO(F3): Handle clip
     609         [ #  # ]:          0 :     const sal_Int32 nGCId = getGCId(rGC);
     610         [ #  # ]:          0 :     FrameElement* pFrame = m_pElFactory->createFrameElement( m_pCurElement, nGCId );
     611         [ #  # ]:          0 :     ImageElement* pImageElement = m_pElFactory->createImageElement( pFrame, nGCId, nImage );
     612         [ #  # ]:          0 :     pFrame->x = pImageElement->x = aRect.getMinX();
     613         [ #  # ]:          0 :     pFrame->y = pImageElement->y = aRect.getMinY();
     614         [ #  # ]:          0 :     pFrame->w = pImageElement->w = aRect.getWidth();
     615         [ #  # ]:          0 :     pFrame->h = pImageElement->h = aRect.getHeight();
     616                 :          0 :     pFrame->ZOrder = m_nNextZOrder++;
     617                 :            : 
     618         [ #  # ]:          0 :     if( bMirrorVertical )
     619                 :            :     {
     620                 :          0 :         pFrame->MirrorVertical = pImageElement->MirrorVertical = true;
     621         [ #  # ]:          0 :         pFrame->x        += aRect.getWidth();
     622         [ #  # ]:          0 :         pImageElement->x += aRect.getWidth();
     623         [ #  # ]:          0 :         pFrame->y        += aRect.getHeight();
     624         [ #  # ]:          0 :         pImageElement->y += aRect.getHeight();
     625         [ #  # ]:          0 :     }
     626                 :          0 : }
     627                 :            : 
     628                 :          0 : void PDFIProcessor::drawMask(const uno::Sequence<beans::PropertyValue>& xBitmap,
     629                 :            :                              bool                                       /*bInvert*/ )
     630                 :            : {
     631                 :            :     // TODO(F3): Handle mask and inversion
     632                 :          0 :     setupImage( m_aImages.addImage(xBitmap) );
     633                 :          0 : }
     634                 :            : 
     635                 :          0 : void PDFIProcessor::drawImage(const uno::Sequence<beans::PropertyValue>& xBitmap )
     636                 :            : {
     637                 :          0 :     setupImage( m_aImages.addImage(xBitmap) );
     638                 :          0 : }
     639                 :            : 
     640                 :          0 : void PDFIProcessor::drawColorMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
     641                 :            :                                          const uno::Sequence<uno::Any>&             /*xMaskColors*/ )
     642                 :            : {
     643                 :            :     // TODO(F3): Handle mask colors
     644                 :          0 :     setupImage( m_aImages.addImage(xBitmap) );
     645                 :          0 : }
     646                 :            : 
     647                 :          0 : void PDFIProcessor::drawMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
     648                 :            :                                     const uno::Sequence<beans::PropertyValue>& /*xMask*/,
     649                 :            :                                     bool                                       /*bInvertMask*/)
     650                 :            : {
     651                 :            :     // TODO(F3): Handle mask and inversion
     652                 :          0 :     setupImage( m_aImages.addImage(xBitmap) );
     653                 :          0 : }
     654                 :            : 
     655                 :          0 : void PDFIProcessor::drawAlphaMaskedImage(const uno::Sequence<beans::PropertyValue>& xBitmap,
     656                 :            :                                          const uno::Sequence<beans::PropertyValue>& /*xMask*/)
     657                 :            : {
     658                 :            :     // TODO(F3): Handle mask
     659                 :            : 
     660                 :          0 :     setupImage( m_aImages.addImage(xBitmap) );
     661                 :            : 
     662                 :          0 : }
     663                 :            : 
     664                 :         12 : void PDFIProcessor::strokePath( const uno::Reference< rendering::XPolyPolygon2D >& rPath )
     665                 :            : {
     666         [ +  - ]:         12 :     basegfx::B2DPolyPolygon aPoly=basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
     667 [ +  - ][ +  - ]:         12 :     aPoly.transform(getCurrentContext().Transformation);
     668                 :            : 
     669                 :         12 :     PolyPolyElement* pPoly = m_pElFactory->createPolyPolyElement(
     670                 :            :         m_pCurElement,
     671         [ +  - ]:         12 :         getGCId(getCurrentContext()),
     672                 :            :         aPoly,
     673 [ +  - ][ +  - ]:         12 :         PATH_STROKE );
     674         [ +  - ]:         12 :     pPoly->updateGeometry();
     675         [ +  - ]:         12 :     pPoly->ZOrder = m_nNextZOrder++;
     676                 :         12 : }
     677                 :            : 
     678                 :          0 : void PDFIProcessor::fillPath( const uno::Reference< rendering::XPolyPolygon2D >& rPath )
     679                 :            : {
     680         [ #  # ]:          0 :     basegfx::B2DPolyPolygon aPoly=basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
     681 [ #  # ][ #  # ]:          0 :     aPoly.transform(getCurrentContext().Transformation);
     682                 :            : 
     683                 :          0 :     PolyPolyElement* pPoly = m_pElFactory->createPolyPolyElement(
     684                 :            :         m_pCurElement,
     685         [ #  # ]:          0 :         getGCId(getCurrentContext()),
     686                 :            :         aPoly,
     687 [ #  # ][ #  # ]:          0 :         PATH_FILL );
     688         [ #  # ]:          0 :     pPoly->updateGeometry();
     689         [ #  # ]:          0 :     pPoly->ZOrder = m_nNextZOrder++;
     690                 :          0 : }
     691                 :            : 
     692                 :          6 : void PDFIProcessor::eoFillPath( const uno::Reference< rendering::XPolyPolygon2D >& rPath )
     693                 :            : {
     694         [ +  - ]:          6 :     basegfx::B2DPolyPolygon aPoly=basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
     695 [ +  - ][ +  - ]:          6 :     aPoly.transform(getCurrentContext().Transformation);
     696                 :            : 
     697                 :          6 :     PolyPolyElement* pPoly = m_pElFactory->createPolyPolyElement(
     698                 :            :         m_pCurElement,
     699         [ +  - ]:          6 :         getGCId(getCurrentContext()),
     700                 :            :         aPoly,
     701 [ +  - ][ +  - ]:          6 :         PATH_EOFILL );
     702         [ +  - ]:          6 :     pPoly->updateGeometry();
     703         [ +  - ]:          6 :     pPoly->ZOrder = m_nNextZOrder++;
     704                 :          6 : }
     705                 :            : 
     706                 :          6 : void PDFIProcessor::intersectClip(const uno::Reference< rendering::XPolyPolygon2D >& rPath)
     707                 :            : {
     708                 :            :     // TODO(F3): interpret fill mode
     709         [ +  - ]:          6 :     basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
     710 [ +  - ][ +  - ]:          6 :     aNewClip.transform(getCurrentContext().Transformation);
     711 [ +  - ][ +  - ]:          6 :     basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
     712                 :            : 
     713 [ +  - ][ +  - ]:          6 :     if( aCurClip.count() )  // #i92985# adapted API from (..., false, false) to (..., true, false)
     714 [ +  - ][ +  - ]:          6 :         aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
                 [ +  - ]
     715                 :            : 
     716 [ +  - ][ +  - ]:          6 :     getCurrentContext().Clip = aNewClip;
         [ +  - ][ +  - ]
     717                 :          6 : }
     718                 :            : 
     719                 :          6 : void PDFIProcessor::intersectEoClip(const uno::Reference< rendering::XPolyPolygon2D >& rPath)
     720                 :            : {
     721                 :            :     // TODO(F3): interpret fill mode
     722         [ +  - ]:          6 :     basegfx::B2DPolyPolygon aNewClip = basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rPath);
     723 [ +  - ][ +  - ]:          6 :     aNewClip.transform(getCurrentContext().Transformation);
     724 [ +  - ][ +  - ]:          6 :     basegfx::B2DPolyPolygon aCurClip = getCurrentContext().Clip;
     725                 :            : 
     726 [ +  - ][ +  - ]:          6 :     if( aCurClip.count() )  // #i92985# adapted API from (..., false, false) to (..., true, false)
     727 [ +  - ][ +  - ]:          6 :         aNewClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aCurClip, aNewClip, true, false );
                 [ +  - ]
     728                 :            : 
     729 [ +  - ][ +  - ]:          6 :     getCurrentContext().Clip = aNewClip;
         [ +  - ][ +  - ]
     730                 :          6 : }
     731                 :            : 
     732                 :          6 : void PDFIProcessor::hyperLink( const geometry::RealRectangle2D& rBounds,
     733                 :            :                                const ::rtl::OUString&           rURI )
     734                 :            : {
     735         [ +  - ]:          6 :     if( !rURI.isEmpty() )
     736                 :            :     {
     737                 :          6 :         HyperlinkElement* pLink = m_pElFactory->createHyperlinkElement(
     738                 :            :             &m_pCurPage->Hyperlinks,
     739                 :          6 :             rURI );
     740                 :          6 :         pLink->x = rBounds.X1;
     741                 :          6 :         pLink->y = rBounds.Y1;
     742                 :          6 :         pLink->w = rBounds.X2-rBounds.X1;
     743                 :          6 :         pLink->h = rBounds.Y2-rBounds.Y1;
     744                 :            :     }
     745                 :          6 : }
     746                 :            : 
     747                 :         66 : const FontAttributes& PDFIProcessor::getFont( sal_Int32 nFontId ) const
     748                 :            : {
     749         [ +  - ]:         66 :     IdToFontMap::const_iterator it = m_aIdToFont.find( nFontId );
     750 [ +  - ][ -  + ]:         66 :     if( it == m_aIdToFont.end() )
     751         [ #  # ]:          0 :         it = m_aIdToFont.find( 0 );
     752         [ +  - ]:         66 :     return it->second;
     753                 :            : }
     754                 :            : 
     755                 :       1398 : sal_Int32 PDFIProcessor::getGCId( const GraphicsContext& rGC )
     756                 :            : {
     757                 :       1398 :     sal_Int32 nGCId = 0;
     758         [ +  - ]:       1398 :     GCToIdMap::const_iterator it = m_aGCToId.find( rGC );
     759 [ +  + ][ +  - ]:       1398 :     if( it != m_aGCToId.end() )
     760         [ +  - ]:       1350 :         nGCId = it->second;
     761                 :            :     else
     762                 :            :     {
     763         [ +  - ]:         48 :         m_aGCToId[ rGC ] = m_nNextGCId;
     764 [ +  - ][ +  - ]:         48 :         m_aIdToGC[ m_nNextGCId ] = rGC;
     765                 :         48 :         nGCId = m_nNextGCId;
     766                 :         48 :         m_nNextGCId++;
     767                 :            :     }
     768                 :            : 
     769                 :       1398 :     return nGCId;
     770                 :            : }
     771                 :            : 
     772                 :       1359 : const GraphicsContext& PDFIProcessor::getGraphicsContext( sal_Int32 nGCId ) const
     773                 :            : {
     774         [ +  - ]:       1359 :     IdToGCMap::const_iterator it = m_aIdToGC.find( nGCId );
     775 [ +  - ][ -  + ]:       1359 :     if( it == m_aIdToGC.end() )
     776         [ #  # ]:          0 :         it = m_aIdToGC.find( 0 );
     777         [ +  - ]:       1359 :     return it->second;
     778                 :            : }
     779                 :            : 
     780                 :          6 : void PDFIProcessor::endPage()
     781                 :            : {
     782                 :          6 :     processGlyphLine(); // draw last line
     783 [ #  # ][ #  # ]:          6 :     if( m_xStatusIndicator.is()
         [ -  + ][ -  + ]
     784                 :            :         && m_pCurPage
     785                 :            :         && m_pCurPage->PageNumber == m_nPages
     786                 :            :     )
     787                 :          0 :         m_xStatusIndicator->end();
     788                 :          6 : }
     789                 :            : 
     790                 :          6 : void PDFIProcessor::startPage( const geometry::RealSize2D& rSize )
     791                 :            : {
     792                 :            :     // initial clip is to page bounds
     793         [ +  - ]:          6 :     getCurrentContext().Clip = basegfx::B2DPolyPolygon(
     794                 :            :         basegfx::tools::createPolygonFromRect(
     795 [ +  - ][ +  - ]:         12 :             basegfx::B2DRange( 0, 0, rSize.Width, rSize.Height )));
         [ +  - ][ +  - ]
                 [ +  - ]
     796                 :            : 
     797         [ -  + ]:          6 :     sal_Int32 nNextPageNr = m_pCurPage ? m_pCurPage->PageNumber+1 : 1;
     798         [ -  + ]:          6 :     if( m_xStatusIndicator.is() )
     799                 :            :     {
     800         [ #  # ]:          0 :         if( nNextPageNr == 1 )
     801         [ #  # ]:          0 :             startIndicator( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
     802                 :          0 :         m_xStatusIndicator->setValue( nNextPageNr );
     803                 :            :     }
     804                 :          6 :     m_pCurPage = m_pElFactory->createPageElement(m_pDocument.get(), nNextPageNr);
     805                 :          6 :     m_pCurElement = m_pCurPage;
     806                 :          6 :     m_pCurPage->w = rSize.Width;
     807                 :          6 :     m_pCurPage->h = rSize.Height;
     808                 :          6 :     m_nNextZOrder = 1;
     809                 :            : 
     810                 :            : 
     811                 :          6 : }
     812                 :            : 
     813                 :          6 : void PDFIProcessor::emit( XmlEmitter&               rEmitter,
     814                 :            :                           const TreeVisitorFactory& rVisitorFactory )
     815                 :            : {
     816                 :            : #if OSL_DEBUG_LEVEL > 1
     817                 :            :     m_pDocument->emitStructure( 0 );
     818                 :            : #endif
     819                 :            : 
     820                 :            :     ElementTreeVisitorSharedPtr optimizingVisitor(
     821         [ +  - ]:          6 :         rVisitorFactory.createOptimizingVisitor(*this));
     822                 :            :     // FIXME: localization
     823 [ +  - ][ +  - ]:          6 :     startIndicator( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " " ) ) );
     824         [ +  - ]:          6 :     m_pDocument->visitedBy( *optimizingVisitor, std::list<Element*>::const_iterator());
     825                 :            : 
     826                 :            : #if OSL_DEBUG_LEVEL > 1
     827                 :            :     m_pDocument->emitStructure( 0 );
     828                 :            : #endif
     829                 :            : 
     830                 :            :     // get styles
     831         [ +  - ]:          6 :     StyleContainer aStyles;
     832                 :            :     ElementTreeVisitorSharedPtr finalizingVisitor(
     833         [ +  - ]:          6 :         rVisitorFactory.createStyleCollectingVisitor(aStyles,*this));
     834                 :            :     // FIXME: localization
     835                 :            : 
     836         [ +  - ]:          6 :     m_pDocument->visitedBy( *finalizingVisitor, std::list<Element*>::const_iterator() );
     837                 :            : 
     838         [ +  - ]:          6 :     EmitContext aContext( rEmitter, aStyles, m_aImages, *this, m_xStatusIndicator, m_xContext );
     839                 :            :     ElementTreeVisitorSharedPtr aEmittingVisitor(
     840         [ +  - ]:          6 :         rVisitorFactory.createEmittingVisitor(aContext, *this));
     841                 :            : 
     842         [ +  - ]:          6 :     PropertyMap aProps;
     843                 :            :     // document prolog
     844                 :            :     #define OASIS_STR "urn:oasis:names:tc:opendocument:xmlns:"
     845 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:office" ) ]      = USTR( OASIS_STR "office:1.0" );
                 [ +  - ]
     846 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:style" ) ]       = USTR( OASIS_STR "style:1.0" );
                 [ +  - ]
     847 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:text" ) ]        = USTR( OASIS_STR "text:1.0" );
                 [ +  - ]
     848 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:svg" ) ]         = USTR( OASIS_STR "svg-compatible:1.0" );
                 [ +  - ]
     849 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:table" ) ]       = USTR( OASIS_STR "table:1.0" );
                 [ +  - ]
     850 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:draw" ) ]        = USTR( OASIS_STR "drawing:1.0" );
                 [ +  - ]
     851 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:fo" ) ]          = USTR( OASIS_STR "xsl-fo-compatible:1.0" );
                 [ +  - ]
     852 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:xlink" )]        = USTR( "http://www.w3.org/1999/xlink" );
                 [ +  - ]
     853 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:dc" )]           = USTR( "http://purl.org/dc/elements/1.1/" );
                 [ +  - ]
     854 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:number" )]       = USTR( OASIS_STR "datastyle:1.0" );
                 [ +  - ]
     855 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:presentation" )] = USTR( OASIS_STR "presentation:1.0" );
                 [ +  - ]
     856 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:math" )]         = USTR( "http://www.w3.org/1998/Math/MathML" );
                 [ +  - ]
     857 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:form" )]         = USTR( OASIS_STR "form:1.0" );
                 [ +  - ]
     858 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:script" )]       = USTR( OASIS_STR "script:1.0" );
                 [ +  - ]
     859 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:dom" )]          = USTR( "http://www.w3.org/2001/xml-events" );
                 [ +  - ]
     860 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:xforms" )]       = USTR( "http://www.w3.org/2002/xforms" );
                 [ +  - ]
     861 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:xsd" )]          = USTR( "http://www.w3.org/2001/XMLSchema" );
                 [ +  - ]
     862 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "xmlns:xsi" )]          = USTR( "http://www.w3.org/2001/XMLSchema-instance" );
                 [ +  - ]
     863 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "office:version" ) ]    = USTR( "1.0" );
                 [ +  - ]
     864 [ +  - ][ +  - ]:          6 :     aProps[ USTR( "office:version" ) ]    = USTR( "1.0" );
                 [ +  - ]
     865                 :            : 
     866         [ +  - ]:          6 :     aContext.rEmitter.beginTag( "office:document", aProps );
     867                 :            : 
     868                 :            :     // emit style list
     869         [ +  - ]:          6 :     aStyles.emit( aContext, *aEmittingVisitor );
     870                 :            : 
     871         [ +  - ]:          6 :     m_pDocument->visitedBy( *aEmittingVisitor, std::list<Element*>::const_iterator() );
     872         [ +  - ]:          6 :     aContext.rEmitter.endTag( "office:document" );
     873 [ +  - ][ +  - ]:          6 :     endIndicator();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     874                 :          6 : }
     875                 :            : 
     876                 :          6 : void PDFIProcessor::startIndicator( const rtl::OUString& rText, sal_Int32 nElements )
     877                 :            : {
     878         [ +  - ]:          6 :     if( nElements == -1 )
     879                 :          6 :         nElements = m_nPages;
     880         [ -  + ]:          6 :     if( m_xStatusIndicator.is() )
     881                 :            :     {
     882                 :          0 :         sal_Int32 nUnicodes = rText.getLength();
     883                 :          0 :         rtl::OUStringBuffer aStr( nUnicodes*2 );
     884                 :          0 :         const sal_Unicode* pText = rText.getStr();
     885         [ #  # ]:          0 :         for( int i = 0; i < nUnicodes; i++ )
     886                 :            :         {
     887 [ #  # ][ #  # ]:          0 :             if( nUnicodes-i > 1&&
                 [ #  # ]
     888                 :          0 :                 pText[i]   == '%' &&
     889                 :          0 :                 pText[i+1] == 'd'
     890                 :            :             )
     891                 :            :             {
     892         [ #  # ]:          0 :                 aStr.append( nElements );
     893                 :          0 :                 i++;
     894                 :            :             }
     895                 :            :             else
     896         [ #  # ]:          0 :                 aStr.append( pText[i] );
     897                 :            :         }
     898 [ #  # ][ #  # ]:          0 :         m_xStatusIndicator->start( aStr.makeStringAndClear(), nElements );
                 [ #  # ]
     899                 :            :     }
     900                 :          6 : }
     901                 :            : 
     902                 :          6 : void PDFIProcessor::endIndicator()
     903                 :            : {
     904         [ -  + ]:          6 :     if( m_xStatusIndicator.is() )
     905                 :          0 :         m_xStatusIndicator->end();
     906                 :          6 : }
     907                 :            : 
     908                 :        246 : static bool lr_tb_sort( Element* pLeft, Element* pRight )
     909                 :            : {
     910                 :            :     // first: top-bottom sorting
     911                 :            : 
     912                 :            :     // Note: allow for 10% overlap on text lines since text lines are usually
     913                 :            :     // of the same order as font height whereas the real paint area
     914                 :            :     // of text is usually smaller
     915                 :        246 :     double fudge_factor = 1.0;
     916 [ +  - ][ +  - ]:        246 :     if( dynamic_cast< TextElement* >(pLeft) || dynamic_cast< TextElement* >(pRight) )
         [ +  - ][ -  + ]
                 [ -  + ]
     917                 :          0 :         fudge_factor = 0.9;
     918                 :            : 
     919                 :            :     // if left's lower boundary is above right's upper boundary
     920                 :            :     // then left is smaller
     921         [ +  + ]:        246 :     if( pLeft->y+pLeft->h*fudge_factor < pRight->y )
     922                 :         90 :         return true;
     923                 :            :     // if right's lower boundary is above left's upper boundary
     924                 :            :     // then left is definitely not smaller
     925         [ +  + ]:        156 :     if( pRight->y+pRight->h*fudge_factor < pLeft->y )
     926                 :         72 :         return false;
     927                 :            : 
     928                 :            :     // by now we have established that left and right are inside
     929                 :            :     // a "line", that is they have vertical overlap
     930                 :            :     // second: left-right sorting
     931                 :            :     // if left's right boundary is left to right's left boundary
     932                 :            :     // then left is smaller
     933         [ +  + ]:         84 :     if( pLeft->x+pLeft->w < pRight->x )
     934                 :         12 :         return true;
     935                 :            :     // if right's right boundary is left to left's left boundary
     936                 :            :     // then left is definitely not smaller
     937         [ +  + ]:         72 :     if( pRight->x+pRight->w < pLeft->x )
     938                 :         48 :         return false;
     939                 :            : 
     940                 :            :     // here we have established vertical and horizontal overlap
     941                 :            :     // so sort left first, top second
     942         [ +  + ]:         24 :     if( pLeft->x < pRight->x )
     943                 :         18 :         return true;
     944         [ +  - ]:          6 :     if( pRight->x < pLeft->x )
     945                 :          6 :         return false;
     946         [ #  # ]:          0 :     if( pLeft->y < pRight->y )
     947                 :          0 :         return true;
     948                 :            : 
     949                 :        246 :     return false;
     950                 :            : }
     951                 :            : 
     952                 :          6 : void PDFIProcessor::sortElements( Element* pEle, bool bDeep )
     953                 :            : {
     954         [ +  - ]:          6 :     if( pEle->Children.empty() )
     955                 :          6 :         return;
     956                 :            : 
     957         [ -  + ]:          6 :     if( bDeep )
     958                 :            :     {
     959         [ #  # ]:          0 :         for( std::list< Element* >::iterator it = pEle->Children.begin();
     960                 :          0 :              it != pEle->Children.end(); ++it )
     961                 :            :         {
     962         [ #  # ]:          0 :             sortElements( *it, bDeep );
     963                 :            :         }
     964                 :            :     }
     965                 :            :     // HACK: the stable sort member on std::list that takes a
     966                 :            :     // strict weak ordering requires member templates - which we
     967                 :            :     // do not have on all compilers. so we need to use std::stable_sort
     968                 :            :     // here - which does need random access iterators which the
     969                 :            :     // list iterators are not.
     970                 :            :     // so we need to copy the Element* to an array, stable sort that and
     971                 :            :     // copy them back.
     972         [ +  - ]:          6 :     std::vector<Element*> aChildren;
     973         [ +  + ]:         90 :     while( ! pEle->Children.empty() )
     974                 :            :     {
     975         [ +  - ]:         84 :         aChildren.push_back( pEle->Children.front() );
     976         [ +  - ]:         84 :         pEle->Children.pop_front();
     977                 :            :     }
     978                 :          6 :     switch( m_eTextDirection )
     979                 :            :     {
     980                 :            :         case LrTb:
     981                 :            :         default:
     982         [ +  - ]:          6 :         std::stable_sort( aChildren.begin(), aChildren.end(), lr_tb_sort );
     983                 :          6 :         break;
     984                 :            :     }
     985                 :          6 :     int nChildren = aChildren.size();
     986         [ +  + ]:         90 :     for( int i = 0; i < nChildren; i++ )
     987         [ +  - ]:         90 :         pEle->Children.push_back( aChildren[i] );
     988                 :            : }
     989                 :            : 
     990                 :            : 
     991                 :        624 : ::basegfx::B2DRange& PDFIProcessor::calcTransformedRectBounds( ::basegfx::B2DRange&         outRect,
     992                 :            :                                                         const ::basegfx::B2DRange&      inRect,
     993                 :            :                                                         const ::basegfx::B2DHomMatrix&  transformation )
     994                 :            :         {
     995         [ +  - ]:        624 :             outRect.reset();
     996                 :            : 
     997 [ +  - ][ -  + ]:        624 :             if( inRect.isEmpty() )
     998                 :          0 :                 return outRect;
     999                 :            : 
    1000                 :            :             // transform all four extremal points of the rectangle,
    1001                 :            :             // take bounding rect of those.
    1002                 :            : 
    1003                 :            :             // transform left-top point
    1004 [ +  - ][ +  - ]:        624 :             outRect.expand( transformation * inRect.getMinimum() );
                 [ +  - ]
    1005                 :            : 
    1006                 :            :             // transform bottom-right point
    1007 [ +  - ][ +  - ]:        624 :             outRect.expand( transformation * inRect.getMaximum() );
                 [ +  - ]
    1008                 :            : 
    1009                 :        624 :             ::basegfx::B2DPoint aPoint;
    1010                 :            : 
    1011                 :            :             // transform top-right point
    1012         [ +  - ]:        624 :             aPoint.setX( inRect.getMaxX() );
    1013         [ +  - ]:        624 :             aPoint.setY( inRect.getMinY() );
    1014                 :            : 
    1015         [ +  - ]:        624 :             aPoint *= transformation;
    1016         [ +  - ]:        624 :             outRect.expand( aPoint );
    1017                 :            : 
    1018                 :            :             // transform bottom-left point
    1019         [ +  - ]:        624 :             aPoint.setX( inRect.getMinX() );
    1020         [ +  - ]:        624 :             aPoint.setY( inRect.getMaxY() );
    1021                 :            : 
    1022         [ +  - ]:        624 :             aPoint *= transformation;
    1023         [ +  - ]:        624 :             outRect.expand( aPoint );
    1024                 :            : 
    1025                 :            :             // over and out.
    1026                 :        624 :             return outRect;
    1027                 :            :         }
    1028                 :            : 
    1029                 :            : // helper method: get a mirrored string
    1030                 :          0 : rtl::OUString PDFIProcessor::mirrorString( const rtl::OUString& i_rString )
    1031                 :            : {
    1032 [ #  # ][ #  # ]:          0 :     if( ! m_xMirrorMapper.is() && ! m_bMirrorMapperTried )
                 [ #  # ]
    1033                 :            :     {
    1034                 :          0 :         m_bMirrorMapperTried = true;
    1035 [ #  # ][ #  # ]:          0 :         uno::Reference< lang::XMultiComponentFactory > xMSF(  m_xContext->getServiceManager(), uno::UNO_SET_THROW );
                 [ #  # ]
    1036 [ #  # ][ #  # ]:          0 :         uno::Reference < uno::XInterface > xInterface = xMSF->createInstanceWithContext(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.StringMirror")), m_xContext);
                 [ #  # ]
    1037 [ #  # ][ #  # ]:          0 :         m_xMirrorMapper = uno::Reference< util::XStringMapping >( xInterface, uno::UNO_QUERY );
    1038                 :            :         #if OSL_DEBUG_LEVEL > 1
    1039                 :            :         if( m_xMirrorMapper.is() )
    1040                 :            :             fprintf( stderr, "using mirror mapper service\n" );
    1041                 :            :         #endif
    1042                 :            :     }
    1043         [ #  # ]:          0 :     if( m_xMirrorMapper.is() )
    1044                 :            :     {
    1045         [ #  # ]:          0 :         uno::Sequence< rtl::OUString > aSeq( 1 );
    1046         [ #  # ]:          0 :         aSeq.getArray()[0] = i_rString;
    1047 [ #  # ][ #  # ]:          0 :         m_xMirrorMapper->mapStrings( aSeq );
    1048 [ #  # ][ #  # ]:          0 :         return  aSeq[0];
    1049                 :            :     }
    1050                 :            : 
    1051         [ #  # ]:          0 :     prepareMirrorMap();
    1052                 :          0 :     sal_Int32 nLen = i_rString.getLength();
    1053                 :          0 :     rtl::OUStringBuffer aRet( nLen );
    1054         [ #  # ]:          0 :     for(int i = nLen - 1; i >= 0; i--)
    1055                 :            :     {
    1056                 :          0 :         sal_Unicode cChar = i_rString[ i ];
    1057 [ #  # ][ #  # ]:          0 :         aRet.append( m_aMirrorMap[cChar] );
    1058                 :            :     }
    1059         [ #  # ]:          0 :     return aRet.makeStringAndClear();
    1060                 :            : }
    1061                 :            : 
    1062                 :          0 : void PDFIProcessor::prepareMirrorMap()
    1063                 :            : {
    1064         [ #  # ]:          0 :     if( m_aMirrorMap.empty() )
    1065                 :            :     {
    1066                 :            :         #if OSL_DEBUG_LEVEL > 1
    1067                 :            :         fprintf( stderr, "falling back to static mirror list\n" );
    1068                 :            :         #endif
    1069                 :            : 
    1070                 :          0 :         m_aMirrorMap.reserve( 0x10000 );
    1071         [ #  # ]:          0 :         for( int i = 0; i < 0x10000; i++ )
    1072         [ #  # ]:          0 :             m_aMirrorMap.push_back( sal_Unicode(i) );
    1073                 :            : 
    1074                 :          0 :         m_aMirrorMap[ 0x0028 ] = 0x0029; // LEFT PARENTHESIS
    1075                 :          0 :         m_aMirrorMap[ 0x0029 ] = 0x0028; // RIGHT PARENTHESIS
    1076                 :          0 :         m_aMirrorMap[ 0x003C ] = 0x003E; // LESS-THAN SIGN
    1077                 :          0 :         m_aMirrorMap[ 0x003E ] = 0x003C; // GREATER-THAN SIGN
    1078                 :          0 :         m_aMirrorMap[ 0x005B ] = 0x005D; // LEFT SQUARE BRACKET
    1079                 :          0 :         m_aMirrorMap[ 0x005D ] = 0x005B; // RIGHT SQUARE BRACKET
    1080                 :          0 :         m_aMirrorMap[ 0x007B ] = 0x007D; // LEFT CURLY BRACKET
    1081                 :          0 :         m_aMirrorMap[ 0x007D ] = 0x007B; // RIGHT CURLY BRACKET
    1082                 :          0 :         m_aMirrorMap[ 0x00AB ] = 0x00BB; // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
    1083                 :          0 :         m_aMirrorMap[ 0x00BB ] = 0x00AB; // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
    1084                 :          0 :         m_aMirrorMap[ 0x0F3A ] = 0x0F3B; // TIBETAN MARK GUG RTAGS GYON
    1085                 :          0 :         m_aMirrorMap[ 0x0F3B ] = 0x0F3A; // TIBETAN MARK GUG RTAGS GYAS
    1086                 :          0 :         m_aMirrorMap[ 0x0F3C ] = 0x0F3D; // TIBETAN MARK ANG KHANG GYON
    1087                 :          0 :         m_aMirrorMap[ 0x0F3D ] = 0x0F3C; // TIBETAN MARK ANG KHANG GYAS
    1088                 :          0 :         m_aMirrorMap[ 0x169B ] = 0x169C; // OGHAM FEATHER MARK
    1089                 :          0 :         m_aMirrorMap[ 0x169C ] = 0x169B; // OGHAM REVERSED FEATHER MARK
    1090                 :          0 :         m_aMirrorMap[ 0x2039 ] = 0x203A; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
    1091                 :          0 :         m_aMirrorMap[ 0x203A ] = 0x2039; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
    1092                 :          0 :         m_aMirrorMap[ 0x2045 ] = 0x2046; // LEFT SQUARE BRACKET WITH QUILL
    1093                 :          0 :         m_aMirrorMap[ 0x2046 ] = 0x2045; // RIGHT SQUARE BRACKET WITH QUILL
    1094                 :          0 :         m_aMirrorMap[ 0x207D ] = 0x207E; // SUPERSCRIPT LEFT PARENTHESIS
    1095                 :          0 :         m_aMirrorMap[ 0x207E ] = 0x207D; // SUPERSCRIPT RIGHT PARENTHESIS
    1096                 :          0 :         m_aMirrorMap[ 0x208D ] = 0x208E; // SUBSCRIPT LEFT PARENTHESIS
    1097                 :          0 :         m_aMirrorMap[ 0x208E ] = 0x208D; // SUBSCRIPT RIGHT PARENTHESIS
    1098                 :          0 :         m_aMirrorMap[ 0x2208 ] = 0x220B; // ELEMENT OF
    1099                 :          0 :         m_aMirrorMap[ 0x2209 ] = 0x220C; // NOT AN ELEMENT OF
    1100                 :          0 :         m_aMirrorMap[ 0x220A ] = 0x220D; // SMALL ELEMENT OF
    1101                 :          0 :         m_aMirrorMap[ 0x220B ] = 0x2208; // CONTAINS AS MEMBER
    1102                 :          0 :         m_aMirrorMap[ 0x220C ] = 0x2209; // DOES NOT CONTAIN AS MEMBER
    1103                 :          0 :         m_aMirrorMap[ 0x220D ] = 0x220A; // SMALL CONTAINS AS MEMBER
    1104                 :          0 :         m_aMirrorMap[ 0x2215 ] = 0x29F5; // DIVISION SLASH
    1105                 :          0 :         m_aMirrorMap[ 0x223C ] = 0x223D; // TILDE OPERATOR
    1106                 :          0 :         m_aMirrorMap[ 0x223D ] = 0x223C; // REVERSED TILDE
    1107                 :          0 :         m_aMirrorMap[ 0x2243 ] = 0x22CD; // ASYMPTOTICALLY EQUAL TO
    1108                 :          0 :         m_aMirrorMap[ 0x2252 ] = 0x2253; // APPROXIMATELY EQUAL TO OR THE IMAGE OF
    1109                 :          0 :         m_aMirrorMap[ 0x2253 ] = 0x2252; // IMAGE OF OR APPROXIMATELY EQUAL TO
    1110                 :          0 :         m_aMirrorMap[ 0x2254 ] = 0x2255; // COLON EQUALS
    1111                 :          0 :         m_aMirrorMap[ 0x2255 ] = 0x2254; // EQUALS COLON
    1112                 :          0 :         m_aMirrorMap[ 0x2264 ] = 0x2265; // LESS-THAN OR EQUAL TO
    1113                 :          0 :         m_aMirrorMap[ 0x2265 ] = 0x2264; // GREATER-THAN OR EQUAL TO
    1114                 :          0 :         m_aMirrorMap[ 0x2266 ] = 0x2267; // LESS-THAN OVER EQUAL TO
    1115                 :          0 :         m_aMirrorMap[ 0x2267 ] = 0x2266; // GREATER-THAN OVER EQUAL TO
    1116                 :          0 :         m_aMirrorMap[ 0x2268 ] = 0x2269; // [BEST FIT] LESS-THAN BUT NOT EQUAL TO
    1117                 :          0 :         m_aMirrorMap[ 0x2269 ] = 0x2268; // [BEST FIT] GREATER-THAN BUT NOT EQUAL TO
    1118                 :          0 :         m_aMirrorMap[ 0x226A ] = 0x226B; // MUCH LESS-THAN
    1119                 :          0 :         m_aMirrorMap[ 0x226B ] = 0x226A; // MUCH GREATER-THAN
    1120                 :          0 :         m_aMirrorMap[ 0x226E ] = 0x226F; // [BEST FIT] NOT LESS-THAN
    1121                 :          0 :         m_aMirrorMap[ 0x226F ] = 0x226E; // [BEST FIT] NOT GREATER-THAN
    1122                 :          0 :         m_aMirrorMap[ 0x2270 ] = 0x2271; // [BEST FIT] NEITHER LESS-THAN NOR EQUAL TO
    1123                 :          0 :         m_aMirrorMap[ 0x2271 ] = 0x2270; // [BEST FIT] NEITHER GREATER-THAN NOR EQUAL TO
    1124                 :          0 :         m_aMirrorMap[ 0x2272 ] = 0x2273; // [BEST FIT] LESS-THAN OR EQUIVALENT TO
    1125                 :          0 :         m_aMirrorMap[ 0x2273 ] = 0x2272; // [BEST FIT] GREATER-THAN OR EQUIVALENT TO
    1126                 :          0 :         m_aMirrorMap[ 0x2274 ] = 0x2275; // [BEST FIT] NEITHER LESS-THAN NOR EQUIVALENT TO
    1127                 :          0 :         m_aMirrorMap[ 0x2275 ] = 0x2274; // [BEST FIT] NEITHER GREATER-THAN NOR EQUIVALENT TO
    1128                 :          0 :         m_aMirrorMap[ 0x2276 ] = 0x2277; // LESS-THAN OR GREATER-THAN
    1129                 :          0 :         m_aMirrorMap[ 0x2277 ] = 0x2276; // GREATER-THAN OR LESS-THAN
    1130                 :          0 :         m_aMirrorMap[ 0x2278 ] = 0x2279; // [BEST FIT] NEITHER LESS-THAN NOR GREATER-THAN
    1131                 :          0 :         m_aMirrorMap[ 0x2279 ] = 0x2278; // [BEST FIT] NEITHER GREATER-THAN NOR LESS-THAN
    1132                 :          0 :         m_aMirrorMap[ 0x227A ] = 0x227B; // PRECEDES
    1133                 :          0 :         m_aMirrorMap[ 0x227B ] = 0x227A; // SUCCEEDS
    1134                 :          0 :         m_aMirrorMap[ 0x227C ] = 0x227D; // PRECEDES OR EQUAL TO
    1135                 :          0 :         m_aMirrorMap[ 0x227D ] = 0x227C; // SUCCEEDS OR EQUAL TO
    1136                 :          0 :         m_aMirrorMap[ 0x227E ] = 0x227F; // [BEST FIT] PRECEDES OR EQUIVALENT TO
    1137                 :          0 :         m_aMirrorMap[ 0x227F ] = 0x227E; // [BEST FIT] SUCCEEDS OR EQUIVALENT TO
    1138                 :          0 :         m_aMirrorMap[ 0x2280 ] = 0x2281; // [BEST FIT] DOES NOT PRECEDE
    1139                 :          0 :         m_aMirrorMap[ 0x2281 ] = 0x2280; // [BEST FIT] DOES NOT SUCCEED
    1140                 :          0 :         m_aMirrorMap[ 0x2282 ] = 0x2283; // SUBSET OF
    1141                 :          0 :         m_aMirrorMap[ 0x2283 ] = 0x2282; // SUPERSET OF
    1142                 :          0 :         m_aMirrorMap[ 0x2284 ] = 0x2285; // [BEST FIT] NOT A SUBSET OF
    1143                 :          0 :         m_aMirrorMap[ 0x2285 ] = 0x2284; // [BEST FIT] NOT A SUPERSET OF
    1144                 :          0 :         m_aMirrorMap[ 0x2286 ] = 0x2287; // SUBSET OF OR EQUAL TO
    1145                 :          0 :         m_aMirrorMap[ 0x2287 ] = 0x2286; // SUPERSET OF OR EQUAL TO
    1146                 :          0 :         m_aMirrorMap[ 0x2288 ] = 0x2289; // [BEST FIT] NEITHER A SUBSET OF NOR EQUAL TO
    1147                 :          0 :         m_aMirrorMap[ 0x2289 ] = 0x2288; // [BEST FIT] NEITHER A SUPERSET OF NOR EQUAL TO
    1148                 :          0 :         m_aMirrorMap[ 0x228A ] = 0x228B; // [BEST FIT] SUBSET OF WITH NOT EQUAL TO
    1149                 :          0 :         m_aMirrorMap[ 0x228B ] = 0x228A; // [BEST FIT] SUPERSET OF WITH NOT EQUAL TO
    1150                 :          0 :         m_aMirrorMap[ 0x228F ] = 0x2290; // SQUARE IMAGE OF
    1151                 :          0 :         m_aMirrorMap[ 0x2290 ] = 0x228F; // SQUARE ORIGINAL OF
    1152                 :          0 :         m_aMirrorMap[ 0x2291 ] = 0x2292; // SQUARE IMAGE OF OR EQUAL TO
    1153                 :          0 :         m_aMirrorMap[ 0x2292 ] = 0x2291; // SQUARE ORIGINAL OF OR EQUAL TO
    1154                 :          0 :         m_aMirrorMap[ 0x2298 ] = 0x29B8; // CIRCLED DIVISION SLASH
    1155                 :          0 :         m_aMirrorMap[ 0x22A2 ] = 0x22A3; // RIGHT TACK
    1156                 :          0 :         m_aMirrorMap[ 0x22A3 ] = 0x22A2; // LEFT TACK
    1157                 :          0 :         m_aMirrorMap[ 0x22A6 ] = 0x2ADE; // ASSERTION
    1158                 :          0 :         m_aMirrorMap[ 0x22A8 ] = 0x2AE4; // TRUE
    1159                 :          0 :         m_aMirrorMap[ 0x22A9 ] = 0x2AE3; // FORCES
    1160                 :          0 :         m_aMirrorMap[ 0x22AB ] = 0x2AE5; // DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE
    1161                 :          0 :         m_aMirrorMap[ 0x22B0 ] = 0x22B1; // PRECEDES UNDER RELATION
    1162                 :          0 :         m_aMirrorMap[ 0x22B1 ] = 0x22B0; // SUCCEEDS UNDER RELATION
    1163                 :          0 :         m_aMirrorMap[ 0x22B2 ] = 0x22B3; // NORMAL SUBGROUP OF
    1164                 :          0 :         m_aMirrorMap[ 0x22B3 ] = 0x22B2; // CONTAINS AS NORMAL SUBGROUP
    1165                 :          0 :         m_aMirrorMap[ 0x22B4 ] = 0x22B5; // NORMAL SUBGROUP OF OR EQUAL TO
    1166                 :          0 :         m_aMirrorMap[ 0x22B5 ] = 0x22B4; // CONTAINS AS NORMAL SUBGROUP OR EQUAL TO
    1167                 :          0 :         m_aMirrorMap[ 0x22B6 ] = 0x22B7; // ORIGINAL OF
    1168                 :          0 :         m_aMirrorMap[ 0x22B7 ] = 0x22B6; // IMAGE OF
    1169                 :          0 :         m_aMirrorMap[ 0x22C9 ] = 0x22CA; // LEFT NORMAL FACTOR SEMIDIRECT PRODUCT
    1170                 :          0 :         m_aMirrorMap[ 0x22CA ] = 0x22C9; // RIGHT NORMAL FACTOR SEMIDIRECT PRODUCT
    1171                 :          0 :         m_aMirrorMap[ 0x22CB ] = 0x22CC; // LEFT SEMIDIRECT PRODUCT
    1172                 :          0 :         m_aMirrorMap[ 0x22CC ] = 0x22CB; // RIGHT SEMIDIRECT PRODUCT
    1173                 :          0 :         m_aMirrorMap[ 0x22CD ] = 0x2243; // REVERSED TILDE EQUALS
    1174                 :          0 :         m_aMirrorMap[ 0x22D0 ] = 0x22D1; // DOUBLE SUBSET
    1175                 :          0 :         m_aMirrorMap[ 0x22D1 ] = 0x22D0; // DOUBLE SUPERSET
    1176                 :          0 :         m_aMirrorMap[ 0x22D6 ] = 0x22D7; // LESS-THAN WITH DOT
    1177                 :          0 :         m_aMirrorMap[ 0x22D7 ] = 0x22D6; // GREATER-THAN WITH DOT
    1178                 :          0 :         m_aMirrorMap[ 0x22D8 ] = 0x22D9; // VERY MUCH LESS-THAN
    1179                 :          0 :         m_aMirrorMap[ 0x22D9 ] = 0x22D8; // VERY MUCH GREATER-THAN
    1180                 :          0 :         m_aMirrorMap[ 0x22DA ] = 0x22DB; // LESS-THAN EQUAL TO OR GREATER-THAN
    1181                 :          0 :         m_aMirrorMap[ 0x22DB ] = 0x22DA; // GREATER-THAN EQUAL TO OR LESS-THAN
    1182                 :          0 :         m_aMirrorMap[ 0x22DC ] = 0x22DD; // EQUAL TO OR LESS-THAN
    1183                 :          0 :         m_aMirrorMap[ 0x22DD ] = 0x22DC; // EQUAL TO OR GREATER-THAN
    1184                 :          0 :         m_aMirrorMap[ 0x22DE ] = 0x22DF; // EQUAL TO OR PRECEDES
    1185                 :          0 :         m_aMirrorMap[ 0x22DF ] = 0x22DE; // EQUAL TO OR SUCCEEDS
    1186                 :          0 :         m_aMirrorMap[ 0x22E0 ] = 0x22E1; // [BEST FIT] DOES NOT PRECEDE OR EQUAL
    1187                 :          0 :         m_aMirrorMap[ 0x22E1 ] = 0x22E0; // [BEST FIT] DOES NOT SUCCEED OR EQUAL
    1188                 :          0 :         m_aMirrorMap[ 0x22E2 ] = 0x22E3; // [BEST FIT] NOT SQUARE IMAGE OF OR EQUAL TO
    1189                 :          0 :         m_aMirrorMap[ 0x22E3 ] = 0x22E2; // [BEST FIT] NOT SQUARE ORIGINAL OF OR EQUAL TO
    1190                 :          0 :         m_aMirrorMap[ 0x22E4 ] = 0x22E5; // [BEST FIT] SQUARE IMAGE OF OR NOT EQUAL TO
    1191                 :          0 :         m_aMirrorMap[ 0x22E5 ] = 0x22E4; // [BEST FIT] SQUARE ORIGINAL OF OR NOT EQUAL TO
    1192                 :          0 :         m_aMirrorMap[ 0x22E6 ] = 0x22E7; // [BEST FIT] LESS-THAN BUT NOT EQUIVALENT TO
    1193                 :          0 :         m_aMirrorMap[ 0x22E7 ] = 0x22E6; // [BEST FIT] GREATER-THAN BUT NOT EQUIVALENT TO
    1194                 :          0 :         m_aMirrorMap[ 0x22E8 ] = 0x22E9; // [BEST FIT] PRECEDES BUT NOT EQUIVALENT TO
    1195                 :          0 :         m_aMirrorMap[ 0x22E9 ] = 0x22E8; // [BEST FIT] SUCCEEDS BUT NOT EQUIVALENT TO
    1196                 :          0 :         m_aMirrorMap[ 0x22EA ] = 0x22EB; // [BEST FIT] NOT NORMAL SUBGROUP OF
    1197                 :          0 :         m_aMirrorMap[ 0x22EB ] = 0x22EA; // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP
    1198                 :          0 :         m_aMirrorMap[ 0x22EC ] = 0x22ED; // [BEST FIT] NOT NORMAL SUBGROUP OF OR EQUAL TO
    1199                 :          0 :         m_aMirrorMap[ 0x22ED ] = 0x22EC; // [BEST FIT] DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL
    1200                 :          0 :         m_aMirrorMap[ 0x22F0 ] = 0x22F1; // UP RIGHT DIAGONAL ELLIPSIS
    1201                 :          0 :         m_aMirrorMap[ 0x22F1 ] = 0x22F0; // DOWN RIGHT DIAGONAL ELLIPSIS
    1202                 :          0 :         m_aMirrorMap[ 0x22F2 ] = 0x22FA; // ELEMENT OF WITH LONG HORIZONTAL STROKE
    1203                 :          0 :         m_aMirrorMap[ 0x22F3 ] = 0x22FB; // ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
    1204                 :          0 :         m_aMirrorMap[ 0x22F4 ] = 0x22FC; // SMALL ELEMENT OF WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
    1205                 :          0 :         m_aMirrorMap[ 0x22F6 ] = 0x22FD; // ELEMENT OF WITH OVERBAR
    1206                 :          0 :         m_aMirrorMap[ 0x22F7 ] = 0x22FE; // SMALL ELEMENT OF WITH OVERBAR
    1207                 :          0 :         m_aMirrorMap[ 0x22FA ] = 0x22F2; // CONTAINS WITH LONG HORIZONTAL STROKE
    1208                 :          0 :         m_aMirrorMap[ 0x22FB ] = 0x22F3; // CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
    1209                 :          0 :         m_aMirrorMap[ 0x22FC ] = 0x22F4; // SMALL CONTAINS WITH VERTICAL BAR AT END OF HORIZONTAL STROKE
    1210                 :          0 :         m_aMirrorMap[ 0x22FD ] = 0x22F6; // CONTAINS WITH OVERBAR
    1211                 :          0 :         m_aMirrorMap[ 0x22FE ] = 0x22F7; // SMALL CONTAINS WITH OVERBAR
    1212                 :          0 :         m_aMirrorMap[ 0x2308 ] = 0x2309; // LEFT CEILING
    1213                 :          0 :         m_aMirrorMap[ 0x2309 ] = 0x2308; // RIGHT CEILING
    1214                 :          0 :         m_aMirrorMap[ 0x230A ] = 0x230B; // LEFT FLOOR
    1215                 :          0 :         m_aMirrorMap[ 0x230B ] = 0x230A; // RIGHT FLOOR
    1216                 :          0 :         m_aMirrorMap[ 0x2329 ] = 0x232A; // LEFT-POINTING ANGLE BRACKET
    1217                 :          0 :         m_aMirrorMap[ 0x232A ] = 0x2329; // RIGHT-POINTING ANGLE BRACKET
    1218                 :          0 :         m_aMirrorMap[ 0x2768 ] = 0x2769; // MEDIUM LEFT PARENTHESIS ORNAMENT
    1219                 :          0 :         m_aMirrorMap[ 0x2769 ] = 0x2768; // MEDIUM RIGHT PARENTHESIS ORNAMENT
    1220                 :          0 :         m_aMirrorMap[ 0x276A ] = 0x276B; // MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
    1221                 :          0 :         m_aMirrorMap[ 0x276B ] = 0x276A; // MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
    1222                 :          0 :         m_aMirrorMap[ 0x276C ] = 0x276D; // MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
    1223                 :          0 :         m_aMirrorMap[ 0x276D ] = 0x276C; // MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
    1224                 :          0 :         m_aMirrorMap[ 0x276E ] = 0x276F; // HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
    1225                 :          0 :         m_aMirrorMap[ 0x276F ] = 0x276E; // HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
    1226                 :          0 :         m_aMirrorMap[ 0x2770 ] = 0x2771; // HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
    1227                 :          0 :         m_aMirrorMap[ 0x2771 ] = 0x2770; // HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
    1228                 :          0 :         m_aMirrorMap[ 0x2772 ] = 0x2773; // LIGHT LEFT TORTOISE SHELL BRACKET
    1229                 :          0 :         m_aMirrorMap[ 0x2773 ] = 0x2772; // LIGHT RIGHT TORTOISE SHELL BRACKET
    1230                 :          0 :         m_aMirrorMap[ 0x2774 ] = 0x2775; // MEDIUM LEFT CURLY BRACKET ORNAMENT
    1231                 :          0 :         m_aMirrorMap[ 0x2775 ] = 0x2774; // MEDIUM RIGHT CURLY BRACKET ORNAMENT
    1232                 :          0 :         m_aMirrorMap[ 0x27C3 ] = 0x27C4; // OPEN SUBSET
    1233                 :          0 :         m_aMirrorMap[ 0x27C4 ] = 0x27C3; // OPEN SUPERSET
    1234                 :          0 :         m_aMirrorMap[ 0x27C5 ] = 0x27C6; // LEFT S-SHAPED BAG DELIMITER
    1235                 :          0 :         m_aMirrorMap[ 0x27C6 ] = 0x27C5; // RIGHT S-SHAPED BAG DELIMITER
    1236                 :          0 :         m_aMirrorMap[ 0x27C8 ] = 0x27C9; // REVERSE SOLIDUS PRECEDING SUBSET
    1237                 :          0 :         m_aMirrorMap[ 0x27C9 ] = 0x27C8; // SUPERSET PRECEDING SOLIDUS
    1238                 :          0 :         m_aMirrorMap[ 0x27D5 ] = 0x27D6; // LEFT OUTER JOIN
    1239                 :          0 :         m_aMirrorMap[ 0x27D6 ] = 0x27D5; // RIGHT OUTER JOIN
    1240                 :          0 :         m_aMirrorMap[ 0x27DD ] = 0x27DE; // LONG RIGHT TACK
    1241                 :          0 :         m_aMirrorMap[ 0x27DE ] = 0x27DD; // LONG LEFT TACK
    1242                 :          0 :         m_aMirrorMap[ 0x27E2 ] = 0x27E3; // WHITE CONCAVE-SIDED DIAMOND WITH LEFTWARDS TICK
    1243                 :          0 :         m_aMirrorMap[ 0x27E3 ] = 0x27E2; // WHITE CONCAVE-SIDED DIAMOND WITH RIGHTWARDS TICK
    1244                 :          0 :         m_aMirrorMap[ 0x27E4 ] = 0x27E5; // WHITE SQUARE WITH LEFTWARDS TICK
    1245                 :          0 :         m_aMirrorMap[ 0x27E5 ] = 0x27E4; // WHITE SQUARE WITH RIGHTWARDS TICK
    1246                 :          0 :         m_aMirrorMap[ 0x27E6 ] = 0x27E7; // MATHEMATICAL LEFT WHITE SQUARE BRACKET
    1247                 :          0 :         m_aMirrorMap[ 0x27E7 ] = 0x27E6; // MATHEMATICAL RIGHT WHITE SQUARE BRACKET
    1248                 :          0 :         m_aMirrorMap[ 0x27E8 ] = 0x27E9; // MATHEMATICAL LEFT ANGLE BRACKET
    1249                 :          0 :         m_aMirrorMap[ 0x27E9 ] = 0x27E8; // MATHEMATICAL RIGHT ANGLE BRACKET
    1250                 :          0 :         m_aMirrorMap[ 0x27EA ] = 0x27EB; // MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
    1251                 :          0 :         m_aMirrorMap[ 0x27EB ] = 0x27EA; // MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
    1252                 :          0 :         m_aMirrorMap[ 0x27EC ] = 0x27ED; // MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
    1253                 :          0 :         m_aMirrorMap[ 0x27ED ] = 0x27EC; // MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
    1254                 :          0 :         m_aMirrorMap[ 0x27EE ] = 0x27EF; // MATHEMATICAL LEFT FLATTENED PARENTHESIS
    1255                 :          0 :         m_aMirrorMap[ 0x27EF ] = 0x27EE; // MATHEMATICAL RIGHT FLATTENED PARENTHESIS
    1256                 :          0 :         m_aMirrorMap[ 0x2983 ] = 0x2984; // LEFT WHITE CURLY BRACKET
    1257                 :          0 :         m_aMirrorMap[ 0x2984 ] = 0x2983; // RIGHT WHITE CURLY BRACKET
    1258                 :          0 :         m_aMirrorMap[ 0x2985 ] = 0x2986; // LEFT WHITE PARENTHESIS
    1259                 :          0 :         m_aMirrorMap[ 0x2986 ] = 0x2985; // RIGHT WHITE PARENTHESIS
    1260                 :          0 :         m_aMirrorMap[ 0x2987 ] = 0x2988; // Z NOTATION LEFT IMAGE BRACKET
    1261                 :          0 :         m_aMirrorMap[ 0x2988 ] = 0x2987; // Z NOTATION RIGHT IMAGE BRACKET
    1262                 :          0 :         m_aMirrorMap[ 0x2989 ] = 0x298A; // Z NOTATION LEFT BINDING BRACKET
    1263                 :          0 :         m_aMirrorMap[ 0x298A ] = 0x2989; // Z NOTATION RIGHT BINDING BRACKET
    1264                 :          0 :         m_aMirrorMap[ 0x298B ] = 0x298C; // LEFT SQUARE BRACKET WITH UNDERBAR
    1265                 :          0 :         m_aMirrorMap[ 0x298C ] = 0x298B; // RIGHT SQUARE BRACKET WITH UNDERBAR
    1266                 :          0 :         m_aMirrorMap[ 0x298D ] = 0x2990; // LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
    1267                 :          0 :         m_aMirrorMap[ 0x298E ] = 0x298F; // RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
    1268                 :          0 :         m_aMirrorMap[ 0x298F ] = 0x298E; // LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
    1269                 :          0 :         m_aMirrorMap[ 0x2990 ] = 0x298D; // RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
    1270                 :          0 :         m_aMirrorMap[ 0x2991 ] = 0x2992; // LEFT ANGLE BRACKET WITH DOT
    1271                 :          0 :         m_aMirrorMap[ 0x2992 ] = 0x2991; // RIGHT ANGLE BRACKET WITH DOT
    1272                 :          0 :         m_aMirrorMap[ 0x2993 ] = 0x2994; // LEFT ARC LESS-THAN BRACKET
    1273                 :          0 :         m_aMirrorMap[ 0x2994 ] = 0x2993; // RIGHT ARC GREATER-THAN BRACKET
    1274                 :          0 :         m_aMirrorMap[ 0x2995 ] = 0x2996; // DOUBLE LEFT ARC GREATER-THAN BRACKET
    1275                 :          0 :         m_aMirrorMap[ 0x2996 ] = 0x2995; // DOUBLE RIGHT ARC LESS-THAN BRACKET
    1276                 :          0 :         m_aMirrorMap[ 0x2997 ] = 0x2998; // LEFT BLACK TORTOISE SHELL BRACKET
    1277                 :          0 :         m_aMirrorMap[ 0x2998 ] = 0x2997; // RIGHT BLACK TORTOISE SHELL BRACKET
    1278                 :          0 :         m_aMirrorMap[ 0x29B8 ] = 0x2298; // CIRCLED REVERSE SOLIDUS
    1279                 :          0 :         m_aMirrorMap[ 0x29C0 ] = 0x29C1; // CIRCLED LESS-THAN
    1280                 :          0 :         m_aMirrorMap[ 0x29C1 ] = 0x29C0; // CIRCLED GREATER-THAN
    1281                 :          0 :         m_aMirrorMap[ 0x29C4 ] = 0x29C5; // SQUARED RISING DIAGONAL SLASH
    1282                 :          0 :         m_aMirrorMap[ 0x29C5 ] = 0x29C4; // SQUARED FALLING DIAGONAL SLASH
    1283                 :          0 :         m_aMirrorMap[ 0x29CF ] = 0x29D0; // LEFT TRIANGLE BESIDE VERTICAL BAR
    1284                 :          0 :         m_aMirrorMap[ 0x29D0 ] = 0x29CF; // VERTICAL BAR BESIDE RIGHT TRIANGLE
    1285                 :          0 :         m_aMirrorMap[ 0x29D1 ] = 0x29D2; // BOWTIE WITH LEFT HALF BLACK
    1286                 :          0 :         m_aMirrorMap[ 0x29D2 ] = 0x29D1; // BOWTIE WITH RIGHT HALF BLACK
    1287                 :          0 :         m_aMirrorMap[ 0x29D4 ] = 0x29D5; // TIMES WITH LEFT HALF BLACK
    1288                 :          0 :         m_aMirrorMap[ 0x29D5 ] = 0x29D4; // TIMES WITH RIGHT HALF BLACK
    1289                 :          0 :         m_aMirrorMap[ 0x29D8 ] = 0x29D9; // LEFT WIGGLY FENCE
    1290                 :          0 :         m_aMirrorMap[ 0x29D9 ] = 0x29D8; // RIGHT WIGGLY FENCE
    1291                 :          0 :         m_aMirrorMap[ 0x29DA ] = 0x29DB; // LEFT DOUBLE WIGGLY FENCE
    1292                 :          0 :         m_aMirrorMap[ 0x29DB ] = 0x29DA; // RIGHT DOUBLE WIGGLY FENCE
    1293                 :          0 :         m_aMirrorMap[ 0x29F5 ] = 0x2215; // REVERSE SOLIDUS OPERATOR
    1294                 :          0 :         m_aMirrorMap[ 0x29F8 ] = 0x29F9; // BIG SOLIDUS
    1295                 :          0 :         m_aMirrorMap[ 0x29F9 ] = 0x29F8; // BIG REVERSE SOLIDUS
    1296                 :          0 :         m_aMirrorMap[ 0x29FC ] = 0x29FD; // LEFT-POINTING CURVED ANGLE BRACKET
    1297                 :          0 :         m_aMirrorMap[ 0x29FD ] = 0x29FC; // RIGHT-POINTING CURVED ANGLE BRACKET
    1298                 :          0 :         m_aMirrorMap[ 0x2A2B ] = 0x2A2C; // MINUS SIGN WITH FALLING DOTS
    1299                 :          0 :         m_aMirrorMap[ 0x2A2C ] = 0x2A2B; // MINUS SIGN WITH RISING DOTS
    1300                 :          0 :         m_aMirrorMap[ 0x2A2D ] = 0x2A2E; // PLUS SIGN IN LEFT HALF CIRCLE
    1301                 :          0 :         m_aMirrorMap[ 0x2A2E ] = 0x2A2D; // PLUS SIGN IN RIGHT HALF CIRCLE
    1302                 :          0 :         m_aMirrorMap[ 0x2A34 ] = 0x2A35; // MULTIPLICATION SIGN IN LEFT HALF CIRCLE
    1303                 :          0 :         m_aMirrorMap[ 0x2A35 ] = 0x2A34; // MULTIPLICATION SIGN IN RIGHT HALF CIRCLE
    1304                 :          0 :         m_aMirrorMap[ 0x2A3C ] = 0x2A3D; // INTERIOR PRODUCT
    1305                 :          0 :         m_aMirrorMap[ 0x2A3D ] = 0x2A3C; // RIGHTHAND INTERIOR PRODUCT
    1306                 :          0 :         m_aMirrorMap[ 0x2A64 ] = 0x2A65; // Z NOTATION DOMAIN ANTIRESTRICTION
    1307                 :          0 :         m_aMirrorMap[ 0x2A65 ] = 0x2A64; // Z NOTATION RANGE ANTIRESTRICTION
    1308                 :          0 :         m_aMirrorMap[ 0x2A79 ] = 0x2A7A; // LESS-THAN WITH CIRCLE INSIDE
    1309                 :          0 :         m_aMirrorMap[ 0x2A7A ] = 0x2A79; // GREATER-THAN WITH CIRCLE INSIDE
    1310                 :          0 :         m_aMirrorMap[ 0x2A7D ] = 0x2A7E; // LESS-THAN OR SLANTED EQUAL TO
    1311                 :          0 :         m_aMirrorMap[ 0x2A7E ] = 0x2A7D; // GREATER-THAN OR SLANTED EQUAL TO
    1312                 :          0 :         m_aMirrorMap[ 0x2A7F ] = 0x2A80; // LESS-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
    1313                 :          0 :         m_aMirrorMap[ 0x2A80 ] = 0x2A7F; // GREATER-THAN OR SLANTED EQUAL TO WITH DOT INSIDE
    1314                 :          0 :         m_aMirrorMap[ 0x2A81 ] = 0x2A82; // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
    1315                 :          0 :         m_aMirrorMap[ 0x2A82 ] = 0x2A81; // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE
    1316                 :          0 :         m_aMirrorMap[ 0x2A83 ] = 0x2A84; // LESS-THAN OR SLANTED EQUAL TO WITH DOT ABOVE RIGHT
    1317                 :          0 :         m_aMirrorMap[ 0x2A84 ] = 0x2A83; // GREATER-THAN OR SLANTED EQUAL TO WITH DOT ABOVE LEFT
    1318                 :          0 :         m_aMirrorMap[ 0x2A8B ] = 0x2A8C; // LESS-THAN ABOVE DOUBLE-LINE EQUAL ABOVE GREATER-THAN
    1319                 :          0 :         m_aMirrorMap[ 0x2A8C ] = 0x2A8B; // GREATER-THAN ABOVE DOUBLE-LINE EQUAL ABOVE LESS-THAN
    1320                 :          0 :         m_aMirrorMap[ 0x2A91 ] = 0x2A92; // LESS-THAN ABOVE GREATER-THAN ABOVE DOUBLE-LINE EQUAL
    1321                 :          0 :         m_aMirrorMap[ 0x2A92 ] = 0x2A91; // GREATER-THAN ABOVE LESS-THAN ABOVE DOUBLE-LINE EQUAL
    1322                 :          0 :         m_aMirrorMap[ 0x2A93 ] = 0x2A94; // LESS-THAN ABOVE SLANTED EQUAL ABOVE GREATER-THAN ABOVE SLANTED EQUAL
    1323                 :          0 :         m_aMirrorMap[ 0x2A94 ] = 0x2A93; // GREATER-THAN ABOVE SLANTED EQUAL ABOVE LESS-THAN ABOVE SLANTED EQUAL
    1324                 :          0 :         m_aMirrorMap[ 0x2A95 ] = 0x2A96; // SLANTED EQUAL TO OR LESS-THAN
    1325                 :          0 :         m_aMirrorMap[ 0x2A96 ] = 0x2A95; // SLANTED EQUAL TO OR GREATER-THAN
    1326                 :          0 :         m_aMirrorMap[ 0x2A97 ] = 0x2A98; // SLANTED EQUAL TO OR LESS-THAN WITH DOT INSIDE
    1327                 :          0 :         m_aMirrorMap[ 0x2A98 ] = 0x2A97; // SLANTED EQUAL TO OR GREATER-THAN WITH DOT INSIDE
    1328                 :          0 :         m_aMirrorMap[ 0x2A99 ] = 0x2A9A; // DOUBLE-LINE EQUAL TO OR LESS-THAN
    1329                 :          0 :         m_aMirrorMap[ 0x2A9A ] = 0x2A99; // DOUBLE-LINE EQUAL TO OR GREATER-THAN
    1330                 :          0 :         m_aMirrorMap[ 0x2A9B ] = 0x2A9C; // DOUBLE-LINE SLANTED EQUAL TO OR LESS-THAN
    1331                 :          0 :         m_aMirrorMap[ 0x2A9C ] = 0x2A9B; // DOUBLE-LINE SLANTED EQUAL TO OR GREATER-THAN
    1332                 :          0 :         m_aMirrorMap[ 0x2AA1 ] = 0x2AA2; // DOUBLE NESTED LESS-THAN
    1333                 :          0 :         m_aMirrorMap[ 0x2AA2 ] = 0x2AA1; // DOUBLE NESTED GREATER-THAN
    1334                 :          0 :         m_aMirrorMap[ 0x2AA6 ] = 0x2AA7; // LESS-THAN CLOSED BY CURVE
    1335                 :          0 :         m_aMirrorMap[ 0x2AA7 ] = 0x2AA6; // GREATER-THAN CLOSED BY CURVE
    1336                 :          0 :         m_aMirrorMap[ 0x2AA8 ] = 0x2AA9; // LESS-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
    1337                 :          0 :         m_aMirrorMap[ 0x2AA9 ] = 0x2AA8; // GREATER-THAN CLOSED BY CURVE ABOVE SLANTED EQUAL
    1338                 :          0 :         m_aMirrorMap[ 0x2AAA ] = 0x2AAB; // SMALLER THAN
    1339                 :          0 :         m_aMirrorMap[ 0x2AAB ] = 0x2AAA; // LARGER THAN
    1340                 :          0 :         m_aMirrorMap[ 0x2AAC ] = 0x2AAD; // SMALLER THAN OR EQUAL TO
    1341                 :          0 :         m_aMirrorMap[ 0x2AAD ] = 0x2AAC; // LARGER THAN OR EQUAL TO
    1342                 :          0 :         m_aMirrorMap[ 0x2AAF ] = 0x2AB0; // PRECEDES ABOVE SINGLE-LINE EQUALS SIGN
    1343                 :          0 :         m_aMirrorMap[ 0x2AB0 ] = 0x2AAF; // SUCCEEDS ABOVE SINGLE-LINE EQUALS SIGN
    1344                 :          0 :         m_aMirrorMap[ 0x2AB3 ] = 0x2AB4; // PRECEDES ABOVE EQUALS SIGN
    1345                 :          0 :         m_aMirrorMap[ 0x2AB4 ] = 0x2AB3; // SUCCEEDS ABOVE EQUALS SIGN
    1346                 :          0 :         m_aMirrorMap[ 0x2ABB ] = 0x2ABC; // DOUBLE PRECEDES
    1347                 :          0 :         m_aMirrorMap[ 0x2ABC ] = 0x2ABB; // DOUBLE SUCCEEDS
    1348                 :          0 :         m_aMirrorMap[ 0x2ABD ] = 0x2ABE; // SUBSET WITH DOT
    1349                 :          0 :         m_aMirrorMap[ 0x2ABE ] = 0x2ABD; // SUPERSET WITH DOT
    1350                 :          0 :         m_aMirrorMap[ 0x2ABF ] = 0x2AC0; // SUBSET WITH PLUS SIGN BELOW
    1351                 :          0 :         m_aMirrorMap[ 0x2AC0 ] = 0x2ABF; // SUPERSET WITH PLUS SIGN BELOW
    1352                 :          0 :         m_aMirrorMap[ 0x2AC1 ] = 0x2AC2; // SUBSET WITH MULTIPLICATION SIGN BELOW
    1353                 :          0 :         m_aMirrorMap[ 0x2AC2 ] = 0x2AC1; // SUPERSET WITH MULTIPLICATION SIGN BELOW
    1354                 :          0 :         m_aMirrorMap[ 0x2AC3 ] = 0x2AC4; // SUBSET OF OR EQUAL TO WITH DOT ABOVE
    1355                 :          0 :         m_aMirrorMap[ 0x2AC4 ] = 0x2AC3; // SUPERSET OF OR EQUAL TO WITH DOT ABOVE
    1356                 :          0 :         m_aMirrorMap[ 0x2AC5 ] = 0x2AC6; // SUBSET OF ABOVE EQUALS SIGN
    1357                 :          0 :         m_aMirrorMap[ 0x2AC6 ] = 0x2AC5; // SUPERSET OF ABOVE EQUALS SIGN
    1358                 :          0 :         m_aMirrorMap[ 0x2ACD ] = 0x2ACE; // SQUARE LEFT OPEN BOX OPERATOR
    1359                 :          0 :         m_aMirrorMap[ 0x2ACE ] = 0x2ACD; // SQUARE RIGHT OPEN BOX OPERATOR
    1360                 :          0 :         m_aMirrorMap[ 0x2ACF ] = 0x2AD0; // CLOSED SUBSET
    1361                 :          0 :         m_aMirrorMap[ 0x2AD0 ] = 0x2ACF; // CLOSED SUPERSET
    1362                 :          0 :         m_aMirrorMap[ 0x2AD1 ] = 0x2AD2; // CLOSED SUBSET OR EQUAL TO
    1363                 :          0 :         m_aMirrorMap[ 0x2AD2 ] = 0x2AD1; // CLOSED SUPERSET OR EQUAL TO
    1364                 :          0 :         m_aMirrorMap[ 0x2AD3 ] = 0x2AD4; // SUBSET ABOVE SUPERSET
    1365                 :          0 :         m_aMirrorMap[ 0x2AD4 ] = 0x2AD3; // SUPERSET ABOVE SUBSET
    1366                 :          0 :         m_aMirrorMap[ 0x2AD5 ] = 0x2AD6; // SUBSET ABOVE SUBSET
    1367                 :          0 :         m_aMirrorMap[ 0x2AD6 ] = 0x2AD5; // SUPERSET ABOVE SUPERSET
    1368                 :          0 :         m_aMirrorMap[ 0x2ADE ] = 0x22A6; // SHORT LEFT TACK
    1369                 :          0 :         m_aMirrorMap[ 0x2AE3 ] = 0x22A9; // DOUBLE VERTICAL BAR LEFT TURNSTILE
    1370                 :          0 :         m_aMirrorMap[ 0x2AE4 ] = 0x22A8; // VERTICAL BAR DOUBLE LEFT TURNSTILE
    1371                 :          0 :         m_aMirrorMap[ 0x2AE5 ] = 0x22AB; // DOUBLE VERTICAL BAR DOUBLE LEFT TURNSTILE
    1372                 :          0 :         m_aMirrorMap[ 0x2AEC ] = 0x2AED; // DOUBLE STROKE NOT SIGN
    1373                 :          0 :         m_aMirrorMap[ 0x2AED ] = 0x2AEC; // REVERSED DOUBLE STROKE NOT SIGN
    1374                 :          0 :         m_aMirrorMap[ 0x2AF7 ] = 0x2AF8; // TRIPLE NESTED LESS-THAN
    1375                 :          0 :         m_aMirrorMap[ 0x2AF8 ] = 0x2AF7; // TRIPLE NESTED GREATER-THAN
    1376                 :          0 :         m_aMirrorMap[ 0x2AF9 ] = 0x2AFA; // DOUBLE-LINE SLANTED LESS-THAN OR EQUAL TO
    1377                 :          0 :         m_aMirrorMap[ 0x2AFA ] = 0x2AF9; // DOUBLE-LINE SLANTED GREATER-THAN OR EQUAL TO
    1378                 :          0 :         m_aMirrorMap[ 0x2E02 ] = 0x2E03; // LEFT SUBSTITUTION BRACKET
    1379                 :          0 :         m_aMirrorMap[ 0x2E03 ] = 0x2E02; // RIGHT SUBSTITUTION BRACKET
    1380                 :          0 :         m_aMirrorMap[ 0x2E04 ] = 0x2E05; // LEFT DOTTED SUBSTITUTION BRACKET
    1381                 :          0 :         m_aMirrorMap[ 0x2E05 ] = 0x2E04; // RIGHT DOTTED SUBSTITUTION BRACKET
    1382                 :          0 :         m_aMirrorMap[ 0x2E09 ] = 0x2E0A; // LEFT TRANSPOSITION BRACKET
    1383                 :          0 :         m_aMirrorMap[ 0x2E0A ] = 0x2E09; // RIGHT TRANSPOSITION BRACKET
    1384                 :          0 :         m_aMirrorMap[ 0x2E0C ] = 0x2E0D; // LEFT RAISED OMISSION BRACKET
    1385                 :          0 :         m_aMirrorMap[ 0x2E0D ] = 0x2E0C; // RIGHT RAISED OMISSION BRACKET
    1386                 :          0 :         m_aMirrorMap[ 0x2E1C ] = 0x2E1D; // LEFT LOW PARAPHRASE BRACKET
    1387                 :          0 :         m_aMirrorMap[ 0x2E1D ] = 0x2E1C; // RIGHT LOW PARAPHRASE BRACKET
    1388                 :          0 :         m_aMirrorMap[ 0x2E20 ] = 0x2E21; // LEFT VERTICAL BAR WITH QUILL
    1389                 :          0 :         m_aMirrorMap[ 0x2E21 ] = 0x2E20; // RIGHT VERTICAL BAR WITH QUILL
    1390                 :          0 :         m_aMirrorMap[ 0x2E22 ] = 0x2E23; // TOP LEFT HALF BRACKET
    1391                 :          0 :         m_aMirrorMap[ 0x2E23 ] = 0x2E22; // TOP RIGHT HALF BRACKET
    1392                 :          0 :         m_aMirrorMap[ 0x2E24 ] = 0x2E25; // BOTTOM LEFT HALF BRACKET
    1393                 :          0 :         m_aMirrorMap[ 0x2E25 ] = 0x2E24; // BOTTOM RIGHT HALF BRACKET
    1394                 :          0 :         m_aMirrorMap[ 0x2E26 ] = 0x2E27; // LEFT SIDEWAYS U BRACKET
    1395                 :          0 :         m_aMirrorMap[ 0x2E27 ] = 0x2E26; // RIGHT SIDEWAYS U BRACKET
    1396                 :          0 :         m_aMirrorMap[ 0x2E28 ] = 0x2E29; // LEFT DOUBLE PARENTHESIS
    1397                 :          0 :         m_aMirrorMap[ 0x2E29 ] = 0x2E28; // RIGHT DOUBLE PARENTHESIS
    1398                 :          0 :         m_aMirrorMap[ 0x3008 ] = 0x3009; // LEFT ANGLE BRACKET
    1399                 :          0 :         m_aMirrorMap[ 0x3009 ] = 0x3008; // RIGHT ANGLE BRACKET
    1400                 :          0 :         m_aMirrorMap[ 0x300A ] = 0x300B; // LEFT DOUBLE ANGLE BRACKET
    1401                 :          0 :         m_aMirrorMap[ 0x300B ] = 0x300A; // RIGHT DOUBLE ANGLE BRACKET
    1402                 :          0 :         m_aMirrorMap[ 0x300C ] = 0x300D; // [BEST FIT] LEFT CORNER BRACKET
    1403                 :          0 :         m_aMirrorMap[ 0x300D ] = 0x300C; // [BEST FIT] RIGHT CORNER BRACKET
    1404                 :          0 :         m_aMirrorMap[ 0x300E ] = 0x300F; // [BEST FIT] LEFT WHITE CORNER BRACKET
    1405                 :          0 :         m_aMirrorMap[ 0x300F ] = 0x300E; // [BEST FIT] RIGHT WHITE CORNER BRACKET
    1406                 :          0 :         m_aMirrorMap[ 0x3010 ] = 0x3011; // LEFT BLACK LENTICULAR BRACKET
    1407                 :          0 :         m_aMirrorMap[ 0x3011 ] = 0x3010; // RIGHT BLACK LENTICULAR BRACKET
    1408                 :          0 :         m_aMirrorMap[ 0x3014 ] = 0x3015; // LEFT TORTOISE SHELL BRACKET
    1409                 :          0 :         m_aMirrorMap[ 0x3015 ] = 0x3014; // RIGHT TORTOISE SHELL BRACKET
    1410                 :          0 :         m_aMirrorMap[ 0x3016 ] = 0x3017; // LEFT WHITE LENTICULAR BRACKET
    1411                 :          0 :         m_aMirrorMap[ 0x3017 ] = 0x3016; // RIGHT WHITE LENTICULAR BRACKET
    1412                 :          0 :         m_aMirrorMap[ 0x3018 ] = 0x3019; // LEFT WHITE TORTOISE SHELL BRACKET
    1413                 :          0 :         m_aMirrorMap[ 0x3019 ] = 0x3018; // RIGHT WHITE TORTOISE SHELL BRACKET
    1414                 :          0 :         m_aMirrorMap[ 0x301A ] = 0x301B; // LEFT WHITE SQUARE BRACKET
    1415                 :          0 :         m_aMirrorMap[ 0x301B ] = 0x301A; // RIGHT WHITE SQUARE BRACKET
    1416                 :          0 :         m_aMirrorMap[ 0xFE59 ] = 0xFE5A; // SMALL LEFT PARENTHESIS
    1417                 :          0 :         m_aMirrorMap[ 0xFE5A ] = 0xFE59; // SMALL RIGHT PARENTHESIS
    1418                 :          0 :         m_aMirrorMap[ 0xFE5B ] = 0xFE5C; // SMALL LEFT CURLY BRACKET
    1419                 :          0 :         m_aMirrorMap[ 0xFE5C ] = 0xFE5B; // SMALL RIGHT CURLY BRACKET
    1420                 :          0 :         m_aMirrorMap[ 0xFE5D ] = 0xFE5E; // SMALL LEFT TORTOISE SHELL BRACKET
    1421                 :          0 :         m_aMirrorMap[ 0xFE5E ] = 0xFE5D; // SMALL RIGHT TORTOISE SHELL BRACKET
    1422                 :          0 :         m_aMirrorMap[ 0xFE64 ] = 0xFE65; // SMALL LESS-THAN SIGN
    1423                 :          0 :         m_aMirrorMap[ 0xFE65 ] = 0xFE64; // SMALL GREATER-THAN SIGN
    1424                 :          0 :         m_aMirrorMap[ 0xFF08 ] = 0xFF09; // FULLWIDTH LEFT PARENTHESIS
    1425                 :          0 :         m_aMirrorMap[ 0xFF09 ] = 0xFF08; // FULLWIDTH RIGHT PARENTHESIS
    1426                 :          0 :         m_aMirrorMap[ 0xFF1C ] = 0xFF1E; // FULLWIDTH LESS-THAN SIGN
    1427                 :          0 :         m_aMirrorMap[ 0xFF1E ] = 0xFF1C; // FULLWIDTH GREATER-THAN SIGN
    1428                 :          0 :         m_aMirrorMap[ 0xFF3B ] = 0xFF3D; // FULLWIDTH LEFT SQUARE BRACKET
    1429                 :          0 :         m_aMirrorMap[ 0xFF3D ] = 0xFF3B; // FULLWIDTH RIGHT SQUARE BRACKET
    1430                 :          0 :         m_aMirrorMap[ 0xFF5B ] = 0xFF5D; // FULLWIDTH LEFT CURLY BRACKET
    1431                 :          0 :         m_aMirrorMap[ 0xFF5D ] = 0xFF5B; // FULLWIDTH RIGHT CURLY BRACKET
    1432                 :          0 :         m_aMirrorMap[ 0xFF5F ] = 0xFF60; // FULLWIDTH LEFT WHITE PARENTHESIS
    1433                 :          0 :         m_aMirrorMap[ 0xFF60 ] = 0xFF5F; // FULLWIDTH RIGHT WHITE PARENTHESIS
    1434                 :          0 :         m_aMirrorMap[ 0xFF62 ] = 0xFF63; // [BEST FIT] HALFWIDTH LEFT CORNER BRACKET
    1435                 :          0 :         m_aMirrorMap[ 0xFF63 ] = 0xFF62; // [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET
    1436                 :            :     }
    1437                 :          0 : }
    1438                 :            : 
    1439                 :            : }
    1440                 :            : 
    1441                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10