LCOV - code coverage report
Current view: top level - svgio/source/svgreader - svgstylenode.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 80 85 94.1 %
Date: 2015-06-13 12:38:46 Functions: 8 8 100.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 <svgio/svgreader/svgstylenode.hxx>
      21             : #include <svgio/svgreader/svgdocument.hxx>
      22             : 
      23             : namespace svgio
      24             : {
      25             :     namespace svgreader
      26             :     {
      27           2 :         SvgStyleNode::SvgStyleNode(
      28             :             SvgDocument& rDocument,
      29             :             SvgNode* pParent)
      30             :         :   SvgNode(SVGTokenStyle, rDocument, pParent),
      31             :             maSvgStyleAttributes(),
      32           2 :             mbTextCss(false)
      33             :         {
      34           2 :         }
      35             : 
      36           6 :         SvgStyleNode::~SvgStyleNode()
      37             :         {
      38           6 :             while(!maSvgStyleAttributes.empty())
      39             :             {
      40           2 :                 delete *(maSvgStyleAttributes.end() - 1);
      41           2 :                 maSvgStyleAttributes.pop_back();
      42             :             }
      43           4 :         }
      44             : 
      45             :         // #i125258# no parent when we are a CssStyle holder to break potential loops because
      46             :         // when using CssStyles we jump uncontrolled inside the node tree hierarchy
      47           2 :         bool SvgStyleNode::supportsParentStyle() const
      48             :         {
      49           2 :             if(isTextCss())
      50             :             {
      51           2 :                 return false;
      52             :             }
      53             : 
      54             :             // call parent
      55           0 :             return SvgNode::supportsParentStyle();
      56             :         }
      57             : 
      58           2 :         void SvgStyleNode::parseAttribute(const OUString& rTokenName, SVGToken aSVGToken, const OUString& aContent)
      59             :         {
      60             :             // call parent
      61           2 :             SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
      62             : 
      63             :             // parse own
      64           2 :             switch(aSVGToken)
      65             :             {
      66             :                 case SVGTokenType:
      67             :                 {
      68           2 :                     if(!aContent.isEmpty())
      69             :                     {
      70           2 :                         if(aContent.startsWith("text/css"))
      71             :                         {
      72           2 :                             setTextCss(true);
      73             :                         }
      74             :                     }
      75           2 :                     break;
      76             :                 }
      77             :                 default:
      78             :                 {
      79           0 :                     break;
      80             :                 }
      81             :             }
      82           2 :         }
      83             : 
      84           2 :         void SvgStyleNode::addCssStyleSheet(const OUString& aSelectors, const SvgStyleAttributes& rNewStyle)
      85             :         {
      86             :             // aSelectors: CssStyle selectors, any combination, no comma separations, no spaces at start/end
      87             :             // rNewStyle: the already preapared style to register on that name
      88           2 :             if(!aSelectors.isEmpty())
      89             :             {
      90           2 :                 std::vector< OUString > aSelectorParts;
      91           2 :                 const sal_Int32 nLen(aSelectors.getLength());
      92           2 :                 sal_Int32 nPos(0);
      93           4 :                 OUStringBuffer aToken;
      94             : 
      95             :                 // split into single tokens (currently only space separator)
      96           6 :                 while(nPos < nLen)
      97             :                 {
      98           2 :                     const sal_Int32 nInitPos(nPos);
      99           2 :                     copyToLimiter(aSelectors, sal_Unicode(' '), nPos, aToken, nLen);
     100           2 :                     skip_char(aSelectors, sal_Unicode(' '), nPos, nLen);
     101           2 :                     const OUString aSelectorPart(aToken.makeStringAndClear().trim());
     102             : 
     103           2 :                     if(!aSelectorPart.isEmpty())
     104             :                     {
     105           2 :                         aSelectorParts.push_back(aSelectorPart);
     106             :                     }
     107             : 
     108           2 :                     if(nInitPos == nPos)
     109             :                     {
     110             :                         OSL_ENSURE(false, "Could not interpret on current position (!)");
     111           0 :                         nPos++;
     112             :                     }
     113           2 :                 }
     114             : 
     115           2 :                 if(aSelectorParts.size())
     116             :                 {
     117           2 :                     OUString aConcatenatedSelector;
     118             : 
     119             :                     // re-combine without spaces, create a unique name (for now)
     120           4 :                     for(size_t a(0); a < aSelectorParts.size(); a++)
     121             :                     {
     122           2 :                         aConcatenatedSelector += aSelectorParts[a];
     123             :                     }
     124             : 
     125             :                     // CssStyles in SVG are currently not completely supported; the current idea for
     126             :                     // supporting the needed minimal set is to register CssStyles associated to a string
     127             :                     // which is just the space-char cleaned, concatenated Selectors. The part to 'match'
     128             :                     // these is in fillCssStyleVectorUsingHierarchyAndSelectors. There, the same string is
     129             :                     // built up using the priorities of local CssStyle, Id, Class and other info combined
     130             :                     // with the existing hierarchy. This creates a specificity- and priority-sorted local
     131             :                     // list for each node which is then chained using get/setCssStyleParent.
     132             :                     // The current solution is capable of solving space-separated selectors which can be
     133             :                     // mixed between Id, Class and type specifiers.
     134             :                     // When CssStyles need more specific solving, the start point is here; remember the
     135             :                     // needed infos not in maIdStyleTokenMapperList at the document, but select evtl.
     136             :                     // more specific infos there in a class capable of handling more complex matchings.
     137             :                     // Additionally fillCssStyleVector (or the mechanism above that when a linked list of
     138             :                     // SvgStyleAttributes will not do it) will have to be adapted to make use of it.
     139             : 
     140             :                     // register new style at document for (evtl. concatenated) stylename
     141           2 :                     const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aConcatenatedSelector, rNewStyle);
     142           2 :                 }
     143             :             }
     144           2 :         }
     145             : 
     146           2 :         void SvgStyleNode::addCssStyleSheet(const OUString& aSelectors, const OUString& aContent)
     147             :         {
     148             :             // aSelectors: possible comma-separated list of CssStyle definitions, no spaces at start/end
     149             :             // aContent: the svg style definitions as string
     150           2 :             if(!aSelectors.isEmpty() && !aContent.isEmpty())
     151             :             {
     152             :                 // create new style and add to local list (for ownership control)
     153           2 :                 SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this);
     154           2 :                 maSvgStyleAttributes.push_back(pNewStyle);
     155             : 
     156             :                 // fill with content
     157           2 :                 pNewStyle->readCssStyle(aContent);
     158             : 
     159             :                 // comma-separated split (Css abbreviation for same style for multiple selectors)
     160           2 :                 const sal_Int32 nLen(aSelectors.getLength());
     161           2 :                 sal_Int32 nPos(0);
     162           2 :                 OUStringBuffer aToken;
     163             : 
     164           6 :                 while(nPos < nLen)
     165             :                 {
     166           2 :                     const sal_Int32 nInitPos(nPos);
     167           2 :                     copyToLimiter(aSelectors, sal_Unicode(','), nPos, aToken, nLen);
     168           2 :                     skip_char(aSelectors, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
     169             : 
     170           2 :                     const OUString aSingleName(aToken.makeStringAndClear().trim());
     171             : 
     172           2 :                     if(aSingleName.getLength())
     173             :                     {
     174           2 :                         addCssStyleSheet(aSingleName, *pNewStyle);
     175             :                     }
     176             : 
     177           2 :                     if(nInitPos == nPos)
     178             :                     {
     179             :                         OSL_ENSURE(false, "Could not interpret on current position (!)");
     180           0 :                         nPos++;
     181             :                     }
     182           4 :                 }
     183             :             }
     184           2 :         }
     185             : 
     186           2 :         void SvgStyleNode::addCssStyleSheet(const OUString& aSelectorsAndContent)
     187             :         {
     188           2 :             const sal_Int32 nLen(aSelectorsAndContent.getLength());
     189             : 
     190           2 :             if(nLen)
     191             :             {
     192           2 :                 sal_Int32 nPos(0);
     193           2 :                 OUStringBuffer aToken;
     194             : 
     195           6 :                 while(nPos < nLen)
     196             :                 {
     197             :                     // read the full selectors (may be multiple, comma-separated)
     198           2 :                     const sal_Int32 nInitPos(nPos);
     199           2 :                     skip_char(aSelectorsAndContent, sal_Unicode(' '), nPos, nLen);
     200           2 :                     copyToLimiter(aSelectorsAndContent, sal_Unicode('{'), nPos, aToken, nLen);
     201           2 :                     skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen);
     202             : 
     203           2 :                     const OUString aSelectors(aToken.makeStringAndClear().trim());
     204           4 :                     OUString aContent;
     205             : 
     206           2 :                     if(!aSelectors.isEmpty() && nPos < nLen)
     207             :                     {
     208             :                         // isolate content as text, embraced by '{' and '}'
     209           2 :                         copyToLimiter(aSelectorsAndContent, sal_Unicode('}'), nPos, aToken, nLen);
     210           2 :                         skip_char(aSelectorsAndContent, sal_Unicode(' '), sal_Unicode('}'), nPos, nLen);
     211             : 
     212           2 :                         aContent = aToken.makeStringAndClear().trim();
     213             :                     }
     214             : 
     215           2 :                     if(!aSelectors.isEmpty() && !aContent.isEmpty())
     216             :                     {
     217           2 :                         addCssStyleSheet(aSelectors, aContent);
     218             :                     }
     219             : 
     220           2 :                     if(nInitPos == nPos)
     221             :                     {
     222             :                         OSL_ENSURE(false, "Could not interpret on current position (!)");
     223           0 :                         nPos++;
     224             :                     }
     225           4 :                 }
     226             :             }
     227           2 :         }
     228             : 
     229             :     } // end of namespace svgreader
     230             : } // end of namespace svgio
     231             : 
     232             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11