LCOV - code coverage report
Current view: top level - libreoffice/drawinglayer/source/primitive2d - textlayoutdevice.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 87 151 57.6 %
Date: 2012-12-27 Functions: 16 30 53.3 %
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 <drawinglayer/primitive2d/textlayoutdevice.hxx>
      21             : #include <comphelper/processfactory.hxx>
      22             : #include <comphelper/scoped_disposing_ptr.hxx>
      23             : #include <vcl/timer.hxx>
      24             : #include <vcl/virdev.hxx>
      25             : #include <vcl/font.hxx>
      26             : #include <vcl/metric.hxx>
      27             : #include <i18npool/languagetag.hxx>
      28             : #include <drawinglayer/primitive2d/textprimitive2d.hxx>
      29             : #include <vcl/svapp.hxx>
      30             : 
      31             : //////////////////////////////////////////////////////////////////////////////
      32             : // VDev RevDevice provider
      33             : 
      34             : namespace
      35             : {
      36             :     class ImpTimedRefDev;
      37             : 
      38             :     //the scoped_timed_RefDev owns a ImpTimeRefDev and releases it on dtor
      39             :     //or disposing of the default XComponentContext which causes the underlying
      40             :     //OutputDevice to get released
      41             :     //
      42             :     //The ImpTimerRefDev itself, if the timeout ever gets hit, will call
      43             :     //reset on the scoped_timed_RefDev to release the ImpTimerRefDev early
      44             :     //if its unused for a few minutes
      45           7 :     class scoped_timed_RefDev : public comphelper::scoped_disposing_ptr<ImpTimedRefDev>
      46             :     {
      47             :     public:
      48           7 :         scoped_timed_RefDev() : comphelper::scoped_disposing_ptr<ImpTimedRefDev>((::com::sun::star::uno::Reference<com::sun::star::lang::XComponent>(::comphelper::getProcessComponentContext(), ::com::sun::star::uno::UNO_QUERY_THROW)))
      49             :         {
      50           7 :         }
      51             :     };
      52             : 
      53             :     class the_scoped_timed_RefDev : public rtl::Static<scoped_timed_RefDev, the_scoped_timed_RefDev> {};
      54             : 
      55             :     class ImpTimedRefDev : public Timer
      56             :     {
      57             :         scoped_timed_RefDev&                mrOwnerOfMe;
      58             :         VirtualDevice*                      mpVirDev;
      59             :         sal_uInt32                          mnUseCount;
      60             : 
      61             :     public:
      62             :         explicit ImpTimedRefDev(scoped_timed_RefDev& rOwnerofMe);
      63             :         ~ImpTimedRefDev();
      64             :         virtual void Timeout();
      65             : 
      66             :         VirtualDevice& acquireVirtualDevice();
      67             :         void releaseVirtualDevice();
      68             :     };
      69             : 
      70           7 :     ImpTimedRefDev::ImpTimedRefDev(scoped_timed_RefDev& rOwnerOfMe)
      71             :     :   mrOwnerOfMe(rOwnerOfMe),
      72             :         mpVirDev(0L),
      73           7 :         mnUseCount(0L)
      74             :     {
      75           7 :         SetTimeout(3L * 60L * 1000L); // three minutes
      76           7 :         Start();
      77           7 :     }
      78             : 
      79          21 :     ImpTimedRefDev::~ImpTimedRefDev()
      80             :     {
      81             :         OSL_ENSURE(0L == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
      82           7 :         delete mpVirDev;
      83          14 :     }
      84             : 
      85           0 :     void ImpTimedRefDev::Timeout()
      86             :     {
      87             :         // for obvious reasons, do not call anything after this
      88           0 :         mrOwnerOfMe.reset();
      89           0 :     }
      90             : 
      91         242 :     VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
      92             :     {
      93         242 :         if(!mpVirDev)
      94             :         {
      95           7 :             mpVirDev = new VirtualDevice();
      96           7 :             mpVirDev->SetReferenceDevice( VirtualDevice::REFDEV_MODE_MSO1 );
      97             :         }
      98             : 
      99         242 :         if(!mnUseCount)
     100             :         {
     101         242 :             Stop();
     102             :         }
     103             : 
     104         242 :         mnUseCount++;
     105             : 
     106         242 :         return *mpVirDev;
     107             :     }
     108             : 
     109         242 :     void ImpTimedRefDev::releaseVirtualDevice()
     110             :     {
     111             :         OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
     112         242 :         mnUseCount--;
     113             : 
     114         242 :         if(!mnUseCount)
     115             :         {
     116         242 :             Start();
     117             :         }
     118         242 :     }
     119             : } // end of anonymous namespace
     120             : 
     121             : //////////////////////////////////////////////////////////////////////////////
     122             : // access to one global ImpTimedRefDev incarnation in namespace drawinglayer::primitive
     123             : 
     124             : namespace drawinglayer
     125             : {
     126             :     namespace primitive2d
     127             :     {
     128             :         // static methods here
     129         242 :         VirtualDevice& acquireGlobalVirtualDevice()
     130             :         {
     131         242 :             scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
     132             : 
     133         242 :             if(!rStdRefDevice)
     134           7 :                 rStdRefDevice.reset(new ImpTimedRefDev(rStdRefDevice));
     135             : 
     136         242 :             return rStdRefDevice->acquireVirtualDevice();
     137             :         }
     138             : 
     139         242 :         void releaseGlobalVirtualDevice()
     140             :         {
     141         242 :             scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
     142             : 
     143             :             OSL_ENSURE(rStdRefDevice, "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
     144         242 :             rStdRefDevice->releaseVirtualDevice();
     145         242 :         }
     146             : 
     147         242 :         TextLayouterDevice::TextLayouterDevice()
     148         242 :         :   mrDevice(acquireGlobalVirtualDevice())
     149             :         {
     150         242 :         }
     151             : 
     152         242 :         TextLayouterDevice::~TextLayouterDevice()
     153             :         {
     154         242 :             releaseGlobalVirtualDevice();
     155         242 :         }
     156             : 
     157         242 :         void TextLayouterDevice::setFont(const Font& rFont)
     158             :         {
     159         242 :             mrDevice.SetFont( rFont );
     160         242 :         }
     161             : 
     162         242 :         void TextLayouterDevice::setFontAttribute(
     163             :             const attribute::FontAttribute& rFontAttribute,
     164             :             double fFontScaleX,
     165             :             double fFontScaleY,
     166             :             const ::com::sun::star::lang::Locale& rLocale)
     167             :         {
     168             :             setFont(getVclFontFromFontAttribute(
     169             :                 rFontAttribute,
     170             :                 fFontScaleX,
     171             :                 fFontScaleY,
     172             :                 0.0,
     173         242 :                 rLocale));
     174         242 :         }
     175             : 
     176           0 :         double TextLayouterDevice::getOverlineOffset() const
     177             :         {
     178           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     179           0 :             double fRet = (rMetric.GetIntLeading() / 2.0) - rMetric.GetAscent();
     180           0 :             return fRet;
     181             :         }
     182             : 
     183           0 :         double TextLayouterDevice::getUnderlineOffset() const
     184             :         {
     185           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     186           0 :             double fRet = rMetric.GetDescent() / 2.0;
     187           0 :             return fRet;
     188             :         }
     189             : 
     190           0 :         double TextLayouterDevice::getStrikeoutOffset() const
     191             :         {
     192           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     193           0 :             double fRet = (rMetric.GetAscent() - rMetric.GetIntLeading()) / 3.0;
     194           0 :             return fRet;
     195             :         }
     196             : 
     197           0 :         double TextLayouterDevice::getOverlineHeight() const
     198             :         {
     199           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     200           0 :             double fRet = rMetric.GetIntLeading() / 2.5;
     201           0 :             return fRet;
     202             :         }
     203             : 
     204           0 :         double TextLayouterDevice::getUnderlineHeight() const
     205             :         {
     206           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     207           0 :             double fRet = rMetric.GetDescent() / 4.0;
     208           0 :             return fRet;
     209             :         }
     210             : 
     211           0 :         double TextLayouterDevice::getTextHeight() const
     212             :         {
     213           0 :             return mrDevice.GetTextHeight();
     214             :         }
     215             : 
     216           0 :         double TextLayouterDevice::getTextWidth(
     217             :             const String& rText,
     218             :             sal_uInt32 nIndex,
     219             :             sal_uInt32 nLength) const
     220             :         {
     221           0 :             return mrDevice.GetTextWidth(rText, nIndex, nLength);
     222             :         }
     223             : 
     224           0 :         bool TextLayouterDevice::getTextOutlines(
     225             :             basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
     226             :             const String& rText,
     227             :             sal_uInt32 nIndex,
     228             :             sal_uInt32 nLength,
     229             :             const ::std::vector< double >& rDXArray) const
     230             :         {
     231           0 :             const sal_uInt32 nDXArrayCount(rDXArray.size());
     232           0 :             sal_uInt32 nTextLength(nLength);
     233           0 :             const sal_uInt32 nStringLength(rText.Len());
     234             : 
     235           0 :             if(nTextLength + nIndex > nStringLength)
     236             :             {
     237           0 :                 nTextLength = nStringLength - nIndex;
     238             :             }
     239             : 
     240           0 :             if(nDXArrayCount)
     241             :             {
     242             :                 OSL_ENSURE(nDXArrayCount == nTextLength, "DXArray size does not correspond to text portion size (!)");
     243           0 :                 std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount);
     244             : 
     245           0 :                 for(sal_uInt32 a(0); a < nDXArrayCount; a++)
     246             :                 {
     247           0 :                     aIntegerDXArray[a] = basegfx::fround(rDXArray[a]);
     248             :                 }
     249             : 
     250             :                 return mrDevice.GetTextOutlines(
     251             :                     rB2DPolyPolyVector,
     252             :                     rText,
     253             :                     nIndex,
     254             :                     nIndex,
     255             :                     nLength,
     256             :                     true,
     257             :                     0,
     258           0 :                     &(aIntegerDXArray[0]));
     259             :             }
     260             :             else
     261             :             {
     262             :                 return mrDevice.GetTextOutlines(
     263             :                     rB2DPolyPolyVector,
     264             :                     rText,
     265             :                     nIndex,
     266             :                     nIndex,
     267             :                     nLength,
     268             :                     true,
     269             :                     0,
     270           0 :                     0);
     271             :             }
     272             :         }
     273             : 
     274         242 :         basegfx::B2DRange TextLayouterDevice::getTextBoundRect(
     275             :             const String& rText,
     276             :             sal_uInt32 nIndex,
     277             :             sal_uInt32 nLength) const
     278             :         {
     279         242 :             sal_uInt32 nTextLength(nLength);
     280         242 :             const sal_uInt32 nStringLength(rText.Len());
     281             : 
     282         242 :             if(nTextLength + nIndex > nStringLength)
     283             :             {
     284           0 :                 nTextLength = nStringLength - nIndex;
     285             :             }
     286             : 
     287         242 :             if(nTextLength)
     288             :             {
     289         242 :                 Rectangle aRect;
     290             : 
     291             :                 mrDevice.GetTextBoundRect(
     292             :                     aRect,
     293             :                     rText,
     294             :                     nIndex,
     295             :                     nIndex,
     296         242 :                     nLength);
     297             : 
     298             :                 // #i104432#, #i102556# take empty results into account
     299         242 :                 if(!aRect.IsEmpty())
     300             :                 {
     301             :                     return basegfx::B2DRange(
     302         378 :                         aRect.Left(), aRect.Top(),
     303         567 :                         aRect.Right(), aRect.Bottom());
     304             :                 }
     305             :             }
     306             : 
     307          53 :             return basegfx::B2DRange();
     308             :         }
     309             : 
     310           0 :         double TextLayouterDevice::getFontAscent() const
     311             :         {
     312           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     313           0 :             return rMetric.GetAscent();
     314             :         }
     315             : 
     316           0 :         double TextLayouterDevice::getFontDescent() const
     317             :         {
     318           0 :             const ::FontMetric& rMetric = mrDevice.GetFontMetric();
     319           0 :             return rMetric.GetDescent();
     320             :         }
     321             : 
     322           0 :         void TextLayouterDevice::addTextRectActions(
     323             :             const Rectangle& rRectangle,
     324             :             const String& rText,
     325             :             sal_uInt16 nStyle,
     326             :             GDIMetaFile& rGDIMetaFile) const
     327             :         {
     328             :             mrDevice.AddTextRectActions(
     329           0 :                 rRectangle, rText, nStyle, rGDIMetaFile);
     330           0 :         }
     331             : 
     332           0 :         ::std::vector< double > TextLayouterDevice::getTextArray(
     333             :             const String& rText,
     334             :             sal_uInt32 nIndex,
     335             :             sal_uInt32 nLength) const
     336             :         {
     337           0 :             ::std::vector< double > aRetval;
     338           0 :             sal_uInt32 nTextLength(nLength);
     339           0 :             const sal_uInt32 nStringLength(rText.Len());
     340             : 
     341           0 :             if(nTextLength + nIndex > nStringLength)
     342             :             {
     343           0 :                 nTextLength = nStringLength - nIndex;
     344             :             }
     345             : 
     346           0 :             if(nTextLength)
     347             :             {
     348           0 :                 aRetval.reserve(nTextLength);
     349           0 :                 ::std::vector<sal_Int32> aArray(nTextLength);
     350           0 :                 mrDevice.GetTextArray(rText, &aArray[0], nIndex, nLength);
     351           0 :                 aRetval.assign(aArray.begin(), aArray.end());
     352             :             }
     353             : 
     354           0 :             return aRetval;
     355             :         }
     356             : 
     357             :     } // end of namespace primitive2d
     358             : } // end of namespace drawinglayer
     359             : 
     360             : //////////////////////////////////////////////////////////////////////////////
     361             : // helper methods for vcl font handling
     362             : 
     363             : namespace drawinglayer
     364             : {
     365             :     namespace primitive2d
     366             :     {
     367         249 :         Font getVclFontFromFontAttribute(
     368             :             const attribute::FontAttribute& rFontAttribute,
     369             :             double fFontScaleX,
     370             :             double fFontScaleY,
     371             :             double fFontRotation,
     372             :             const ::com::sun::star::lang::Locale& rLocale)
     373             :         {
     374             :             // detect FontScaling
     375         249 :             const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
     376         249 :             const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
     377         249 :             const bool bFontIsScaled(nHeight != nWidth);
     378             : 
     379             : #ifdef WIN32
     380             :             // for WIN32 systems, start with creating an unscaled font. If FontScaling
     381             :             // is wanted, that width needs to be adapted using FontMetric again to get a
     382             :             // width of the unscaled font
     383             :             Font aRetval(
     384             :                 rFontAttribute.getFamilyName(),
     385             :                 rFontAttribute.getStyleName(),
     386             :                 Size(0, nHeight));
     387             : #else
     388             :             // for non-WIN32 systems things are easier since these accept a Font creation
     389             :             // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
     390             :             // FontWidth when no scaling is used to explicitly have that zero when e.g. the
     391             :             // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
     392             :             // set FontWidth; import that in a WIN32 system, and trouble is there)
     393             :             Font aRetval(
     394         249 :                 rFontAttribute.getFamilyName(),
     395         249 :                 rFontAttribute.getStyleName(),
     396         498 :                 Size(bFontIsScaled ? nWidth : 0, nHeight));
     397             : #endif
     398             :             // define various other FontAttribute
     399         249 :             aRetval.SetAlign(ALIGN_BASELINE);
     400         249 :             aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE);
     401         249 :             aRetval.SetVertical(rFontAttribute.getVertical() ? sal_True : sal_False);
     402         249 :             aRetval.SetWeight(static_cast<FontWeight>(rFontAttribute.getWeight()));
     403         249 :             aRetval.SetItalic(rFontAttribute.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
     404         249 :             aRetval.SetOutline(rFontAttribute.getOutline());
     405         249 :             aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE);
     406         249 :             aRetval.SetLanguage(LanguageTag(rLocale).getLanguageType(false));
     407             : 
     408             : #ifdef WIN32
     409             :             // for WIN32 systems, correct the FontWidth if FontScaling is used
     410             :             if(bFontIsScaled && nHeight > 0)
     411             :             {
     412             :                 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval));
     413             : 
     414             :                 if(aUnscaledFontMetric.GetWidth() > 0)
     415             :                 {
     416             :                     const double fScaleFactor((double)nWidth / (double)nHeight);
     417             :                     const sal_uInt32 nScaledWidth(basegfx::fround((double)aUnscaledFontMetric.GetWidth() * fScaleFactor));
     418             :                     aRetval.SetWidth(nScaledWidth);
     419             :                 }
     420             :             }
     421             : #endif
     422             :             // handle FontRotation (if defined)
     423         249 :             if(!basegfx::fTools::equalZero(fFontRotation))
     424             :             {
     425           0 :                 sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI)));
     426           0 :                 aRetval.SetOrientation(aRotate10th % 3600);
     427             :             }
     428             : 
     429         249 :             return aRetval;
     430             :         }
     431             : 
     432         244 :         attribute::FontAttribute getFontAttributeFromVclFont(
     433             :             basegfx::B2DVector& o_rSize,
     434             :             const Font& rFont,
     435             :             bool bRTL,
     436             :             bool bBiDiStrong)
     437             :         {
     438             :             const attribute::FontAttribute aRetval(
     439         244 :                 rFont.GetName(),
     440         244 :                 rFont.GetStyleName(),
     441         244 :                 static_cast<sal_uInt16>(rFont.GetWeight()),
     442         244 :                 RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(),
     443         244 :                 rFont.IsVertical(),
     444         244 :                 ITALIC_NONE != rFont.GetItalic(),
     445         244 :                 PITCH_FIXED == rFont.GetPitch(),
     446         244 :                 rFont.IsOutline(),
     447             :                 bRTL,
     448        1952 :                 bBiDiStrong);
     449             :             // TODO: eKerning
     450             : 
     451             :             // set FontHeight and init to no FontScaling
     452         244 :             o_rSize.setY(rFont.GetSize().getHeight() > 0 ? rFont.GetSize().getHeight() : 0);
     453         244 :             o_rSize.setX(o_rSize.getY());
     454             : 
     455             : #ifdef WIN32
     456             :             // for WIN32 systems, the FontScaling at the Font is detected by
     457             :             // checking that FontWidth != 0. When FontScaling is used, WIN32
     458             :             // needs to do extra stuff to detect the correct width (since it's
     459             :             // zero and not equal the font height) and it's relationship to
     460             :             // the height
     461             :             if(rFont.GetSize().getWidth() > 0)
     462             :             {
     463             :                 Font aUnscaledFont(rFont);
     464             :                 aUnscaledFont.SetWidth(0);
     465             :                 const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
     466             : 
     467             :                 if(aUnscaledFontMetric.GetWidth() > 0)
     468             :                 {
     469             :                     const double fScaleFactor((double)rFont.GetSize().getWidth() / (double)aUnscaledFontMetric.GetWidth());
     470             :                     o_rSize.setX(fScaleFactor * o_rSize.getY());
     471             :                 }
     472             :             }
     473             : #else
     474             :             // For non-WIN32 systems the detection is the same, but the value
     475             :             // is easier achieved since width == height is interpreted as no
     476             :             // scaling. Ergo, Width == 0 means width == height, and width != 0
     477             :             // means the scaling is in the direct relation of width to height
     478         244 :             if(rFont.GetSize().getWidth() > 0)
     479             :             {
     480           0 :                 o_rSize.setX((double)rFont.GetSize().getWidth());
     481             :             }
     482             : #endif
     483         244 :             return aRetval;
     484             :         }
     485             :     } // end of namespace primitive2d
     486             : } // end of namespace drawinglayer
     487             : 
     488             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10