1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: text_gfx.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
36 #include "psputil.hxx"
37 #include "glyphset.hxx"
39 #include "vcl/printergfx.hxx"
40 #include "vcl/fontmanager.hxx"
41 #include "vcl/helper.hxx"
43 #include "osl/thread.h"
45 #include "sal/alloca.h"
51 container for a font and its helper fonts:
52 1st font is the font substitute e.g. helvetica substitutes arial on the printer
53 2nd is the font itself
54 3rd is a fallback font, usually a font with unicode glyph repertoir (e.g. andale)
55 symbol fonts (adobe-fontspecific) may need special glyphmapping
56 (symbol page vc. latin page)
64 fontID mpFont
[Font3Size
];
69 fontID
GetFont (int nIdx
) const
70 { return nIdx
< Font3Size
? mpFont
[nIdx
] : -1 ; }
71 bool IsSymbolFont () const
74 Font3 (const PrinterGfx
&rGfx
);
78 Font3::Font3(const PrinterGfx
&rGfx
)
80 mpFont
[0] = rGfx
.getFontSubstitute();
81 mpFont
[1] = rGfx
.GetFontID();
82 mpFont
[2] = rGfx
.getFallbackID();
83 // mpFont[2] = rGfx.GetFontID();
85 PrintFontManager
&rMgr
= PrintFontManager::get();
86 mbSymbol
= mpFont
[1] != -1 ?
87 rMgr
.getFontEncoding(mpFont
[1]) == RTL_TEXTENCODING_SYMBOL
: false;
92 static int getVerticalDeltaAngle( sal_Unicode nChar
)
95 if( ( nChar
>= 0x1100 && nChar
< 0x11fa ) ||
96 ( nChar
>= 0x3000 && nChar
< 0xfb00 ) ||
97 ( nChar
>= 0xfe20 && nChar
< 0xfe70 ) ||
98 ( nChar
>= 0xff00 && nChar
< 0xff64 )
101 /* #i52932# remember:
102 nChar == 0x2010 || nChar == 0x2015
103 nChar == 0x2016 || nChar == 0x2026
105 are nAngle = 0 also, but already handled in the first if
107 if( ( nChar
>= 0x3008 && nChar
< 0x3019 && nChar
!= 0x3012 ) ||
108 nChar
== 0xff3b || nChar
== 0xff3d ||
109 (nChar
>= 0xff6b && nChar
< 0xff64 ) ||
113 else if( nChar
== 0x30fc )
122 PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID
)
124 std::list
< sal_Int32
>::iterator aFont
;
125 // already in the document header ?
126 for (aFont
= maPS1Font
.begin(); aFont
!= maPS1Font
.end(); ++aFont
)
127 if( nFontID
== *aFont
)
130 // no occurrenc yet, mark for download
131 // add the fontid to the list
132 maPS1Font
.push_back (nFontID
);
136 * implement text handling printer routines,
150 // font and encoding will be set by drawText again immediately
153 maVirtualStatus
.maFont
= rtl::OString();
154 maVirtualStatus
.maEncoding
= RTL_TEXTENCODING_DONTKNOW
;
155 maVirtualStatus
.mnTextHeight
= nHeight
;
156 maVirtualStatus
.mnTextWidth
= nWidth
;
157 maVirtualStatus
.mbArtItalic
= bArtItalic
;
158 maVirtualStatus
.mbArtBold
= bArtBold
;
159 mnTextAngle
= nAngle
;
160 mbTextVertical
= bVertical
;
166 PrinterGfx::SetFallbackFont ( sal_Int32 nFontID
)
168 mnFallbackID
= nFontID
;
172 void PrinterGfx::drawGlyphs(
174 sal_uInt32
* pGlyphIds
,
175 sal_Unicode
* pUnicodes
,
177 sal_Int32
* pDeltaArray
182 // search for a glyph set matching the set font
183 std::list
< GlyphSet
>::iterator aIter
;
184 for (aIter
= maPS3Font
.begin(); aIter
!= maPS3Font
.end(); aIter
++)
185 if ( ((*aIter
).GetFontID() == mnFontID
)
186 && ((*aIter
).IsVertical() == mbTextVertical
))
188 (*aIter
).DrawGlyphs (*this, rPoint
, pGlyphIds
, pUnicodes
, nLen
, pDeltaArray
);
192 // not found ? create a new one
193 if (aIter
== maPS3Font
.end())
195 maPS3Font
.push_back (GlyphSet(mnFontID
, mbTextVertical
));
196 maPS3Font
.back().DrawGlyphs (*this, rPoint
, pGlyphIds
, pUnicodes
, nLen
, pDeltaArray
);
200 void PrinterGfx::DrawGlyphs(
202 sal_GlyphId
* pGlyphIds
,
203 sal_Unicode
* pUnicodes
,
205 sal_Int32
* pDeltaArray
211 if ( !mrFontMgr
.isFontDownloadingAllowed( mnFontID
) )
213 LicenseWarning(rPoint
, pUnicodes
, nLen
, pDeltaArray
);
217 if( mrFontMgr
.getFontType( mnFontID
) != fonttype::TrueType
)
219 DrawText( rPoint
, pUnicodes
, nLen
, pDeltaArray
);
223 // move and rotate the user coordinate system
224 // avoid the gsave/grestore for the simple cases since it allows
225 // reuse of the current font if it hasn't changed
226 sal_Int32 nCurrentTextAngle
= mnTextAngle
;
227 Point
aPoint( rPoint
);
229 if (nCurrentTextAngle
!= 0)
232 PSTranslate (rPoint
);
233 PSRotate (nCurrentTextAngle
);
235 aPoint
= Point( 0, 0 );
240 // vertical glyphs can have an additional rotation ... sigh.
241 // so break up text in chunks of normal glyphs and print out
242 // specially rotated glyphs extra
243 sal_uInt32
* pTempGlyphIds
= (sal_uInt32
*)alloca(sizeof(sal_Int32
)*nLen
);
244 sal_Int32
* pTempDelta
= (sal_Int32
*)alloca(sizeof(sal_Int32
)*nLen
);
245 sal_Unicode
* pTempUnicodes
= (sal_Unicode
*)alloca(sizeof(sal_Unicode
)*nLen
);
246 sal_Int16 nTempLen
= 0;
247 sal_Int32 nTempFirstDelta
= 0;
249 sal_Int32 nTextHeight
= maVirtualStatus
.mnTextHeight
;
250 sal_Int32 nTextWidth
= maVirtualStatus
.mnTextWidth
? maVirtualStatus
.mnTextWidth
: maVirtualStatus
.mnTextHeight
;
251 sal_Int32 nAscend
= mrFontMgr
.getFontAscend( mnFontID
);
252 sal_Int32 nDescend
= mrFontMgr
.getFontDescend( mnFontID
);
254 nDescend
= nDescend
* nTextHeight
/ 1000;
255 nAscend
= nAscend
* nTextHeight
/ 1000;
257 for( sal_Int16 i
= 0; i
< nLen
; i
++ )
259 const sal_GlyphId nRot
= pGlyphIds
[i
] & GF_ROTMASK
;
260 if( nRot
== GF_NONE
)
262 pTempUnicodes
[nTempLen
] = pUnicodes
[i
];
263 pTempGlyphIds
[nTempLen
] = pGlyphIds
[i
];
265 pTempDelta
[nTempLen
-1] = pDeltaArray
[i
-1]-nTempFirstDelta
;
268 // the first element in pDeltaArray shows
269 // the offset of the second character
270 // so if the first glyph is normal
271 // then we do not need to move the delta indices
272 // else we have to move them down by one and
273 // recalculate aPoint and all deltas
275 nTempFirstDelta
= pDeltaArray
[ i
-1 ];
281 sal_Int32 nOffset
= i
> 0 ? pDeltaArray
[i
-1] : 0;
282 sal_Int32 nRotAngle
= 0;
287 aRotPoint
= Point( -nAscend
*nTextWidth
/nTextHeight
, -nDescend
*nTextWidth
/nTextHeight
- nOffset
);
291 aRotPoint
= Point( -nOffset
, (nAscend
+nDescend
) );
295 aRotPoint
= Point( -nDescend
*nTextWidth
/nTextHeight
, nOffset
+ nAscend
*nTextWidth
/nTextHeight
);
298 sal_GlyphId nRotGlyphId
= pGlyphIds
[i
];
299 sal_Unicode nRotUnicode
= pUnicodes
[i
];
300 sal_Int32 nRotDelta
= 0;
302 // transform matrix to new individual direction
304 GraphicsStatus aSaveStatus
= maVirtualStatus
;
305 if( nRot
!= 2 ) // switch font aspect
307 maVirtualStatus
.mnTextWidth
= nTextHeight
;
308 maVirtualStatus
.mnTextHeight
= nTextWidth
;
310 if( aPoint
.X() || aPoint
.Y() )
311 PSTranslate( aPoint
);
312 PSRotate (nRotAngle
);
313 // draw the rotated glyph
314 drawGlyphs( aRotPoint
, &nRotGlyphId
, &nRotUnicode
, 1, &nRotDelta
);
316 // restore previous state
317 maVirtualStatus
= aSaveStatus
;
322 pGlyphIds
= pTempGlyphIds
;
323 pUnicodes
= pTempUnicodes
;
324 pDeltaArray
= pTempDelta
;
327 aPoint
.X() += nTempFirstDelta
;
331 drawGlyphs( aPoint
, pGlyphIds
, pUnicodes
, nLen
, pDeltaArray
);
333 // restore the user coordinate system
334 if (nCurrentTextAngle
!= 0)
337 mnTextAngle
= nCurrentTextAngle
;
342 PrinterGfx::DrawText (
344 const sal_Unicode
* pStr
,
346 const sal_Int32
* pDeltaArray
349 fontID nRestoreFont
= mnFontID
;
351 // setup font[substitutes] and map the string into the symbol area in case of
354 sal_Unicode
*pEffectiveStr
;
355 if ( aFont
.IsSymbolFont() )
357 pEffectiveStr
= (sal_Unicode
*)alloca(nLen
* sizeof(pStr
[0]));
358 for (int i
= 0; i
< nLen
; i
++)
359 pEffectiveStr
[i
] = pStr
[i
] < 256 ? pStr
[i
] + 0xF000 : pStr
[i
];
363 pEffectiveStr
= const_cast<sal_Unicode
*>(pStr
);
366 fontID
*pFontMap
= (fontID
*) alloca(nLen
* sizeof(fontID
));
367 sal_Int32
*pCharWidth
= (sal_Int32
*) alloca(nLen
* sizeof(sal_Int32
));
369 for( int n
= 0; n
< nLen
; n
++ )
371 CharacterMetric aBBox
;
372 pFontMap
[n
] = getCharMetric (aFont
, pEffectiveStr
[n
], &aBBox
);
373 pCharWidth
[n
] = getCharWidth (mbTextVertical
, pEffectiveStr
[n
], &aBBox
);
376 // setup a new delta array, use virtual resolution of 1000
377 sal_Int32
* pNewDeltaArray
= (sal_Int32
*)alloca( sizeof( sal_Int32
)*nLen
);
378 if ( pDeltaArray
!= 0)
380 for (int i
= 0; i
< nLen
- 1; i
++)
381 pNewDeltaArray
[i
] = 1000 * pDeltaArray
[i
];
382 pNewDeltaArray
[nLen
- 1] = 0;
386 pNewDeltaArray
[0] = pCharWidth
[0];
387 for (int i
= 1; i
< nLen
; i
++)
388 pNewDeltaArray
[i
] = pNewDeltaArray
[i
-1] + pCharWidth
[i
];
391 // move and rotate the user coordinate system
392 // avoid the gsave/grestore for the simple cases since it allows
393 // reuse of the current font if it hasn't changed
394 sal_Int32 nCurrentTextAngle
= mnTextAngle
;
395 sal_Int32 nCurrentPointX
;
396 sal_Int32 nCurrentPointY
;
398 if (nCurrentTextAngle
!= 0)
401 PSTranslate (rPoint
);
402 PSRotate (nCurrentTextAngle
);
410 nCurrentPointX
= rPoint
.X();
411 nCurrentPointY
= rPoint
.Y();
415 sal_Int32 nDelta
= 0;
416 for (int nTo
= 0; nTo
< nLen
; )
419 fontID nFont
= pFontMap
[ nFrom
];
421 while ((nTo
< nLen
) && (nFont
== pFontMap
[nTo
]))
423 pNewDeltaArray
[ nTo
] = (sal_Int32
)(((0.5 + pNewDeltaArray
[ nTo
]) / 1000.0) - nDelta
);
428 maVirtualStatus
.mnTextHeight
, maVirtualStatus
.mnTextWidth
,
431 maVirtualStatus
.mbArtItalic
,
432 maVirtualStatus
.mbArtBold
437 drawVerticalizedText(
438 Point(nCurrentPointX
+ nDelta
, nCurrentPointY
),
439 pEffectiveStr
+ nFrom
, nTo
- nFrom
,
440 pNewDeltaArray
+ nFrom
);
445 Point(nCurrentPointX
+ nDelta
, nCurrentPointY
),
446 pEffectiveStr
+ nFrom
, nTo
- nFrom
,
447 pDeltaArray
== NULL
? NULL
: pNewDeltaArray
+ nFrom
);
449 nDelta
+= pNewDeltaArray
[ nTo
- 1 ];
452 // restore the user coordinate system
453 if (nCurrentTextAngle
!= 0)
456 mnTextAngle
= nCurrentTextAngle
;
459 // restore the original font settings
460 SetFont( nRestoreFont
,
461 maVirtualStatus
.mnTextHeight
, maVirtualStatus
.mnTextWidth
,
462 mnTextAngle
, mbTextVertical
,
463 maVirtualStatus
.mbArtItalic
,
464 maVirtualStatus
.mbArtBold
468 void PrinterGfx::drawVerticalizedText(
470 const sal_Unicode
* pStr
,
472 const sal_Int32
* pDeltaArray
475 sal_Int32
* pDelta
= (sal_Int32
*)alloca( nLen
* sizeof(sal_Int32
) );
477 int nTextScale
= maVirtualStatus
.mnTextWidth
? maVirtualStatus
.mnTextWidth
: maVirtualStatus
.mnTextHeight
;
478 int nNormalAngle
= mnTextAngle
;
479 int nDeltaAngle
, nLastPos
= 0;
481 double fSin
= sin( -2.0*M_PI
*nNormalAngle
/3600 );
482 double fCos
= cos( -2.0*M_PI
*nNormalAngle
/3600 );
484 PrintFontManager
&rMgr
= PrintFontManager::get();
486 rMgr
.getFontInfo( mnFontID
, aInfo
);
488 bool* pGsubFlags
= (bool*)alloca( nLen
* sizeof(bool) );
489 rMgr
.hasVerticalSubstitutions( mnFontID
, pStr
, nLen
, pGsubFlags
);
491 Point
aPoint( rPoint
);
492 for( int i
= 0; i
< nLen
; )
494 while( ( nDeltaAngle
= getVerticalDeltaAngle( pStr
[i
] ) ) == 0 && i
< nLen
)
496 if( i
<= nLen
&& i
> nLastPos
)
498 for( int n
= nLastPos
; n
< i
; n
++ )
499 pDelta
[n
] = pDeltaArray
[n
] - (aPoint
.X() - rPoint
.X() );
502 maVirtualStatus
.mnTextHeight
, maVirtualStatus
.mnTextWidth
,
503 nNormalAngle
, mbTextVertical
,
504 maVirtualStatus
.mbArtItalic
,
505 maVirtualStatus
.mbArtBold
);
506 drawText( aPoint
, pStr
+ nLastPos
, i
- nLastPos
, pDelta
+ nLastPos
);
508 aPoint
.X() = (sal_Int32
)(rPoint
.X() + ((double)pDeltaArray
[i
-1] * fCos
));
509 aPoint
.Y() = (sal_Int32
)(rPoint
.Y() + ((double)pDeltaArray
[i
-1] * fSin
));
513 int nOldWidth
= maVirtualStatus
.mnTextWidth
;
514 int nOldHeight
= maVirtualStatus
.mnTextHeight
;
517 maVirtualStatus
.mnTextHeight
,
518 nNormalAngle
+ nDeltaAngle
,
520 maVirtualStatus
.mbArtItalic
,
521 maVirtualStatus
.mbArtBold
);
523 double nA
= nTextScale
* aInfo
.m_nAscend
/ 1000.0;
524 double nD
= nTextScale
* aInfo
.m_nDescend
/ 1000.0;
525 double fStretch
= (double)maVirtualStatus
.mnTextWidth
/ maVirtualStatus
.mnTextHeight
;
529 Point
aPos( aPoint
);
530 switch( nDeltaAngle
)
533 aPos
.X() += (sal_Int32
)(+nA
* fCos
+ nD
* fSin
);
534 aPos
.Y() += (sal_Int32
)(-nA
* fSin
+ nD
* fCos
);
537 aPos
.X() += (sal_Int32
)(+nA
* fSin
+ nD
* fCos
);
538 aPos
.Y() += (sal_Int32
)(-(nTextScale
*fStretch
- nD
) * fCos
);
541 drawText( aPos
, pStr
+i
, 1, NULL
);
542 if( i
< nLen
-1 && pDeltaArray
)
544 aPoint
.X() = (sal_Int32
)(rPoint
.X() + ((double)pDeltaArray
[i
] * fCos
));
545 aPoint
.Y() = (sal_Int32
)(rPoint
.Y() + ((double)pDeltaArray
[i
] * fSin
));
548 // swap text width/height again
554 maVirtualStatus
.mbArtItalic
,
555 maVirtualStatus
.mbArtBold
);
560 mnTextAngle
= nNormalAngle
;
564 PrinterGfx::LicenseWarning(const Point
& rPoint
, const sal_Unicode
* pStr
,
565 sal_Int16 nLen
, const sal_Int32
* pDeltaArray
)
567 // treat it like a builtin font in case a user has that font also in the
568 // printer. This is not so unlikely as it may seem; no print embedding
569 // licensed fonts are often used (or so they say) in companies:
570 // they are installed on displays and printers, but get not embedded in
571 // they are installed on displays and printers, but get not embedded in
572 // print files or documents because they are not licensed for use outside
574 rtl::OString
aMessage( "The font " );
575 aMessage
+= rtl::OUStringToOString( mrFontMgr
.getPSName(mnFontID
),
576 RTL_TEXTENCODING_ASCII_US
);
577 aMessage
+= " could not be downloaded\nbecause its license does not allow for that";
578 PSComment( aMessage
.getStr() );
580 rtl::OString aFontName
= rtl::OUStringToOString(
581 mrFontMgr
.getPSName(mnFontID
),
582 RTL_TEXTENCODING_ASCII_US
);
583 PSSetFont (aFontName
, RTL_TEXTENCODING_ISO_8859_1
);
585 sal_Size nSize
= 4 * nLen
;
586 sal_uChar
* pBuffer
= (sal_uChar
*)alloca (nSize
* sizeof(sal_uChar
));
588 ConverterFactory
* pCvt
= GetConverterFactory ();
589 nSize
= pCvt
->Convert (pStr
, nLen
, pBuffer
, nSize
, RTL_TEXTENCODING_ISO_8859_1
);
592 PSShowText (pBuffer
, nLen
, nSize
, pDeltaArray
);
596 PrinterGfx::drawText(
598 const sal_Unicode
* pStr
,
600 const sal_Int32
* pDeltaArray
606 fonttype::type eType
= mrFontMgr
.getFontType (mnFontID
);
608 if (eType
== fonttype::Type1
)
609 PSUploadPS1Font (mnFontID
);
611 if ( eType
== fonttype::TrueType
612 && !mrFontMgr
.isFontDownloadingAllowed(mnFontID
))
614 LicenseWarning(rPoint
, pStr
, nLen
, pDeltaArray
);
618 if( mrFontMgr
.getUseOnlyFontEncoding( mnFontID
) )
620 GlyphSet
aGSet( mnFontID
, mbTextVertical
);
621 aGSet
.DrawText( *this, rPoint
, pStr
, nLen
, pDeltaArray
);
625 // search for a glyph set matching the set font
626 std::list
< GlyphSet
>::iterator aIter
;
627 for (aIter
= maPS3Font
.begin(); aIter
!= maPS3Font
.end(); aIter
++)
628 if ( ((*aIter
).GetFontID() == mnFontID
)
629 && ((*aIter
).IsVertical() == mbTextVertical
))
631 (*aIter
).DrawText (*this, rPoint
, pStr
, nLen
, pDeltaArray
);
635 // not found ? create a new one
636 if (aIter
== maPS3Font
.end())
638 maPS3Font
.push_back (GlyphSet(mnFontID
, mbTextVertical
));
639 maPS3Font
.back().DrawText (*this, rPoint
, pStr
, nLen
, pDeltaArray
);
644 PrinterGfx::getCharWidth (sal_Bool b_vert
, sal_Unicode n_char
, CharacterMetric
*p_bbox
)
646 b_vert
= b_vert
&& (getVerticalDeltaAngle(n_char
) != 0);
647 int w
= b_vert
? p_bbox
->height
: p_bbox
->width
;
648 w
*= maVirtualStatus
.mnTextWidth
? maVirtualStatus
.mnTextWidth
: maVirtualStatus
.mnTextHeight
;
653 PrinterGfx::getCharMetric (const Font3
&rFont
, sal_Unicode n_char
, CharacterMetric
*p_bbox
)
658 for (fontID n
= 0; n
< 3; n
++)
660 fontID n_font
= rFont
.GetFont(n
);
663 if( mbStrictSO52Compatibility
)
665 fonttype::type eType
= mrFontMgr
.getFontType( n_font
);
666 if( (eType
== fonttype::Builtin
|| eType
== fonttype::Type1
) )
668 // note: any character exchanged here MUST also be changed
669 // in the compatibility ISO encoding vector in the prolog
671 sal_Unicode aRepl
= 0;
674 else if( n_char
== 0x27 )
677 additional characters that may need backwards compatibility:
678 ISO5589 StdEnc Unicode suggested n_char -> aRepl
679 0264 0302 0x00B4 0x00B4 (acute) -> 0x2019 (quiteright)
680 0246 - 0x00A6 0x00A6 (brokenbar) -> 0x007C (bar)
681 0225 0267 0x0095 0x0095 () -> 0x2022 (bullet)
682 0140 0301 0x0060 0x0060 (grave) -> ?
686 mrFontMgr
.getMetrics( n_font
, aRepl
, aRepl
, p_bbox
);
687 if (p_bbox
->width
>= 0 && p_bbox
->height
>= 0)
692 mrFontMgr
.getMetrics( n_font
, n_char
, n_char
, p_bbox
);
694 if (p_bbox
->width
>= 0 && p_bbox
->height
>= 0)
698 return getCharMetric (rFont
, '?', p_bbox
);
700 return rFont
.GetFont(0) != -1 ? rFont
.GetFont(0) : rFont
.GetFont(1);
704 PrinterGfx::getFontSubstitute () const
706 if( mpFontSubstitutes
)
708 ::std::hash_map
< fontID
, fontID
>::const_iterator it
=
709 mpFontSubstitutes
->find( mnFontID
);
710 if( it
!= mpFontSubstitutes
->end() )
718 PrinterGfx::GetCharWidth (sal_Unicode nFrom
, sal_Unicode nTo
, long *pWidthArray
)
721 if (aFont
.IsSymbolFont() && (nFrom
< 256) && (nTo
< 256))
727 for( int n
= 0; n
< (nTo
- nFrom
+ 1); n
++ )
729 CharacterMetric aBBox
;
730 getCharMetric (aFont
, n
+ nFrom
, &aBBox
);
731 pWidthArray
[n
] = getCharWidth (mbTextVertical
, n
+ nFrom
, &aBBox
);
734 // returned metrics have postscript precision
738 const ::std::list
< KernPair
>& PrinterGfx::getKernPairs( bool bVertical
) const
741 * Note: this is only a 80% solution: if a font is only
742 * partially substituted in a string due to missing glyphs
743 * the results may not be perfect; the more so the more the
744 * substitution differs from the original metricwise. But
745 * vcl only asks for KernPairs for each font once and NOT
746 * in a string context this is the best we can do.
747 * In future the kerning should be done on a per string basis.
749 fontID nFont
= mnFontID
;
750 if( mpFontSubstitutes
)
752 ::std::hash_map
< fontID
, fontID
>::const_iterator it
=
753 mpFontSubstitutes
->find( mnFontID
);
754 if( it
!= mpFontSubstitutes
->end() )
757 return mrFontMgr
.getKernPairs( nFont
, bVertical
);
761 * advanced glyph handling
765 PrinterGfx::GetGlyphBoundRect (sal_Unicode
/*c*/, Rectangle
& /*rOutRect*/)
771 PrinterGfx::GetGlyphOutline (sal_Unicode
/*c*/,
772 sal_uInt16
**/
*ppPolySizes*/
, Point
**/
*ppPoints*/
, sal_uInt8
**/
*ppFlags*/
)
778 * spool the converted truetype fonts to the page header after the page body is
780 * for Type1 fonts spool additional reencoding vectors that are necessary to access the
785 PrinterGfx::OnEndPage ()
790 PrinterGfx::OnEndJob ()
797 PrinterGfx::writeResources( osl::File
* pFile
, std::list
< rtl::OString
>& rSuppliedFonts
, std::list
< rtl::OString
>& rNeededFonts
)
799 // write all type 1 fonts
800 std::list
< sal_Int32
>::iterator aFont
;
801 // already in the document header ?
802 for (aFont
= maPS1Font
.begin(); aFont
!= maPS1Font
.end(); ++aFont
)
804 const rtl::OString
& rSysPath (mrFontMgr
.getFontFileSysPath(*aFont
) );
805 rtl::OUString aUNCPath
;
806 osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath
, osl_getThreadTextEncoding()), aUNCPath
);
807 osl::File
aFontFile (aUNCPath
);
809 // provide the pfb or pfa font as a (pfa-)font resource
810 rtl::OString aPostScriptName
=
811 rtl::OUStringToOString ( mrFontMgr
.getPSName(*aFont
),
812 RTL_TEXTENCODING_ASCII_US
);
814 WritePS (pFile
, "%%BeginResource: font ");
815 WritePS (pFile
, aPostScriptName
.getStr());
816 WritePS (pFile
, "\n");
818 osl::File::RC nError
= aFontFile
.open (OpenFlag_Read
);
819 if (nError
== osl::File::E_None
)
821 convertPfbToPfa (aFontFile
, *pFile
);
824 pFile
->setPos(osl_Pos_Current
, -1);
825 char lastchar
= '\n';
826 sal_uInt64
uBytes(1);
827 pFile
->read((void *)(&lastchar
), uBytes
, uBytes
);
828 if (lastchar
!= '\n')
829 WritePS (pFile
, "\n");
831 WritePS (pFile
, "%%EndResource\n");
832 rSuppliedFonts
.push_back( aPostScriptName
);
835 // write glyphsets and reencodings
836 std::list
< GlyphSet
>::iterator aIter
;
837 for (aIter
= maPS3Font
.begin(); aIter
!= maPS3Font
.end(); ++aIter
)
839 if (aIter
->GetFontType() == fonttype::TrueType
)
841 aIter
->PSUploadFont (*pFile
, *this, mbUploadPS42Fonts
? true : false, rSuppliedFonts
);
844 // ( aIter->GetFontType() == fonttype::Type1
845 // || aIter->GetFontType() == fonttype::Builtin )
847 aIter
->PSUploadEncoding (pFile
, *this);
848 if( aIter
->GetFontType() == fonttype::Builtin
)
849 rNeededFonts
.push_back(
850 rtl::OUStringToOString(
851 mrFontMgr
.getPSName( aIter
->GetFontID() ),
852 RTL_TEXTENCODING_ASCII_US
) );
857 bool PrinterGfx::getStrictSO52Compatibility() const
859 return mbStrictSO52Compatibility
;
862 void PrinterGfx::setStrictSO52Compatibility( bool bCompat
)
864 mbStrictSO52Compatibility
= bCompat
;