Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / headless / svptextrender.cxx
blobf143da1651d68b43914538eb0110be8d40cccb78
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/types.h>
22 #include <cassert>
24 #include <basebmp/scanlineformats.hxx>
25 #include <basegfx/polygon/b2dpolypolygon.hxx>
26 #include <basegfx/range/b2drange.hxx>
27 #include <basegfx/range/b2ibox.hxx>
28 #include <rtl/instance.hxx>
29 #include <tools/debug.hxx>
30 #include <vcl/sysdata.hxx>
32 #include "generic/geninst.h"
33 #include "generic/genpspgraphics.h"
34 #include "generic/glyphcache.hxx"
35 #include "headless/svpbmp.hxx"
36 #include "headless/svpgdi.hxx"
37 #include "headless/svptextrender.hxx"
38 #include "impfont.hxx"
39 #include "outfont.hxx"
40 #include "PhysicalFontFace.hxx"
42 class PhysicalFontCollection;
44 using namespace basegfx;
45 using namespace basebmp;
47 class SvpGlyphPeer : public GlyphCachePeer
49 public:
50 SvpGlyphPeer() {}
52 BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, sal_GlyphId,
53 basebmp::Format nBmpFormat, B2IPoint& rTargetPos );
55 protected:
56 virtual void RemovingFont( ServerFont& ) SAL_OVERRIDE;
57 virtual void RemovingGlyph( GlyphData& ) SAL_OVERRIDE;
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 SvpGlyphCache& getGlyphCache()
90 return *m_pSvpGlyphCache;
92 ~GlyphCacheHolder()
94 delete m_pSvpGlyphCache;
95 delete m_pSvpGlyphPeer;
99 struct theGlyphCacheHolder :
100 public rtl::Static<GlyphCacheHolder, theGlyphCacheHolder>
104 SvpGlyphCache& SvpGlyphCache::GetInstance()
106 return theGlyphCacheHolder::get().getGlyphCache();
109 BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
110 sal_GlyphId aGlyphId, basebmp::Format nBmpFormat, B2IPoint& rTargetPos )
112 GlyphData& rGlyphData = rServerFont.GetGlyphData( aGlyphId );
114 if( rGlyphData.ExtDataRef().meInfo != nBmpFormat )
116 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
117 rGlyphData.ExtDataRef().mpData);
118 bool bNew = pGcpHelper == 0;
119 if( bNew )
120 pGcpHelper = new SvpGcpHelper;
122 // get glyph bitmap in matching format
123 bool bFound = false;
124 switch( nBmpFormat )
126 case FORMAT_ONE_BIT_LSB_GREY:
127 bFound = rServerFont.GetGlyphBitmap1( aGlyphId, pGcpHelper->maRawBitmap );
128 break;
129 case FORMAT_EIGHT_BIT_GREY:
130 bFound = rServerFont.GetGlyphBitmap8( aGlyphId, pGcpHelper->maRawBitmap );
131 break;
132 default:
133 OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format");
134 // fall back to black&white mask
135 nBmpFormat = FORMAT_ONE_BIT_LSB_GREY;
136 bFound = false;
137 break;
140 // return .notdef glyph if needed
141 if( !bFound && (aGlyphId != 0) )
143 if( bNew )
144 delete pGcpHelper;
145 return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
148 // construct alpha mask from raw bitmap
149 if (pGcpHelper->maRawBitmap.mnScanlineSize && pGcpHelper->maRawBitmap.mnHeight)
151 const B2IVector aSize(
152 pGcpHelper->maRawBitmap.mnScanlineSize,
153 pGcpHelper->maRawBitmap.mnHeight );
154 static PaletteMemorySharedVector aDummyPAL;
155 pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aSize.getX(), pGcpHelper->maRawBitmap.mpBits, aDummyPAL );
158 rGlyphData.ExtDataRef().meInfo = nBmpFormat;
159 rGlyphData.ExtDataRef().mpData = pGcpHelper;
162 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
163 rGlyphData.ExtDataRef().mpData);
164 assert(pGcpHelper != 0);
165 rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
166 return pGcpHelper->maBitmapDev;
169 void SvpGlyphPeer::RemovingFont( ServerFont& )
171 // nothing to do: no font resources held in SvpGlyphPeer
174 void SvpGlyphPeer::RemovingGlyph( GlyphData& rGlyphData )
176 SvpGcpHelper* pGcpHelper = static_cast<SvpGcpHelper*>(
177 rGlyphData.ExtDataRef().mpData);
178 rGlyphData.ExtDataRef().meInfo = basebmp::FORMAT_NONE;
179 rGlyphData.ExtDataRef().mpData = 0;
180 delete pGcpHelper;
183 SvpTextRender::SvpTextRender(SvpSalGraphics& rParent)
184 : m_rParent(rParent)
185 , m_aTextColor(COL_BLACK)
186 , m_eTextFmt(basebmp::FORMAT_EIGHT_BIT_GREY)
188 for( int i = 0; i < MAX_FALLBACK; ++i )
189 m_pServerFont[i] = NULL;
192 sal_uInt16 SvpTextRender::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;
226 void SvpTextRender::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel )
228 if( nFallbackLevel >= MAX_FALLBACK )
229 return;
231 if( m_pServerFont[nFallbackLevel] != NULL )
233 long rDummyFactor;
234 m_pServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
238 const FontCharMapPtr SvpTextRender::GetFontCharMap() const
240 if( !m_pServerFont[0] )
241 return NULL;
243 const FontCharMapPtr pFCMap = m_pServerFont[0]->GetFontCharMap();
244 return pFCMap;
247 bool SvpTextRender::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
249 if (!m_pServerFont[0])
250 return false;
252 return m_pServerFont[0]->GetFontCapabilities(rFontCapabilities);
255 void SvpTextRender::GetDevFontList( PhysicalFontCollection* pFontCollection )
257 GlyphCache& rGC = SvpGlyphCache::GetInstance();
259 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
260 psp::FastPrintFontInfo aInfo;
261 ::std::list< psp::fontID > aList;
262 rMgr.getFontList( aList );
263 ::std::list< psp::fontID >::iterator it;
264 for( it = aList.begin(); it != aList.end(); ++it )
266 if( !rMgr.getFontFastInfo( *it, aInfo ) )
267 continue;
269 // normalize face number to the GlyphCache
270 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
272 // inform GlyphCache about this font provided by the PsPrint subsystem
273 ImplDevFontAttributes aDFA = GenPspGraphics::Info2DevFontAttributes( aInfo );
274 aDFA.mnQuality += 4096;
275 const OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
276 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
279 // announce glyphcache fonts
280 rGC.AnnounceFonts( pFontCollection );
282 // register platform specific font substitutions if available
283 SalGenericInstance::RegisterFontSubstitutors( pFontCollection );
285 ImplGetSVData()->maGDIData.mbNativeFontConfig = true;
288 void SvpTextRender::ClearDevFontCache()
290 GlyphCache& rGC = SvpGlyphCache::GetInstance();
291 rGC.ClearFontCache();
294 bool SvpTextRender::AddTempDevFont( PhysicalFontCollection*,
295 const OUString&, const OUString& )
297 return false;
300 bool SvpTextRender::CreateFontSubset(
301 const OUString& rToFile,
302 const PhysicalFontFace* pFont,
303 const sal_GlyphId* pGlyphIds,
304 const sal_uInt8* pEncoding,
305 sal_Int32* pWidths,
306 int nGlyphCount,
307 FontSubsetInfo& rInfo
310 // in this context the pFont->GetFontId() is a valid PSP
311 // font since they are the only ones left after the PDF
312 // export has filtered its list of subsettable fonts (for
313 // which this method was created). The correct way would
314 // be to have the GlyphCache search for the PhysicalFontFace pFont
315 psp::fontID aFont = pFont->GetFontId();
317 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
318 bool bSuccess = rMgr.createFontSubset( rInfo,
319 aFont,
320 rToFile,
321 pGlyphIds,
322 pEncoding,
323 pWidths,
324 nGlyphCount );
325 return bSuccess;
328 const Ucs2SIntMap* SvpTextRender::GetFontEncodingVector( const PhysicalFontFace* pFont, const Ucs2OStrMap** pNonEncoded, std::set<sal_Unicode> const** ppPriority)
330 // in this context the pFont->GetFontId() is a valid PSP
331 // font since they are the only ones left after the PDF
332 // export has filtered its list of subsettable fonts (for
333 // which this method was created). The correct way would
334 // be to have the GlyphCache search for the PhysicalFontFace pFont
335 psp::fontID aFont = pFont->GetFontId();
336 return GenPspGraphics::DoGetFontEncodingVector(aFont, pNonEncoded, ppPriority);
339 const void* SvpTextRender::GetEmbedFontData(
340 const PhysicalFontFace* pFont,
341 const sal_Ucs* pUnicodes,
342 sal_Int32* pWidths,
343 size_t nLen,
344 FontSubsetInfo& rInfo,
345 long* pDataLen
348 // in this context the pFont->GetFontId() is a valid PSP
349 // font since they are the only ones left after the PDF
350 // export has filtered its list of subsettable fonts (for
351 // which this method was created). The correct way would
352 // be to have the GlyphCache search for the PhysicalFontFace pFont
353 psp::fontID aFont = pFont->GetFontId();
354 return GenPspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, nLen, rInfo, pDataLen );
357 void SvpTextRender::FreeEmbedFontData( const void* pData, long nLen )
359 GenPspGraphics::DoFreeEmbedFontData( pData, nLen );
362 void SvpTextRender::GetGlyphWidths( const PhysicalFontFace* pFont,
363 bool bVertical,
364 Int32Vector& rWidths,
365 Ucs2UIntMap& rUnicodeEnc )
367 // in this context the pFont->GetFontId() is a valid PSP
368 // font since they are the only ones left after the PDF
369 // export has filtered its list of subsettable fonts (for
370 // which this method was created). The correct way would
371 // be to have the GlyphCache search for the PhysicalFontFace pFont
372 psp::fontID aFont = pFont->GetFontId();
373 GenPspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
376 bool SvpTextRender::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
378 const int nLevel = aGlyphId >> GF_FONTSHIFT;
379 if( nLevel >= MAX_FALLBACK )
380 return false;
382 ServerFont* pSF = m_pServerFont[ nLevel ];
383 if( !pSF )
384 return false;
386 aGlyphId &= GF_IDXMASK;
387 const GlyphMetric& rGM = pSF->GetGlyphMetric( aGlyphId );
388 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
389 return true;
392 bool SvpTextRender::GetGlyphOutline( sal_GlyphId aGlyphId, B2DPolyPolygon& rPolyPoly )
394 const int nLevel = aGlyphId >> GF_FONTSHIFT;
395 if( nLevel >= MAX_FALLBACK )
396 return false;
398 const ServerFont* pSF = m_pServerFont[ nLevel ];
399 if( !pSF )
400 return false;
402 aGlyphId &= GF_IDXMASK;
403 if( pSF->GetGlyphOutline( aGlyphId, rPolyPoly ) )
404 return true;
406 return false;
409 SalLayout* SvpTextRender::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
411 GenericSalLayout* pLayout = NULL;
413 if( m_pServerFont[ nFallbackLevel ] )
414 pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] );
416 return pLayout;
419 void SvpTextRender::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
421 // iterate over all glyphs in the layout
422 Point aPos;
423 sal_GlyphId aGlyphId;
424 SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer();
425 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
427 ServerFont& rFont = rSalLayout.GetServerFont();
428 // get the glyph's alpha mask and adjust the drawing position
429 aGlyphId &= GF_IDXMASK;
430 B2IPoint aDstPoint( aPos.X(), aPos.Y() );
431 BitmapDeviceSharedPtr aAlphaMask
432 = rGlyphPeer.GetGlyphBmp(rFont, aGlyphId, m_eTextFmt, aDstPoint);
433 if( !aAlphaMask ) // ignore empty glyphs
434 continue;
436 // blend text color into target using the glyph's mask
437 m_rParent.BlendTextColor(m_aTextColor, aAlphaMask, aDstPoint);
441 void SvpTextRender::SetTextColor( SalColor nSalColor )
443 m_aTextColor = basebmp::Color( nSalColor );
446 SystemFontData SvpTextRender::GetSysFontData( int nFallbackLevel ) const
448 SystemFontData aSysFontData;
450 if (nFallbackLevel >= MAX_FALLBACK) nFallbackLevel = MAX_FALLBACK - 1;
451 if (nFallbackLevel < 0 ) nFallbackLevel = 0;
453 if (m_pServerFont[nFallbackLevel] != NULL)
455 ServerFont* rFont = m_pServerFont[nFallbackLevel];
456 aSysFontData.nFontId = rFont->GetFtFace();
457 aSysFontData.nFontFlags = rFont->GetLoadFlags();
458 aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
459 aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
460 aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
461 aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
464 return aSysFontData;
467 void SvpTextRender::setDevice( basebmp::BitmapDeviceSharedPtr& rDevice )
469 // determine matching bitmap format for masks
470 basebmp::Format nDeviceFmt = rDevice ? rDevice->getScanlineFormat() : basebmp::FORMAT_EIGHT_BIT_GREY;
471 switch( nDeviceFmt )
473 case basebmp::FORMAT_EIGHT_BIT_GREY:
474 case basebmp::FORMAT_SIXTEEN_BIT_LSB_TC_MASK:
475 case basebmp::FORMAT_SIXTEEN_BIT_MSB_TC_MASK:
476 case basebmp::FORMAT_TWENTYFOUR_BIT_TC_MASK:
477 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRX:
478 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA:
479 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ARGB:
480 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_ABGR:
481 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA:
482 m_eTextFmt = basebmp::FORMAT_EIGHT_BIT_GREY;
483 break;
484 default:
485 m_eTextFmt = basebmp::FORMAT_ONE_BIT_LSB_GREY;
486 break;
490 GlyphCache& SvpSalGraphics::getPlatformGlyphCache()
492 return SvpGlyphCache::GetInstance();
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */