Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <math.h>
21 :
22 : #include "psputil.hxx"
23 : #include "glyphset.hxx"
24 :
25 : #include "generic/printergfx.hxx"
26 : #include "fontmanager.hxx"
27 : #include "vcl/helper.hxx"
28 :
29 : #include "osl/thread.h"
30 :
31 : #include "sal/alloca.h"
32 :
33 : using namespace psp ;
34 :
35 : namespace psp {
36 : /*
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)
42 : */
43 : class Font2
44 : {
45 : private:
46 :
47 : #define Font2Size 2
48 :
49 : fontID mpFont [Font2Size];
50 : bool mbSymbol;
51 :
52 : public:
53 :
54 0 : fontID GetFont (int nIdx) const
55 0 : { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
56 0 : bool IsSymbolFont () const
57 0 : { return mbSymbol; }
58 :
59 : Font2 (const PrinterGfx &rGfx);
60 0 : ~Font2 () {}
61 : };
62 :
63 0 : Font2::Font2(const PrinterGfx &rGfx)
64 : {
65 0 : mpFont[0] = rGfx.GetFontID();
66 0 : mpFont[1] = rGfx.getFallbackID();
67 :
68 0 : PrintFontManager &rMgr = PrintFontManager::get();
69 0 : mbSymbol = mpFont[0] != -1 ?
70 0 : rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL : false;
71 0 : }
72 :
73 : } // namespace psp
74 :
75 0 : static int getVerticalDeltaAngle( sal_Unicode nChar )
76 : {
77 0 : int nRotation = GetVerticalFlags(nChar);
78 0 : if (nRotation == GF_ROTR)
79 0 : return -900;
80 0 : if (nRotation == GF_ROTL)
81 0 : return 900;
82 0 : return 0;
83 : }
84 :
85 : void
86 0 : PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID)
87 : {
88 0 : std::list< sal_Int32 >::iterator aFont;
89 : // already in the document header ?
90 0 : for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont )
91 0 : if( nFontID == *aFont )
92 0 : return;
93 :
94 : // no occurrenc yet, mark for download
95 : // add the fontid to the list
96 0 : maPS1Font.push_back (nFontID);
97 : }
98 :
99 : /*
100 : * implement text handling printer routines,
101 : */
102 :
103 : sal_uInt16
104 0 : 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
112 : )
113 : {
114 : // font and encoding will be set by drawText again immediately
115 : // before PSShowText
116 0 : mnFontID = nFontID;
117 0 : maVirtualStatus.maFont = OString();
118 0 : maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW;
119 0 : maVirtualStatus.mnTextHeight = nHeight;
120 0 : maVirtualStatus.mnTextWidth = nWidth;
121 0 : maVirtualStatus.mbArtItalic = bArtItalic;
122 0 : maVirtualStatus.mbArtBold = bArtBold;
123 0 : mnTextAngle = nAngle;
124 0 : mbTextVertical = bVertical;
125 :
126 0 : return 0;
127 : }
128 :
129 0 : void PrinterGfx::drawGlyphs(
130 : const Point& rPoint,
131 : sal_GlyphId* pGlyphIds,
132 : sal_Unicode* pUnicodes,
133 : sal_Int16 nLen,
134 : sal_Int32* pDeltaArray
135 : )
136 : {
137 :
138 : // draw the string
139 : // search for a glyph set matching the set font
140 0 : std::list< GlyphSet >::iterator aIter;
141 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
142 0 : if ( ((*aIter).GetFontID() == mnFontID)
143 0 : && ((*aIter).IsVertical() == mbTextVertical))
144 : {
145 0 : (*aIter).DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
146 0 : break;
147 : }
148 :
149 : // not found ? create a new one
150 0 : if (aIter == maPS3Font.end())
151 : {
152 0 : maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
153 0 : maPS3Font.back().DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray);
154 : }
155 0 : }
156 :
157 0 : void PrinterGfx::DrawGlyphs(
158 : const Point& rPoint,
159 : sal_GlyphId* pGlyphIds,
160 : sal_Unicode* pUnicodes,
161 : sal_Int16 nLen,
162 : sal_Int32* pDeltaArray
163 : )
164 : {
165 0 : if( nLen <= 0 )
166 0 : return;
167 :
168 0 : if ( !mrFontMgr.isFontDownloadingAllowedForPrinting( mnFontID ) )
169 : {
170 0 : LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray);
171 0 : return;
172 : }
173 :
174 0 : if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType )
175 : {
176 0 : DrawText( rPoint, pUnicodes, nLen, pDeltaArray );
177 0 : return;
178 : }
179 :
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 0 : sal_Int32 nCurrentTextAngle = mnTextAngle;
184 0 : Point aPoint( rPoint );
185 :
186 0 : if (nCurrentTextAngle != 0)
187 : {
188 0 : PSGSave ();
189 0 : PSTranslate (rPoint);
190 0 : PSRotate (nCurrentTextAngle);
191 0 : mnTextAngle = 0;
192 0 : aPoint = Point( 0, 0 );
193 : }
194 :
195 0 : if( mbTextVertical )
196 : {
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 0 : sal_GlyphId* pTempGlyphIds = (sal_GlyphId*)alloca(sizeof(sal_Int32)*nLen);
201 0 : sal_Int32* pTempDelta = (sal_Int32*)alloca(sizeof(sal_Int32)*nLen);
202 0 : sal_Unicode* pTempUnicodes = (sal_Unicode*)alloca(sizeof(sal_Unicode)*nLen);
203 0 : sal_Int16 nTempLen = 0;
204 0 : sal_Int32 nTempFirstDelta = 0;
205 0 : Point aRotPoint;
206 0 : sal_Int32 nTextHeight = maVirtualStatus.mnTextHeight;
207 0 : sal_Int32 nTextWidth = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
208 0 : sal_Int32 nAscend = mrFontMgr.getFontAscend( mnFontID );
209 0 : sal_Int32 nDescend = mrFontMgr.getFontDescend( mnFontID );
210 :
211 0 : nDescend = nDescend * nTextHeight / 1000;
212 0 : nAscend = nAscend * nTextHeight / 1000;
213 :
214 0 : for( sal_Int16 i = 0; i < nLen; i++ )
215 : {
216 0 : const sal_GlyphId nRot = pGlyphIds[i] & GF_ROTMASK;
217 0 : if( nRot == GF_NONE )
218 : {
219 0 : pTempUnicodes[nTempLen] = pUnicodes[i];
220 0 : pTempGlyphIds[nTempLen] = pGlyphIds[i];
221 0 : if( nTempLen > 0 )
222 0 : pTempDelta[nTempLen-1] = pDeltaArray[i-1]-nTempFirstDelta;
223 : else
224 : {
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 0 : if( i != 0 )
232 0 : nTempFirstDelta = pDeltaArray[ i-1 ];
233 : }
234 0 : nTempLen++;
235 : }
236 : else
237 : {
238 0 : sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0;
239 0 : sal_Int32 nRotAngle = 0;
240 0 : switch( nRot )
241 : {
242 : case GF_ROTR:
243 0 : nRotAngle = 2700;
244 0 : aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset );
245 0 : break;
246 : case GF_VERT:
247 0 : nRotAngle = 1800;
248 0 : aRotPoint = Point( -nOffset, (nAscend+nDescend) );
249 0 : break;
250 : case GF_ROTL:
251 0 : nRotAngle = 900;
252 0 : aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight );
253 0 : break;
254 : }
255 0 : sal_GlyphId nRotGlyphId = pGlyphIds[i];
256 0 : sal_Unicode nRotUnicode = pUnicodes[i];
257 0 : sal_Int32 nRotDelta = 0;
258 :
259 : // transform matrix to new individual direction
260 0 : PSGSave ();
261 0 : GraphicsStatus aSaveStatus = maVirtualStatus;
262 0 : if( nRot != 2 ) // switch font aspect
263 : {
264 0 : maVirtualStatus.mnTextWidth = nTextHeight;
265 0 : maVirtualStatus.mnTextHeight = nTextWidth;
266 : }
267 0 : if( aPoint.X() || aPoint.Y() )
268 0 : PSTranslate( aPoint );
269 0 : PSRotate (nRotAngle);
270 : // draw the rotated glyph
271 0 : drawGlyphs( aRotPoint, &nRotGlyphId, &nRotUnicode, 1, &nRotDelta );
272 :
273 : // restore previous state
274 0 : maVirtualStatus = aSaveStatus;
275 0 : PSGRestore();
276 : }
277 : }
278 :
279 0 : pGlyphIds = pTempGlyphIds;
280 0 : pUnicodes = pTempUnicodes;
281 0 : pDeltaArray = pTempDelta;
282 0 : nLen = nTempLen;
283 :
284 0 : aPoint.X() += nTempFirstDelta;
285 : }
286 :
287 0 : if( nLen > 0 )
288 0 : drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray );
289 :
290 : // restore the user coordinate system
291 0 : if (nCurrentTextAngle != 0)
292 : {
293 0 : PSGRestore ();
294 0 : mnTextAngle = nCurrentTextAngle;
295 : }
296 : }
297 :
298 : void
299 0 : PrinterGfx::DrawText (
300 : const Point& rPoint,
301 : const sal_Unicode* pStr,
302 : sal_Int16 nLen,
303 : const sal_Int32* pDeltaArray
304 : )
305 : {
306 0 : fontID nRestoreFont = mnFontID;
307 :
308 : // setup font[substitutes] and map the string into the symbol area in case of
309 : // symbol font
310 0 : Font2 aFont(*this);
311 : sal_Unicode *pEffectiveStr;
312 0 : if ( aFont.IsSymbolFont() )
313 : {
314 0 : pEffectiveStr = (sal_Unicode*)alloca(nLen * sizeof(pStr[0]));
315 0 : for (int i = 0; i < nLen; i++)
316 0 : pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
317 : }
318 : else
319 : {
320 0 : pEffectiveStr = const_cast<sal_Unicode*>(pStr);
321 : }
322 :
323 0 : fontID *pFontMap = (fontID*) alloca(nLen * sizeof(fontID));
324 0 : sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32));
325 :
326 0 : for( int n = 0; n < nLen; n++ )
327 : {
328 0 : CharacterMetric aBBox;
329 0 : pFontMap[n] = getCharMetric (aFont, pEffectiveStr[n], &aBBox);
330 0 : pCharWidth[n] = getCharWidth (mbTextVertical, pEffectiveStr[n], &aBBox);
331 : }
332 :
333 : // setup a new delta array, use virtual resolution of 1000
334 0 : sal_Int32* pNewDeltaArray = (sal_Int32*)alloca( sizeof( sal_Int32 )*nLen );
335 0 : if ( pDeltaArray != 0)
336 : {
337 0 : for (int i = 0; i < nLen - 1; i++)
338 0 : pNewDeltaArray[i] = 1000 * pDeltaArray[i];
339 0 : pNewDeltaArray[nLen - 1] = 0;
340 : }
341 : else
342 : {
343 0 : pNewDeltaArray[0] = pCharWidth[0];
344 0 : for (int i = 1; i < nLen; i++)
345 0 : pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i];
346 : }
347 :
348 : // move and rotate the user coordinate system
349 : // avoid the gsave/grestore for the simple cases since it allows
350 : // reuse of the current font if it hasn't changed
351 0 : sal_Int32 nCurrentTextAngle = mnTextAngle;
352 : sal_Int32 nCurrentPointX;
353 : sal_Int32 nCurrentPointY;
354 :
355 0 : if (nCurrentTextAngle != 0)
356 : {
357 0 : PSGSave ();
358 0 : PSTranslate (rPoint);
359 0 : PSRotate (nCurrentTextAngle);
360 0 : mnTextAngle = 0;
361 :
362 0 : nCurrentPointX = 0;
363 0 : nCurrentPointY = 0;
364 : }
365 : else
366 : {
367 0 : nCurrentPointX = rPoint.X();
368 0 : nCurrentPointY = rPoint.Y();
369 : }
370 :
371 : // draw the string
372 0 : sal_Int32 nDelta = 0;
373 0 : for (int nTo = 0; nTo < nLen; )
374 : {
375 0 : int nFrom = nTo;
376 0 : fontID nFont = pFontMap[ nFrom ];
377 :
378 0 : while ((nTo < nLen) && (nFont == pFontMap[nTo]))
379 : {
380 0 : pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
381 0 : nTo++ ;
382 : }
383 :
384 : SetFont( nFont,
385 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
386 : mnTextAngle,
387 : mbTextVertical,
388 : maVirtualStatus.mbArtItalic,
389 : maVirtualStatus.mbArtBold
390 0 : );
391 :
392 0 : if (mbTextVertical)
393 : {
394 : drawVerticalizedText(
395 : Point(nCurrentPointX + nDelta, nCurrentPointY),
396 : pEffectiveStr + nFrom, nTo - nFrom,
397 0 : pNewDeltaArray + nFrom );
398 : }
399 : else
400 : {
401 : drawText(
402 : Point(nCurrentPointX + nDelta, nCurrentPointY),
403 : pEffectiveStr + nFrom, nTo - nFrom,
404 0 : pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom );
405 : }
406 0 : nDelta += pNewDeltaArray[ nTo - 1 ];
407 : }
408 :
409 : // restore the user coordinate system
410 0 : if (nCurrentTextAngle != 0)
411 : {
412 0 : PSGRestore ();
413 0 : mnTextAngle = nCurrentTextAngle;
414 : }
415 :
416 : // restore the original font settings
417 : SetFont( nRestoreFont,
418 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
419 : mnTextAngle, mbTextVertical,
420 : maVirtualStatus.mbArtItalic,
421 : maVirtualStatus.mbArtBold
422 0 : );
423 0 : }
424 :
425 0 : void PrinterGfx::drawVerticalizedText(
426 : const Point& rPoint,
427 : const sal_Unicode* pStr,
428 : sal_Int16 nLen,
429 : const sal_Int32* pDeltaArray
430 : )
431 : {
432 0 : sal_Int32* pDelta = (sal_Int32*)alloca( nLen * sizeof(sal_Int32) );
433 :
434 0 : int nTextScale = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
435 0 : int nNormalAngle = mnTextAngle;
436 0 : int nDeltaAngle, nLastPos = 0;
437 :
438 0 : double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
439 0 : double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
440 :
441 0 : PrintFontManager &rMgr = PrintFontManager::get();
442 0 : PrintFontInfo aInfo;
443 0 : rMgr.getFontInfo( mnFontID, aInfo );
444 :
445 0 : bool* pGsubFlags = (bool*)alloca( nLen * sizeof(bool) );
446 0 : rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
447 :
448 0 : Point aPoint( rPoint );
449 0 : for( int i = 0; i < nLen; )
450 : {
451 0 : while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
452 0 : i++;
453 0 : if( i <= nLen && i > nLastPos )
454 : {
455 0 : for( int n = nLastPos; n < i; n++ )
456 0 : pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
457 :
458 : SetFont( mnFontID,
459 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
460 : nNormalAngle, mbTextVertical,
461 : maVirtualStatus.mbArtItalic,
462 0 : maVirtualStatus.mbArtBold );
463 0 : drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
464 :
465 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
466 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
467 : }
468 0 : if( i < nLen )
469 : {
470 0 : int nOldWidth = maVirtualStatus.mnTextWidth;
471 0 : int nOldHeight = maVirtualStatus.mnTextHeight;
472 : SetFont( mnFontID,
473 : nTextScale,
474 : maVirtualStatus.mnTextHeight,
475 0 : nNormalAngle + nDeltaAngle,
476 : mbTextVertical,
477 : maVirtualStatus.mbArtItalic,
478 0 : maVirtualStatus.mbArtBold );
479 :
480 0 : double nA = nTextScale * aInfo.m_nAscend / 1000.0;
481 0 : double nD = nTextScale * aInfo.m_nDescend / 1000.0;
482 0 : double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
483 0 : if( !pGsubFlags[i] )
484 0 : nD *= fStretch;
485 :
486 0 : Point aPos( aPoint );
487 0 : switch( nDeltaAngle )
488 : {
489 : case +900:
490 0 : aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
491 0 : aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
492 0 : break;
493 : case -900:
494 0 : aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
495 0 : aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
496 0 : break;
497 : }
498 0 : drawText( aPos, pStr+i, 1, NULL );
499 0 : if( i < nLen-1 && pDeltaArray )
500 : {
501 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
502 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
503 : }
504 :
505 : // swap text width/height again
506 : SetFont( mnFontID,
507 : nOldHeight,
508 : nOldWidth,
509 : nNormalAngle,
510 : mbTextVertical,
511 : maVirtualStatus.mbArtItalic,
512 0 : maVirtualStatus.mbArtBold );
513 : }
514 0 : i++;
515 0 : nLastPos = i;
516 : }
517 0 : mnTextAngle = nNormalAngle;
518 0 : }
519 :
520 : void
521 0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
522 : sal_Int16 nLen, const sal_Int32* pDeltaArray)
523 : {
524 : // treat it like a builtin font in case a user has that font also in the
525 : // printer. This is not so unlikely as it may seem; no print embedding
526 : // licensed fonts are often used (or so they say) in companies:
527 : // they are installed on displays and printers, but get not embedded in
528 : // print files or documents because they are not licensed for use outside
529 : // the company.
530 0 : OString aMessage( "The font " );
531 0 : aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
532 0 : RTL_TEXTENCODING_ASCII_US );
533 0 : aMessage += " could not be downloaded\nbecause its license does not allow for that";
534 0 : PSComment( aMessage.getStr() );
535 :
536 : OString aFontName = OUStringToOString(
537 0 : mrFontMgr.getPSName(mnFontID),
538 0 : RTL_TEXTENCODING_ASCII_US);
539 0 : PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
540 :
541 0 : sal_Size nSize = 4 * nLen;
542 0 : unsigned char* pBuffer = (unsigned char*)alloca (nSize* sizeof(unsigned char));
543 :
544 0 : ConverterFactory &rCvt = GetConverterFactory ();
545 0 : nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
546 :
547 0 : PSMoveTo (rPoint);
548 0 : PSShowText (pBuffer, nLen, nSize, pDeltaArray);
549 0 : }
550 :
551 : void
552 0 : PrinterGfx::drawText(
553 : const Point& rPoint,
554 : const sal_Unicode* pStr,
555 : sal_Int16 nLen,
556 : const sal_Int32* pDeltaArray
557 : )
558 : {
559 0 : if (!(nLen > 0))
560 0 : return;
561 :
562 0 : fonttype::type eType = mrFontMgr.getFontType (mnFontID);
563 :
564 0 : if (eType == fonttype::Type1)
565 0 : PSUploadPS1Font (mnFontID);
566 :
567 0 : if ( eType == fonttype::TrueType
568 0 : && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
569 : {
570 0 : LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
571 0 : return;
572 : }
573 :
574 0 : if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
575 : {
576 0 : GlyphSet aGSet( mnFontID, mbTextVertical );
577 0 : aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
578 0 : return;
579 : }
580 :
581 : // search for a glyph set matching the set font
582 0 : std::list< GlyphSet >::iterator aIter;
583 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
584 0 : if ( ((*aIter).GetFontID() == mnFontID)
585 0 : && ((*aIter).IsVertical() == mbTextVertical))
586 : {
587 0 : (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
588 0 : break;
589 : }
590 :
591 : // not found ? create a new one
592 0 : if (aIter == maPS3Font.end())
593 : {
594 0 : maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
595 0 : maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
596 : }
597 : }
598 :
599 : int
600 0 : PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
601 : {
602 0 : b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
603 0 : int w = b_vert ? p_bbox->height : p_bbox->width;
604 0 : w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
605 0 : return w;
606 : }
607 :
608 : fontID
609 0 : PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
610 : {
611 0 : p_bbox->width = -1;
612 0 : p_bbox->height = -1;
613 :
614 0 : for (fontID n = 0; n < Font2Size; n++)
615 : {
616 0 : fontID n_font = rFont.GetFont(n);
617 0 : if (n_font != -1)
618 0 : mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
619 0 : if (p_bbox->width >= 0 && p_bbox->height >= 0)
620 0 : return n_font;
621 : }
622 0 : if (n_char != '?')
623 0 : return getCharMetric (rFont, '?', p_bbox);
624 :
625 0 : return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
626 : }
627 :
628 : sal_Int32
629 0 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
630 : {
631 0 : Font2 aFont(*this);
632 0 : if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
633 : {
634 0 : nFrom += 0xF000;
635 0 : nTo += 0xF000;
636 : }
637 :
638 0 : for( int n = 0; n < (nTo - nFrom + 1); n++ )
639 : {
640 0 : CharacterMetric aBBox;
641 0 : getCharMetric (aFont, n + nFrom, &aBBox);
642 0 : pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
643 : }
644 :
645 : // returned metrics have postscript precision
646 0 : return 1000;
647 : }
648 :
649 : /*
650 : * spool the converted truetype fonts to the page header after the page body is
651 : * complete
652 : * for Type1 fonts spool additional reencoding vectors that are necessary to access the
653 : * whole font
654 : */
655 :
656 : void
657 0 : PrinterGfx::OnEndPage ()
658 : {
659 0 : }
660 :
661 : void
662 0 : PrinterGfx::OnEndJob ()
663 : {
664 0 : maPS3Font.clear();
665 0 : maPS1Font.clear();
666 0 : }
667 :
668 : void
669 0 : PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
670 : {
671 : // write all type 1 fonts
672 0 : std::list< sal_Int32 >::iterator aFont;
673 : // already in the document header ?
674 0 : for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
675 : {
676 0 : const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
677 0 : OUString aUNCPath;
678 0 : osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
679 0 : osl::File aFontFile (aUNCPath);
680 :
681 : // provide the pfb or pfa font as a (pfa-)font resource
682 : OString aPostScriptName =
683 0 : OUStringToOString ( mrFontMgr.getPSName(*aFont),
684 0 : RTL_TEXTENCODING_ASCII_US );
685 :
686 0 : WritePS (pFile, "%%BeginResource: font ");
687 0 : WritePS (pFile, aPostScriptName.getStr());
688 0 : WritePS (pFile, "\n");
689 :
690 0 : osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
691 0 : if (nError == osl::File::E_None)
692 : {
693 0 : convertPfbToPfa (aFontFile, *pFile);
694 0 : aFontFile.close ();
695 :
696 0 : char lastchar = '\n';
697 :
698 0 : if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
699 : {
700 0 : sal_uInt64 uBytes(1);
701 0 : pFile->read((void *)(&lastchar), uBytes, uBytes);
702 : }
703 :
704 0 : if (lastchar != '\n')
705 0 : WritePS (pFile, "\n");
706 : }
707 0 : WritePS (pFile, "%%EndResource\n");
708 0 : rSuppliedFonts.push_back( aPostScriptName );
709 0 : }
710 :
711 : // write glyphsets and reencodings
712 0 : std::list< GlyphSet >::iterator aIter;
713 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
714 : {
715 0 : if (aIter->GetFontType() == fonttype::TrueType)
716 : {
717 0 : aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts ? true : false, rSuppliedFonts );
718 : }
719 : else
720 : {
721 0 : aIter->PSUploadEncoding (pFile, *this);
722 : }
723 : }
724 3 : }
725 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|