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