Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / vcl / headless / svptext.cxx
bloba97b0776e3eed4c422dc806514626ebe216c3b77
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basegfx/range/b2drange.hxx>
21 #include <basegfx/range/b2ibox.hxx>
22 #include <basegfx/polygon/b2dpolypolygon.hxx>
24 #include <basebmp/scanlineformats.hxx>
26 #include <tools/debug.hxx>
28 #include <outfont.hxx>
29 #include <impfont.hxx>
30 #include <rtl/instance.hxx>
32 #include "generic/geninst.h"
33 #include "generic/genpspgraphics.h"
34 #include "generic/glyphcache.hxx"
35 #include "headless/svpgdi.hxx"
36 #include "headless/svpbmp.hxx"
38 using namespace basegfx;
39 using namespace basebmp;
41 // ===========================================================================
43 class SvpGlyphPeer
44 : public GlyphCachePeer
46 public:
47 SvpGlyphPeer() {}
49 BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, int nGlyphIndex,
50 sal_uInt32 nBmpFormat, B2IPoint& rTargetPos );
52 protected:
53 virtual void RemovingFont( ServerFont& );
54 virtual void RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
56 class SvpGcpHelper
58 public:
59 RawBitmap maRawBitmap;
60 BitmapDeviceSharedPtr maBitmapDev;
64 // ===========================================================================
66 class SvpGlyphCache : public GlyphCache
68 public:
69 SvpGlyphCache( SvpGlyphPeer& rPeer ) : GlyphCache( rPeer) {}
70 SvpGlyphPeer& GetPeer() { return reinterpret_cast<SvpGlyphPeer&>( mrPeer ); }
71 static SvpGlyphCache& GetInstance();
74 namespace
76 struct GlyphCacheHolder
78 private:
79 SvpGlyphPeer* m_pSvpGlyphPeer;
80 SvpGlyphCache* m_pSvpGlyphCache;
81 public:
82 GlyphCacheHolder()
84 m_pSvpGlyphPeer = new SvpGlyphPeer();
85 m_pSvpGlyphCache = new SvpGlyphCache( *m_pSvpGlyphPeer );
87 void release()
89 delete m_pSvpGlyphCache;
90 delete m_pSvpGlyphPeer;
91 m_pSvpGlyphCache = NULL;
92 m_pSvpGlyphPeer = NULL;
94 SvpGlyphCache& getGlyphCache()
96 return *m_pSvpGlyphCache;
98 ~GlyphCacheHolder()
100 release();
104 struct theGlyphCacheHolder :
105 public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder>
109 SvpGlyphCache& SvpGlyphCache::GetInstance()
111 return theGlyphCacheHolder::get().getGlyphCache();
114 // ===========================================================================
116 BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
117 int nGlyphIndex, sal_uInt32 nBmpFormat, B2IPoint& rTargetPos )
119 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
120 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
122 // nothing to do if the GlyphPeer hasn't allocated resources for the glyph
123 if( rGlyphData.ExtDataRef().meInfo != sal::static_int_cast<int>(nBmpFormat) )
125 if( rGlyphData.ExtDataRef().meInfo == Format::NONE )
126 pGcpHelper = new SvpGcpHelper;
127 RawBitmap& rRawBitmap = pGcpHelper->maRawBitmap;
129 // get glyph bitmap in matching format
130 bool bFound = false;
131 switch( nBmpFormat )
133 case Format::ONE_BIT_LSB_GREY:
134 bFound = rServerFont.GetGlyphBitmap1( nGlyphIndex, pGcpHelper->maRawBitmap );
135 break;
136 case Format::EIGHT_BIT_GREY:
137 bFound = rServerFont.GetGlyphBitmap8( nGlyphIndex, pGcpHelper->maRawBitmap );
138 break;
139 default:
140 OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format");
141 // fall back to black&white mask
142 nBmpFormat = Format::ONE_BIT_LSB_GREY;
143 bFound = false;
144 break;
147 // return .notdef glyph if needed
148 if( !bFound && (nGlyphIndex != 0) )
150 delete pGcpHelper;
151 return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
154 // construct alpha mask from raw bitmap
155 const B2IVector aSize( rRawBitmap.mnScanlineSize, rRawBitmap.mnHeight );
156 if( aSize.getX() && aSize.getY() )
158 static PaletteMemorySharedVector aDummyPAL;
159 RawMemorySharedArray aRawPtr( rRawBitmap.mpBits );
160 pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aRawPtr, aDummyPAL );
163 rServerFont.SetExtended( nBmpFormat, (void*)pGcpHelper );
166 rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
167 return pGcpHelper->maBitmapDev;
170 //--------------------------------------------------------------------------
172 void SvpGlyphPeer::RemovingFont( ServerFont& )
174 // nothing to do: no font resources held in SvpGlyphPeer
177 //--------------------------------------------------------------------------
179 void SvpGlyphPeer::RemovingGlyph( ServerFont&, GlyphData& rGlyphData, int /*nGlyphIndex*/ )
181 if( rGlyphData.ExtDataRef().mpData != Format::NONE )
183 // release the glyph related resources
184 DBG_ASSERT( (rGlyphData.ExtDataRef().meInfo <= Format::MAX), "SVP::RG() invalid alpha format" );
185 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
186 delete[] pGcpHelper->maRawBitmap.mpBits;
187 delete pGcpHelper;
191 // ===========================================================================
193 // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
194 class PspKernInfo : public ExtraKernInfo
196 public:
197 PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
198 protected:
199 virtual void Initialize() const;
202 //--------------------------------------------------------------------------
204 void PspKernInfo::Initialize() const
206 mbInitialized = true;
208 // get the kerning pairs from psprint
209 const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
210 typedef std::list< psp::KernPair > PspKernPairs;
211 const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
212 if( rKernPairs.empty() )
213 return;
215 PspKernPairs::const_iterator it = rKernPairs.begin();
216 for(; it != rKernPairs.end(); ++it )
218 ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
219 maUnicodeKernPairs.insert( aKernPair );
223 // ===========================================================================
225 sal_uInt16 SvpSalGraphics::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel )
227 // release all no longer needed font resources
228 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
230 if( m_pServerFont[i] != NULL )
232 // old server side font is no longer referenced
233 SvpGlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] );
234 m_pServerFont[i] = NULL;
238 // return early if there is no new font
239 if( !pIFSD )
240 return 0;
242 // handle the request for a non-native X11-font => use the GlyphCache
243 ServerFont* pServerFont = SvpGlyphCache::GetInstance().CacheFont( *pIFSD );
244 if( !pServerFont )
245 return SAL_SETFONT_BADFONT;
247 // check selected font
248 if( !pServerFont->TestFont() )
250 SvpGlyphCache::GetInstance().UncacheFont( *pServerFont );
251 return SAL_SETFONT_BADFONT;
254 // update SalGraphics font settings
255 m_pServerFont[ nFallbackLevel ] = pServerFont;
256 return SAL_SETFONT_USEDRAWTEXTARRAY;
259 // ---------------------------------------------------------------------------
261 void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel )
263 if( nFallbackLevel >= MAX_FALLBACK )
264 return;
266 if( m_pServerFont[nFallbackLevel] != NULL )
268 long rDummyFactor;
269 m_pServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
273 // ---------------------------------------------------------------------------
275 sal_uLong SvpSalGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData* pKernPairs )
277 sal_uLong nGotPairs = 0;
279 if( m_pServerFont[0] != NULL )
281 ImplKernPairData* pTmpKernPairs = NULL;
282 nGotPairs = m_pServerFont[0]->GetKernPairs( &pTmpKernPairs );
283 for( sal_uLong i = 0; i < nPairs && i < nGotPairs; ++i )
284 pKernPairs[ i ] = pTmpKernPairs[ i ];
285 delete[] pTmpKernPairs;
288 return nGotPairs;
291 // ---------------------------------------------------------------------------
293 const ImplFontCharMap* SvpSalGraphics::GetImplFontCharMap() const
295 if( !m_pServerFont[0] )
296 return NULL;
298 const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
299 return pIFCMap;
302 bool SvpSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
304 if (!m_pServerFont[0])
305 return false;
307 return m_pServerFont[0]->GetFontCapabilities(rFontCapabilities);
310 // ---------------------------------------------------------------------------
312 void SvpSalGraphics::GetDevFontList( ImplDevFontList* pDevFontList )
314 GlyphCache& rGC = SvpGlyphCache::GetInstance();
316 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
317 psp::FastPrintFontInfo aInfo;
318 ::std::list< psp::fontID > aList;
319 rMgr.getFontList( aList );
320 ::std::list< psp::fontID >::iterator it;
321 for( it = aList.begin(); it != aList.end(); ++it )
323 if( !rMgr.getFontFastInfo( *it, aInfo ) )
324 continue;
326 // the GlyphCache must not bother with builtin fonts because
327 // it cannot access or use them anyway
328 if( aInfo.m_eType == psp::fonttype::Builtin )
329 continue;
331 // normalize face number to the GlyphCache
332 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
334 // for fonts where extra kerning info can be provided on demand
335 // an ExtraKernInfo object is supplied
336 const ExtraKernInfo* pExtraKernInfo = NULL;
337 if( aInfo.m_eType == psp::fonttype::Type1 )
338 pExtraKernInfo = new PspKernInfo( *it );
340 // inform GlyphCache about this font provided by the PsPrint subsystem
341 ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
342 aDFA.mnQuality += 4096;
343 const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
344 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
347 // announce glyphcache fonts
348 rGC.AnnounceFonts( pDevFontList );
350 // register platform specific font substitutions if available
351 SalGenericInstance::RegisterFontSubstitutors( pDevFontList );
353 ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
356 void SvpSalGraphics::ClearDevFontCache()
358 GlyphCache& rGC = SvpGlyphCache::GetInstance();
359 rGC.ClearFontCache();
362 // ---------------------------------------------------------------------------
364 void SvpSalGraphics::GetDevFontSubstList( OutputDevice* )
367 // ---------------------------------------------------------------------------
369 bool SvpSalGraphics::AddTempDevFont( ImplDevFontList*,
370 const rtl::OUString&, const rtl::OUString& )
372 return false;
375 // ---------------------------------------------------------------------------
377 sal_Bool SvpSalGraphics::CreateFontSubset(
378 const rtl::OUString& rToFile,
379 const PhysicalFontFace* pFont,
380 sal_Int32* pGlyphIDs,
381 sal_uInt8* pEncoding,
382 sal_Int32* pWidths,
383 int nGlyphCount,
384 FontSubsetInfo& rInfo
387 // in this context the pFont->GetFontId() is a valid PSP
388 // font since they are the only ones left after the PDF
389 // export has filtered its list of subsettable fonts (for
390 // which this method was created). The correct way would
391 // be to have the GlyphCache search for the PhysicalFontFace pFont
392 psp::fontID aFont = pFont->GetFontId();
394 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
395 bool bSuccess = rMgr.createFontSubset( rInfo,
396 aFont,
397 rToFile,
398 pGlyphIDs,
399 pEncoding,
400 pWidths,
401 nGlyphCount );
402 return bSuccess;
405 // ---------------------------------------------------------------------------
407 const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
409 // in this context the pFont->GetFontId() is a valid PSP
410 // font since they are the only ones left after the PDF
411 // export has filtered its list of subsettable fonts (for
412 // which this method was created). The correct way would
413 // be to have the GlyphCache search for the PhysicalFontFace pFont
414 psp::fontID aFont = pFont->GetFontId();
415 return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
418 // ---------------------------------------------------------------------------
420 const void* SvpSalGraphics::GetEmbedFontData(
421 const PhysicalFontFace* pFont,
422 const sal_Ucs* pUnicodes,
423 sal_Int32* pWidths,
424 FontSubsetInfo& rInfo,
425 long* pDataLen
428 // in this context the pFont->GetFontId() is a valid PSP
429 // font since they are the only ones left after the PDF
430 // export has filtered its list of subsettable fonts (for
431 // which this method was created). The correct way would
432 // be to have the GlyphCache search for the PhysicalFontFace pFont
433 psp::fontID aFont = pFont->GetFontId();
434 return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
437 // ---------------------------------------------------------------------------
439 void SvpSalGraphics::FreeEmbedFontData( const void* pData, long nLen )
441 GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
444 void SvpSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
445 bool bVertical,
446 Int32Vector& rWidths,
447 Ucs2UIntMap& rUnicodeEnc )
449 // in this context the pFont->GetFontId() is a valid PSP
450 // font since they are the only ones left after the PDF
451 // export has filtered its list of subsettable fonts (for
452 // which this method was created). The correct way would
453 // be to have the GlyphCache search for the PhysicalFontFace pFont
454 psp::fontID aFont = pFont->GetFontId();
455 GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
458 // ---------------------------------------------------------------------------
460 sal_Bool SvpSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphIndex, Rectangle& rRect )
462 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
463 if( nLevel >= MAX_FALLBACK )
464 return sal_False;
466 ServerFont* pSF = m_pServerFont[ nLevel ];
467 if( !pSF )
468 return sal_False;
470 nGlyphIndex &= GF_IDXMASK;
471 const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
472 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
473 return sal_True;
476 // ---------------------------------------------------------------------------
478 sal_Bool SvpSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphIndex, B2DPolyPolygon& rPolyPoly )
480 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
481 if( nLevel >= MAX_FALLBACK )
482 return sal_False;
484 const ServerFont* pSF = m_pServerFont[ nLevel ];
485 if( !pSF )
486 return sal_False;
488 nGlyphIndex &= GF_IDXMASK;
489 if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
490 return sal_True;
492 return sal_False;
495 // ---------------------------------------------------------------------------
497 SalLayout* SvpSalGraphics::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
499 GenericSalLayout* pLayout = NULL;
501 if( m_pServerFont[ nFallbackLevel ] )
502 pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] );
504 return pLayout;
507 // ---------------------------------------------------------------------------
509 void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
511 // iterate over all glyphs in the layout
512 Point aPos;
513 sal_GlyphId nGlyphIndex;
514 SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer();
515 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart ); )
517 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
518 DBG_ASSERT( nLevel < MAX_FALLBACK, "SvpGDI: invalid glyph fallback level" );
519 ServerFont* pSF = m_pServerFont[ nLevel ];
520 if( !pSF )
521 continue;
523 // get the glyph's alpha mask and adjust the drawing position
524 nGlyphIndex &= GF_IDXMASK;
525 B2IPoint aDstPoint( aPos.X(), aPos.Y() );
526 BitmapDeviceSharedPtr aAlphaMask
527 = rGlyphPeer.GetGlyphBmp( *pSF, nGlyphIndex, m_eTextFmt, aDstPoint );
528 if( !aAlphaMask ) // ignore empty glyphs
529 continue;
531 // blend text color into target using the glyph's mask
532 const B2IBox aSrcRect( B2ITuple(0,0), aAlphaMask->getSize() );
533 const B2IBox aClipRect( aDstPoint, aAlphaMask->getSize() );
535 SvpSalGraphics::ClipUndoHandle aUndo( this );
536 if( !isClippedSetup( aClipRect, aUndo ) )
537 m_aDevice->drawMaskedColor( m_aTextColor, aAlphaMask,
538 aSrcRect, aDstPoint, m_aClipMap );
542 // ===========================================================================
544 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */