xref: /aoo41x/main/vcl/unx/generic/gdi/pspgraphics.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
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.
14  *
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).
20  *
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.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 
38 #include "unx/pspgraphics.h"
39 
40 #include "vcl/jobdata.hxx"
41 #include "vcl/printerinfomanager.hxx"
42 #include "vcl/bmpacc.hxx"
43 #include "vcl/svapp.hxx"
44 #include "vcl/sysdata.hxx"
45 
46 #include "printergfx.hxx"
47 #include "salbmp.hxx"
48 #include "glyphcache.hxx"
49 #include "impfont.hxx"
50 #include "outfont.hxx"
51 #include "fontsubset.hxx"
52 #include "salprn.hxx"
53 #include "region.h"
54 
55 #ifdef ENABLE_GRAPHITE
56 #include <graphite_layout.hxx>
57 #include <graphite_serverfont.hxx>
58 #endif
59 
60 using namespace psp;
61 using namespace rtl;
62 
63 // ----- Implementation of PrinterBmp by means of SalBitmap/BitmapBuffer ---------------
64 
65 class SalPrinterBmp : public psp::PrinterBmp
66 {
67 	private:
68     BitmapBuffer*		mpBmpBuffer;
69 
70     FncGetPixel			mpFncGetPixel;
71     Scanline			mpScanAccess;
72     sal_PtrDiff			mnScanOffset;
73 
74     sal_uInt32			ColorOf (BitmapColor& rColor) const;
75     sal_uInt8			GrayOf  (BitmapColor& rColor) const;
76 
77     SalPrinterBmp ();
78 
79 	public:
80 
81 							SalPrinterBmp (BitmapBuffer* pBitmap);
82 		virtual				~SalPrinterBmp ();
83 		virtual sal_uInt32	GetPaletteColor (sal_uInt32 nIdx) const;
84 		virtual sal_uInt32	GetPaletteEntryCount () const;
85 		virtual sal_uInt32	GetPixelRGB  (sal_uInt32 nRow, sal_uInt32 nColumn) const;
86 		virtual sal_uInt8	GetPixelGray (sal_uInt32 nRow, sal_uInt32 nColumn) const;
87 		virtual sal_uInt8	GetPixelIdx  (sal_uInt32 nRow, sal_uInt32 nColumn) const;
88 		virtual sal_uInt32	GetWidth () const;
89 		virtual sal_uInt32	GetHeight() const;
90 		virtual sal_uInt32	GetDepth ()	const;
91 };
92 
93 SalPrinterBmp::SalPrinterBmp (BitmapBuffer* pBuffer) :
94 		mpBmpBuffer (pBuffer)
95 {
96 	DBG_ASSERT (mpBmpBuffer, "SalPrinterBmp::SalPrinterBmp () can't acquire Bitmap");
97 
98 	// calibrate scanline buffer
99 	if( BMP_SCANLINE_ADJUSTMENT( mpBmpBuffer->mnFormat ) == BMP_FORMAT_TOP_DOWN )
100 	{
101 		mpScanAccess = mpBmpBuffer->mpBits;
102 		mnScanOffset = mpBmpBuffer->mnScanlineSize;
103 	}
104 	else
105 	{
106 		mpScanAccess = mpBmpBuffer->mpBits
107 					   + (mpBmpBuffer->mnHeight - 1) * mpBmpBuffer->mnScanlineSize;
108 		mnScanOffset = - mpBmpBuffer->mnScanlineSize;
109 	}
110 
111 	// request read access to the pixels
112 	switch( BMP_SCANLINE_FORMAT( mpBmpBuffer->mnFormat ) )
113 	{
114 		case BMP_FORMAT_1BIT_MSB_PAL:
115 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_MSB_PAL;	 break;
116 		case BMP_FORMAT_1BIT_LSB_PAL:
117 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_1BIT_LSB_PAL;	 break;
118 		case BMP_FORMAT_4BIT_MSN_PAL:
119 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_4BIT_MSN_PAL;	 break;
120 		case BMP_FORMAT_4BIT_LSN_PAL:
121 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_4BIT_LSN_PAL;	 break;
122 		case BMP_FORMAT_8BIT_PAL:
123 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_8BIT_PAL; 	 break;
124 		case BMP_FORMAT_8BIT_TC_MASK:
125 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_8BIT_TC_MASK;	 break;
126 		case BMP_FORMAT_16BIT_TC_MSB_MASK:
127 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_16BIT_TC_MSB_MASK; break;
128 		case BMP_FORMAT_16BIT_TC_LSB_MASK:
129 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_16BIT_TC_LSB_MASK; break;
130 		case BMP_FORMAT_24BIT_TC_BGR:
131 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_24BIT_TC_BGR;  break;
132 		case BMP_FORMAT_24BIT_TC_RGB:
133 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_24BIT_TC_RGB;  break;
134 		case BMP_FORMAT_24BIT_TC_MASK:
135 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_24BIT_TC_MASK; break;
136 		case BMP_FORMAT_32BIT_TC_ABGR:
137 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_32BIT_TC_ABGR; break;
138 		case BMP_FORMAT_32BIT_TC_ARGB:
139 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_32BIT_TC_ARGB; break;
140 		case BMP_FORMAT_32BIT_TC_BGRA:
141 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_32BIT_TC_BGRA; break;
142 		case BMP_FORMAT_32BIT_TC_RGBA:
143 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_32BIT_TC_RGBA; break;
144 		case BMP_FORMAT_32BIT_TC_MASK:
145 			mpFncGetPixel = BitmapReadAccess::GetPixelFor_32BIT_TC_MASK; break;
146 
147 		default:
148 			DBG_ERROR("Error: SalPrinterBmp::SalPrinterBmp() unknown bitmap format");
149 		break;
150 	}
151 }
152 
153 SalPrinterBmp::~SalPrinterBmp ()
154 {
155 }
156 
157 sal_uInt32
158 SalPrinterBmp::GetWidth () const
159 {
160 	return mpBmpBuffer->mnWidth;
161 }
162 
163 sal_uInt32
164 SalPrinterBmp::GetHeight () const
165 {
166 	return mpBmpBuffer->mnHeight;
167 }
168 
169 sal_uInt32
170 SalPrinterBmp::GetDepth () const
171 {
172 	sal_uInt32 nDepth;
173 
174 	switch (mpBmpBuffer->mnBitCount)
175 	{
176 		case 1:
177 			nDepth = 1;
178 			break;
179 
180 		case 4:
181 		case 8:
182 			nDepth = 8;
183 			break;
184 
185 		case 16:
186 		case 24:
187 		case 32:
188 			nDepth = 24;
189 			break;
190 
191 		default:
192 			nDepth = 1;
193 			DBG_ERROR ("Error: unsupported bitmap depth in SalPrinterBmp::GetDepth()");
194 			break;
195 	}
196 
197 	return nDepth;
198 }
199 
200 sal_uInt32
201 SalPrinterBmp::ColorOf (BitmapColor& rColor) const
202 {
203 	if (rColor.IsIndex())
204 		return ColorOf (mpBmpBuffer->maPalette[rColor.GetIndex()]);
205 	else
206 		return 	  ((rColor.GetBlue()) 		 & 0x000000ff)
207 				| ((rColor.GetGreen() <<  8) & 0x0000ff00)
208 				| ((rColor.GetRed()   << 16) & 0x00ff0000);
209 }
210 
211 sal_uInt8
212 SalPrinterBmp::GrayOf (BitmapColor& rColor) const
213 {
214 	if (rColor.IsIndex())
215 		return GrayOf (mpBmpBuffer->maPalette[rColor.GetIndex()]);
216 	else
217 		return (  rColor.GetBlue()  *  28UL
218 				+ rColor.GetGreen() * 151UL
219 				+ rColor.GetRed()   *  77UL ) >> 8;
220 }
221 
222 sal_uInt32
223 SalPrinterBmp::GetPaletteEntryCount () const
224 {
225 	return mpBmpBuffer->maPalette.GetEntryCount ();
226 }
227 
228 sal_uInt32
229 SalPrinterBmp::GetPaletteColor (sal_uInt32 nIdx) const
230 {
231 	return ColorOf (mpBmpBuffer->maPalette[nIdx]);
232 }
233 
234 sal_uInt32
235 SalPrinterBmp::GetPixelRGB (sal_uInt32 nRow, sal_uInt32 nColumn) const
236 {
237 	Scanline pScan = mpScanAccess + nRow * mnScanOffset;
238 	BitmapColor aColor = mpFncGetPixel (pScan, nColumn, mpBmpBuffer->maColorMask);
239 
240 	return ColorOf (aColor);
241 }
242 
243 sal_uInt8
244 SalPrinterBmp::GetPixelGray (sal_uInt32 nRow, sal_uInt32 nColumn) const
245 {
246 	Scanline pScan = mpScanAccess + nRow * mnScanOffset;
247 	BitmapColor aColor = mpFncGetPixel (pScan, nColumn, mpBmpBuffer->maColorMask);
248 
249 	return GrayOf (aColor);
250 }
251 
252 sal_uInt8
253 SalPrinterBmp::GetPixelIdx (sal_uInt32 nRow, sal_uInt32 nColumn) const
254 {
255 	Scanline pScan = mpScanAccess + nRow * mnScanOffset;
256 	BitmapColor aColor = mpFncGetPixel (pScan, nColumn, mpBmpBuffer->maColorMask);
257 
258 	if (aColor.IsIndex())
259 		return aColor.GetIndex();
260 	else
261 		return 0;
262 }
263 
264 /*******************************************************
265  * PspGraphics                                         *
266  *******************************************************/
267 
268 PspGraphics::~PspGraphics()
269 {
270     ReleaseFonts();
271 }
272 
273 void PspGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY )
274 {
275 	if (m_pJobData != NULL)
276 	{
277 		int x = m_pJobData->m_aContext.getRenderResolution();
278 
279 		rDPIX = x;
280 		rDPIY = x;
281 	}
282 }
283 
284 sal_uInt16 PspGraphics::GetBitCount()
285 {
286     return m_pPrinterGfx->GetBitCount();
287 }
288 
289 long PspGraphics::GetGraphicsWidth() const
290 {
291     return 0;
292 }
293 
294 void PspGraphics::ResetClipRegion()
295 {
296     m_pPrinterGfx->ResetClipRegion();
297 }
298 
299 bool PspGraphics::setClipRegion( const Region& i_rClip )
300 {
301     // TODO: support polygonal clipregions here
302     m_pPrinterGfx->BeginSetClipRegion( i_rClip.GetRectCount() );
303 
304     ImplRegionInfo aInfo;
305     long nX, nY, nW, nH;
306     bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
307     while( bRegionRect )
308     {
309         if ( nW && nH )
310         {
311             m_pPrinterGfx->UnionClipRegion( nX, nY, nW, nH );
312         }
313         bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
314     }
315     m_pPrinterGfx->EndSetClipRegion();
316     return true;
317 }
318 
319 void PspGraphics::SetLineColor()
320 {
321     m_pPrinterGfx->SetLineColor ();
322 }
323 
324 void PspGraphics::SetLineColor( SalColor nSalColor )
325 {
326     psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
327                               SALCOLOR_GREEN (nSalColor),
328                               SALCOLOR_BLUE  (nSalColor));
329     m_pPrinterGfx->SetLineColor (aColor);
330 }
331 
332 void PspGraphics::SetFillColor()
333 {
334     m_pPrinterGfx->SetFillColor ();
335 }
336 
337 void PspGraphics::SetFillColor( SalColor nSalColor )
338 {
339     psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
340                               SALCOLOR_GREEN (nSalColor),
341                               SALCOLOR_BLUE  (nSalColor));
342     m_pPrinterGfx->SetFillColor (aColor);
343 }
344 
345 void PspGraphics::SetROPLineColor( SalROPColor )
346 {
347     DBG_ASSERT( 0, "Error: PrinterGfx::SetROPLineColor() not implemented" );
348 }
349 
350 void PspGraphics::SetROPFillColor( SalROPColor )
351 {
352     DBG_ASSERT( 0, "Error: PrinterGfx::SetROPFillColor() not implemented" );
353 }
354 
355 void PspGraphics::SetXORMode( bool bSet, bool )
356 {
357     (void)bSet;
358     DBG_ASSERT( !bSet, "Error: PrinterGfx::SetXORMode() not implemented" );
359 }
360 
361 void PspGraphics::drawPixel( long nX, long nY )
362 {
363     m_pPrinterGfx->DrawPixel (Point(nX, nY));
364 }
365 
366 void PspGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
367 {
368     psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
369                               SALCOLOR_GREEN (nSalColor),
370                               SALCOLOR_BLUE  (nSalColor));
371     m_pPrinterGfx->DrawPixel (Point(nX, nY), aColor);
372 }
373 
374 void PspGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
375 {
376     m_pPrinterGfx->DrawLine (Point(nX1, nY1), Point(nX2, nY2));
377 }
378 
379 void PspGraphics::drawRect( long nX, long nY, long nDX, long nDY )
380 {
381     m_pPrinterGfx->DrawRect (Rectangle(Point(nX, nY), Size(nDX, nDY)));
382 }
383 
384 void PspGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry )
385 {
386     m_pPrinterGfx->DrawPolyLine (nPoints, (Point*)pPtAry);
387 }
388 
389 void PspGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry )
390 {
391 	// Point must be equal to SalPoint! see vcl/inc/salgtype.hxx
392     m_pPrinterGfx->DrawPolygon (nPoints, (Point*)pPtAry);
393 }
394 
395 void PspGraphics::drawPolyPolygon( sal_uInt32			nPoly,
396 								   const sal_uInt32   *pPoints,
397 								   PCONSTSALPOINT  *pPtAry )
398 {
399     m_pPrinterGfx->DrawPolyPolygon (nPoly, pPoints, (const Point**)pPtAry);
400 }
401 
402 bool PspGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
403 {
404         // TODO: implement and advertise OutDevSupport_B2DDraw support
405         return false;
406 }
407 
408 bool PspGraphics::drawPolyLine( const basegfx::B2DPolygon&, double /*fTranspareny*/, const basegfx::B2DVector& /*rLineWidths*/, basegfx::B2DLineJoin /*eJoin*/)
409 {
410     // TODO: a PS printer can draw B2DPolyLines almost directly
411     return false;
412 }
413 
414 sal_Bool PspGraphics::drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
415 {
416     m_pPrinterGfx->DrawPolyLineBezier (nPoints, (Point*)pPtAry, pFlgAry);
417     return sal_True;
418 }
419 
420 sal_Bool PspGraphics::drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry )
421 {
422     m_pPrinterGfx->DrawPolygonBezier (nPoints, (Point*)pPtAry, pFlgAry);
423     return sal_True;
424 }
425 
426 sal_Bool PspGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly,
427                                              const sal_uInt32* pPoints,
428                                              const SalPoint* const* pPtAry,
429                                              const sal_uInt8* const* pFlgAry )
430 {
431 	// Point must be equal to SalPoint! see vcl/inc/salgtype.hxx
432     m_pPrinterGfx->DrawPolyPolygonBezier (nPoly, pPoints, (Point**)pPtAry, (sal_uInt8**)pFlgAry);
433     return sal_True;
434 }
435 
436 void PspGraphics::invert( sal_uLong,
437                           const SalPoint*,
438                           SalInvert )
439 {
440     DBG_ASSERT( 0, "Error: PrinterGfx::Invert() not implemented" );
441 }
442 sal_Bool PspGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize )
443 {
444     return m_pPrinterGfx->DrawEPS( Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) ), pPtr, nSize );
445 }
446 
447 void PspGraphics::copyBits( const SalTwoRect*,
448                             SalGraphics* )
449 {
450     DBG_ERROR( "Error: PrinterGfx::CopyBits() not implemented" );
451 }
452 
453 void PspGraphics::copyArea ( long,long,long,long,long,long,sal_uInt16 )
454 {
455     DBG_ERROR( "Error: PrinterGfx::CopyArea() not implemented" );
456 }
457 
458 void PspGraphics::drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap )
459 {
460     Rectangle aSrc (Point(pPosAry->mnSrcX, pPosAry->mnSrcY),
461                     Size(pPosAry->mnSrcWidth, pPosAry->mnSrcHeight));
462     Rectangle aDst (Point(pPosAry->mnDestX, pPosAry->mnDestY),
463                     Size(pPosAry->mnDestWidth, pPosAry->mnDestHeight));
464 
465     BitmapBuffer* pBuffer= const_cast<SalBitmap&>(rSalBitmap).AcquireBuffer(sal_True);
466 
467     SalPrinterBmp aBmp (pBuffer);
468     m_pPrinterGfx->DrawBitmap (aDst, aSrc, aBmp);
469 
470     const_cast<SalBitmap&>(rSalBitmap).ReleaseBuffer (pBuffer, sal_True);
471 }
472 
473 void PspGraphics::drawBitmap( const SalTwoRect*,
474                               const SalBitmap&,
475                               const SalBitmap& )
476 {
477     DBG_ERROR("Error: no PrinterGfx::DrawBitmap() for transparent bitmap");
478 }
479 
480 void PspGraphics::drawBitmap( const SalTwoRect*,
481                               const SalBitmap&,
482                               SalColor )
483 {
484     DBG_ERROR("Error: no PrinterGfx::DrawBitmap() for transparent color");
485 }
486 
487 void PspGraphics::drawMask( const SalTwoRect*,
488                             const SalBitmap &,
489                             SalColor )
490 {
491     DBG_ERROR("Error: PrinterGfx::DrawMask() not implemented");
492 }
493 
494 SalBitmap* PspGraphics::getBitmap( long, long, long, long )
495 {
496     DBG_WARNING ("Warning: PrinterGfx::GetBitmap() not implemented");
497     return NULL;
498 }
499 
500 SalColor PspGraphics::getPixel( long, long )
501 {
502     DBG_ERROR ("Warning: PrinterGfx::GetPixel() not implemented");
503     return 0;
504 }
505 
506 void PspGraphics::invert(long,long,long,long,SalInvert)
507 {
508     DBG_ERROR ("Warning: PrinterGfx::Invert() not implemented");
509 }
510 
511 //==========================================================================
512 
513 class ImplPspFontData : public ImplFontData
514 {
515 private:
516     enum { PSPFD_MAGIC = 0xb5bf01f0 };
517     sal_IntPtr              mnFontId;
518 
519 public:
520                             ImplPspFontData( const psp::FastPrintFontInfo& );
521     virtual sal_IntPtr      GetFontId() const { return mnFontId; }
522     virtual ImplFontData*   Clone() const { return new ImplPspFontData( *this ); }
523     virtual ImplFontEntry*  CreateFontInstance( ImplFontSelectData& ) const;
524     static bool             CheckFontData( const ImplFontData& r ) { return r.CheckMagic( PSPFD_MAGIC ); }
525 };
526 
527 //--------------------------------------------------------------------------
528 
529 ImplPspFontData::ImplPspFontData( const psp::FastPrintFontInfo& rInfo )
530 :   ImplFontData( PspGraphics::Info2DevFontAttributes(rInfo), PSPFD_MAGIC ),
531     mnFontId( rInfo.m_nID )
532 {}
533 
534 //--------------------------------------------------------------------------
535 
536 ImplFontEntry* ImplPspFontData::CreateFontInstance( ImplFontSelectData& rFSD ) const
537 {
538     ImplServerFontEntry* pEntry = new ImplServerFontEntry( rFSD );
539     return pEntry;
540 }
541 
542 //==========================================================================
543 
544 class PspFontLayout : public GenericSalLayout
545 {
546 public:
547                         PspFontLayout( ::psp::PrinterGfx& );
548     virtual bool        LayoutText( ImplLayoutArgs& );
549     virtual void        InitFont() const;
550     virtual void        DrawText( SalGraphics& ) const;
551 private:
552     ::psp::PrinterGfx&  mrPrinterGfx;
553     sal_IntPtr          mnFontID;
554     int                 mnFontHeight;
555     int                 mnFontWidth;
556     bool                mbVertical;
557     bool                mbArtItalic;
558     bool                mbArtBold;
559 };
560 
561 //--------------------------------------------------------------------------
562 
563 PspFontLayout::PspFontLayout( ::psp::PrinterGfx& rGfx )
564 :   mrPrinterGfx( rGfx )
565 {
566     mnFontID     = mrPrinterGfx.GetFontID();
567     mnFontHeight = mrPrinterGfx.GetFontHeight();
568     mnFontWidth  = mrPrinterGfx.GetFontWidth();
569     mbVertical   = mrPrinterGfx.GetFontVertical();
570     mbArtItalic	 = mrPrinterGfx.GetArtificialItalic();
571     mbArtBold	 = mrPrinterGfx.GetArtificialBold();
572 }
573 
574 //--------------------------------------------------------------------------
575 
576 bool PspFontLayout::LayoutText( ImplLayoutArgs& rArgs )
577 {
578     mbVertical = ((rArgs.mnFlags & SAL_LAYOUT_VERTICAL) != 0);
579 
580     long nUnitsPerPixel = 1;
581     int nOldGlyphId = -1;
582     long nGlyphWidth = 0;
583     int nCharPos = -1;
584     Point aNewPos( 0, 0 );
585     GlyphItem aPrevItem;
586     rtl_TextEncoding aFontEnc = mrPrinterGfx.GetFontMgr().getFontEncoding( mnFontID );
587     for(;;)
588     {
589         bool bRightToLeft;
590         if( !rArgs.GetNextPos( &nCharPos, &bRightToLeft ) )
591             break;
592 
593         sal_Unicode cChar = rArgs.mpStr[ nCharPos ];
594         if( bRightToLeft )
595             cChar = GetMirroredChar( cChar );
596         // symbol font aliasing: 0x0020-0x00ff -> 0xf020 -> 0xf0ff
597         if( aFontEnc == RTL_TEXTENCODING_SYMBOL )
598             if( cChar < 256 )
599                 cChar += 0xf000;
600         int nGlyphIndex = cChar;  // printer glyphs = unicode
601 
602         // update fallback_runs if needed
603         psp::CharacterMetric aMetric;
604         mrPrinterGfx.GetFontMgr().getMetrics( mnFontID, cChar, cChar, &aMetric, mbVertical );
605         if( aMetric.width == -1 && aMetric.height == -1 )
606             rArgs.NeedFallback( nCharPos, bRightToLeft );
607 
608         // apply pair kerning to prev glyph if requested
609         if( SAL_LAYOUT_KERNING_PAIRS & rArgs.mnFlags )
610         {
611             if( nOldGlyphId > 0 )
612             {
613                 const std::list< KernPair >& rKernPairs = mrPrinterGfx.getKernPairs(mbVertical);
614                 for( std::list< KernPair >::const_iterator it = rKernPairs.begin();
615                      it != rKernPairs.end(); ++it )
616                 {
617                     if( it->first == nOldGlyphId && it->second == nGlyphIndex )
618                     {
619                         int nTextScale = mrPrinterGfx.GetFontWidth();
620                         if( ! nTextScale )
621                             nTextScale = mrPrinterGfx.GetFontHeight();
622                         int nKern = (mbVertical ? it->kern_y : it->kern_x) * nTextScale;
623                         nGlyphWidth += nKern;
624                         aPrevItem.mnNewWidth = nGlyphWidth;
625                         break;
626                     }
627                 }
628             }
629         }
630 
631         // finish previous glyph
632         if( nOldGlyphId >= 0 )
633             AppendGlyph( aPrevItem );
634         nOldGlyphId = nGlyphIndex;
635         aNewPos.X() += nGlyphWidth;
636 
637         // prepare GlyphItem for appending it in next round
638         nUnitsPerPixel = mrPrinterGfx.GetCharWidth( cChar, cChar, &nGlyphWidth );
639         int nGlyphFlags = bRightToLeft ? GlyphItem::IS_RTL_GLYPH : 0;
640         nGlyphIndex |= GF_ISCHAR;
641         aPrevItem = GlyphItem( nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nGlyphWidth );
642     }
643 
644     // append last glyph item if any
645     if( nOldGlyphId >= 0 )
646         AppendGlyph( aPrevItem );
647 
648     SetOrientation( mrPrinterGfx.GetFontAngle() );
649     SetUnitsPerPixel( nUnitsPerPixel );
650     return (nOldGlyphId >= 0);
651 }
652 
653 class PspServerFontLayout : public ServerFontLayout
654 {
655 public:
656     PspServerFontLayout( psp::PrinterGfx&, ServerFont& rFont, const ImplLayoutArgs& rArgs );
657 
658     virtual void        InitFont() const;
659     const sal_Unicode*	getTextPtr() const { return maText.getStr() - mnMinCharPos; }
660     int					getMinCharPos() const { return mnMinCharPos; }
661     int					getMaxCharPos() const { return mnMinCharPos+maText.getLength()-1; }
662 private:
663     ::psp::PrinterGfx&  mrPrinterGfx;
664     sal_IntPtr          mnFontID;
665     int                 mnFontHeight;
666     int                 mnFontWidth;
667     bool                mbVertical;
668     bool				mbArtItalic;
669     bool				mbArtBold;
670     rtl::OUString		maText;
671     int					mnMinCharPos;
672 };
673 
674 PspServerFontLayout::PspServerFontLayout( ::psp::PrinterGfx& rGfx, ServerFont& rFont, const ImplLayoutArgs& rArgs )
675         :   ServerFontLayout( rFont ),
676             mrPrinterGfx( rGfx )
677 {
678     mnFontID     = mrPrinterGfx.GetFontID();
679     mnFontHeight = mrPrinterGfx.GetFontHeight();
680     mnFontWidth  = mrPrinterGfx.GetFontWidth();
681     mbVertical   = mrPrinterGfx.GetFontVertical();
682     mbArtItalic	 = mrPrinterGfx.GetArtificialItalic();
683     mbArtBold	 = mrPrinterGfx.GetArtificialBold();
684     maText		 = OUString( rArgs.mpStr + rArgs.mnMinCharPos, rArgs.mnEndCharPos - rArgs.mnMinCharPos+1 );
685     mnMinCharPos = rArgs.mnMinCharPos;
686 }
687 
688 void PspServerFontLayout::InitFont() const
689 {
690     mrPrinterGfx.SetFont( mnFontID, mnFontHeight, mnFontWidth,
691                           mnOrientation, mbVertical, mbArtItalic, mbArtBold );
692 }
693 
694 //--------------------------------------------------------------------------
695 
696 static void DrawPrinterLayout( const SalLayout& rLayout, ::psp::PrinterGfx& rGfx, bool bIsPspServerFontLayout )
697 {
698     const int nMaxGlyphs = 200;
699     sal_uInt32 aGlyphAry[ nMaxGlyphs ]; // TODO: use sal_GlyphId
700     sal_Int32   aWidthAry[ nMaxGlyphs ];
701     sal_Int32   aIdxAry  [ nMaxGlyphs ];
702     sal_Unicode aUnicodes[ nMaxGlyphs ];
703     int			aCharPosAry	[ nMaxGlyphs ];
704 
705     Point aPos;
706     long nUnitsPerPixel = rLayout.GetUnitsPerPixel();
707     const sal_Unicode* pText = NULL;
708     int nMinCharPos = 0;
709     int nMaxCharPos = 0;
710     if (bIsPspServerFontLayout)
711     {
712         const PspServerFontLayout * pPspLayout = dynamic_cast<const PspServerFontLayout*>(&rLayout);
713 #ifdef ENABLE_GRAPHITE
714         const GraphiteServerFontLayout * pGrLayout = dynamic_cast<const GraphiteServerFontLayout*>(&rLayout);
715 #endif
716         if (pPspLayout)
717         {
718             pText = pPspLayout->getTextPtr();
719             nMinCharPos = pPspLayout->getMinCharPos();
720             nMaxCharPos = pPspLayout->getMaxCharPos();
721         }
722 #ifdef ENABLE_GRAPHITE
723         else if (pGrLayout)
724         {
725         #if 0 // HACK: disabled for now due to #i114460#, see #desc12 there
726               // TODO: get rid of glyph->string mapping altogether for printing
727 	      // TODO: fix GraphiteServerFontLayout's returned aCharPosAry
728 	      // TODO: fix PrinterGfx's caching?
729             pText = pGrLayout->getTextPtr();
730             nMinCharPos = pGrLayout->getMinCharPos();
731             nMaxCharPos = pGrLayout->getMaxCharPos();
732 	#endif
733         }
734 #endif
735     }
736     for( int nStart = 0;; )
737     {
738         int nGlyphCount = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart, aWidthAry, pText ? aCharPosAry : NULL );
739         if( !nGlyphCount )
740             break;
741 
742         sal_Int32 nXOffset = 0;
743         for( int i = 0; i < nGlyphCount; ++i )
744         {
745             nXOffset += aWidthAry[ i ];
746             aIdxAry[ i ] = nXOffset / nUnitsPerPixel;
747             sal_Int32 nGlyphIdx = aGlyphAry[i] & (GF_IDXMASK | GF_ROTMASK);
748             if( pText )
749                 aUnicodes[i] = (aCharPosAry[i] >= nMinCharPos && aCharPosAry[i] <= nMaxCharPos) ? pText[ aCharPosAry[i] ] : 0;
750             else
751                 aUnicodes[i] = (aGlyphAry[i] & GF_ISCHAR) ? nGlyphIdx : 0;
752             aGlyphAry[i] = nGlyphIdx;
753         }
754 
755         rGfx.DrawGlyphs( aPos, (sal_uInt32 *)aGlyphAry, aUnicodes, nGlyphCount, aIdxAry );
756     }
757 }
758 
759 //--------------------------------------------------------------------------
760 
761 void PspFontLayout::InitFont() const
762 {
763     mrPrinterGfx.SetFont( mnFontID, mnFontHeight, mnFontWidth,
764         mnOrientation, mbVertical, mbArtItalic, mbArtBold );
765 }
766 
767 //--------------------------------------------------------------------------
768 
769 void PspFontLayout::DrawText( SalGraphics& ) const
770 {
771     DrawPrinterLayout( *this, mrPrinterGfx, false );
772 }
773 
774 void PspGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
775 {
776     // print complex text
777     DrawPrinterLayout( rLayout, *m_pPrinterGfx, true );
778 }
779 
780 const ImplFontCharMap* PspGraphics::GetImplFontCharMap() const
781 {
782     if( !m_pServerFont[0] )
783         return NULL;
784 
785     const ImplFontCharMap* pIFCMap = m_pServerFont[0]->GetImplFontCharMap();
786     return pIFCMap;
787 }
788 
789 sal_uInt16 PspGraphics::SetFont( ImplFontSelectData *pEntry, int nFallbackLevel )
790 {
791     // release all fonts that are to be overridden
792     for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
793     {
794         if( m_pServerFont[i] != NULL )
795         {
796             // old server side font is no longer referenced
797             GlyphCache::GetInstance().UncacheFont( *m_pServerFont[i] );
798             m_pServerFont[i] = NULL;
799         }
800     }
801 
802     // return early if there is no new font
803     if( !pEntry )
804         return 0;
805 
806     sal_IntPtr nID = pEntry->mpFontData ? pEntry->mpFontData->GetFontId() : 0;
807 
808     // determine which font attributes need to be emulated
809     bool bArtItalic = false;
810     bool bArtBold = false;
811     if( pEntry->meItalic == ITALIC_OBLIQUE || pEntry->meItalic == ITALIC_NORMAL )
812     {
813         psp::italic::type eItalic = m_pPrinterGfx->GetFontMgr().getFontItalic( nID );
814         if( eItalic != psp::italic::Italic && eItalic != psp::italic::Oblique )
815             bArtItalic = true;
816     }
817     int nWeight = (int)pEntry->meWeight;
818     int nRealWeight = (int)m_pPrinterGfx->GetFontMgr().getFontWeight( nID );
819     if( nRealWeight <= (int)psp::weight::Medium && nWeight > (int)WEIGHT_MEDIUM )
820     {
821         bArtBold = true;
822     }
823 
824     // also set the serverside font for layouting
825     m_bFontVertical = pEntry->mbVertical;
826     if( pEntry->mpFontData )
827     {
828         // requesting a font provided by builtin rasterizer
829         ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
830         if( pServerFont != NULL )
831         {
832             if( pServerFont->TestFont() )
833                 m_pServerFont[ nFallbackLevel ] = pServerFont;
834             else
835                 GlyphCache::GetInstance().UncacheFont( *pServerFont );
836         }
837     }
838 
839     // set the printer font
840     return m_pPrinterGfx->SetFont( nID,
841                                    pEntry->mnHeight,
842                                    pEntry->mnWidth,
843                                    pEntry->mnOrientation,
844                                    pEntry->mbVertical,
845                                    bArtItalic,
846                                    bArtBold
847                                    );
848 }
849 
850 void PspGraphics::SetTextColor( SalColor nSalColor )
851 {
852     psp::PrinterColor aColor (SALCOLOR_RED   (nSalColor),
853                               SALCOLOR_GREEN (nSalColor),
854                               SALCOLOR_BLUE  (nSalColor));
855     m_pPrinterGfx->SetTextColor (aColor);
856 }
857 
858 bool PspGraphics::AddTempDevFont( ImplDevFontList*, const String&,const String& )
859 {
860     return false;
861 }
862 
863 void RegisterFontSubstitutors( ImplDevFontList* );
864 
865 void PspGraphics::GetDevFontList( ImplDevFontList *pList )
866 {
867     ::std::list< psp::fontID > aList;
868     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
869     rMgr.getFontList( aList, m_pJobData->m_pParser, m_pInfoPrinter->m_bCompatMetrics );
870 
871     ::std::list< psp::fontID >::iterator it;
872     psp::FastPrintFontInfo aInfo;
873     for (it = aList.begin(); it != aList.end(); ++it)
874         if (rMgr.getFontFastInfo (*it, aInfo))
875             AnnounceFonts( pList, aInfo );
876 
877    // register platform specific font substitutions if available
878    if( rMgr.hasFontconfig() )
879 	RegisterFontSubstitutors( pList );
880 }
881 
882 void PspGraphics::GetDevFontSubstList( OutputDevice* pOutDev )
883 {
884     const psp::PrinterInfo& rInfo = psp::PrinterInfoManager::get().getPrinterInfo( m_pJobData->m_aPrinterName );
885     if( rInfo.m_bPerformFontSubstitution )
886     {
887         for( std::hash_map< rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator it = rInfo.m_aFontSubstitutes.begin(); it != rInfo.m_aFontSubstitutes.end(); ++it )
888             pOutDev->ImplAddDevFontSubstitute( it->first, it->second, FONT_SUBSTITUTE_ALWAYS );
889     }
890 }
891 
892 void PspGraphics::GetFontMetric( ImplFontMetricData *pMetric, int )
893 {
894     const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
895     psp::PrintFontInfo aInfo;
896 
897     if (rMgr.getFontInfo (m_pPrinterGfx->GetFontID(), aInfo))
898     {
899         ImplDevFontAttributes aDFA = Info2DevFontAttributes( aInfo );
900         static_cast<ImplFontAttributes&>(*pMetric) = aDFA;
901         pMetric->mbDevice       = aDFA.mbDevice;
902         pMetric->mbScalableFont = true;
903 
904         pMetric->mnOrientation 	= m_pPrinterGfx->GetFontAngle();
905         pMetric->mnSlant		= 0;
906 
907         sal_Int32 nTextHeight	= m_pPrinterGfx->GetFontHeight();
908         sal_Int32 nTextWidth	= m_pPrinterGfx->GetFontWidth();
909         if( ! nTextWidth )
910             nTextWidth = nTextHeight;
911 
912         pMetric->mnWidth		= nTextWidth;
913         pMetric->mnAscent		= ( aInfo.m_nAscend * nTextHeight + 500 ) / 1000;
914         pMetric->mnDescent		= ( aInfo.m_nDescend * nTextHeight + 500 ) / 1000;
915         pMetric->mnIntLeading	= ( aInfo.m_nLeading * nTextHeight + 500 ) / 1000;
916         pMetric->mnExtLeading	= 0;
917     }
918 }
919 
920 sal_uLong PspGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData *pKernPairs )
921 {
922     const ::std::list< ::psp::KernPair >& rPairs( m_pPrinterGfx->getKernPairs() );
923     sal_uLong nHavePairs = rPairs.size();
924     if( pKernPairs && nPairs )
925     {
926         ::std::list< ::psp::KernPair >::const_iterator it;
927         unsigned int i;
928         int nTextScale = m_pPrinterGfx->GetFontWidth();
929         if( ! nTextScale )
930             nTextScale = m_pPrinterGfx->GetFontHeight();
931         for( i = 0, it = rPairs.begin(); i < nPairs && i < nHavePairs; i++, ++it )
932         {
933             pKernPairs[i].mnChar1	= it->first;
934             pKernPairs[i].mnChar2	= it->second;
935             pKernPairs[i].mnKern	= it->kern_x * nTextScale / 1000;
936         }
937 
938     }
939     return nHavePairs;
940 }
941 
942 sal_Bool PspGraphics::GetGlyphBoundRect( long nGlyphIndex, Rectangle& rRect )
943 {
944     int nLevel = nGlyphIndex >> GF_FONTSHIFT;
945     if( nLevel >= MAX_FALLBACK )
946         return sal_False;
947 
948     ServerFont* pSF = m_pServerFont[ nLevel ];
949     if( !pSF )
950         return sal_False;
951 
952     nGlyphIndex &= ~GF_FONTMASK;
953     const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
954     rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
955     return sal_True;
956 }
957 
958 sal_Bool PspGraphics::GetGlyphOutline( long nGlyphIndex,
959     ::basegfx::B2DPolyPolygon& rB2DPolyPoly )
960 {
961     int nLevel = nGlyphIndex >> GF_FONTSHIFT;
962     if( nLevel >= MAX_FALLBACK )
963         return sal_False;
964 
965     ServerFont* pSF = m_pServerFont[ nLevel ];
966     if( !pSF )
967         return sal_False;
968 
969     nGlyphIndex &= ~GF_FONTMASK;
970     if( pSF->GetGlyphOutline( nGlyphIndex, rB2DPolyPoly ) )
971         return sal_True;
972 
973     return sal_False;
974 }
975 
976 SalLayout* PspGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
977 {
978     // workaround for printers not handling glyph indexing for non-TT fonts
979     int nFontId = m_pPrinterGfx->GetFontID();
980     if( psp::fonttype::TrueType != psp::PrintFontManager::get().getFontType( nFontId ) )
981         rArgs.mnFlags |= SAL_LAYOUT_DISABLE_GLYPH_PROCESSING;
982     else if( nFallbackLevel > 0 )
983         rArgs.mnFlags &= ~SAL_LAYOUT_DISABLE_GLYPH_PROCESSING;
984 
985     GenericSalLayout* pLayout = NULL;
986 
987     if( m_pServerFont[ nFallbackLevel ]
988         && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
989     {
990 #ifdef ENABLE_GRAPHITE
991         // Is this a Graphite font?
992         if (GraphiteFontAdaptor::IsGraphiteEnabledFont(*m_pServerFont[nFallbackLevel]))
993         {
994             sal_Int32 xdpi, ydpi;
995             GetResolution(xdpi, ydpi);
996             GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *m_pServerFont[nFallbackLevel], xdpi, ydpi);
997             if (!pGrfont) return NULL;
998             pLayout = new GraphiteServerFontLayout(pGrfont);
999         }
1000         else
1001 #endif
1002             pLayout = new PspServerFontLayout( *m_pPrinterGfx, *m_pServerFont[nFallbackLevel], rArgs );
1003     }
1004     else
1005         pLayout = new PspFontLayout( *m_pPrinterGfx );
1006 
1007     return pLayout;
1008 }
1009 
1010 //--------------------------------------------------------------------------
1011 
1012 sal_Bool PspGraphics::CreateFontSubset(
1013                                    const rtl::OUString& rToFile,
1014                                    const ImplFontData* pFont,
1015                                    sal_Int32* pGlyphIDs,
1016                                    sal_uInt8* pEncoding,
1017                                    sal_Int32* pWidths,
1018                                    int nGlyphCount,
1019                                    FontSubsetInfo& rInfo
1020                                    )
1021 {
1022     // in this context the pFont->GetFontId() is a valid PSP
1023     // font since they are the only ones left after the PDF
1024     // export has filtered its list of subsettable fonts (for
1025     // which this method was created). The correct way would
1026     // be to have the GlyphCache search for the ImplFontData pFont
1027     psp::fontID aFont = pFont->GetFontId();
1028 
1029     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1030     bool bSuccess = rMgr.createFontSubset( rInfo,
1031                                  aFont,
1032                                  rToFile,
1033                                  pGlyphIDs,
1034                                  pEncoding,
1035                                  pWidths,
1036                                  nGlyphCount );
1037     return bSuccess;
1038 }
1039 
1040 //--------------------------------------------------------------------------
1041 
1042 const void* PspGraphics::GetEmbedFontData( const ImplFontData* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
1043 {
1044     // in this context the pFont->GetFontId() is a valid PSP
1045     // font since they are the only ones left after the PDF
1046     // export has filtered its list of subsettable fonts (for
1047     // which this method was created). The correct way would
1048     // be to have the GlyphCache search for the ImplFontData pFont
1049     psp::fontID aFont = pFont->GetFontId();
1050     return PspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
1051 }
1052 
1053 //--------------------------------------------------------------------------
1054 
1055 void PspGraphics::FreeEmbedFontData( const void* pData, long nLen )
1056 {
1057     PspGraphics::DoFreeEmbedFontData( pData, nLen );
1058 }
1059 
1060 //--------------------------------------------------------------------------
1061 
1062 const Ucs2SIntMap* PspGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
1063 {
1064     // in this context the pFont->GetFontId() is a valid PSP
1065     // font since they are the only ones left after the PDF
1066     // export has filtered its list of subsettable fonts (for
1067     // which this method was created). The correct way would
1068     // be to have the GlyphCache search for the ImplFontData pFont
1069     psp::fontID aFont = pFont->GetFontId();
1070     return PspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
1071 }
1072 
1073 //--------------------------------------------------------------------------
1074 
1075 void PspGraphics::GetGlyphWidths( const ImplFontData* pFont,
1076                                   bool bVertical,
1077                                   Int32Vector& rWidths,
1078                                   Ucs2UIntMap& rUnicodeEnc )
1079 {
1080     // in this context the pFont->GetFontId() is a valid PSP
1081     // font since they are the only ones left after the PDF
1082     // export has filtered its list of subsettable fonts (for
1083     // which this method was created). The correct way would
1084     // be to have the GlyphCache search for the ImplFontData pFont
1085     psp::fontID aFont = pFont->GetFontId();
1086     PspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
1087 }
1088 
1089 
1090 // static helpers of PspGraphics
1091 
1092 const void* PspGraphics::DoGetEmbedFontData( fontID aFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
1093 {
1094     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1095 
1096     psp::PrintFontInfo aFontInfo;
1097     if( ! rMgr.getFontInfo( aFont, aFontInfo ) )
1098         return NULL;
1099 
1100     // fill in font info
1101     rInfo.m_nAscent		= aFontInfo.m_nAscend;
1102     rInfo.m_nDescent	= aFontInfo.m_nDescend;
1103     rInfo.m_aPSName		= rMgr.getPSName( aFont );
1104 
1105     int xMin, yMin, xMax, yMax;
1106     rMgr.getFontBoundingBox( aFont, xMin, yMin, xMax, yMax );
1107 
1108     psp::CharacterMetric aMetrics[256];
1109     sal_Ucs aUnicodes[256];
1110     if( aFontInfo.m_aEncoding == RTL_TEXTENCODING_SYMBOL && aFontInfo.m_eType == psp::fonttype::Type1 )
1111     {
1112         for( int i = 0; i < 256; i++ )
1113             aUnicodes[i] = pUnicodes[i] < 0x0100 ? pUnicodes[i] + 0xf000 : pUnicodes[i];
1114         pUnicodes = aUnicodes;
1115     }
1116     if( ! rMgr.getMetrics( aFont, pUnicodes, 256, aMetrics ) )
1117         return NULL;
1118 
1119     OString aSysPath = rMgr.getFontFileSysPath( aFont );
1120     struct stat aStat;
1121     if( stat( aSysPath.getStr(), &aStat ) )
1122         return NULL;
1123     int fd = open( aSysPath.getStr(), O_RDONLY );
1124     if( fd < 0 )
1125         return NULL;
1126     void* pFile = mmap( NULL, aStat.st_size, PROT_READ, MAP_SHARED, fd, 0 );
1127     close( fd );
1128     if( pFile == MAP_FAILED )
1129         return NULL;
1130 
1131     *pDataLen = aStat.st_size;
1132 
1133     rInfo.m_aFontBBox	= Rectangle( Point( xMin, yMin ), Size( xMax-xMin, yMax-yMin ) );
1134     rInfo.m_nCapHeight	= yMax; // Well ...
1135 
1136     for( int i = 0; i < 256; i++ )
1137         pWidths[i] = (aMetrics[i].width > 0 ? aMetrics[i].width : 0);
1138 
1139     switch( aFontInfo.m_eType )
1140     {
1141         case psp::fonttype::TrueType:
1142             rInfo.m_nFontType = FontSubsetInfo::SFNT_TTF;
1143             break;
1144         case psp::fonttype::Type1: {
1145             const bool bPFA = ((*(unsigned char*)pFile) < 0x80);
1146             rInfo.m_nFontType = bPFA ? FontSubsetInfo::TYPE1_PFA : FontSubsetInfo::TYPE1_PFB;
1147             }
1148             break;
1149         default:
1150             return NULL;
1151     }
1152 
1153     return pFile;
1154 }
1155 
1156 void PspGraphics::DoFreeEmbedFontData( const void* pData, long nLen )
1157 {
1158     if( pData )
1159         munmap( (char*)pData, nLen );
1160 }
1161 
1162 const Ucs2SIntMap* PspGraphics::DoGetFontEncodingVector( fontID aFont, const Ucs2OStrMap** pNonEncoded )
1163 {
1164     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1165 
1166     psp::PrintFontInfo aFontInfo;
1167     if( ! rMgr.getFontInfo( aFont, aFontInfo ) )
1168     {
1169         if( pNonEncoded )
1170             *pNonEncoded = NULL;
1171         return NULL;
1172     }
1173 
1174     return rMgr.getEncodingMap( aFont, pNonEncoded );
1175 }
1176 
1177 void PspGraphics::DoGetGlyphWidths( psp::fontID aFont,
1178                                     bool bVertical,
1179                                     Int32Vector& rWidths,
1180                                     Ucs2UIntMap& rUnicodeEnc )
1181 {
1182     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1183     rMgr.getGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
1184 }
1185 // ----------------------------------------------------------------------------
1186 
1187 FontWidth PspGraphics::ToFontWidth (psp::width::type eWidth)
1188 {
1189 	switch (eWidth)
1190 	{
1191 		case psp::width::UltraCondensed: return WIDTH_ULTRA_CONDENSED;
1192 		case psp::width::ExtraCondensed: return WIDTH_EXTRA_CONDENSED;
1193 		case psp::width::Condensed:		 return WIDTH_CONDENSED;
1194 		case psp::width::SemiCondensed:	 return WIDTH_SEMI_CONDENSED;
1195 		case psp::width::Normal:		 return WIDTH_NORMAL;
1196 		case psp::width::SemiExpanded:	 return WIDTH_SEMI_EXPANDED;
1197 		case psp::width::Expanded:		 return WIDTH_EXPANDED;
1198 		case psp::width::ExtraExpanded:	 return WIDTH_EXTRA_EXPANDED;
1199 		case psp::width::UltraExpanded:	 return WIDTH_ULTRA_EXPANDED;
1200         case psp::width::Unknown:        return WIDTH_DONTKNOW;
1201         default:
1202             DBG_ERROR( "unknown width mapping" );
1203             break;
1204 	}
1205 	return WIDTH_DONTKNOW;
1206 }
1207 
1208 FontWeight PspGraphics::ToFontWeight (psp::weight::type eWeight)
1209 {
1210 	switch (eWeight)
1211 	{
1212 		case psp::weight::Thin:		  return WEIGHT_THIN;
1213 		case psp::weight::UltraLight: return WEIGHT_ULTRALIGHT;
1214 		case psp::weight::Light:	  return WEIGHT_LIGHT;
1215 		case psp::weight::SemiLight:  return WEIGHT_SEMILIGHT;
1216 		case psp::weight::Normal:	  return WEIGHT_NORMAL;
1217 		case psp::weight::Medium:	  return WEIGHT_MEDIUM;
1218 		case psp::weight::SemiBold:	  return WEIGHT_SEMIBOLD;
1219 		case psp::weight::Bold:		  return WEIGHT_BOLD;
1220 		case psp::weight::UltraBold:  return WEIGHT_ULTRABOLD;
1221 		case psp::weight::Black:	  return WEIGHT_BLACK;
1222 		case psp::weight::Unknown:	  return WEIGHT_DONTKNOW;
1223         default:
1224             DBG_ERROR( "unknown weight mapping" );
1225             break;
1226 	}
1227 	return WEIGHT_DONTKNOW;
1228 }
1229 
1230 FontPitch PspGraphics::ToFontPitch (psp::pitch::type ePitch)
1231 {
1232 	switch (ePitch)
1233 	{
1234 		case psp::pitch::Fixed:		return PITCH_FIXED;
1235 		case psp::pitch::Variable:	return PITCH_VARIABLE;
1236 		case psp::pitch::Unknown:	return PITCH_DONTKNOW;
1237         default:
1238             DBG_ERROR( "unknown pitch mapping" );
1239             break;
1240 	}
1241 	return PITCH_DONTKNOW;
1242 }
1243 
1244 FontItalic PspGraphics::ToFontItalic (psp::italic::type eItalic)
1245 {
1246 	switch (eItalic)
1247 	{
1248 		case psp::italic::Upright:	return ITALIC_NONE;
1249 		case psp::italic::Oblique:	return ITALIC_OBLIQUE;
1250 		case psp::italic::Italic:	return ITALIC_NORMAL;
1251 		case psp::italic::Unknown:	return ITALIC_DONTKNOW;
1252         default:
1253             DBG_ERROR( "unknown italic mapping" );
1254             break;
1255 	}
1256 	return ITALIC_DONTKNOW;
1257 }
1258 
1259 FontFamily PspGraphics::ToFontFamily (psp::family::type eFamily)
1260 {
1261 	switch (eFamily)
1262 	{
1263 		case psp::family::Decorative: return FAMILY_DECORATIVE;
1264 		case psp::family::Modern:	  return FAMILY_MODERN;
1265 		case psp::family::Roman:	  return FAMILY_ROMAN;
1266 		case psp::family::Script:	  return FAMILY_SCRIPT;
1267 		case psp::family::Swiss:	  return FAMILY_SWISS;
1268 		case psp::family::System:	  return FAMILY_SYSTEM;
1269 		case psp::family::Unknown:	  return FAMILY_DONTKNOW;
1270         default:
1271             DBG_ERROR( "unknown family mapping" );
1272             break;
1273 	}
1274 	return FAMILY_DONTKNOW;
1275 }
1276 
1277 ImplDevFontAttributes PspGraphics::Info2DevFontAttributes( const psp::FastPrintFontInfo& rInfo )
1278 {
1279     ImplDevFontAttributes aDFA;
1280     aDFA.maName         = rInfo.m_aFamilyName;
1281     aDFA.maStyleName    = rInfo.m_aStyleName;
1282     aDFA.meFamily       = ToFontFamily (rInfo.m_eFamilyStyle);
1283     aDFA.meWeight       = ToFontWeight (rInfo.m_eWeight);
1284     aDFA.meItalic       = ToFontItalic (rInfo.m_eItalic);
1285     aDFA.meWidthType    = ToFontWidth (rInfo.m_eWidth);
1286     aDFA.mePitch        = ToFontPitch (rInfo.m_ePitch);
1287     aDFA.mbSymbolFlag   = (rInfo.m_aEncoding == RTL_TEXTENCODING_SYMBOL);
1288     aDFA.mbSubsettable  = rInfo.m_bSubsettable;
1289     aDFA.mbEmbeddable   = rInfo.m_bEmbeddable;
1290 
1291     switch( rInfo.m_eType )
1292     {
1293         case psp::fonttype::Builtin:
1294             aDFA.mnQuality       = 1024;
1295             aDFA.mbDevice        = true;
1296             break;
1297         case psp::fonttype::TrueType:
1298             aDFA.mnQuality       = 512;
1299             aDFA.mbDevice        = false;
1300             break;
1301         case psp::fonttype::Type1:
1302             aDFA.mnQuality       = 0;
1303             aDFA.mbDevice        = false;
1304             break;
1305         default:
1306             aDFA.mnQuality       = 0;
1307             aDFA.mbDevice        = false;
1308             break;
1309     }
1310 
1311     aDFA.mbOrientation   = true;
1312 
1313     // add font family name aliases
1314     ::std::list< OUString >::const_iterator it = rInfo.m_aAliases.begin();
1315     bool bHasMapNames = false;
1316     for(; it != rInfo.m_aAliases.end(); ++it )
1317     {
1318         if( bHasMapNames )
1319             aDFA.maMapNames.Append( ';' );
1320         aDFA.maMapNames.Append( (*it).getStr() );
1321 	bHasMapNames = true;
1322     }
1323 
1324 #if OSL_DEBUG_LEVEL > 2
1325     if( bHasMapNames )
1326     {
1327         ByteString aOrigName( aDFA.maName, osl_getThreadTextEncoding() );
1328         ByteString aAliasNames( aDFA.maMapNames, osl_getThreadTextEncoding() );
1329         fprintf( stderr, "using alias names \"%s\" for font family \"%s\"\n",
1330             aAliasNames.GetBuffer(), aOrigName.GetBuffer() );
1331     }
1332 #endif
1333 
1334     return aDFA;
1335 }
1336 
1337 // -----------------------------------------------------------------------
1338 
1339 void PspGraphics::AnnounceFonts( ImplDevFontList* pFontList, const psp::FastPrintFontInfo& aInfo )
1340 {
1341     int nQuality = 0;
1342 
1343     if( aInfo.m_eType == psp::fonttype::TrueType )
1344     {
1345         // asian type 1 fonts are not known
1346         psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1347         ByteString aFileName( rMgr.getFontFileSysPath( aInfo.m_nID ) );
1348         int nPos = aFileName.SearchBackward( '_' );
1349         if( nPos == STRING_NOTFOUND || aFileName.GetChar( nPos+1 ) == '.' )
1350             nQuality += 5;
1351         else
1352         {
1353             static const char* pLangBoost = NULL;
1354             static bool bOnce = true;
1355             if( bOnce )
1356             {
1357                 bOnce = false;
1358                 const LanguageType aLang = Application::GetSettings().GetUILanguage();
1359                 switch( aLang )
1360                 {
1361                     case LANGUAGE_JAPANESE:
1362                         pLangBoost = "jan";
1363                         break;
1364                     case LANGUAGE_CHINESE:
1365                     case LANGUAGE_CHINESE_SIMPLIFIED:
1366                     case LANGUAGE_CHINESE_SINGAPORE:
1367                         pLangBoost = "zhs";
1368                         break;
1369                     case LANGUAGE_CHINESE_TRADITIONAL:
1370                     case LANGUAGE_CHINESE_HONGKONG:
1371                     case LANGUAGE_CHINESE_MACAU:
1372                         pLangBoost = "zht";
1373                         break;
1374                     case LANGUAGE_KOREAN:
1375                     case LANGUAGE_KOREAN_JOHAB:
1376                         pLangBoost = "kor";
1377                         break;
1378                 }
1379             }
1380 
1381             if( pLangBoost )
1382                 if( aFileName.Copy( nPos+1, 3 ).EqualsIgnoreCaseAscii( pLangBoost ) )
1383                     nQuality += 10;
1384         }
1385     }
1386 
1387     ImplPspFontData* pFD = new ImplPspFontData( aInfo );
1388     pFD->mnQuality += nQuality;
1389     pFontList->Add( pFD );
1390 }
1391 
1392 bool PspGraphics::filterText( const String& rOrig, String& rNewText, xub_StrLen nIndex, xub_StrLen& rLen, xub_StrLen& rCutStart, xub_StrLen& rCutStop )
1393 {
1394 	if( ! m_pPhoneNr )
1395 		return false;
1396 
1397     rCutStop = rCutStart = STRING_NOTFOUND;
1398 
1399 #define FAX_PHONE_TOKEN          "@@#"
1400 #define FAX_PHONE_TOKEN_LENGTH   3
1401 #define FAX_END_TOKEN            "@@"
1402 #define FAX_END_TOKEN_LENGTH     2
1403 
1404 	bool bRet = false;
1405 	bool bStarted = false;
1406 	bool bStopped = false;
1407 	sal_uInt16 nPos;
1408 	sal_uInt16 nStart = 0;
1409 	sal_uInt16 nStop = rLen;
1410 	String aPhone = rOrig.Copy( nIndex, rLen );
1411 
1412 	if( ! m_bPhoneCollectionActive )
1413 	{
1414 		if( ( nPos = aPhone.SearchAscii( FAX_PHONE_TOKEN ) ) != STRING_NOTFOUND )
1415 		{
1416 			nStart = nPos;
1417 			m_bPhoneCollectionActive = true;
1418 			m_aPhoneCollection.Erase();
1419 			bRet = true;
1420 			bStarted = true;
1421 		}
1422 	}
1423 	if( m_bPhoneCollectionActive )
1424 	{
1425 		bRet = true;
1426 		nPos = bStarted ? nStart + FAX_PHONE_TOKEN_LENGTH : 0;
1427 		if( ( nPos = aPhone.SearchAscii( FAX_END_TOKEN, nPos ) ) != STRING_NOTFOUND )
1428 		{
1429 			m_bPhoneCollectionActive = false;
1430 			nStop = nPos + FAX_END_TOKEN_LENGTH;
1431 			bStopped = true;
1432 		}
1433 		int nTokenStart = nStart + (bStarted ? FAX_PHONE_TOKEN_LENGTH : 0);
1434 		int nTokenStop = nStop - (bStopped ? FAX_END_TOKEN_LENGTH : 0);
1435 		m_aPhoneCollection += aPhone.Copy( nTokenStart, nTokenStop - nTokenStart );
1436 		if( ! m_bPhoneCollectionActive )
1437 		{
1438             m_pPhoneNr->AppendAscii( "<Fax#>" );
1439 			m_pPhoneNr->Append( m_aPhoneCollection );
1440             m_pPhoneNr->AppendAscii( "</Fax#>" );
1441 			m_aPhoneCollection.Erase();
1442 		}
1443 	}
1444 	if( m_aPhoneCollection.Len() > 1024 )
1445 	{
1446 		m_bPhoneCollectionActive = false;
1447 		m_aPhoneCollection.Erase();
1448 		bRet = false;
1449 	}
1450 
1451     if( bRet && m_bSwallowFaxNo )
1452     {
1453         rLen -= nStop - nStart;
1454         rCutStart = nStart+nIndex;
1455         rCutStop = nStop+nIndex;
1456         if( rCutStart )
1457             rNewText = rOrig.Copy( 0, rCutStart );
1458         rNewText += rOrig.Copy( rCutStop );
1459     }
1460 
1461     return bRet && m_bSwallowFaxNo;
1462 }
1463 
1464 bool PspGraphics::drawAlphaBitmap( const SalTwoRect&,
1465                                    const SalBitmap&,
1466                                    const SalBitmap& )
1467 {
1468     return false;
1469 }
1470 
1471 bool PspGraphics::drawAlphaRect( long, long, long, long, sal_uInt8 )
1472 {
1473     return false;
1474 }
1475 
1476 SystemGraphicsData PspGraphics::GetGraphicsData() const
1477 {
1478     SystemGraphicsData aRes;
1479     aRes.nSize = sizeof(aRes);
1480         aRes.hDrawable = 0;
1481         aRes.pRenderFormat = 0;
1482     return aRes;
1483 }
1484 
1485 SystemFontData PspGraphics::GetSysFontData( int nFallbacklevel ) const
1486 {
1487     SystemFontData aSysFontData;
1488 
1489     if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
1490     if (nFallbacklevel < 0 ) nFallbacklevel = 0;
1491 
1492     aSysFontData.nSize = sizeof( SystemFontData );
1493     aSysFontData.nFontId = 0;
1494     aSysFontData.nFontFlags = 0;
1495     aSysFontData.bFakeBold = false;
1496     aSysFontData.bFakeItalic = false;
1497     aSysFontData.bAntialias = true;
1498     return aSysFontData;
1499 }
1500 
1501 bool PspGraphics::supportsOperation( OutDevSupportType ) const
1502 {
1503     return false;
1504 }
1505