Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / generic / print / text_gfx.cxx
blob569a10e4ed353f9a42b09f4dc16a92d9adcea187
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <math.h>
22 #include "psputil.hxx"
23 #include "glyphset.hxx"
25 #include "generic/printergfx.hxx"
26 #include "fontmanager.hxx"
27 #include "vcl/helper.hxx"
29 #include "osl/thread.h"
31 #include "sal/alloca.h"
33 using namespace psp ;
35 namespace psp {
37 container for a font and its helper fonts:
38 1st is the font itself
39 2nd is a fallback font, usually a font with unicode glyph repertoir (e.g. andale)
40 symbol fonts (adobe-fontspecific) may need special glyphmapping
41 (symbol page vc. latin page)
43 class Font2
45 private:
47 #define Font2Size 2
49 fontID mpFont [Font2Size];
50 bool mbSymbol;
52 public:
54 fontID GetFont (int nIdx) const
55 { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
56 bool IsSymbolFont () const
57 { return mbSymbol; }
59 Font2 (const PrinterGfx &rGfx);
60 ~Font2 () {}
63 Font2::Font2(const PrinterGfx &rGfx)
65 mpFont[0] = rGfx.GetFontID();
66 mpFont[1] = rGfx.getFallbackID();
68 PrintFontManager &rMgr = PrintFontManager::get();
69 mbSymbol = mpFont[0] != -1 &&
70 rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL;
73 } // namespace psp
75 static int getVerticalDeltaAngle( sal_Unicode nChar )
77 int nRotation = GetVerticalFlags(nChar);
78 if (nRotation == GF_ROTR)
79 return -900;
80 if (nRotation == GF_ROTL)
81 return 900;
82 return 0;
85 void
86 PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID)
88 std::list< sal_Int32 >::iterator aFont;
89 // already in the document header ?
90 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont )
91 if( nFontID == *aFont )
92 return;
94 // no occurrenc yet, mark for download
95 // add the fontid to the list
96 maPS1Font.push_back (nFontID);
100 * implement text handling printer routines,
103 sal_uInt16
104 PrinterGfx::SetFont(
105 sal_Int32 nFontID,
106 sal_Int32 nHeight,
107 sal_Int32 nWidth,
108 sal_Int32 nAngle,
109 bool bVertical,
110 bool bArtItalic,
111 bool bArtBold
114 // font and encoding will be set by drawText again immediately
115 // before PSShowText
116 mnFontID = nFontID;
117 maVirtualStatus.maFont.clear();
118 maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW;
119 maVirtualStatus.mnTextHeight = nHeight;
120 maVirtualStatus.mnTextWidth = nWidth;
121 maVirtualStatus.mbArtItalic = bArtItalic;
122 maVirtualStatus.mbArtBold = bArtBold;
123 mnTextAngle = nAngle;
124 mbTextVertical = bVertical;
126 return 0;
129 void PrinterGfx::drawGlyphs(
130 const Point& rPoint,
131 sal_GlyphId* pGlyphIds,
132 sal_Unicode* pUnicodes,
133 sal_Int16 nLen,
134 sal_Int32* pDeltaArray
138 // draw the string
139 // search for a glyph set matching the set font
140 std::list< GlyphSet >::iterator aIter;
141 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
142 if ( ((*aIter).GetFontID() == mnFontID)
143 && ((*aIter).IsVertical() == mbTextVertical))
145 (*aIter).DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
146 break;
149 // not found ? create a new one
150 if (aIter == maPS3Font.end())
152 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
153 maPS3Font.back().DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
157 void PrinterGfx::DrawGlyphs(
158 const Point& rPoint,
159 sal_GlyphId* pGlyphIds,
160 sal_Unicode* pUnicodes,
161 sal_Int16 nLen,
162 sal_Int32* pDeltaArray
165 if( nLen <= 0 )
166 return;
168 if ( !mrFontMgr.isFontDownloadingAllowedForPrinting( mnFontID ) )
170 LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray);
171 return;
174 if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType )
176 DrawText( rPoint, pUnicodes, nLen, pDeltaArray );
177 return;
180 // move and rotate the user coordinate system
181 // avoid the gsave/grestore for the simple cases since it allows
182 // reuse of the current font if it hasn't changed
183 sal_Int32 nCurrentTextAngle = mnTextAngle;
184 Point aPoint( rPoint );
186 if (nCurrentTextAngle != 0)
188 PSGSave ();
189 PSTranslate (rPoint);
190 PSRotate (nCurrentTextAngle);
191 mnTextAngle = 0;
192 aPoint = Point( 0, 0 );
195 if( mbTextVertical )
197 // vertical glyphs can have an additional rotation ... sigh.
198 // so break up text in chunks of normal glyphs and print out
199 // specially rotated glyphs extra
200 sal_GlyphId* pTempGlyphIds = static_cast<sal_GlyphId*>(alloca(sizeof(sal_Int32)*nLen));
201 sal_Int32* pTempDelta = static_cast<sal_Int32*>(alloca(sizeof(sal_Int32)*nLen));
202 sal_Unicode* pTempUnicodes = static_cast<sal_Unicode*>(alloca(sizeof(sal_Unicode)*nLen));
203 sal_Int16 nTempLen = 0;
204 sal_Int32 nTempFirstDelta = 0;
205 Point aRotPoint;
206 sal_Int32 nTextHeight = maVirtualStatus.mnTextHeight;
207 sal_Int32 nTextWidth = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
208 sal_Int32 nAscend = mrFontMgr.getFontAscend( mnFontID );
209 sal_Int32 nDescend = mrFontMgr.getFontDescend( mnFontID );
211 nDescend = nDescend * nTextHeight / 1000;
212 nAscend = nAscend * nTextHeight / 1000;
214 for( sal_Int16 i = 0; i < nLen; i++ )
216 const sal_GlyphId nRot = pGlyphIds[i] & GF_ROTMASK;
217 if( nRot == GF_NONE )
219 pTempUnicodes[nTempLen] = pUnicodes[i];
220 pTempGlyphIds[nTempLen] = pGlyphIds[i];
221 if( nTempLen > 0 )
222 pTempDelta[nTempLen-1] = pDeltaArray[i-1]-nTempFirstDelta;
223 else
225 // the first element in pDeltaArray shows
226 // the offset of the second character
227 // so if the first glyph is normal
228 // then we do not need to move the delta indices
229 // else we have to move them down by one and
230 // recalculate aPoint and all deltas
231 if( i != 0 )
232 nTempFirstDelta = pDeltaArray[ i-1 ];
234 nTempLen++;
236 else
238 sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0;
239 sal_Int32 nRotAngle = 0;
240 switch( nRot )
242 case GF_ROTR:
243 nRotAngle = 2700;
244 aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset );
245 break;
246 case GF_VERT:
247 nRotAngle = 1800;
248 aRotPoint = Point( -nOffset, (nAscend+nDescend) );
249 break;
250 case GF_ROTL:
251 nRotAngle = 900;
252 aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight );
253 break;
255 sal_GlyphId nRotGlyphId = pGlyphIds[i];
256 sal_Unicode nRotUnicode = pUnicodes[i];
257 sal_Int32 nRotDelta = 0;
259 // transform matrix to new individual direction
260 PSGSave ();
261 GraphicsStatus aSaveStatus = maVirtualStatus;
262 if( nRot != 2 ) // switch font aspect
264 maVirtualStatus.mnTextWidth = nTextHeight;
265 maVirtualStatus.mnTextHeight = nTextWidth;
267 if( aPoint.X() || aPoint.Y() )
268 PSTranslate( aPoint );
269 PSRotate (nRotAngle);
270 // draw the rotated glyph
271 drawGlyphs( aRotPoint, &nRotGlyphId, &nRotUnicode, 1, &nRotDelta );
273 // restore previous state
274 maVirtualStatus = aSaveStatus;
275 PSGRestore();
279 pGlyphIds = pTempGlyphIds;
280 pUnicodes = pTempUnicodes;
281 pDeltaArray = pTempDelta;
282 nLen = nTempLen;
284 aPoint.X() += nTempFirstDelta;
287 if( nLen > 0 )
288 drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray );
290 // restore the user coordinate system
291 if (nCurrentTextAngle != 0)
293 PSGRestore ();
294 mnTextAngle = nCurrentTextAngle;
298 void
299 PrinterGfx::DrawText (
300 const Point& rPoint,
301 const sal_Unicode* pStr,
302 sal_Int16 nLen,
303 const sal_Int32* pDeltaArray
306 if (!nLen)
307 return;
309 fontID nRestoreFont = mnFontID;
311 // setup font[substitutes] and map the string into the symbol area in case of
312 // symbol font
313 Font2 aFont(*this);
314 sal_Unicode *pEffectiveStr;
315 if ( aFont.IsSymbolFont() )
317 pEffectiveStr = static_cast<sal_Unicode*>(alloca(nLen * sizeof(pStr[0])));
318 for (int i = 0; i < nLen; i++)
319 pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
321 else
323 pEffectiveStr = const_cast<sal_Unicode*>(pStr);
326 fontID *pFontMap = static_cast<fontID*>(alloca(nLen * sizeof(fontID)));
327 sal_Int32 *pCharWidth = static_cast<sal_Int32*>(alloca(nLen * sizeof(sal_Int32)));
329 for( int n = 0; n < nLen; n++ )
331 CharacterMetric aBBox;
332 // coverity[callee_ptr_arith]
333 pFontMap[n] = getCharMetric(aFont, pEffectiveStr[n], &aBBox);
334 pCharWidth[n] = getCharWidth(mbTextVertical, pEffectiveStr[n], &aBBox);
337 // setup a new delta array, use virtual resolution of 1000
338 sal_Int32* pNewDeltaArray = static_cast<sal_Int32*>(alloca( sizeof( sal_Int32 )*nLen ));
339 if ( pDeltaArray != 0)
341 for (int i = 0; i < nLen - 1; i++)
342 pNewDeltaArray[i] = 1000 * pDeltaArray[i];
343 pNewDeltaArray[nLen - 1] = 0;
345 else
347 pNewDeltaArray[0] = pCharWidth[0];
348 for (int i = 1; i < nLen; i++)
349 pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i];
352 // move and rotate the user coordinate system
353 // avoid the gsave/grestore for the simple cases since it allows
354 // reuse of the current font if it hasn't changed
355 sal_Int32 nCurrentTextAngle = mnTextAngle;
356 sal_Int32 nCurrentPointX;
357 sal_Int32 nCurrentPointY;
359 if (nCurrentTextAngle != 0)
361 PSGSave ();
362 PSTranslate (rPoint);
363 PSRotate (nCurrentTextAngle);
364 mnTextAngle = 0;
366 nCurrentPointX = 0;
367 nCurrentPointY = 0;
369 else
371 nCurrentPointX = rPoint.X();
372 nCurrentPointY = rPoint.Y();
375 // draw the string
376 sal_Int32 nDelta = 0;
377 for (int nTo = 0; nTo < nLen; )
379 int nFrom = nTo;
380 fontID nFont = pFontMap[ nFrom ];
382 while ((nTo < nLen) && (nFont == pFontMap[nTo]))
384 pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
385 nTo++ ;
388 SetFont( nFont,
389 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
390 mnTextAngle,
391 mbTextVertical,
392 maVirtualStatus.mbArtItalic,
393 maVirtualStatus.mbArtBold
396 if (mbTextVertical)
398 drawVerticalizedText(
399 Point(nCurrentPointX + nDelta, nCurrentPointY),
400 pEffectiveStr + nFrom, nTo - nFrom,
401 pNewDeltaArray + nFrom );
403 else
405 drawText(
406 Point(nCurrentPointX + nDelta, nCurrentPointY),
407 pEffectiveStr + nFrom, nTo - nFrom,
408 pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom );
410 nDelta += pNewDeltaArray[ nTo - 1 ];
413 // restore the user coordinate system
414 if (nCurrentTextAngle != 0)
416 PSGRestore ();
417 mnTextAngle = nCurrentTextAngle;
420 // restore the original font settings
421 SetFont( nRestoreFont,
422 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
423 mnTextAngle, mbTextVertical,
424 maVirtualStatus.mbArtItalic,
425 maVirtualStatus.mbArtBold
429 bool PrinterGfx::drawVerticalizedText(
430 const Point& rPoint,
431 const sal_Unicode* pStr,
432 sal_Int16 nLen,
433 const sal_Int32* pDeltaArray
436 PrintFontManager &rMgr = PrintFontManager::get();
437 PrintFontInfo aInfo;
438 if (!rMgr.getFontInfo(mnFontID, aInfo))
439 return false;
441 sal_Int32* pDelta = static_cast<sal_Int32*>(alloca( nLen * sizeof(sal_Int32) ));
443 int nTextScale = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
444 int nNormalAngle = mnTextAngle;
445 int nLastPos = 0;
447 double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
448 double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
450 bool* pGsubFlags = static_cast<bool*>(alloca( nLen * sizeof(bool) ));
451 rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
453 Point aPoint( rPoint );
454 for( int i = 0; i < nLen; )
456 int nDeltaAngle;
457 while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
458 i++;
459 if( i <= nLen && i > nLastPos )
461 for( int n = nLastPos; n < i; n++ )
462 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
464 SetFont( mnFontID,
465 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
466 nNormalAngle, mbTextVertical,
467 maVirtualStatus.mbArtItalic,
468 maVirtualStatus.mbArtBold );
469 drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
471 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
472 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
474 if( i < nLen )
476 int nOldWidth = maVirtualStatus.mnTextWidth;
477 int nOldHeight = maVirtualStatus.mnTextHeight;
478 SetFont( mnFontID,
479 nTextScale,
480 maVirtualStatus.mnTextHeight,
481 nNormalAngle + nDeltaAngle,
482 mbTextVertical,
483 maVirtualStatus.mbArtItalic,
484 maVirtualStatus.mbArtBold );
486 double nA = nTextScale * aInfo.m_nAscend / 1000.0;
487 double nD = nTextScale * aInfo.m_nDescend / 1000.0;
488 double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
489 if( !pGsubFlags[i] )
490 nD *= fStretch;
492 Point aPos( aPoint );
493 switch( nDeltaAngle )
495 case +900:
496 aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
497 aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
498 break;
499 case -900:
500 aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
501 aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
502 break;
504 drawText( aPos, pStr+i, 1, NULL );
505 if( i < nLen-1 && pDeltaArray )
507 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
508 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
511 // swap text width/height again
512 SetFont( mnFontID,
513 nOldHeight,
514 nOldWidth,
515 nNormalAngle,
516 mbTextVertical,
517 maVirtualStatus.mbArtItalic,
518 maVirtualStatus.mbArtBold );
520 i++;
521 nLastPos = i;
523 mnTextAngle = nNormalAngle;
524 return true;
527 void
528 PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
529 sal_Int16 nLen, const sal_Int32* pDeltaArray)
531 // treat it like a builtin font in case a user has that font also in the
532 // printer. This is not so unlikely as it may seem; no print embedding
533 // licensed fonts are often used (or so they say) in companies:
534 // they are installed on displays and printers, but get not embedded in
535 // print files or documents because they are not licensed for use outside
536 // the company.
537 OString aMessage( "The font " );
538 aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
539 RTL_TEXTENCODING_ASCII_US );
540 aMessage += " could not be downloaded\nbecause its license does not allow for that";
541 PSComment( aMessage.getStr() );
543 OString aFontName = OUStringToOString(
544 mrFontMgr.getPSName(mnFontID),
545 RTL_TEXTENCODING_ASCII_US);
546 PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
548 sal_Size nSize = 4 * nLen;
549 unsigned char* pBuffer = static_cast<unsigned char*>(alloca (nSize* sizeof(unsigned char)));
551 ConverterFactory &rCvt = GetConverterFactory ();
552 nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
554 PSMoveTo (rPoint);
555 PSShowText (pBuffer, nLen, nSize, pDeltaArray);
558 void
559 PrinterGfx::drawText(
560 const Point& rPoint,
561 const sal_Unicode* pStr,
562 sal_Int16 nLen,
563 const sal_Int32* pDeltaArray
566 if (!(nLen > 0))
567 return;
569 fonttype::type eType = mrFontMgr.getFontType (mnFontID);
571 if (eType == fonttype::Type1)
572 PSUploadPS1Font (mnFontID);
574 if ( eType == fonttype::TrueType
575 && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
577 LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
578 return;
581 if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
583 GlyphSet aGSet( mnFontID, mbTextVertical );
584 aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
585 return;
588 // search for a glyph set matching the set font
589 std::list< GlyphSet >::iterator aIter;
590 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
591 if ( ((*aIter).GetFontID() == mnFontID)
592 && ((*aIter).IsVertical() == mbTextVertical))
594 (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
595 break;
598 // not found ? create a new one
599 if (aIter == maPS3Font.end())
601 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
602 maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
607 PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
609 b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
610 int w = b_vert ? p_bbox->height : p_bbox->width;
611 w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
612 return w;
615 fontID
616 PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
618 p_bbox->width = -1;
619 p_bbox->height = -1;
621 for (fontID n = 0; n < Font2Size; n++)
623 fontID n_font = rFont.GetFont(n);
624 if (n_font != -1)
625 mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
626 if (p_bbox->width >= 0 && p_bbox->height >= 0)
627 return n_font;
629 if (n_char != '?')
630 return getCharMetric (rFont, '?', p_bbox);
632 return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
635 sal_Int32
636 PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
638 Font2 aFont(*this);
639 if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
641 nFrom += 0xF000;
642 nTo += 0xF000;
645 for( int n = 0; n < (nTo - nFrom + 1); n++ )
647 CharacterMetric aBBox;
648 // coverity[callee_ptr_arith]
649 getCharMetric(aFont, n + nFrom, &aBBox);
650 pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
653 // returned metrics have postscript precision
654 return 1000;
658 * spool the converted truetype fonts to the page header after the page body is
659 * complete
660 * for Type1 fonts spool additional reencoding vectors that are necessary to access the
661 * whole font
664 void
665 PrinterGfx::OnEndJob ()
667 maPS3Font.clear();
668 maPS1Font.clear();
671 void
672 PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
674 // write all type 1 fonts
675 std::list< sal_Int32 >::iterator aFont;
676 // already in the document header ?
677 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
679 const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
680 OUString aUNCPath;
681 osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
682 osl::File aFontFile (aUNCPath);
684 // provide the pfb or pfa font as a (pfa-)font resource
685 OString aPostScriptName =
686 OUStringToOString ( mrFontMgr.getPSName(*aFont),
687 RTL_TEXTENCODING_ASCII_US );
689 WritePS (pFile, "%%BeginResource: font ");
690 WritePS (pFile, aPostScriptName.getStr());
691 WritePS (pFile, "\n");
693 osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
694 if (nError == osl::File::E_None)
696 convertPfbToPfa (aFontFile, *pFile);
697 aFontFile.close ();
699 char lastchar = '\n';
701 if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
703 sal_uInt64 uBytes(1);
704 pFile->read((void *)(&lastchar), uBytes, uBytes);
707 if (lastchar != '\n')
708 WritePS (pFile, "\n");
710 WritePS (pFile, "%%EndResource\n");
711 rSuppliedFonts.push_back( aPostScriptName );
714 // write glyphsets and reencodings
715 std::list< GlyphSet >::iterator aIter;
716 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
718 if (aIter->GetFontType() == fonttype::TrueType)
720 aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts, rSuppliedFonts );
722 else
724 aIter->PSUploadEncoding (pFile, *this);
728 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */