update credits
[LibreOffice.git] / vcl / headless / svptext.cxx
blob2b657461036d47f2f9c4fcce09361ebfc437717a
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 "vcl/sysdata.hxx"
33 #include "generic/geninst.h"
34 #include "generic/genpspgraphics.h"
35 #include "generic/glyphcache.hxx"
36 #include "headless/svpgdi.hxx"
37 #include "headless/svpbmp.hxx"
39 using namespace basegfx;
40 using namespace basebmp;
42 class SvpGlyphPeer
43 : public GlyphCachePeer
45 public:
46 SvpGlyphPeer() {}
48 BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, int nGlyphIndex,
49 sal_uInt32 nBmpFormat, B2IPoint& rTargetPos );
51 protected:
52 virtual void RemovingFont( ServerFont& );
53 virtual void RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
55 class SvpGcpHelper
57 public:
58 RawBitmap maRawBitmap;
59 BitmapDeviceSharedPtr maBitmapDev;
63 class SvpGlyphCache : public GlyphCache
65 public:
66 SvpGlyphCache( SvpGlyphPeer& rPeer ) : GlyphCache( rPeer) {}
67 SvpGlyphPeer& GetPeer() { return reinterpret_cast<SvpGlyphPeer&>( mrPeer ); }
68 static SvpGlyphCache& GetInstance();
71 namespace
73 struct GlyphCacheHolder
75 private:
76 SvpGlyphPeer* m_pSvpGlyphPeer;
77 SvpGlyphCache* m_pSvpGlyphCache;
78 public:
79 GlyphCacheHolder()
81 m_pSvpGlyphPeer = new SvpGlyphPeer();
82 m_pSvpGlyphCache = new SvpGlyphCache( *m_pSvpGlyphPeer );
84 void release()
86 delete m_pSvpGlyphCache;
87 delete m_pSvpGlyphPeer;
88 m_pSvpGlyphCache = NULL;
89 m_pSvpGlyphPeer = NULL;
91 SvpGlyphCache& getGlyphCache()
93 return *m_pSvpGlyphCache;
95 ~GlyphCacheHolder()
97 release();
101 struct theGlyphCacheHolder :
102 public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder>
106 SvpGlyphCache& SvpGlyphCache::GetInstance()
108 return theGlyphCacheHolder::get().getGlyphCache();
112 BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
113 int nGlyphIndex, sal_uInt32 nBmpFormat, B2IPoint& rTargetPos )
115 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
116 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
118 // nothing to do if the GlyphPeer hasn't allocated resources for the glyph
119 if( rGlyphData.ExtDataRef().meInfo != sal::static_int_cast<int>(nBmpFormat) )
121 if( rGlyphData.ExtDataRef().meInfo == Format::NONE )
122 pGcpHelper = new SvpGcpHelper;
123 RawBitmap& rRawBitmap = pGcpHelper->maRawBitmap;
125 // get glyph bitmap in matching format
126 bool bFound = false;
127 switch( nBmpFormat )
129 case Format::ONE_BIT_LSB_GREY:
130 bFound = rServerFont.GetGlyphBitmap1( nGlyphIndex, pGcpHelper->maRawBitmap );
131 break;
132 case Format::EIGHT_BIT_GREY:
133 bFound = rServerFont.GetGlyphBitmap8( nGlyphIndex, pGcpHelper->maRawBitmap );
134 break;
135 default:
136 OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format");
137 // fall back to black&white mask
138 nBmpFormat = Format::ONE_BIT_LSB_GREY;
139 bFound = false;
140 break;
143 // return .notdef glyph if needed
144 if( !bFound && (nGlyphIndex != 0) )
146 delete pGcpHelper;
147 return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
150 // construct alpha mask from raw bitmap
151 const B2IVector aSize( rRawBitmap.mnScanlineSize, rRawBitmap.mnHeight );
152 if( aSize.getX() && aSize.getY() )
154 static PaletteMemorySharedVector aDummyPAL;
155 RawMemorySharedArray aRawPtr( rRawBitmap.mpBits );
156 pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aRawPtr, aDummyPAL );
159 rServerFont.SetExtended( nBmpFormat, (void*)pGcpHelper );
162 rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
163 return pGcpHelper->maBitmapDev;
167 void SvpGlyphPeer::RemovingFont( ServerFont& )
169 // nothing to do: no font resources held in SvpGlyphPeer
173 void SvpGlyphPeer::RemovingGlyph( ServerFont&, GlyphData& rGlyphData, int /*nGlyphIndex*/ )
175 if( rGlyphData.ExtDataRef().mpData != Format::NONE )
177 // release the glyph related resources
178 DBG_ASSERT( (rGlyphData.ExtDataRef().meInfo <= Format::MAX), "SVP::RG() invalid alpha format" );
179 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
180 delete[] pGcpHelper->maRawBitmap.mpBits;
181 delete pGcpHelper;
186 // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
187 class PspKernInfo : public ExtraKernInfo
189 public:
190 PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
191 protected:
192 virtual void Initialize() const;
196 void PspKernInfo::Initialize() const
198 mbInitialized = true;
200 // get the kerning pairs from psprint
201 const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
202 typedef std::list< psp::KernPair > PspKernPairs;
203 const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
204 if( rKernPairs.empty() )
205 return;
207 PspKernPairs::const_iterator it = rKernPairs.begin();
208 for(; it != rKernPairs.end(); ++it )
210 ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
211 maUnicodeKernPairs.insert( aKernPair );
216 sal_uInt16 SvpSalGraphics::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel )
218 // release all no longer needed font resources
219 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
221 if( m_pServerFont[i] != NULL )
223 // old server side font is no longer referenced
224 SvpGlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] );
225 m_pServerFont[i] = NULL;
229 // return early if there is no new font
230 if( !pIFSD )
231 return 0;
233 // handle the request for a non-native X11-font => use the GlyphCache
234 ServerFont* pServerFont = SvpGlyphCache::GetInstance().CacheFont( *pIFSD );
235 if( !pServerFont )
236 return SAL_SETFONT_BADFONT;
238 // check selected font
239 if( !pServerFont->TestFont() )
241 SvpGlyphCache::GetInstance().UncacheFont( *pServerFont );
242 return SAL_SETFONT_BADFONT;
245 // update SalGraphics font settings
246 m_pServerFont[ nFallbackLevel ] = pServerFont;
247 return SAL_SETFONT_USEDRAWTEXTARRAY;
251 void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel )
253 if( nFallbackLevel >= MAX_FALLBACK )
254 return;
256 if( m_pServerFont[nFallbackLevel] != NULL )
258 long rDummyFactor;
259 m_pServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
264 sal_uLong SvpSalGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData* pKernPairs )
266 sal_uLong nGotPairs = 0;
268 if( m_pServerFont[0] != NULL )
270 ImplKernPairData* pTmpKernPairs = NULL;
271 nGotPairs = m_pServerFont[0]->GetKernPairs( &pTmpKernPairs );
272 for( sal_uLong i = 0; i < nPairs && i < nGotPairs; ++i )
273 pKernPairs[ i ] = pTmpKernPairs[ i ];
274 delete[] pTmpKernPairs;
277 return nGotPairs;
281 const ImplFontCharMap* SvpSalGraphics::GetImplFontCharMap() const
283 if( !m_pServerFont[0] )
284 return NULL;
286 const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
287 return pIFCMap;
290 bool SvpSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
292 if (!m_pServerFont[0])
293 return false;
295 return m_pServerFont[0]->GetFontCapabilities(rFontCapabilities);
299 void SvpSalGraphics::GetDevFontList( ImplDevFontList* pDevFontList )
301 GlyphCache& rGC = SvpGlyphCache::GetInstance();
303 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
304 psp::FastPrintFontInfo aInfo;
305 ::std::list< psp::fontID > aList;
306 rMgr.getFontList( aList );
307 ::std::list< psp::fontID >::iterator it;
308 for( it = aList.begin(); it != aList.end(); ++it )
310 if( !rMgr.getFontFastInfo( *it, aInfo ) )
311 continue;
313 // the GlyphCache must not bother with builtin fonts because
314 // it cannot access or use them anyway
315 if( aInfo.m_eType == psp::fonttype::Builtin )
316 continue;
318 // normalize face number to the GlyphCache
319 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
321 // for fonts where extra kerning info can be provided on demand
322 // an ExtraKernInfo object is supplied
323 const ExtraKernInfo* pExtraKernInfo = NULL;
324 if( aInfo.m_eType == psp::fonttype::Type1 )
325 pExtraKernInfo = new PspKernInfo( *it );
327 // inform GlyphCache about this font provided by the PsPrint subsystem
328 ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
329 aDFA.mnQuality += 4096;
330 const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
331 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
334 // announce glyphcache fonts
335 rGC.AnnounceFonts( pDevFontList );
337 // register platform specific font substitutions if available
338 SalGenericInstance::RegisterFontSubstitutors( pDevFontList );
340 ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
343 void SvpSalGraphics::ClearDevFontCache()
345 GlyphCache& rGC = SvpGlyphCache::GetInstance();
346 rGC.ClearFontCache();
350 void SvpSalGraphics::GetDevFontSubstList( OutputDevice* )
354 bool SvpSalGraphics::AddTempDevFont( ImplDevFontList*,
355 const OUString&, const OUString& )
357 return false;
361 sal_Bool SvpSalGraphics::CreateFontSubset(
362 const OUString& rToFile,
363 const PhysicalFontFace* pFont,
364 sal_Int32* pGlyphIDs,
365 sal_uInt8* pEncoding,
366 sal_Int32* pWidths,
367 int nGlyphCount,
368 FontSubsetInfo& rInfo
371 // in this context the pFont->GetFontId() is a valid PSP
372 // font since they are the only ones left after the PDF
373 // export has filtered its list of subsettable fonts (for
374 // which this method was created). The correct way would
375 // be to have the GlyphCache search for the PhysicalFontFace pFont
376 psp::fontID aFont = pFont->GetFontId();
378 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
379 bool bSuccess = rMgr.createFontSubset( rInfo,
380 aFont,
381 rToFile,
382 pGlyphIDs,
383 pEncoding,
384 pWidths,
385 nGlyphCount );
386 return bSuccess;
390 const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
392 // in this context the pFont->GetFontId() is a valid PSP
393 // font since they are the only ones left after the PDF
394 // export has filtered its list of subsettable fonts (for
395 // which this method was created). The correct way would
396 // be to have the GlyphCache search for the PhysicalFontFace pFont
397 psp::fontID aFont = pFont->GetFontId();
398 return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
402 const void* SvpSalGraphics::GetEmbedFontData(
403 const PhysicalFontFace* pFont,
404 const sal_Ucs* pUnicodes,
405 sal_Int32* pWidths,
406 FontSubsetInfo& rInfo,
407 long* pDataLen
410 // in this context the pFont->GetFontId() is a valid PSP
411 // font since they are the only ones left after the PDF
412 // export has filtered its list of subsettable fonts (for
413 // which this method was created). The correct way would
414 // be to have the GlyphCache search for the PhysicalFontFace pFont
415 psp::fontID aFont = pFont->GetFontId();
416 return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
420 void SvpSalGraphics::FreeEmbedFontData( const void* pData, long nLen )
422 GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
425 void SvpSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
426 bool bVertical,
427 Int32Vector& rWidths,
428 Ucs2UIntMap& rUnicodeEnc )
430 // in this context the pFont->GetFontId() is a valid PSP
431 // font since they are the only ones left after the PDF
432 // export has filtered its list of subsettable fonts (for
433 // which this method was created). The correct way would
434 // be to have the GlyphCache search for the PhysicalFontFace pFont
435 psp::fontID aFont = pFont->GetFontId();
436 GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
440 sal_Bool SvpSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphIndex, Rectangle& rRect )
442 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
443 if( nLevel >= MAX_FALLBACK )
444 return sal_False;
446 ServerFont* pSF = m_pServerFont[ nLevel ];
447 if( !pSF )
448 return sal_False;
450 nGlyphIndex &= GF_IDXMASK;
451 const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
452 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
453 return sal_True;
457 sal_Bool SvpSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphIndex, B2DPolyPolygon& rPolyPoly )
459 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
460 if( nLevel >= MAX_FALLBACK )
461 return sal_False;
463 const ServerFont* pSF = m_pServerFont[ nLevel ];
464 if( !pSF )
465 return sal_False;
467 nGlyphIndex &= GF_IDXMASK;
468 if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
469 return sal_True;
471 return sal_False;
475 SalLayout* SvpSalGraphics::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
477 GenericSalLayout* pLayout = NULL;
479 if( m_pServerFont[ nFallbackLevel ] )
480 pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] );
482 return pLayout;
486 void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
488 // iterate over all glyphs in the layout
489 Point aPos;
490 sal_GlyphId nGlyphIndex;
491 SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer();
492 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart ); )
494 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
495 DBG_ASSERT( nLevel < MAX_FALLBACK, "SvpGDI: invalid glyph fallback level" );
496 ServerFont* pSF = m_pServerFont[ nLevel ];
497 if( !pSF )
498 continue;
500 // get the glyph's alpha mask and adjust the drawing position
501 nGlyphIndex &= GF_IDXMASK;
502 B2IPoint aDstPoint( aPos.X(), aPos.Y() );
503 BitmapDeviceSharedPtr aAlphaMask
504 = rGlyphPeer.GetGlyphBmp( *pSF, nGlyphIndex, m_eTextFmt, aDstPoint );
505 if( !aAlphaMask ) // ignore empty glyphs
506 continue;
508 // blend text color into target using the glyph's mask
509 const B2IBox aSrcRect( B2ITuple(0,0), aAlphaMask->getSize() );
510 const B2IBox aClipRect( aDstPoint, aAlphaMask->getSize() );
512 SvpSalGraphics::ClipUndoHandle aUndo( this );
513 if( !isClippedSetup( aClipRect, aUndo ) )
514 m_aDevice->drawMaskedColor( m_aTextColor, aAlphaMask,
515 aSrcRect, aDstPoint, m_aClipMap );
519 void SvpSalGraphics::SetTextColor( SalColor nSalColor )
521 m_aTextColor = basebmp::Color( nSalColor );
524 SystemFontData SvpSalGraphics::GetSysFontData( int nFallbacklevel ) const
526 SystemFontData aSysFontData;
528 if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
529 if (nFallbacklevel < 0 ) nFallbacklevel = 0;
531 aSysFontData.nSize = sizeof( SystemFontData );
532 aSysFontData.nFontId = 0;
533 aSysFontData.nFontFlags = 0;
534 aSysFontData.bFakeBold = false;
535 aSysFontData.bFakeItalic = false;
536 aSysFontData.bAntialias = true;
537 return aSysFontData;
540 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */