merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / headless / svptext.cxx
blob6119b202a614963aa795c9341dc74a2d406e7137
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #include "svpgdi.hxx"
29 #include "svpbmp.hxx"
31 #include <basegfx/range/b2drange.hxx>
32 #include <basegfx/range/b2irange.hxx>
33 #include <basegfx/polygon/b2dpolypolygon.hxx>
34 #include <basebmp/scanlineformats.hxx>
36 #include <tools/debug.hxx>
38 #if OSL_DEBUG_LEVEL > 2
39 #include <basebmp/debug.hxx>
40 #endif
42 #include <vcl/outfont.hxx>
43 #include <vcl/glyphcache.hxx>
44 #include <vcl/impfont.hxx>
46 #include "svppspgraphics.hxx"
48 using namespace basegfx;
49 using namespace basebmp;
51 // ===========================================================================
53 class SvpGlyphPeer
54 : public GlyphCachePeer
56 public:
57 SvpGlyphPeer() {}
59 BitmapDeviceSharedPtr GetGlyphBmp( ServerFont&, int nGlyphIndex,
60 sal_uInt32 nBmpFormat, B2IPoint& rTargetPos );
62 protected:
63 virtual void RemovingFont( ServerFont& );
64 virtual void RemovingGlyph( ServerFont&, GlyphData&, int nGlyphIndex );
66 class SvpGcpHelper
68 public:
69 RawBitmap maRawBitmap;
70 BitmapDeviceSharedPtr maBitmapDev;
74 // ===========================================================================
76 class SvpGlyphCache : public GlyphCache
78 public:
79 SvpGlyphPeer& GetPeer() { return reinterpret_cast<SvpGlyphPeer&>( mrPeer ); }
80 static SvpGlyphCache& GetInstance();
81 private:
82 SvpGlyphCache( SvpGlyphPeer& rPeer ) : GlyphCache( rPeer) {}
85 //--------------------------------------------------------------------------
87 SvpGlyphCache& SvpGlyphCache::GetInstance()
89 static SvpGlyphPeer aSvpGlyphPeer;
90 static SvpGlyphCache aGC( aSvpGlyphPeer );
91 return aGC;
94 // ===========================================================================
96 BitmapDeviceSharedPtr SvpGlyphPeer::GetGlyphBmp( ServerFont& rServerFont,
97 int nGlyphIndex, sal_uInt32 nBmpFormat, B2IPoint& rTargetPos )
99 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
100 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
102 // nothing to do if the GlyphPeer hasn't allocated resources for the glyph
103 if( rGlyphData.ExtDataRef().meInfo != sal::static_int_cast<int>(nBmpFormat) )
105 if( rGlyphData.ExtDataRef().meInfo == Format::NONE )
106 pGcpHelper = new SvpGcpHelper;
107 RawBitmap& rRawBitmap = pGcpHelper->maRawBitmap;
109 // get glyph bitmap in matching format
110 bool bFound = false;
111 switch( nBmpFormat )
113 case Format::ONE_BIT_LSB_GREY:
114 bFound = rServerFont.GetGlyphBitmap1( nGlyphIndex, pGcpHelper->maRawBitmap );
115 break;
116 case Format::EIGHT_BIT_GREY:
117 bFound = rServerFont.GetGlyphBitmap8( nGlyphIndex, pGcpHelper->maRawBitmap );
118 break;
119 default:
120 DBG_ERROR( "SVP GCP::GetGlyphBmp(): illegal scanline format");
121 // fall back to black&white mask
122 nBmpFormat = Format::ONE_BIT_LSB_GREY;
123 bFound = false;
124 break;
127 // return .notdef glyph if needed
128 if( !bFound && (nGlyphIndex != 0) )
130 delete pGcpHelper;
131 return GetGlyphBmp( rServerFont, 0, nBmpFormat, rTargetPos );
134 // construct alpha mask from raw bitmap
135 const B2IVector aSize( rRawBitmap.mnScanlineSize, rRawBitmap.mnHeight );
136 if( aSize.getX() && aSize.getY() )
138 static PaletteMemorySharedVector aDummyPAL;
139 RawMemorySharedArray aRawPtr( rRawBitmap.mpBits );
140 pGcpHelper->maBitmapDev = createBitmapDevice( aSize, true, nBmpFormat, aRawPtr, aDummyPAL );
143 rServerFont.SetExtended( nBmpFormat, (void*)pGcpHelper );
146 rTargetPos += B2IPoint( pGcpHelper->maRawBitmap.mnXOffset, pGcpHelper->maRawBitmap.mnYOffset );
147 return pGcpHelper->maBitmapDev;
150 //--------------------------------------------------------------------------
152 void SvpGlyphPeer::RemovingFont( ServerFont& )
154 // nothing to do: no font resources held in SvpGlyphPeer
157 //--------------------------------------------------------------------------
159 void SvpGlyphPeer::RemovingGlyph( ServerFont&, GlyphData& rGlyphData, int /*nGlyphIndex*/ )
161 if( rGlyphData.ExtDataRef().mpData != Format::NONE )
163 // release the glyph related resources
164 DBG_ASSERT( (rGlyphData.ExtDataRef().meInfo <= Format::MAX), "SVP::RG() invalid alpha format" );
165 SvpGcpHelper* pGcpHelper = (SvpGcpHelper*)rGlyphData.ExtDataRef().mpData;
166 delete[] pGcpHelper->maRawBitmap.mpBits;
167 delete pGcpHelper;
171 // ===========================================================================
173 // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
174 class PspKernInfo : public ExtraKernInfo
176 public:
177 PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
178 protected:
179 virtual void Initialize() const;
182 //--------------------------------------------------------------------------
184 void PspKernInfo::Initialize() const
186 mbInitialized = true;
188 // get the kerning pairs from psprint
189 const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
190 typedef std::list< psp::KernPair > PspKernPairs;
191 const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
192 if( rKernPairs.empty() )
193 return;
195 // feed psprint's kerning list into a lookup-friendly container
196 maUnicodeKernPairs.resize( rKernPairs.size() );
197 PspKernPairs::const_iterator it = rKernPairs.begin();
198 for(; it != rKernPairs.end(); ++it )
200 ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
201 maUnicodeKernPairs.insert( aKernPair );
205 // ===========================================================================
207 USHORT SvpSalGraphics::SetFont( ImplFontSelectData* pIFSD, int nFallbackLevel )
209 // release all no longer needed font resources
210 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
212 if( m_pServerFont[i] != NULL )
214 // old server side font is no longer referenced
215 SvpGlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] );
216 m_pServerFont[i] = NULL;
220 // return early if there is no new font
221 if( !pIFSD )
222 return 0;
224 // handle the request for a non-native X11-font => use the GlyphCache
225 ServerFont* pServerFont = SvpGlyphCache::GetInstance().CacheFont( *pIFSD );
226 if( !pServerFont )
227 return SAL_SETFONT_BADFONT;
229 // check selected font
230 if( !pServerFont->TestFont() )
232 SvpGlyphCache::GetInstance().UncacheFont( *pServerFont );
233 return SAL_SETFONT_BADFONT;
236 // update SalGraphics font settings
237 m_pServerFont[ nFallbackLevel ] = pServerFont;
238 return SAL_SETFONT_USEDRAWTEXTARRAY;
241 // ---------------------------------------------------------------------------
243 void SvpSalGraphics::GetFontMetric( ImplFontMetricData* pMetric )
245 if( m_pServerFont[0] != NULL )
247 long rDummyFactor;
248 m_pServerFont[0]->FetchFontMetric( *pMetric, rDummyFactor );
252 // ---------------------------------------------------------------------------
254 ULONG SvpSalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData* pKernPairs )
256 ULONG nGotPairs = 0;
258 if( m_pServerFont[0] != NULL )
260 ImplKernPairData* pTmpKernPairs = NULL;
261 nGotPairs = m_pServerFont[0]->GetKernPairs( &pTmpKernPairs );
262 for( ULONG i = 0; i < nPairs && i < nGotPairs; ++i )
263 pKernPairs[ i ] = pTmpKernPairs[ i ];
264 delete[] pTmpKernPairs;
267 return nGotPairs;
270 // ---------------------------------------------------------------------------
272 ImplFontCharMap* SvpSalGraphics::GetImplFontCharMap() const
274 if( !m_pServerFont[0] )
275 return NULL;
277 CmapResult aCmapResult;
278 if( !m_pServerFont[0]->GetFontCodeRanges( aCmapResult ) )
279 return NULL;
280 return new ImplFontCharMap( aCmapResult );
283 // ---------------------------------------------------------------------------
285 void SvpSalGraphics::GetDevFontList( ImplDevFontList* pDevFontList )
287 GlyphCache& rGC = SvpGlyphCache::GetInstance();
289 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
290 psp::FastPrintFontInfo aInfo;
291 ::std::list< psp::fontID > aList;
292 rMgr.getFontList( aList );
293 ::std::list< psp::fontID >::iterator it;
294 for( it = aList.begin(); it != aList.end(); ++it )
296 if( !rMgr.getFontFastInfo( *it, aInfo ) )
297 continue;
299 // the GlyphCache must not bother with builtin fonts because
300 // it cannot access or use them anyway
301 if( aInfo.m_eType == psp::fonttype::Builtin )
302 continue;
304 // normalize face number to the GlyphCache
305 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
306 if( nFaceNum < 0 )
307 nFaceNum = 0;
309 // for fonts where extra kerning info can be provided on demand
310 // an ExtraKernInfo object is supplied
311 const ExtraKernInfo* pExtraKernInfo = NULL;
312 if( aInfo.m_eType == psp::fonttype::Type1 )
313 pExtraKernInfo = new PspKernInfo( *it );
315 // inform GlyphCache about this font provided by the PsPrint subsystem
316 ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo );
317 aDFA.mnQuality += 4096;
318 const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
319 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
322 // announce glyphcache fonts
323 rGC.AnnounceFonts( pDevFontList );
326 // ---------------------------------------------------------------------------
328 void SvpSalGraphics::GetDevFontSubstList( OutputDevice* )
331 // ---------------------------------------------------------------------------
333 bool SvpSalGraphics::AddTempDevFont( ImplDevFontList*,
334 const String&, const String& )
336 return false;
339 // ---------------------------------------------------------------------------
341 BOOL SvpSalGraphics::CreateFontSubset(
342 const rtl::OUString& rToFile,
343 const ImplFontData* pFont,
344 sal_Int32* pGlyphIDs,
345 sal_uInt8* pEncoding,
346 sal_Int32* pWidths,
347 int nGlyphCount,
348 FontSubsetInfo& rInfo
351 // in this context the pFont->GetFontId() is a valid PSP
352 // font since they are the only ones left after the PDF
353 // export has filtered its list of subsettable fonts (for
354 // which this method was created). The correct way would
355 // be to have the GlyphCache search for the ImplFontData pFont
356 psp::fontID aFont = pFont->GetFontId();
358 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
359 bool bSuccess = rMgr.createFontSubset( rInfo,
360 aFont,
361 rToFile,
362 pGlyphIDs,
363 pEncoding,
364 pWidths,
365 nGlyphCount );
366 return bSuccess;
369 // ---------------------------------------------------------------------------
371 const Ucs2SIntMap* SvpSalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
373 // in this context the pFont->GetFontId() is a valid PSP
374 // font since they are the only ones left after the PDF
375 // export has filtered its list of subsettable fonts (for
376 // which this method was created). The correct way would
377 // be to have the GlyphCache search for the ImplFontData pFont
378 psp::fontID aFont = pFont->GetFontId();
379 return PspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
382 // ---------------------------------------------------------------------------
384 const void* SvpSalGraphics::GetEmbedFontData(
385 const ImplFontData* pFont,
386 const sal_Ucs* pUnicodes,
387 sal_Int32* pWidths,
388 FontSubsetInfo& rInfo,
389 long* pDataLen
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 ImplFontData pFont
397 psp::fontID aFont = pFont->GetFontId();
398 return PspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
401 // ---------------------------------------------------------------------------
403 void SvpSalGraphics::FreeEmbedFontData( const void* pData, long nLen )
405 PspGraphics::DoFreeEmbedFontData( pData, nLen );
408 void SvpSalGraphics::GetGlyphWidths( const ImplFontData* pFont,
409 bool bVertical,
410 Int32Vector& rWidths,
411 Ucs2UIntMap& rUnicodeEnc )
413 // in this context the pFont->GetFontId() is a valid PSP
414 // font since they are the only ones left after the PDF
415 // export has filtered its list of subsettable fonts (for
416 // which this method was created). The correct way would
417 // be to have the GlyphCache search for the ImplFontData pFont
418 psp::fontID aFont = pFont->GetFontId();
419 PspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
422 // ---------------------------------------------------------------------------
424 BOOL SvpSalGraphics::GetGlyphBoundRect( long nGlyphIndex, Rectangle& rRect )
426 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
427 if( nLevel >= MAX_FALLBACK )
428 return FALSE;
430 ServerFont* pSF = m_pServerFont[ nLevel ];
431 if( !pSF )
432 return FALSE;
434 nGlyphIndex &= ~GF_FONTMASK;
435 const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
436 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
437 return TRUE;
440 // ---------------------------------------------------------------------------
442 BOOL SvpSalGraphics::GetGlyphOutline( long nGlyphIndex, B2DPolyPolygon& rPolyPoly )
444 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
445 if( nLevel >= MAX_FALLBACK )
446 return FALSE;
448 const ServerFont* pSF = m_pServerFont[ nLevel ];
449 if( !pSF )
450 return FALSE;
452 nGlyphIndex &= ~GF_FONTMASK;
453 if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
454 return TRUE;
456 return FALSE;
459 // ---------------------------------------------------------------------------
461 SalLayout* SvpSalGraphics::GetTextLayout( ImplLayoutArgs&, int nFallbackLevel )
463 GenericSalLayout* pLayout = NULL;
465 if( m_pServerFont[ nFallbackLevel ] )
466 pLayout = new ServerFontLayout( *m_pServerFont[ nFallbackLevel ] );
468 return pLayout;
471 // ---------------------------------------------------------------------------
473 void SvpSalGraphics::DrawServerFontLayout( const ServerFontLayout& rSalLayout )
475 // iterate over all glyphs in the layout
476 Point aPos;
477 sal_GlyphId nGlyphIndex;
478 SvpGlyphPeer& rGlyphPeer = SvpGlyphCache::GetInstance().GetPeer();
479 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyphIndex, aPos, nStart ); )
481 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
482 DBG_ASSERT( nLevel < MAX_FALLBACK, "SvpGDI: invalid glyph fallback level" );
483 ServerFont* pSF = m_pServerFont[ nLevel ];
484 if( !pSF )
485 continue;
487 // get the glyph's alpha mask and adjust the drawing position
488 nGlyphIndex &= ~GF_FONTMASK;
489 B2IPoint aDstPoint( aPos.X(), aPos.Y() );
490 BitmapDeviceSharedPtr aAlphaMask
491 = rGlyphPeer.GetGlyphBmp( *pSF, nGlyphIndex, m_eTextFmt, aDstPoint );
492 if( !aAlphaMask ) // ignore empty glyphs
493 continue;
495 // blend text color into target using the glyph's mask
496 const B2IRange aSrcRect( B2ITuple(0,0), aAlphaMask->getSize() );
497 m_aDevice->drawMaskedColor( m_aTextColor, aAlphaMask, aSrcRect, aDstPoint, m_aClipMap );
501 // ===========================================================================