sync master with lastest vba changes
[ooovba.git] / psprint / source / printergfx / text_gfx.cxx
blob5ab634e4d672619aa0145263f1daff4090d17b19
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_psprint.hxx"
33 #include <psprint/printergfx.hxx>
34 #include <psprint/fontmanager.hxx>
35 #include <psprint/helper.hxx>
36 #include "psputil.hxx"
37 #include <glyphset.hxx>
38 #include <osl/thread.h>
39 #include <sal/alloca.h>
40 #include <math.h>
42 using namespace psp ;
44 namespace psp {
46 container for a font and its helper fonts:
47 1st font is the font substitute e.g. helvetica substitutes arial on the printer
48 2nd is the font itself
49 3rd is a fallback font, usually a font with unicode glyph repertoir (e.g. andale)
50 symbol fonts (adobe-fontspecific) may need special glyphmapping
51 (symbol page vc. latin page)
53 class Font3
55 private:
57 #define Font3Size 3
59 fontID mpFont [Font3Size];
60 bool mbSymbol;
62 public:
64 fontID GetFont (int nIdx) const
65 { return nIdx < Font3Size ? mpFont[nIdx] : -1 ; }
66 bool IsSymbolFont () const
67 { return mbSymbol; }
69 Font3 (const PrinterGfx &rGfx);
70 ~Font3 () {}
73 Font3::Font3(const PrinterGfx &rGfx)
75 mpFont[0] = rGfx.getFontSubstitute();
76 mpFont[1] = rGfx.GetFontID();
77 mpFont[2] = rGfx.getFallbackID();
78 // mpFont[2] = rGfx.GetFontID();
80 PrintFontManager &rMgr = PrintFontManager::get();
81 mbSymbol = mpFont[1] != -1 ?
82 rMgr.getFontEncoding(mpFont[1]) == RTL_TEXTENCODING_SYMBOL : false;
85 } // namespace psp
87 static int getVerticalDeltaAngle( sal_Unicode nChar )
89 int nAngle = 0;
90 if( ( nChar >= 0x1100 && nChar < 0x11fa ) ||
91 ( nChar >= 0x3000 && nChar < 0xfb00 ) ||
92 ( nChar >= 0xfe20 && nChar < 0xfe70 ) ||
93 ( nChar >= 0xff00 && nChar < 0xff64 )
96 /* #i52932# remember:
97 nChar == 0x2010 || nChar == 0x2015
98 nChar == 0x2016 || nChar == 0x2026
100 are nAngle = 0 also, but already handled in the first if
102 if( ( nChar >= 0x3008 && nChar < 0x3019 && nChar != 0x3012 ) ||
103 nChar == 0xff3b || nChar == 0xff3d ||
104 (nChar >= 0xff6b && nChar < 0xff64 ) ||
105 nChar == 0xffe3
107 nAngle = 0;
108 else if( nChar == 0x30fc )
109 nAngle = -900;
110 else
111 nAngle = 900;
113 return nAngle;
116 void
117 PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID)
119 std::list< sal_Int32 >::iterator aFont;
120 // already in the document header ?
121 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont )
122 if( nFontID == *aFont )
123 return;
125 // no occurrenc yet, mark for download
126 // add the fontid to the list
127 maPS1Font.push_back (nFontID);
131 * implement text handling printer routines,
134 sal_uInt16
135 PrinterGfx::SetFont(
136 sal_Int32 nFontID,
137 sal_Int32 nHeight,
138 sal_Int32 nWidth,
139 sal_Int32 nAngle,
140 bool bVertical,
141 bool bArtItalic,
142 bool bArtBold
145 // font and encoding will be set by drawText again immediately
146 // before PSShowText
147 mnFontID = nFontID;
148 maVirtualStatus.maFont = rtl::OString();
149 maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW;
150 maVirtualStatus.mnTextHeight = nHeight;
151 maVirtualStatus.mnTextWidth = nWidth;
152 maVirtualStatus.mbArtItalic = bArtItalic;
153 maVirtualStatus.mbArtBold = bArtBold;
154 mnTextAngle = nAngle;
155 mbTextVertical = bVertical;
157 return 0;
160 sal_uInt16
161 PrinterGfx::SetFallbackFont ( sal_Int32 nFontID )
163 mnFallbackID = nFontID;
164 return 0;
167 void PrinterGfx::drawGlyphs(
168 const Point& rPoint,
169 sal_uInt32* pGlyphIds,
170 sal_Unicode* pUnicodes,
171 sal_Int16 nLen,
172 sal_Int32* pDeltaArray
176 // draw the string
177 // search for a glyph set matching the set font
178 std::list< GlyphSet >::iterator aIter;
179 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); aIter++)
180 if ( ((*aIter).GetFontID() == mnFontID)
181 && ((*aIter).IsVertical() == mbTextVertical))
183 (*aIter).DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
184 break;
187 // not found ? create a new one
188 if (aIter == maPS3Font.end())
190 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
191 maPS3Font.back().DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
195 void PrinterGfx::DrawGlyphs(
196 const Point& rPoint,
197 sal_uInt32* pGlyphIds,
198 sal_Unicode* pUnicodes,
199 sal_Int16 nLen,
200 sal_Int32* pDeltaArray
203 if( nLen <= 0 )
204 return;
206 if ( !mrFontMgr.isFontDownloadingAllowed( mnFontID ) )
208 LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray);
209 return;
212 if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType )
214 DrawText( rPoint, pUnicodes, nLen, pDeltaArray );
215 return;
218 // move and rotate the user coordinate system
219 // avoid the gsave/grestore for the simple cases since it allows
220 // reuse of the current font if it hasn't changed
221 sal_Int32 nCurrentTextAngle = mnTextAngle;
222 Point aPoint( rPoint );
224 if (nCurrentTextAngle != 0)
226 PSGSave ();
227 PSTranslate (rPoint);
228 PSRotate (nCurrentTextAngle);
229 mnTextAngle = 0;
230 aPoint = Point( 0, 0 );
233 if( mbTextVertical )
235 // vertical glyphs can have an additional rotation ... sigh.
236 // so break up text in chunks of normal glyphs and print out
237 // specially rotated glyphs extra
238 sal_uInt32* pTempGlyphIds = (sal_uInt32*)alloca(sizeof(sal_Int32)*nLen);
239 sal_Int32* pTempDelta = (sal_Int32*)alloca(sizeof(sal_Int32)*nLen);
240 sal_Unicode* pTempUnicodes = (sal_Unicode*)alloca(sizeof(sal_Unicode)*nLen);
241 sal_Int16 nTempLen = 0;
242 sal_Int32 nTempFirstDelta = 0;
243 Point aRotPoint;
244 sal_Int32 nTextHeight = maVirtualStatus.mnTextHeight;
245 sal_Int32 nTextWidth = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
246 sal_Int32 nAscend = mrFontMgr.getFontAscend( mnFontID );
247 sal_Int32 nDescend = mrFontMgr.getFontDescend( mnFontID );
249 nDescend = nDescend * nTextHeight / 1000;
250 nAscend = nAscend * nTextHeight / 1000;
252 for( sal_Int16 i = 0; i < nLen; i++ )
254 sal_Int32 nRot = ((pGlyphIds[i] >> 24) & 3);
255 if( nRot == 0 )
257 pTempUnicodes[nTempLen] = pUnicodes[i];
258 pTempGlyphIds[nTempLen] = pGlyphIds[i];
259 if( nTempLen > 0 )
260 pTempDelta[nTempLen-1] = pDeltaArray[i-1]-nTempFirstDelta;
261 else
263 // the first element in pDeltaArray shows
264 // the offset of the second character
265 // so if the first glyph is normal
266 // then we do not need to move the delta indices
267 // else we have to move them down by one and
268 // recalculate aPoint and all deltas
269 if( i != 0 )
270 nTempFirstDelta = pDeltaArray[ i-1 ];
272 nTempLen++;
274 else
276 sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0;
277 sal_Int32 nRotAngle = 0;
278 switch( nRot )
280 case 3:
281 nRotAngle = 2700;
282 aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset );
283 break;
284 case 2:
285 nRotAngle = 1800;
286 aRotPoint = Point( -nOffset, (nAscend+nDescend) );
287 break;
288 case 1:
289 nRotAngle = 900;
290 aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight );
291 break;
293 sal_uInt32 nRotGlyphId = pGlyphIds[i];
294 sal_Unicode nRotUnicode = pUnicodes[i];
295 sal_Int32 nRotDelta = 0;
297 // transform matrix to new individual direction
298 PSGSave ();
299 GraphicsStatus aSaveStatus = maVirtualStatus;
300 if( nRot != 2 ) // switch font aspect
302 maVirtualStatus.mnTextWidth = nTextHeight;
303 maVirtualStatus.mnTextHeight = nTextWidth;
305 if( aPoint.X() || aPoint.Y() )
306 PSTranslate( aPoint );
307 PSRotate (nRotAngle);
308 // draw the rotated glyph
309 drawGlyphs( aRotPoint, &nRotGlyphId, &nRotUnicode, 1, &nRotDelta );
311 // restore previous state
312 maVirtualStatus = aSaveStatus;
313 PSGRestore();
317 pGlyphIds = pTempGlyphIds;
318 pUnicodes = pTempUnicodes;
319 pDeltaArray = pTempDelta;
320 nLen = nTempLen;
322 aPoint.X() += nTempFirstDelta;
325 if( nLen > 0 )
326 drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray );
328 // restore the user coordinate system
329 if (nCurrentTextAngle != 0)
331 PSGRestore ();
332 mnTextAngle = nCurrentTextAngle;
336 void
337 PrinterGfx::DrawText (
338 const Point& rPoint,
339 const sal_Unicode* pStr,
340 sal_Int16 nLen,
341 const sal_Int32* pDeltaArray
344 fontID nRestoreFont = mnFontID;
346 // setup font[substitutes] and map the string into the symbol area in case of
347 // symbol font
348 Font3 aFont(*this);
349 sal_Unicode *pEffectiveStr;
350 if ( aFont.IsSymbolFont() )
352 pEffectiveStr = (sal_Unicode*)alloca(nLen * sizeof(pStr[0]));
353 for (int i = 0; i < nLen; i++)
354 pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
356 else
358 pEffectiveStr = const_cast<sal_Unicode*>(pStr);
361 fontID *pFontMap = (fontID*) alloca(nLen * sizeof(fontID));
362 sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32));
364 for( int n = 0; n < nLen; n++ )
366 CharacterMetric aBBox;
367 pFontMap[n] = getCharMetric (aFont, pEffectiveStr[n], &aBBox);
368 pCharWidth[n] = getCharWidth (mbTextVertical, pEffectiveStr[n], &aBBox);
371 // setup a new delta array, use virtual resolution of 1000
372 sal_Int32* pNewDeltaArray = (sal_Int32*)alloca( sizeof( sal_Int32 )*nLen );
373 if ( pDeltaArray != 0)
375 for (int i = 0; i < nLen - 1; i++)
376 pNewDeltaArray[i] = 1000 * pDeltaArray[i];
377 pNewDeltaArray[nLen - 1] = 0;
379 else
381 pNewDeltaArray[0] = pCharWidth[0];
382 for (int i = 1; i < nLen; i++)
383 pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i];
386 // move and rotate the user coordinate system
387 // avoid the gsave/grestore for the simple cases since it allows
388 // reuse of the current font if it hasn't changed
389 sal_Int32 nCurrentTextAngle = mnTextAngle;
390 sal_Int32 nCurrentPointX;
391 sal_Int32 nCurrentPointY;
393 if (nCurrentTextAngle != 0)
395 PSGSave ();
396 PSTranslate (rPoint);
397 PSRotate (nCurrentTextAngle);
398 mnTextAngle = 0;
400 nCurrentPointX = 0;
401 nCurrentPointY = 0;
403 else
405 nCurrentPointX = rPoint.X();
406 nCurrentPointY = rPoint.Y();
409 // draw the string
410 sal_Int32 nDelta = 0;
411 for (int nTo = 0; nTo < nLen; )
413 int nFrom = nTo;
414 fontID nFont = pFontMap[ nFrom ];
416 while ((nTo < nLen) && (nFont == pFontMap[nTo]))
418 pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
419 nTo++ ;
422 SetFont( nFont,
423 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
424 mnTextAngle,
425 mbTextVertical,
426 maVirtualStatus.mbArtItalic,
427 maVirtualStatus.mbArtBold
430 if (mbTextVertical)
432 drawVerticalizedText(
433 Point(nCurrentPointX + nDelta, nCurrentPointY),
434 pEffectiveStr + nFrom, nTo - nFrom,
435 pNewDeltaArray + nFrom );
437 else
439 drawText(
440 Point(nCurrentPointX + nDelta, nCurrentPointY),
441 pEffectiveStr + nFrom, nTo - nFrom,
442 pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom );
444 nDelta += pNewDeltaArray[ nTo - 1 ];
447 // restore the user coordinate system
448 if (nCurrentTextAngle != 0)
450 PSGRestore ();
451 mnTextAngle = nCurrentTextAngle;
454 // restore the original font settings
455 SetFont( nRestoreFont,
456 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
457 mnTextAngle, mbTextVertical,
458 maVirtualStatus.mbArtItalic,
459 maVirtualStatus.mbArtBold
463 void PrinterGfx::drawVerticalizedText(
464 const Point& rPoint,
465 const sal_Unicode* pStr,
466 sal_Int16 nLen,
467 const sal_Int32* pDeltaArray
470 sal_Int32* pDelta = (sal_Int32*)alloca( nLen * sizeof(sal_Int32) );
472 int nTextScale = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
473 int nNormalAngle = mnTextAngle;
474 int nDeltaAngle, nLastPos = 0;
476 double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
477 double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
479 PrintFontManager &rMgr = PrintFontManager::get();
480 PrintFontInfo aInfo;
481 rMgr.getFontInfo( mnFontID, aInfo );
483 bool* pGsubFlags = (bool*)alloca( nLen * sizeof(bool) );
484 rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
486 Point aPoint( rPoint );
487 for( int i = 0; i < nLen; )
489 while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
490 i++;
491 if( i <= nLen && i > nLastPos )
493 for( int n = nLastPos; n < i; n++ )
494 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
496 SetFont( mnFontID,
497 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
498 nNormalAngle, mbTextVertical,
499 maVirtualStatus.mbArtItalic,
500 maVirtualStatus.mbArtBold );
501 drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
503 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
504 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
506 if( i < nLen )
508 int nOldWidth = maVirtualStatus.mnTextWidth;
509 int nOldHeight = maVirtualStatus.mnTextHeight;
510 SetFont( mnFontID,
511 nTextScale,
512 maVirtualStatus.mnTextHeight,
513 nNormalAngle + nDeltaAngle,
514 mbTextVertical,
515 maVirtualStatus.mbArtItalic,
516 maVirtualStatus.mbArtBold );
518 double nA = nTextScale * aInfo.m_nAscend / 1000.0;
519 double nD = nTextScale * aInfo.m_nDescend / 1000.0;
520 double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
521 if( !pGsubFlags[i] )
522 nD *= fStretch;
524 Point aPos( aPoint );
525 switch( nDeltaAngle )
527 case +900:
528 aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
529 aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
530 break;
531 case -900:
532 aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
533 aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
534 break;
536 drawText( aPos, pStr+i, 1, NULL );
537 if( i < nLen-1 && pDeltaArray )
539 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
540 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
543 // swap text width/height again
544 SetFont( mnFontID,
545 nOldHeight,
546 nOldWidth,
547 nNormalAngle,
548 mbTextVertical,
549 maVirtualStatus.mbArtItalic,
550 maVirtualStatus.mbArtBold );
552 i++;
553 nLastPos = i;
555 mnTextAngle = nNormalAngle;
558 void
559 PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
560 sal_Int16 nLen, const sal_Int32* pDeltaArray)
562 // treat it like a builtin font in case a user has that font also in the
563 // printer. This is not so unlikely as it may seem; no print embedding
564 // licensed fonts are often used (or so they say) in companies:
565 // they are installed on displays and printers, but get not embedded in
566 // they are installed on displays and printers, but get not embedded in
567 // print files or documents because they are not licensed for use outside
568 // the company.
569 rtl::OString aMessage( "The font " );
570 aMessage += rtl::OUStringToOString( mrFontMgr.getPSName(mnFontID),
571 RTL_TEXTENCODING_ASCII_US );
572 aMessage += " could not be downloaded\nbecause its license does not allow for that";
573 PSComment( aMessage.getStr() );
575 rtl::OString aFontName = rtl::OUStringToOString(
576 mrFontMgr.getPSName(mnFontID),
577 RTL_TEXTENCODING_ASCII_US);
578 PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
580 sal_Size nSize = 4 * nLen;
581 sal_uChar* pBuffer = (sal_uChar*)alloca (nSize* sizeof(sal_uChar));
583 ConverterFactory* pCvt = GetConverterFactory ();
584 nSize = pCvt->Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
586 PSMoveTo (rPoint);
587 PSShowText (pBuffer, nLen, nSize, pDeltaArray);
590 void
591 PrinterGfx::drawText(
592 const Point& rPoint,
593 const sal_Unicode* pStr,
594 sal_Int16 nLen,
595 const sal_Int32* pDeltaArray
598 if (!(nLen > 0))
599 return;
601 fonttype::type eType = mrFontMgr.getFontType (mnFontID);
603 if (eType == fonttype::Type1)
604 PSUploadPS1Font (mnFontID);
606 if ( eType == fonttype::TrueType
607 && !mrFontMgr.isFontDownloadingAllowed(mnFontID))
609 LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
610 return;
613 if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
615 GlyphSet aGSet( mnFontID, mbTextVertical );
616 aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
617 return;
620 // search for a glyph set matching the set font
621 std::list< GlyphSet >::iterator aIter;
622 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); aIter++)
623 if ( ((*aIter).GetFontID() == mnFontID)
624 && ((*aIter).IsVertical() == mbTextVertical))
626 (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
627 break;
630 // not found ? create a new one
631 if (aIter == maPS3Font.end())
633 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
634 maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
639 PrinterGfx::getCharWidth (sal_Bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
641 b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
642 int w = b_vert ? p_bbox->height : p_bbox->width;
643 w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
644 return w;
647 fontID
648 PrinterGfx::getCharMetric (const Font3 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
650 p_bbox->width = -1;
651 p_bbox->height = -1;
653 for (fontID n = 0; n < 3; n++)
655 fontID n_font = rFont.GetFont(n);
656 if (n_font != -1)
658 if( mbStrictSO52Compatibility )
660 fonttype::type eType = mrFontMgr.getFontType( n_font );
661 if( (eType == fonttype::Builtin || eType == fonttype::Type1) )
663 // note: any character exchanged here MUST also be changed
664 // in the compatibility ISO encoding vector in the prolog
665 // in printerjob.cxx
666 sal_Unicode aRepl = 0;
667 if( n_char == 0x2d )
668 aRepl = 0x2212;
669 else if( n_char == 0x27 )
670 aRepl = 0x2019;
672 additional characters that may need backwards compatibility:
673 ISO5589 StdEnc Unicode suggested n_char -> aRepl
674 0264 0302 0x00B4 0x00B4 (acute) -> 0x2019 (quiteright)
675 0246 - 0x00A6 0x00A6 (brokenbar) -> 0x007C (bar)
676 0225 0267 0x0095 0x0095 () -> 0x2022 (bullet)
677 0140 0301 0x0060 0x0060 (grave) -> ?
679 if( aRepl )
681 mrFontMgr.getMetrics( n_font, aRepl, aRepl, p_bbox );
682 if (p_bbox->width >= 0 && p_bbox->height >= 0)
683 return n_font;
687 mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
689 if (p_bbox->width >= 0 && p_bbox->height >= 0)
690 return n_font;
692 if (n_char != '?')
693 return getCharMetric (rFont, '?', p_bbox);
695 return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
698 fontID
699 PrinterGfx::getFontSubstitute () const
701 if( mpFontSubstitutes )
703 ::std::hash_map< fontID, fontID >::const_iterator it =
704 mpFontSubstitutes->find( mnFontID );
705 if( it != mpFontSubstitutes->end() )
706 return it->second;
709 return -1;
712 sal_Int32
713 PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
715 Font3 aFont(*this);
716 if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
718 nFrom += 0xF000;
719 nTo += 0xF000;
722 for( int n = 0; n < (nTo - nFrom + 1); n++ )
724 CharacterMetric aBBox;
725 getCharMetric (aFont, n + nFrom, &aBBox);
726 pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
729 // returned metrics have postscript precision
730 return 1000;
733 const ::std::list< KernPair >& PrinterGfx::getKernPairs( bool bVertical ) const
736 * Note: this is only a 80% solution: if a font is only
737 * partially substituted in a string due to missing glyphs
738 * the results may not be perfect; the more so the more the
739 * substitution differs from the original metricwise. But
740 * vcl only asks for KernPairs for each font once and NOT
741 * in a string context this is the best we can do.
742 * In future the kerning should be done on a per string basis.
744 fontID nFont = mnFontID;
745 if( mpFontSubstitutes )
747 ::std::hash_map< fontID, fontID >::const_iterator it =
748 mpFontSubstitutes->find( mnFontID );
749 if( it != mpFontSubstitutes->end() )
750 nFont = it->second;
752 return mrFontMgr.getKernPairs( nFont, bVertical );
756 * advanced glyph handling
759 sal_Bool
760 PrinterGfx::GetGlyphBoundRect (sal_Unicode /*c*/, Rectangle& /*rOutRect*/)
762 return 0;
765 sal_uInt32
766 PrinterGfx::GetGlyphOutline (sal_Unicode /*c*/,
767 sal_uInt16 **/*ppPolySizes*/, Point **/*ppPoints*/, sal_uInt8 **/*ppFlags*/)
769 return 0;
773 * spool the converted truetype fonts to the page header after the page body is
774 * complete
775 * for Type1 fonts spool additional reencoding vectors that are necessary to access the
776 * whole font
779 void
780 PrinterGfx::OnEndPage ()
784 void
785 PrinterGfx::OnEndJob ()
787 maPS3Font.clear();
788 maPS1Font.clear();
791 void
792 PrinterGfx::writeResources( osl::File* pFile, std::list< rtl::OString >& rSuppliedFonts, std::list< rtl::OString >& rNeededFonts )
794 // write all type 1 fonts
795 std::list< sal_Int32 >::iterator aFont;
796 // already in the document header ?
797 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
799 const rtl::OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
800 rtl::OUString aUNCPath;
801 osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
802 osl::File aFontFile (aUNCPath);
804 // provide the pfb or pfa font as a (pfa-)font resource
805 rtl::OString aPostScriptName =
806 rtl::OUStringToOString ( mrFontMgr.getPSName(*aFont),
807 RTL_TEXTENCODING_ASCII_US );
809 WritePS (pFile, "%%BeginResource: font ");
810 WritePS (pFile, aPostScriptName.getStr());
811 WritePS (pFile, "\n");
813 osl::File::RC nError = aFontFile.open (OpenFlag_Read);
814 if (nError == osl::File::E_None)
816 convertPfbToPfa (aFontFile, *pFile);
817 aFontFile.close ();
819 pFile->setPos(osl_Pos_Current, -1);
820 char lastchar = '\n';
821 sal_uInt64 uBytes(1);
822 pFile->read((void *)(&lastchar), uBytes, uBytes);
823 if (lastchar != '\n')
824 WritePS (pFile, "\n");
826 WritePS (pFile, "%%EndResource\n");
827 rSuppliedFonts.push_back( aPostScriptName );
830 // write glyphsets and reencodings
831 std::list< GlyphSet >::iterator aIter;
832 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
834 if (aIter->GetFontType() == fonttype::TrueType)
836 aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts ? true : false, rSuppliedFonts );
838 else
839 // ( aIter->GetFontType() == fonttype::Type1
840 // || aIter->GetFontType() == fonttype::Builtin )
842 aIter->PSUploadEncoding (pFile, *this);
843 if( aIter->GetFontType() == fonttype::Builtin )
844 rNeededFonts.push_back(
845 rtl::OUStringToOString(
846 mrFontMgr.getPSName( aIter->GetFontID() ),
847 RTL_TEXTENCODING_ASCII_US ) );
852 bool PrinterGfx::getStrictSO52Compatibility() const
854 return mbStrictSO52Compatibility;
857 void PrinterGfx::setStrictSO52Compatibility( bool bCompat)
859 mbStrictSO52Compatibility = bCompat;