LCOV - code coverage report
Current view: top level - xmloff/source/style - XMLFontAutoStylePool.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 107 198 54.0 %
Date: 2015-06-13 12:38:46 Functions: 18 20 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <o3tl/sorted_vector.hxx>
      21             : #include <tools/fontenum.hxx>
      22             : #include <xmloff/xmlnmspe.hxx>
      23             : #include <xmloff/xmltoken.hxx>
      24             : #include <xmloff/xmluconv.hxx>
      25             : #include "fonthdl.hxx"
      26             : #include <xmloff/xmlexp.hxx>
      27             : #include <xmloff/XMLFontAutoStylePool.hxx>
      28             : #include <vcl/embeddedfontshelper.hxx>
      29             : #include <osl/file.hxx>
      30             : 
      31             : #include <com/sun/star/embed/ElementModes.hpp>
      32             : #include <com/sun/star/embed/XTransactedObject.hpp>
      33             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      34             : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
      35             : 
      36             : #include "XMLBase64Export.hxx"
      37             : 
      38             : using namespace ::com::sun::star;
      39             : using namespace ::com::sun::star::uno;
      40             : using namespace ::xmloff::token;
      41             : 
      42       13143 : class XMLFontAutoStylePoolEntry_Impl
      43             : {
      44             :     OUString    sName;
      45             :     OUString    sFamilyName;
      46             :     OUString    sStyleName;
      47             :     FontFamily  nFamily;
      48             :     FontPitch   nPitch;
      49             :     rtl_TextEncoding eEnc;
      50             : 
      51             : public:
      52             : 
      53             :     inline XMLFontAutoStylePoolEntry_Impl(
      54             :             const OUString& rName,
      55             :             const OUString& rFamilyName,
      56             :             const OUString& rStyleName,
      57             :             FontFamily nFamily,
      58             :             FontPitch nPitch,
      59             :             rtl_TextEncoding eEnc );
      60             : 
      61             :     inline XMLFontAutoStylePoolEntry_Impl(
      62             :             const OUString& rFamilyName,
      63             :             const OUString& rStyleName,
      64             :             FontFamily nFamily,
      65             :             FontPitch nPitch,
      66             :             rtl_TextEncoding eEnc );
      67             : 
      68        8284 :     const OUString& GetName() const { return sName; }
      69       42328 :     const OUString& GetFamilyName() const { return sFamilyName; }
      70       29764 :     const OUString& GetStyleName() const { return sStyleName; }
      71       74912 :     FontFamily GetFamily() const {   return nFamily; }
      72       75684 :     FontPitch GetPitch() const { return nPitch; }
      73       67770 :     rtl_TextEncoding GetEncoding() const { return eEnc; }
      74             : };
      75             : 
      76             : 
      77        1226 : inline XMLFontAutoStylePoolEntry_Impl::XMLFontAutoStylePoolEntry_Impl(
      78             :         const OUString& rName,
      79             :         const OUString& rFamilyName,
      80             :         const OUString& rStyleName,
      81             :         FontFamily nFam,
      82             :         FontPitch nP,
      83             :         rtl_TextEncoding eE ) :
      84             :     sName( rName ),
      85             :     sFamilyName( rFamilyName ),
      86             :     sStyleName( rStyleName ),
      87             :     nFamily( nFam ),
      88             :     nPitch( nP ),
      89        1226 :     eEnc( eE )
      90             : {
      91        1226 : }
      92             : 
      93       11917 : inline XMLFontAutoStylePoolEntry_Impl::XMLFontAutoStylePoolEntry_Impl(
      94             :         const OUString& rFamilyName,
      95             :         const OUString& rStyleName,
      96             :         FontFamily nFam,
      97             :         FontPitch nP,
      98             :         rtl_TextEncoding eE ) :
      99             :     sFamilyName( rFamilyName ),
     100             :     sStyleName( rStyleName ),
     101             :     nFamily( nFam ),
     102             :     nPitch( nP ),
     103       11917 :     eEnc( eE )
     104             : {
     105       11917 : }
     106             : 
     107             : struct XMLFontAutoStylePoolEntryCmp_Impl {
     108       33270 :     bool operator()(
     109             :         XMLFontAutoStylePoolEntry_Impl* const& r1,
     110             :         XMLFontAutoStylePoolEntry_Impl* const& r2 ) const
     111             :     {
     112       33270 :         bool nEnc1(r1->GetEncoding() != RTL_TEXTENCODING_SYMBOL);
     113       33270 :         bool nEnc2(r2->GetEncoding() != RTL_TEXTENCODING_SYMBOL);
     114       33270 :         if( nEnc1 != nEnc2 )
     115         309 :             return nEnc1 < nEnc2;
     116       32961 :         else if( r1->GetPitch() != r2->GetPitch() )
     117        4266 :             return r1->GetPitch() < r2->GetPitch();
     118       28695 :         else if( r1->GetFamily() != r2->GetFamily() )
     119        8146 :             return r1->GetFamily() < r2->GetFamily();
     120             :         else
     121             :         {
     122       20549 :             sal_Int32 nCmp = r1->GetFamilyName().compareTo( r2->GetFamilyName() );
     123       20549 :             if( 0 == nCmp )
     124       14267 :                 return r1->GetStyleName().compareTo( r2->GetStyleName() ) < 0;
     125             :             else
     126        6282 :                 return nCmp < 0;
     127             :         }
     128             :     }
     129             : };
     130             : 
     131         583 : class XMLFontAutoStylePool_Impl : public o3tl::sorted_vector<XMLFontAutoStylePoolEntry_Impl*, XMLFontAutoStylePoolEntryCmp_Impl>
     132             : {
     133             : public:
     134         583 :     ~XMLFontAutoStylePool_Impl() { DeleteAndDestroyAll(); }
     135             : };
     136             : 
     137         583 : XMLFontAutoStylePool::XMLFontAutoStylePool( SvXMLExport& rExp, bool _tryToEmbedFonts ) :
     138             :     rExport( rExp ),
     139         583 :     pPool( new XMLFontAutoStylePool_Impl ),
     140        1166 :     tryToEmbedFonts( _tryToEmbedFonts )
     141             : {
     142         583 : }
     143             : 
     144        1547 : XMLFontAutoStylePool::~XMLFontAutoStylePool()
     145             : {
     146         583 :     delete pPool;
     147         964 : }
     148             : 
     149        6588 : OUString XMLFontAutoStylePool::Add(
     150             :             const OUString& rFamilyName,
     151             :             const OUString& rStyleName,
     152             :             FontFamily nFamily,
     153             :             FontPitch nPitch,
     154             :             rtl_TextEncoding eEnc )
     155             : {
     156        6588 :     OUString sPoolName;
     157             :     XMLFontAutoStylePoolEntry_Impl aTmp( rFamilyName, rStyleName, nFamily,
     158       13176 :                                           nPitch, eEnc );
     159        6588 :     XMLFontAutoStylePool_Impl::const_iterator it = pPool->find( &aTmp );
     160        6588 :     if( it != pPool->end() )
     161             :     {
     162        5362 :         sPoolName = (*it)->GetName();
     163             :     }
     164             :     else
     165             :     {
     166        1226 :         OUString sName;
     167        1226 :         sal_Int32 nLen = rFamilyName.indexOf( ';', 0 );
     168        1226 :         if( -1 == nLen )
     169             :         {
     170        1226 :             sName = rFamilyName;
     171             :         }
     172           0 :         else if( nLen > 0 )
     173             :         {
     174           0 :             sName = rFamilyName.copy( 0, nLen );
     175           0 :             sName = sName.trim();
     176             :         }
     177             : 
     178        1226 :         if( sName.isEmpty() )
     179           8 :             sName = "F";
     180             : 
     181        1226 :         if( m_aNames.find(sName) != m_aNames.end() )
     182             :         {
     183         225 :             sal_Int32 nCount = 1;
     184         225 :             OUString sPrefix( sName );
     185         225 :             sName += OUString::number( nCount );
     186         480 :             while( m_aNames.find(sName) != m_aNames.end() )
     187             :             {
     188          30 :                 sName = sPrefix;
     189          30 :                 sName += OUString::number( ++nCount );
     190         225 :             }
     191             :         }
     192             : 
     193             :         XMLFontAutoStylePoolEntry_Impl *pEntry =
     194             :             new XMLFontAutoStylePoolEntry_Impl( sName, rFamilyName, rStyleName,
     195        1226 :                                                 nFamily, nPitch, eEnc );
     196        1226 :         pPool->insert( pEntry );
     197        1226 :         m_aNames.insert(sName);
     198             :     }
     199             : 
     200       13176 :     return sPoolName;
     201             : }
     202             : 
     203        5329 : OUString XMLFontAutoStylePool::Find(
     204             :             const OUString& rFamilyName,
     205             :             const OUString& rStyleName,
     206             :             FontFamily nFamily,
     207             :             FontPitch nPitch,
     208             :             rtl_TextEncoding eEnc ) const
     209             : {
     210        5329 :     OUString sName;
     211             :     XMLFontAutoStylePoolEntry_Impl aTmp( rFamilyName, rStyleName, nFamily,
     212       10658 :                                           nPitch, eEnc );
     213        5329 :     XMLFontAutoStylePool_Impl::const_iterator it = pPool->find( &aTmp );
     214        5329 :     if( it != pPool->end() )
     215             :     {
     216        1692 :         sName = (*it)->GetName();
     217             :     }
     218             : 
     219       10658 :     return sName;
     220             : }
     221             : 
     222             : namespace
     223             : {
     224             : 
     225           0 : OUString lcl_checkFontFile( const OUString &fileUrl )
     226             : {
     227           0 :     osl::DirectoryItem aDirItem;
     228           0 :     if( osl::DirectoryItem::get( fileUrl, aDirItem ) == osl::File::E_None )
     229             :     {
     230           0 :         osl::FileStatus aStatus( osl_FileStatus_Mask_Type );
     231           0 :         if( aDirItem.getFileStatus( aStatus ) == osl::File::E_None )
     232             :         {
     233           0 :             if( !aStatus.isDirectory() )
     234           0 :                 return fileUrl;
     235           0 :         }
     236             :     }
     237           0 :     return OUString();
     238             : }
     239             : 
     240             : }
     241             : 
     242         326 : void XMLFontAutoStylePool::exportXML()
     243             : {
     244         326 :     SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE,
     245             :                               XML_FONT_FACE_DECLS,
     246         326 :                               true, true );
     247         652 :     Any aAny;
     248         652 :     OUString sTmp;
     249         652 :     XMLFontFamilyNamePropHdl aFamilyNameHdl;
     250         652 :     XMLFontFamilyPropHdl aFamilyHdl;
     251         652 :     XMLFontPitchPropHdl aPitchHdl;
     252         652 :     XMLFontEncodingPropHdl aEncHdl;
     253         326 :     const SvXMLUnitConverter& rUnitConv = GetExport().GetMM100UnitConverter();
     254             : 
     255         652 :     std::map< OUString, OUString > fontFilesMap; // our url to document url
     256         326 :     sal_uInt32 nCount = pPool->size();
     257        1556 :     for( sal_uInt32 i=0; i<nCount; i++ )
     258             :     {
     259        1230 :         const XMLFontAutoStylePoolEntry_Impl *pEntry = (*pPool)[ i ];
     260             : 
     261        1230 :         GetExport().AddAttribute( XML_NAMESPACE_STYLE,
     262        2460 :                                   XML_NAME, pEntry->GetName() );
     263             : 
     264        1230 :         aAny <<= pEntry->GetFamilyName();
     265        1230 :         if( aFamilyNameHdl.exportXML( sTmp, aAny, rUnitConv ) )
     266        1230 :             GetExport().AddAttribute( XML_NAMESPACE_SVG,
     267        1230 :                                       XML_FONT_FAMILY, sTmp );
     268             : 
     269        1230 :         const OUString& rStyleName = pEntry->GetStyleName();
     270        1230 :         if( !rStyleName.isEmpty() )
     271          18 :             GetExport().AddAttribute( XML_NAMESPACE_STYLE,
     272             :                                       XML_FONT_ADORNMENTS,
     273          18 :                                       rStyleName );
     274             : 
     275        1230 :         aAny <<= (sal_Int16)pEntry->GetFamily();
     276        1230 :         if( aFamilyHdl.exportXML( sTmp, aAny, rUnitConv  ) )
     277        1173 :             GetExport().AddAttribute( XML_NAMESPACE_STYLE,
     278        1173 :                                       XML_FONT_FAMILY_GENERIC, sTmp );
     279             : 
     280        1230 :         aAny <<= (sal_Int16)pEntry->GetPitch();
     281        1230 :         if( aPitchHdl.exportXML( sTmp, aAny, rUnitConv  ) )
     282        1070 :             GetExport().AddAttribute( XML_NAMESPACE_STYLE,
     283        1070 :                                       XML_FONT_PITCH, sTmp );
     284             : 
     285        1230 :         aAny <<= (sal_Int16)pEntry->GetEncoding();
     286        1230 :         if( aEncHdl.exportXML( sTmp, aAny, rUnitConv  ) )
     287           4 :             GetExport().AddAttribute( XML_NAMESPACE_STYLE,
     288           4 :                                       XML_FONT_CHARSET, sTmp );
     289             : 
     290        1230 :         SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_STYLE,
     291             :                                   XML_FONT_FACE,
     292        1230 :                                   true, true );
     293             : 
     294        1230 :         if( tryToEmbedFonts )
     295             :         {
     296           0 :             const bool bExportFlat( GetExport().getExportFlags() & SvXMLExportFlags::EMBEDDED );
     297           0 :             std::vector< OUString > fileUrls;
     298             :             static const FontWeight weight[] = { WEIGHT_NORMAL, WEIGHT_BOLD, WEIGHT_NORMAL, WEIGHT_BOLD };
     299             :             static const FontItalic italic[] = { ITALIC_NONE, ITALIC_NONE, ITALIC_NORMAL, ITALIC_NORMAL };
     300             :             assert( SAL_N_ELEMENTS( weight ) == SAL_N_ELEMENTS( italic ));
     301           0 :             for( unsigned int j = 0;
     302           0 :                  j < SAL_N_ELEMENTS( weight );
     303             :                  ++j )
     304             :             {
     305             :                 // Embed font if at least viewing is allowed (in which case the opening app must check
     306             :                 // the font license rights too and open either read-only or not use the font for editing).
     307           0 :                 OUString fileUrl = EmbeddedFontsHelper::fontFileUrl( pEntry->GetFamilyName(), pEntry->GetFamily(),
     308           0 :                     italic[ j ], weight[ j ], pEntry->GetPitch(), pEntry->GetEncoding(),
     309           0 :                     EmbeddedFontsHelper::ViewingAllowed );
     310           0 :                 if( fileUrl.isEmpty())
     311           0 :                     continue;
     312           0 :                 if( !fontFilesMap.count( fileUrl ))
     313             :                 {
     314           0 :                     const OUString docUrl = bExportFlat ? lcl_checkFontFile( fileUrl ) : embedFontFile( fileUrl );
     315           0 :                     if( !docUrl.isEmpty())
     316           0 :                         fontFilesMap[ fileUrl ] = docUrl;
     317             :                     else
     318           0 :                         continue; // --> failed to embed
     319             :                 }
     320           0 :                 fileUrls.push_back( fileUrl );
     321           0 :             }
     322           0 :             if( !fileUrls.empty())
     323             :             {
     324           0 :                 SvXMLElementExport fontFaceSrc( GetExport(), XML_NAMESPACE_SVG,
     325           0 :                     XML_FONT_FACE_SRC, true, true );
     326           0 :                 for( std::vector< OUString >::const_iterator it = fileUrls.begin();
     327           0 :                      it != fileUrls.end();
     328             :                      ++it )
     329             :                 {
     330           0 :                     if( fontFilesMap.count( *it ))
     331             :                     {
     332           0 :                         if( !bExportFlat )
     333             :                         {
     334           0 :                             GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, fontFilesMap[ *it ] );
     335           0 :                             GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, "simple" );
     336             :                         }
     337           0 :                         SvXMLElementExport fontFaceUri( GetExport(), XML_NAMESPACE_SVG,
     338           0 :                             XML_FONT_FACE_URI, true, true );
     339             : 
     340           0 :                         if( bExportFlat )
     341             :                         {
     342           0 :                             const uno::Reference< ucb::XSimpleFileAccess > xFileAccess( ucb::SimpleFileAccess::create( GetExport().getComponentContext() ) );
     343             :                             try
     344             :                             {
     345           0 :                                 const uno::Reference< io::XInputStream > xInput( xFileAccess->openFileRead( fontFilesMap[ *it ] ) );
     346           0 :                                 XMLBase64Export aBase64Exp( GetExport() );
     347           0 :                                 aBase64Exp.exportOfficeBinaryDataElement( xInput );
     348             :                             }
     349           0 :                             catch( const uno::Exception & )
     350             :                             {
     351             :                                 // opening the file failed, ignore
     352           0 :                             }
     353             :                         }
     354             : 
     355           0 :                         GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_STRING, "truetype" );
     356           0 :                         SvXMLElementExport fontFaceFormat( GetExport(), XML_NAMESPACE_SVG,
     357           0 :                             XML_FONT_FACE_FORMAT, true, true );
     358             :                     }
     359           0 :                 }
     360           0 :             }
     361             :         }
     362        1556 :     }
     363         326 : }
     364             : 
     365           0 : OUString XMLFontAutoStylePool::embedFontFile( const OUString& fileUrl )
     366             : {
     367             :     try
     368             :     {
     369           0 :         osl::File file( fileUrl );
     370           0 :         if( file.open( osl_File_OpenFlag_Read ) != osl::File::E_None )
     371           0 :             return OUString();
     372             : 
     373           0 :         if ( !GetExport().GetTargetStorage().is() )
     374           0 :             return OUString();
     375             : 
     376           0 :         uno::Reference< embed::XStorage > storage;
     377           0 :         storage.set( GetExport().GetTargetStorage()->openStorageElement( OUString( "Fonts" ),
     378           0 :             ::embed::ElementModes::WRITE ), uno::UNO_QUERY_THROW );
     379           0 :         int index = 0;
     380           0 :         OUString name;
     381           0 :         do
     382             :         {
     383           0 :             name = "font" + OUString::number( ++index ) + ".ttf";
     384           0 :         } while( storage->hasByName( name ) );
     385           0 :         uno::Reference< io::XOutputStream > outputStream;
     386           0 :         outputStream.set( storage->openStreamElement( name, ::embed::ElementModes::WRITE ), UNO_QUERY_THROW );
     387           0 :         uno::Reference < beans::XPropertySet > propertySet( outputStream, uno::UNO_QUERY );
     388             :         assert( propertySet.is());
     389           0 :         propertySet->setPropertyValue( "MediaType", uno::makeAny( OUString( "application/x-font-ttf" ))); // TODO
     390             :         for(;;)
     391             :         {
     392             :             char buffer[ 4096 ];
     393             :             sal_uInt64 readSize;
     394             :             sal_Bool eof;
     395           0 :             if( file.isEndOfFile( &eof ) != osl::File::E_None )
     396             :             {
     397             :                 SAL_WARN( "xmloff", "Error reading font file " << fileUrl );
     398           0 :                 outputStream->closeOutput();
     399           0 :                 return OUString();
     400             :             }
     401           0 :             if( eof )
     402           0 :                 break;
     403           0 :             if( file.read( buffer, 4096, readSize ) != osl::File::E_None )
     404             :             {
     405             :                 SAL_WARN( "xmloff", "Error reading font file " << fileUrl );
     406           0 :                 outputStream->closeOutput();
     407           0 :                 return OUString();
     408             :             }
     409           0 :             if( readSize == 0 )
     410           0 :                 break;
     411           0 :             outputStream->writeBytes( uno::Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( buffer ), readSize ));
     412           0 :         }
     413           0 :         outputStream->closeOutput();
     414           0 :         if( storage.is() )
     415             :         {
     416           0 :             Reference< embed::XTransactedObject > transaction( storage, UNO_QUERY );
     417           0 :             if( transaction.is())
     418             :             {
     419           0 :                 transaction->commit();
     420           0 :                 return "Fonts/" + name;
     421           0 :             }
     422           0 :         }
     423           0 :     } catch( const Exception& e )
     424             :     {
     425             :         SAL_WARN( "xmloff", "Exception when embedding a font file:" << e.Message );
     426             :     }
     427           0 :     return OUString();
     428             : }
     429             : 
     430             : 
     431             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11