merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / printergfx / text_gfx.cxx
blobee73217768b79847087cee4026a035e6a5f66a17
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: text_gfx.cxx,v $
10 * $Revision: 1.31 $
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"
34 #include <math.h>
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"
47 using namespace psp ;
49 namespace psp {
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)
58 class Font3
60 private:
62 #define Font3Size 3
64 fontID mpFont [Font3Size];
65 bool mbSymbol;
67 public:
69 fontID GetFont (int nIdx) const
70 { return nIdx < Font3Size ? mpFont[nIdx] : -1 ; }
71 bool IsSymbolFont () const
72 { return mbSymbol; }
74 Font3 (const PrinterGfx &rGfx);
75 ~Font3 () {}
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;
90 } // namespace psp
92 static int getVerticalDeltaAngle( sal_Unicode nChar )
94 int nAngle = 0;
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 ) ||
110 nChar == 0xffe3
112 nAngle = 0;
113 else if( nChar == 0x30fc )
114 nAngle = -900;
115 else
116 nAngle = 900;
118 return nAngle;
121 void
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 )
128 return;
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,
139 sal_uInt16
140 PrinterGfx::SetFont(
141 sal_Int32 nFontID,
142 sal_Int32 nHeight,
143 sal_Int32 nWidth,
144 sal_Int32 nAngle,
145 bool bVertical,
146 bool bArtItalic,
147 bool bArtBold
150 // font and encoding will be set by drawText again immediately
151 // before PSShowText
152 mnFontID = nFontID;
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;
162 return 0;
165 sal_uInt16
166 PrinterGfx::SetFallbackFont ( sal_Int32 nFontID )
168 mnFallbackID = nFontID;
169 return 0;
172 void PrinterGfx::drawGlyphs(
173 const Point& rPoint,
174 sal_uInt32* pGlyphIds,
175 sal_Unicode* pUnicodes,
176 sal_Int16 nLen,
177 sal_Int32* pDeltaArray
181 // draw the string
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);
189 break;
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(
201 const Point& rPoint,
202 sal_GlyphId* pGlyphIds,
203 sal_Unicode* pUnicodes,
204 sal_Int16 nLen,
205 sal_Int32* pDeltaArray
208 if( nLen <= 0 )
209 return;
211 if ( !mrFontMgr.isFontDownloadingAllowed( mnFontID ) )
213 LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray);
214 return;
217 if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType )
219 DrawText( rPoint, pUnicodes, nLen, pDeltaArray );
220 return;
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)
231 PSGSave ();
232 PSTranslate (rPoint);
233 PSRotate (nCurrentTextAngle);
234 mnTextAngle = 0;
235 aPoint = Point( 0, 0 );
238 if( mbTextVertical )
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;
248 Point aRotPoint;
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];
264 if( nTempLen > 0 )
265 pTempDelta[nTempLen-1] = pDeltaArray[i-1]-nTempFirstDelta;
266 else
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
274 if( i != 0 )
275 nTempFirstDelta = pDeltaArray[ i-1 ];
277 nTempLen++;
279 else
281 sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0;
282 sal_Int32 nRotAngle = 0;
283 switch( nRot )
285 case GF_ROTR:
286 nRotAngle = 2700;
287 aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset );
288 break;
289 case GF_VERT:
290 nRotAngle = 1800;
291 aRotPoint = Point( -nOffset, (nAscend+nDescend) );
292 break;
293 case GF_ROTL:
294 nRotAngle = 900;
295 aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight );
296 break;
298 sal_GlyphId nRotGlyphId = pGlyphIds[i];
299 sal_Unicode nRotUnicode = pUnicodes[i];
300 sal_Int32 nRotDelta = 0;
302 // transform matrix to new individual direction
303 PSGSave ();
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;
318 PSGRestore();
322 pGlyphIds = pTempGlyphIds;
323 pUnicodes = pTempUnicodes;
324 pDeltaArray = pTempDelta;
325 nLen = nTempLen;
327 aPoint.X() += nTempFirstDelta;
330 if( nLen > 0 )
331 drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray );
333 // restore the user coordinate system
334 if (nCurrentTextAngle != 0)
336 PSGRestore ();
337 mnTextAngle = nCurrentTextAngle;
341 void
342 PrinterGfx::DrawText (
343 const Point& rPoint,
344 const sal_Unicode* pStr,
345 sal_Int16 nLen,
346 const sal_Int32* pDeltaArray
349 fontID nRestoreFont = mnFontID;
351 // setup font[substitutes] and map the string into the symbol area in case of
352 // symbol font
353 Font3 aFont(*this);
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];
361 else
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;
384 else
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)
400 PSGSave ();
401 PSTranslate (rPoint);
402 PSRotate (nCurrentTextAngle);
403 mnTextAngle = 0;
405 nCurrentPointX = 0;
406 nCurrentPointY = 0;
408 else
410 nCurrentPointX = rPoint.X();
411 nCurrentPointY = rPoint.Y();
414 // draw the string
415 sal_Int32 nDelta = 0;
416 for (int nTo = 0; nTo < nLen; )
418 int nFrom = nTo;
419 fontID nFont = pFontMap[ nFrom ];
421 while ((nTo < nLen) && (nFont == pFontMap[nTo]))
423 pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
424 nTo++ ;
427 SetFont( nFont,
428 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
429 mnTextAngle,
430 mbTextVertical,
431 maVirtualStatus.mbArtItalic,
432 maVirtualStatus.mbArtBold
435 if (mbTextVertical)
437 drawVerticalizedText(
438 Point(nCurrentPointX + nDelta, nCurrentPointY),
439 pEffectiveStr + nFrom, nTo - nFrom,
440 pNewDeltaArray + nFrom );
442 else
444 drawText(
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)
455 PSGRestore ();
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(
469 const Point& rPoint,
470 const sal_Unicode* pStr,
471 sal_Int16 nLen,
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();
485 PrintFontInfo aInfo;
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 )
495 i++;
496 if( i <= nLen && i > nLastPos )
498 for( int n = nLastPos; n < i; n++ )
499 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
501 SetFont( mnFontID,
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));
511 if( i < nLen )
513 int nOldWidth = maVirtualStatus.mnTextWidth;
514 int nOldHeight = maVirtualStatus.mnTextHeight;
515 SetFont( mnFontID,
516 nTextScale,
517 maVirtualStatus.mnTextHeight,
518 nNormalAngle + nDeltaAngle,
519 mbTextVertical,
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;
526 if( !pGsubFlags[i] )
527 nD *= fStretch;
529 Point aPos( aPoint );
530 switch( nDeltaAngle )
532 case +900:
533 aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
534 aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
535 break;
536 case -900:
537 aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
538 aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
539 break;
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
549 SetFont( mnFontID,
550 nOldHeight,
551 nOldWidth,
552 nNormalAngle,
553 mbTextVertical,
554 maVirtualStatus.mbArtItalic,
555 maVirtualStatus.mbArtBold );
557 i++;
558 nLastPos = i;
560 mnTextAngle = nNormalAngle;
563 void
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
573 // the company.
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);
591 PSMoveTo (rPoint);
592 PSShowText (pBuffer, nLen, nSize, pDeltaArray);
595 void
596 PrinterGfx::drawText(
597 const Point& rPoint,
598 const sal_Unicode* pStr,
599 sal_Int16 nLen,
600 const sal_Int32* pDeltaArray
603 if (!(nLen > 0))
604 return;
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);
615 return;
618 if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
620 GlyphSet aGSet( mnFontID, mbTextVertical );
621 aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
622 return;
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);
632 break;
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;
649 return w;
652 fontID
653 PrinterGfx::getCharMetric (const Font3 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
655 p_bbox->width = -1;
656 p_bbox->height = -1;
658 for (fontID n = 0; n < 3; n++)
660 fontID n_font = rFont.GetFont(n);
661 if (n_font != -1)
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
670 // in printerjob.cxx
671 sal_Unicode aRepl = 0;
672 if( n_char == 0x2d )
673 aRepl = 0x2212;
674 else if( n_char == 0x27 )
675 aRepl = 0x2019;
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) -> ?
684 if( aRepl )
686 mrFontMgr.getMetrics( n_font, aRepl, aRepl, p_bbox );
687 if (p_bbox->width >= 0 && p_bbox->height >= 0)
688 return n_font;
692 mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
694 if (p_bbox->width >= 0 && p_bbox->height >= 0)
695 return n_font;
697 if (n_char != '?')
698 return getCharMetric (rFont, '?', p_bbox);
700 return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
703 fontID
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() )
711 return it->second;
714 return -1;
717 sal_Int32
718 PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
720 Font3 aFont(*this);
721 if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
723 nFrom += 0xF000;
724 nTo += 0xF000;
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
735 return 1000;
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() )
755 nFont = it->second;
757 return mrFontMgr.getKernPairs( nFont, bVertical );
761 * advanced glyph handling
764 sal_Bool
765 PrinterGfx::GetGlyphBoundRect (sal_Unicode /*c*/, Rectangle& /*rOutRect*/)
767 return 0;
770 sal_uInt32
771 PrinterGfx::GetGlyphOutline (sal_Unicode /*c*/,
772 sal_uInt16 **/*ppPolySizes*/, Point **/*ppPoints*/, sal_uInt8 **/*ppFlags*/)
774 return 0;
778 * spool the converted truetype fonts to the page header after the page body is
779 * complete
780 * for Type1 fonts spool additional reencoding vectors that are necessary to access the
781 * whole font
784 void
785 PrinterGfx::OnEndPage ()
789 void
790 PrinterGfx::OnEndJob ()
792 maPS3Font.clear();
793 maPS1Font.clear();
796 void
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);
822 aFontFile.close ();
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 );
843 else
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;