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/config.h"
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
;
47 : public GlyphCachePeer
52 BitmapDeviceSharedPtr
GetGlyphBmp( ServerFont
&, int nGlyphIndex
,
53 basebmp::Format nBmpFormat
, B2IPoint
& rTargetPos
);
56 virtual void RemovingFont( ServerFont
& );
57 virtual void RemovingGlyph( GlyphData
& );
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
);
90 delete m_pSvpGlyphCache
;
91 delete m_pSvpGlyphPeer
;
92 m_pSvpGlyphCache
= NULL
;
93 m_pSvpGlyphPeer
= NULL
;
95 SvpGlyphCache
& getGlyphCache()
97 return *m_pSvpGlyphCache
;
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;
127 pGcpHelper
= new SvpGcpHelper
;
129 // get glyph bitmap in matching format
133 case FORMAT_ONE_BIT_LSB_GREY
:
134 bFound
= rServerFont
.GetGlyphBitmap1( nGlyphIndex
, pGcpHelper
->maRawBitmap
);
136 case FORMAT_EIGHT_BIT_GREY
:
137 bFound
= rServerFont
.GetGlyphBitmap8( nGlyphIndex
, pGcpHelper
->maRawBitmap
);
140 OSL_FAIL( "SVP GCP::GetGlyphBmp(): illegal scanline format");
141 // fall back to black&white mask
142 nBmpFormat
= FORMAT_ONE_BIT_LSB_GREY
;
147 // return .notdef glyph if needed
148 if( !bFound
&& (nGlyphIndex
!= 0) )
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;
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
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
;
227 void SvpSalGraphics::GetFontMetric( ImplFontMetricData
* pMetric
, int nFallbackLevel
)
229 if( nFallbackLevel
>= MAX_FALLBACK
)
232 if( m_pServerFont
[nFallbackLevel
] != NULL
)
235 m_pServerFont
[nFallbackLevel
]->FetchFontMetric( *pMetric
, rDummyFactor
);
240 const ImplFontCharMap
* SvpSalGraphics::GetImplFontCharMap() const
242 if( !m_pServerFont
[0] )
245 const ImplFontCharMap
* pIFCMap
= m_pServerFont
[0]->GetImplFontCharMap();
249 bool SvpSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
251 if (!m_pServerFont
[0])
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
) )
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
)
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
& )
314 sal_Bool
SvpSalGraphics::CreateFontSubset(
315 const OUString
& rToFile
,
316 const PhysicalFontFace
* pFont
,
317 sal_Int32
* pGlyphIDs
,
318 sal_uInt8
* pEncoding
,
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
,
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
,
359 FontSubsetInfo
& rInfo
,
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
,
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
)
399 ServerFont
* pSF
= m_pServerFont
[ nLevel
];
403 nGlyphIndex
&= GF_IDXMASK
;
404 const GlyphMetric
& rGM
= pSF
->GetGlyphMetric( nGlyphIndex
);
405 rRect
= Rectangle( rGM
.GetOffset(), rGM
.GetSize() );
410 sal_Bool
SvpSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphIndex
, B2DPolyPolygon
& rPolyPoly
)
412 int nLevel
= nGlyphIndex
>> GF_FONTSHIFT
;
413 if( nLevel
>= MAX_FALLBACK
)
416 const ServerFont
* pSF
= m_pServerFont
[ nLevel
];
420 nGlyphIndex
&= GF_IDXMASK
;
421 if( pSF
->GetGlyphOutline( nGlyphIndex
, rPolyPoly
) )
428 SalLayout
* SvpSalGraphics::GetTextLayout( ImplLayoutArgs
&, int nFallbackLevel
)
430 GenericSalLayout
* pLayout
= NULL
;
432 if( m_pServerFont
[ nFallbackLevel
] )
433 pLayout
= new ServerFontLayout( *m_pServerFont
[ nFallbackLevel
] );
439 void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout
& rSalLayout
)
441 // iterate over all glyphs in the layout
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
];
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
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;
493 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */