1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
52 BitmapDeviceSharedPtr
GetGlyphBmp( ServerFont
&, sal_GlyphId
,
53 basebmp::Format nBmpFormat
, B2IPoint
& rTargetPos
);
56 virtual void RemovingFont( ServerFont
& ) SAL_OVERRIDE
;
57 virtual void RemovingGlyph( GlyphData
& ) SAL_OVERRIDE
;
62 RawBitmap maRawBitmap
;
63 BitmapDeviceSharedPtr maBitmapDev
;
67 class SvpGlyphCache
: public GlyphCache
70 SvpGlyphCache( SvpGlyphPeer
& rPeer
) : GlyphCache( rPeer
) {}
71 SvpGlyphPeer
& GetPeer() { return reinterpret_cast<SvpGlyphPeer
&>( mrPeer
); }
72 static SvpGlyphCache
& GetInstance();
77 struct GlyphCacheHolder
80 SvpGlyphPeer
* m_pSvpGlyphPeer
;
81 SvpGlyphCache
* m_pSvpGlyphCache
;
85 m_pSvpGlyphPeer
= new SvpGlyphPeer();
86 m_pSvpGlyphCache
= new SvpGlyphCache( *m_pSvpGlyphPeer
);
88 SvpGlyphCache
& getGlyphCache()
90 return *m_pSvpGlyphCache
;
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;
120 pGcpHelper
= new SvpGcpHelper
;
122 // get glyph bitmap in matching format
126 case FORMAT_ONE_BIT_LSB_GREY
:
127 bFound
= rServerFont
.GetGlyphBitmap1( aGlyphId
, pGcpHelper
->maRawBitmap
);
129 case FORMAT_EIGHT_BIT_GREY
:
130 bFound
= rServerFont
.GetGlyphBitmap8( aGlyphId
, pGcpHelper
->maRawBitmap
);
133 OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format");
134 // fall back to black&white mask
135 nBmpFormat
= FORMAT_ONE_BIT_LSB_GREY
;
140 // return .notdef glyph if needed
141 if( !bFound
&& (aGlyphId
!= 0) )
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;
183 SvpTextRender::SvpTextRender(SvpSalGraphics
& 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
209 // handle the request for a non-native X11-font => use the GlyphCache
210 ServerFont
* pServerFont
= SvpGlyphCache::GetInstance().CacheFont( *pIFSD
);
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
)
231 if( m_pServerFont
[nFallbackLevel
] != NULL
)
234 m_pServerFont
[nFallbackLevel
]->FetchFontMetric( *pMetric
, rDummyFactor
);
238 const FontCharMapPtr
SvpTextRender::GetFontCharMap() const
240 if( !m_pServerFont
[0] )
243 const FontCharMapPtr pFCMap
= m_pServerFont
[0]->GetFontCharMap();
247 bool SvpTextRender::GetFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
249 if (!m_pServerFont
[0])
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
) )
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
& )
300 bool SvpTextRender::CreateFontSubset(
301 const OUString
& rToFile
,
302 const PhysicalFontFace
* pFont
,
303 const sal_GlyphId
* pGlyphIds
,
304 const sal_uInt8
* pEncoding
,
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
,
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
,
344 FontSubsetInfo
& rInfo
,
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
,
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
)
382 ServerFont
* pSF
= m_pServerFont
[ nLevel
];
386 aGlyphId
&= GF_IDXMASK
;
387 const GlyphMetric
& rGM
= pSF
->GetGlyphMetric( aGlyphId
);
388 rRect
= Rectangle( rGM
.GetOffset(), rGM
.GetSize() );
392 bool SvpTextRender::GetGlyphOutline( sal_GlyphId aGlyphId
, B2DPolyPolygon
& rPolyPoly
)
394 const int nLevel
= aGlyphId
>> GF_FONTSHIFT
;
395 if( nLevel
>= MAX_FALLBACK
)
398 const ServerFont
* pSF
= m_pServerFont
[ nLevel
];
402 aGlyphId
&= GF_IDXMASK
;
403 if( pSF
->GetGlyphOutline( aGlyphId
, rPolyPoly
) )
409 SalLayout
* SvpTextRender::GetTextLayout( ImplLayoutArgs
&, int nFallbackLevel
)
411 GenericSalLayout
* pLayout
= NULL
;
413 if( m_pServerFont
[ nFallbackLevel
] )
414 pLayout
= new ServerFontLayout( *m_pServerFont
[ nFallbackLevel
] );
419 void SvpTextRender::DrawServerFontLayout( const ServerFontLayout
& rSalLayout
)
421 // iterate over all glyphs in the layout
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
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
;
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
;
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
;
485 m_eTextFmt
= basebmp::FORMAT_ONE_BIT_LSB_GREY
;
490 GlyphCache
& SvpSalGraphics::getPlatformGlyphCache()
492 return SvpGlyphCache::GetInstance();
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */