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