Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / vcl / headless / svptext.cxx
blob0a4bbd14cc702fe1498cf766aa10f6c45681d892
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 "sal/config.h"
22 #include <cassert>
24 #include <basegfx/range/b2drange.hxx>
25 #include <basegfx/range/b2ibox.hxx>
26 #include <basegfx/polygon/b2dpolypolygon.hxx>
28 #include <basebmp/scanlineformats.hxx>
30 #include <tools/debug.hxx>
32 #include <outfont.hxx>
33 #include <impfont.hxx>
34 #include <rtl/instance.hxx>
36 #include "vcl/sysdata.hxx"
37 #include "generic/geninst.h"
38 #include "generic/genpspgraphics.h"
39 #include "generic/glyphcache.hxx"
40 #include "headless/svpgdi.hxx"
41 #include "headless/svpbmp.hxx"
43 using namespace basegfx;
44 using namespace basebmp;
46 class SvpGlyphPeer
47 : public GlyphCachePeer
49 public:
50 SvpGlyphPeer() {}
52 BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, int nGlyphIndex,
53 basebmp::Format nBmpFormat, B2IPoint& rTargetPos );
55 protected:
56 virtual void RemovingFont( ServerFont& );
57 virtual void RemovingGlyph( GlyphData& );
59 class SvpGcpHelper
61 public:
62 RawBitmap maRawBitmap;
63 BitmapDeviceSharedPtr maBitmapDev;
67 class SvpGlyphCache : public GlyphCache
69 public:
70 SvpGlyphCache( SvpGlyphPeer& rPeer ) : GlyphCache( rPeer) {}
71 SvpGlyphPeer& GetPeer() { return reinterpret_cast<SvpGlyphPeer&>( mrPeer ); }
72 static SvpGlyphCache& GetInstance();
75 namespace
77 struct GlyphCacheHolder
79 private:
80 SvpGlyphPeer* m_pSvpGlyphPeer;
81 SvpGlyphCache* m_pSvpGlyphCache;
82 public:
83 GlyphCacheHolder()
85 m_pSvpGlyphPeer = new SvpGlyphPeer();
86 m_pSvpGlyphCache = new SvpGlyphCache( *m_pSvpGlyphPeer );
88 void release()
90 delete m_pSvpGlyphCache;
91 delete m_pSvpGlyphPeer;
92 m_pSvpGlyphCache = NULL;
93 m_pSvpGlyphPeer = NULL;
95 SvpGlyphCache& getGlyphCache()
97 return *m_pSvpGlyphCache;
99 ~GlyphCacheHolder()
101 release();
105 struct theGlyphCacheHolder :
106 public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder>
110 SvpGlyphCache& SvpGlyphCache::GetInstance()
112 return theGlyphCacheHolder::get().getGlyphCache();
116 BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
117 int nGlyphIndex, basebmp::Format nBmpFormat, B2IPoint& rTargetPos )
119 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
121 if( rGlyphData.ExtDataRef().meInfo != nBmpFormat )
123 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
124 rGlyphData.ExtDataRef().mpData);
125 bool bNew = pGcpHelper == 0;
126 if( bNew )
127 pGcpHelper = new SvpGcpHelper;
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 if( bNew )
151 delete pGcpHelper;
152 return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
155 // construct alpha mask from raw bitmap
156 const B2IVector aSize(
157 pGcpHelper->maRawBitmap.mnScanlineSize,
158 pGcpHelper->maRawBitmap.mnHeight );
159 if( aSize.getX() && aSize.getY() )
161 static PaletteMemorySharedVector aDummyPAL;
162 pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, pGcpHelper->maRawBitmap.mpBits, aDummyPAL );
165 rGlyphData.ExtDataRef().meInfo = nBmpFormat;
166 rGlyphData.ExtDataRef().mpData = pGcpHelper;
169 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
170 rGlyphData.ExtDataRef().mpData);
171 assert(pGcpHelper != 0);
172 rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
173 return pGcpHelper->maBitmapDev;
177 void SvpGlyphPeer::RemovingFont( ServerFont& )
179 // nothing to do: no font resources held in SvpGlyphPeer
183 void SvpGlyphPeer::RemovingGlyph( GlyphData& rGlyphData )
185 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
186 rGlyphData.ExtDataRef().mpData);
187 rGlyphData.ExtDataRef().meInfo = basebmp::FORMAT_NONE;
188 rGlyphData.ExtDataRef().mpData = 0;
189 delete pGcpHelper;
192 sal_uInt16 SvpSalGraphics::SetFont( FontSelectPattern* pIFSD, int nFallbackLevel )
194 // release all no longer needed font resources
195 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
197 if( m_pServerFont[i] != NULL )
199 // old server side font is no longer referenced
200 SvpGlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] );
201 m_pServerFont[i] = NULL;
205 // return early if there is no new font
206 if( !pIFSD )
207 return 0;
209 // handle the request for a non-native X11-font => use the GlyphCache
210 ServerFont* pServerFont = SvpGlyphCache::GetInstance().CacheFont( *pIFSD );
211 if( !pServerFont )
212 return SAL_SETFONT_BADFONT;
214 // check selected font
215 if( !pServerFont->TestFont() )
217 SvpGlyphCache::GetInstance().UncacheFont( *pServerFont );
218 return SAL_SETFONT_BADFONT;
221 // update SalGraphics font settings
222 m_pServerFont[ nFallbackLevel ] = pServerFont;
223 return SAL_SETFONT_USEDRAWTEXTARRAY;
227 void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel )
229 if( nFallbackLevel >= MAX_FALLBACK )
230 return;
232 if( m_pServerFont[nFallbackLevel] != NULL )
234 long rDummyFactor;
235 m_pServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
240 const ImplFontCharMap* SvpSalGraphics::GetImplFontCharMap() const
242 if( !m_pServerFont[0] )
243 return NULL;
245 const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
246 return pIFCMap;
249 bool SvpSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
251 if (!m_pServerFont[0])
252 return false;
254 return m_pServerFont[0]->GetFontCapabilities(rFontCapabilities);
258 void SvpSalGraphics::GetDevFontList( ImplDevFontList* pDevFontList )
260 GlyphCache& rGC = SvpGlyphCache::GetInstance();
262 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
263 psp::FastPrintFontInfo aInfo;
264 ::std::list< psp::fontID > aList;
265 rMgr.getFontList( aList );
266 ::std::list< psp::fontID >::iterator it;
267 for( it = aList.begin(); it != aList.end(); ++it )
269 if( !rMgr.getFontFastInfo( *it, aInfo ) )
270 continue;
272 // the GlyphCache must not bother with builtin fonts because
273 // it cannot access or use them anyway
274 if( aInfo.m_eType == psp::fonttype::Builtin )
275 continue;
277 // normalize face number to the GlyphCache
278 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
280 // inform GlyphCache about this font provided by the PsPrint subsystem
281 ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
282 aDFA.mnQuality += 4096;
283 const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
284 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
287 // announce glyphcache fonts
288 rGC.AnnounceFonts( pDevFontList );
290 // register platform specific font substitutions if available
291 SalGenericInstance::RegisterFontSubstitutors( pDevFontList );
293 ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
296 void SvpSalGraphics::ClearDevFontCache()
298 GlyphCache& rGC = SvpGlyphCache::GetInstance();
299 rGC.ClearFontCache();
303 void SvpSalGraphics::GetDevFontSubstList( OutputDevice* )
307 bool SvpSalGraphics::AddTempDevFont( ImplDevFontList*,
308 const OUString&, const OUString& )
310 return false;
314 sal_Bool SvpSalGraphics::CreateFontSubset(
315 const OUString& rToFile,
316 const PhysicalFontFace* pFont,
317 sal_Int32* pGlyphIDs,
318 sal_uInt8* pEncoding,
319 sal_Int32* pWidths,
320 int nGlyphCount,
321 FontSubsetInfo& rInfo
324 // in this context the pFont->GetFontId() is a valid PSP
325 // font since they are the only ones left after the PDF
326 // export has filtered its list of subsettable fonts (for
327 // which this method was created). The correct way would
328 // be to have the GlyphCache search for the PhysicalFontFace pFont
329 psp::fontID aFont = pFont->GetFontId();
331 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
332 bool bSuccess = rMgr.createFontSubset( rInfo,
333 aFont,
334 rToFile,
335 pGlyphIDs,
336 pEncoding,
337 pWidths,
338 nGlyphCount );
339 return bSuccess;
343 const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded )
345 // in this context the pFont->GetFontId() is a valid PSP
346 // font since they are the only ones left after the PDF
347 // export has filtered its list of subsettable fonts (for
348 // which this method was created). The correct way would
349 // be to have the GlyphCache search for the PhysicalFontFace pFont
350 psp::fontID aFont = pFont->GetFontId();
351 return GenPspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
355 const void* SvpSalGraphics::GetEmbedFontData(
356 const PhysicalFontFace* pFont,
357 const sal_Ucs* pUnicodes,
358 sal_Int32* pWidths,
359 FontSubsetInfo& rInfo,
360 long* pDataLen
363 // in this context the pFont->GetFontId() is a valid PSP
364 // font since they are the only ones left after the PDF
365 // export has filtered its list of subsettable fonts (for
366 // which this method was created). The correct way would
367 // be to have the GlyphCache search for the PhysicalFontFace pFont
368 psp::fontID aFont = pFont->GetFontId();
369 return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
373 void SvpSalGraphics::FreeEmbedFontData( const void* pData, long nLen )
375 GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
378 void SvpSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFont,
379 bool bVertical,
380 Int32Vector& rWidths,
381 Ucs2UIntMap& rUnicodeEnc )
383 // in this context the pFont->GetFontId() is a valid PSP
384 // font since they are the only ones left after the PDF
385 // export has filtered its list of subsettable fonts (for
386 // which this method was created). The correct way would
387 // be to have the GlyphCache search for the PhysicalFontFace pFont
388 psp::fontID aFont = pFont->GetFontId();
389 GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
393 sal_Bool SvpSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphIndex, Rectangle& rRect )
395 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
396 if( nLevel >= MAX_FALLBACK )
397 return sal_False;
399 ServerFont* pSF = m_pServerFont[ nLevel ];
400 if( !pSF )
401 return sal_False;
403 nGlyphIndex &= GF_IDXMASK;
404 const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
405 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
406 return sal_True;
410 sal_Bool SvpSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphIndex, B2DPolyPolygon& rPolyPoly )
412 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
413 if( nLevel >= MAX_FALLBACK )
414 return sal_False;
416 const ServerFont* pSF = m_pServerFont[ nLevel ];
417 if( !pSF )
418 return sal_False;
420 nGlyphIndex &= GF_IDXMASK;
421 if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
422 return sal_True;
424 return sal_False;
428 SalLayout* SvpSalGraphics::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
430 GenericSalLayout* pLayout = NULL;
432 if( m_pServerFont[ nFallbackLevel ] )
433 pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] );
435 return pLayout;
439 void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
441 // iterate over all glyphs in the layout
442 Point aPos;
443 sal_GlyphId nGlyphIndex;
444 SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer();
445 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart ); )
447 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
448 DBG_ASSERT( nLevel < MAX_FALLBACK, "SvpGDI: invalid glyph fallback level" );
449 ServerFont* pSF = m_pServerFont[ nLevel ];
450 if( !pSF )
451 continue;
453 // get the glyph's alpha mask and adjust the drawing position
454 nGlyphIndex &= GF_IDXMASK;
455 B2IPoint aDstPoint( aPos.X(), aPos.Y() );
456 BitmapDeviceSharedPtr aAlphaMask
457 = rGlyphPeer.GetGlyphBmp( *pSF, nGlyphIndex, m_eTextFmt, aDstPoint );
458 if( !aAlphaMask ) // ignore empty glyphs
459 continue;
461 // blend text color into target using the glyph's mask
462 const B2IBox aSrcRect( B2ITuple(0,0), aAlphaMask->getSize() );
463 const B2IBox aClipRect( aDstPoint, aAlphaMask->getSize() );
465 SvpSalGraphics::ClipUndoHandle aUndo( this );
466 if( !isClippedSetup( aClipRect, aUndo ) )
467 m_aDevice->drawMaskedColor( m_aTextColor, aAlphaMask,
468 aSrcRect, aDstPoint, m_aClipMap );
472 void SvpSalGraphics::SetTextColor( SalColor nSalColor )
474 m_aTextColor = basebmp::Color( nSalColor );
477 SystemFontData SvpSalGraphics::GetSysFontData( int nFallbacklevel ) const
479 SystemFontData aSysFontData;
481 if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
482 if (nFallbacklevel < 0 ) nFallbacklevel = 0;
484 aSysFontData.nSize = sizeof( SystemFontData );
485 aSysFontData.nFontId = 0;
486 aSysFontData.nFontFlags = 0;
487 aSysFontData.bFakeBold = false;
488 aSysFontData.bFakeItalic = false;
489 aSysFontData.bAntialias = true;
490 return aSysFontData;
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */