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 2086 : fontID GetFont (int nIdx) const
55 2086 : { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
56 2086 : bool IsSymbolFont () const
57 2086 : { return mbSymbol; }
58 :
59 : explicit Font2 (const PrinterGfx &rGfx);
60 2086 : ~Font2 () {}
61 : };
62 :
63 2086 : Font2::Font2(const PrinterGfx &rGfx)
64 : {
65 2086 : mpFont[0] = rGfx.GetFontID();
66 2086 : mpFont[1] = rGfx.getFallbackID();
67 :
68 2086 : PrintFontManager &rMgr = PrintFontManager::get();
69 4172 : mbSymbol = mpFont[0] != -1 &&
70 4172 : rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL;
71 2086 : }
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 753 : 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 753 : mnFontID = nFontID;
117 753 : maVirtualStatus.maFont.clear();
118 753 : maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW;
119 753 : maVirtualStatus.mnTextHeight = nHeight;
120 753 : maVirtualStatus.mnTextWidth = nWidth;
121 753 : maVirtualStatus.mbArtItalic = bArtItalic;
122 753 : maVirtualStatus.mbArtBold = bArtBold;
123 753 : mnTextAngle = nAngle;
124 753 : mbTextVertical = bVertical;
125 :
126 753 : 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 = static_cast<sal_GlyphId*>(alloca(sizeof(sal_Int32)*nLen));
201 0 : sal_Int32* pTempDelta = static_cast<sal_Int32*>(alloca(sizeof(sal_Int32)*nLen));
202 0 : sal_Unicode* pTempUnicodes = static_cast<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 : if (!nLen)
307 0 : return;
308 :
309 0 : fontID nRestoreFont = mnFontID;
310 :
311 : // setup font[substitutes] and map the string into the symbol area in case of
312 : // symbol font
313 0 : Font2 aFont(*this);
314 : sal_Unicode *pEffectiveStr;
315 0 : if ( aFont.IsSymbolFont() )
316 : {
317 0 : pEffectiveStr = static_cast<sal_Unicode*>(alloca(nLen * sizeof(pStr[0])));
318 0 : for (int i = 0; i < nLen; i++)
319 0 : pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i];
320 : }
321 : else
322 : {
323 0 : pEffectiveStr = const_cast<sal_Unicode*>(pStr);
324 : }
325 :
326 0 : fontID *pFontMap = static_cast<fontID*>(alloca(nLen * sizeof(fontID)));
327 0 : sal_Int32 *pCharWidth = static_cast<sal_Int32*>(alloca(nLen * sizeof(sal_Int32)));
328 :
329 0 : for( int n = 0; n < nLen; n++ )
330 : {
331 0 : CharacterMetric aBBox;
332 : // coverity[callee_ptr_arith]
333 0 : pFontMap[n] = getCharMetric(aFont, pEffectiveStr[n], &aBBox);
334 0 : pCharWidth[n] = getCharWidth(mbTextVertical, pEffectiveStr[n], &aBBox);
335 : }
336 :
337 : // setup a new delta array, use virtual resolution of 1000
338 0 : sal_Int32* pNewDeltaArray = static_cast<sal_Int32*>(alloca( sizeof( sal_Int32 )*nLen ));
339 0 : if ( pDeltaArray != 0)
340 : {
341 0 : for (int i = 0; i < nLen - 1; i++)
342 0 : pNewDeltaArray[i] = 1000 * pDeltaArray[i];
343 0 : pNewDeltaArray[nLen - 1] = 0;
344 : }
345 : else
346 : {
347 0 : pNewDeltaArray[0] = pCharWidth[0];
348 0 : for (int i = 1; i < nLen; i++)
349 0 : pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i];
350 : }
351 :
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 0 : sal_Int32 nCurrentTextAngle = mnTextAngle;
356 : sal_Int32 nCurrentPointX;
357 : sal_Int32 nCurrentPointY;
358 :
359 0 : if (nCurrentTextAngle != 0)
360 : {
361 0 : PSGSave ();
362 0 : PSTranslate (rPoint);
363 0 : PSRotate (nCurrentTextAngle);
364 0 : mnTextAngle = 0;
365 :
366 0 : nCurrentPointX = 0;
367 0 : nCurrentPointY = 0;
368 : }
369 : else
370 : {
371 0 : nCurrentPointX = rPoint.X();
372 0 : nCurrentPointY = rPoint.Y();
373 : }
374 :
375 : // draw the string
376 0 : sal_Int32 nDelta = 0;
377 0 : for (int nTo = 0; nTo < nLen; )
378 : {
379 0 : int nFrom = nTo;
380 0 : fontID nFont = pFontMap[ nFrom ];
381 :
382 0 : while ((nTo < nLen) && (nFont == pFontMap[nTo]))
383 : {
384 0 : pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta);
385 0 : nTo++ ;
386 : }
387 :
388 : SetFont( nFont,
389 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
390 : mnTextAngle,
391 : mbTextVertical,
392 : maVirtualStatus.mbArtItalic,
393 : maVirtualStatus.mbArtBold
394 0 : );
395 :
396 0 : if (mbTextVertical)
397 : {
398 : drawVerticalizedText(
399 0 : Point(nCurrentPointX + nDelta, nCurrentPointY),
400 : pEffectiveStr + nFrom, nTo - nFrom,
401 0 : pNewDeltaArray + nFrom );
402 : }
403 : else
404 : {
405 : drawText(
406 0 : Point(nCurrentPointX + nDelta, nCurrentPointY),
407 : pEffectiveStr + nFrom, nTo - nFrom,
408 0 : pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom );
409 : }
410 0 : nDelta += pNewDeltaArray[ nTo - 1 ];
411 : }
412 :
413 : // restore the user coordinate system
414 0 : if (nCurrentTextAngle != 0)
415 : {
416 0 : PSGRestore ();
417 0 : mnTextAngle = nCurrentTextAngle;
418 : }
419 :
420 : // restore the original font settings
421 : SetFont( nRestoreFont,
422 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
423 : mnTextAngle, mbTextVertical,
424 : maVirtualStatus.mbArtItalic,
425 : maVirtualStatus.mbArtBold
426 0 : );
427 : }
428 :
429 0 : bool PrinterGfx::drawVerticalizedText(
430 : const Point& rPoint,
431 : const sal_Unicode* pStr,
432 : sal_Int16 nLen,
433 : const sal_Int32* pDeltaArray
434 : )
435 : {
436 0 : PrintFontManager &rMgr = PrintFontManager::get();
437 0 : PrintFontInfo aInfo;
438 0 : if (!rMgr.getFontInfo(mnFontID, aInfo))
439 0 : return false;
440 :
441 0 : sal_Int32* pDelta = static_cast<sal_Int32*>(alloca( nLen * sizeof(sal_Int32) ));
442 :
443 0 : int nTextScale = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
444 0 : int nNormalAngle = mnTextAngle;
445 0 : int nLastPos = 0;
446 :
447 0 : double fSin = sin( -2.0*M_PI*nNormalAngle/3600 );
448 0 : double fCos = cos( -2.0*M_PI*nNormalAngle/3600 );
449 :
450 0 : bool* pGsubFlags = static_cast<bool*>(alloca( nLen * sizeof(bool) ));
451 0 : rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags );
452 :
453 0 : Point aPoint( rPoint );
454 0 : for( int i = 0; i < nLen; )
455 : {
456 : int nDeltaAngle;
457 0 : while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
458 0 : i++;
459 0 : if( i <= nLen && i > nLastPos )
460 : {
461 0 : for( int n = nLastPos; n < i; n++ )
462 0 : pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
463 :
464 : SetFont( mnFontID,
465 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
466 : nNormalAngle, mbTextVertical,
467 : maVirtualStatus.mbArtItalic,
468 0 : maVirtualStatus.mbArtBold );
469 0 : drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
470 :
471 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
472 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
473 : }
474 0 : if( i < nLen )
475 : {
476 0 : int nOldWidth = maVirtualStatus.mnTextWidth;
477 0 : int nOldHeight = maVirtualStatus.mnTextHeight;
478 : SetFont( mnFontID,
479 : nTextScale,
480 : maVirtualStatus.mnTextHeight,
481 : nNormalAngle + nDeltaAngle,
482 : mbTextVertical,
483 : maVirtualStatus.mbArtItalic,
484 0 : maVirtualStatus.mbArtBold );
485 :
486 0 : double nA = nTextScale * aInfo.m_nAscend / 1000.0;
487 0 : double nD = nTextScale * aInfo.m_nDescend / 1000.0;
488 0 : double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
489 0 : if( !pGsubFlags[i] )
490 0 : nD *= fStretch;
491 :
492 0 : Point aPos( aPoint );
493 0 : switch( nDeltaAngle )
494 : {
495 : case +900:
496 0 : aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
497 0 : aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
498 0 : break;
499 : case -900:
500 0 : aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
501 0 : aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
502 0 : break;
503 : }
504 0 : drawText( aPos, pStr+i, 1, NULL );
505 0 : if( i < nLen-1 && pDeltaArray )
506 : {
507 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
508 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
509 : }
510 :
511 : // swap text width/height again
512 : SetFont( mnFontID,
513 : nOldHeight,
514 : nOldWidth,
515 : nNormalAngle,
516 : mbTextVertical,
517 : maVirtualStatus.mbArtItalic,
518 0 : maVirtualStatus.mbArtBold );
519 : }
520 0 : i++;
521 0 : nLastPos = i;
522 : }
523 0 : mnTextAngle = nNormalAngle;
524 0 : return true;
525 : }
526 :
527 : void
528 0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
529 : sal_Int16 nLen, const sal_Int32* pDeltaArray)
530 : {
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 0 : OString aMessage( "The font " );
538 0 : aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
539 0 : RTL_TEXTENCODING_ASCII_US );
540 0 : aMessage += " could not be downloaded\nbecause its license does not allow for that";
541 0 : PSComment( aMessage.getStr() );
542 :
543 : OString aFontName = OUStringToOString(
544 0 : mrFontMgr.getPSName(mnFontID),
545 0 : RTL_TEXTENCODING_ASCII_US);
546 0 : PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
547 :
548 0 : sal_Size nSize = 4 * nLen;
549 0 : unsigned char* pBuffer = static_cast<unsigned char*>(alloca (nSize* sizeof(unsigned char)));
550 :
551 0 : ConverterFactory &rCvt = GetConverterFactory ();
552 0 : nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
553 :
554 0 : PSMoveTo (rPoint);
555 0 : PSShowText (pBuffer, nLen, nSize, pDeltaArray);
556 0 : }
557 :
558 : void
559 0 : PrinterGfx::drawText(
560 : const Point& rPoint,
561 : const sal_Unicode* pStr,
562 : sal_Int16 nLen,
563 : const sal_Int32* pDeltaArray
564 : )
565 : {
566 0 : if (!(nLen > 0))
567 0 : return;
568 :
569 0 : fonttype::type eType = mrFontMgr.getFontType (mnFontID);
570 :
571 0 : if (eType == fonttype::Type1)
572 0 : PSUploadPS1Font (mnFontID);
573 :
574 0 : if ( eType == fonttype::TrueType
575 0 : && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
576 : {
577 0 : LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
578 0 : return;
579 : }
580 :
581 0 : if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
582 : {
583 0 : GlyphSet aGSet( mnFontID, mbTextVertical );
584 0 : aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
585 0 : return;
586 : }
587 :
588 : // search for a glyph set matching the set font
589 0 : std::list< GlyphSet >::iterator aIter;
590 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
591 0 : if ( ((*aIter).GetFontID() == mnFontID)
592 0 : && ((*aIter).IsVertical() == mbTextVertical))
593 : {
594 0 : (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
595 0 : break;
596 : }
597 :
598 : // not found ? create a new one
599 0 : if (aIter == maPS3Font.end())
600 : {
601 0 : maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
602 0 : maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
603 : }
604 : }
605 :
606 : int
607 2086 : PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
608 : {
609 2086 : b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
610 2086 : int w = b_vert ? p_bbox->height : p_bbox->width;
611 2086 : w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
612 2086 : return w;
613 : }
614 :
615 : fontID
616 2086 : PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
617 : {
618 2086 : p_bbox->width = -1;
619 2086 : p_bbox->height = -1;
620 :
621 2086 : for (fontID n = 0; n < Font2Size; n++)
622 : {
623 2086 : fontID n_font = rFont.GetFont(n);
624 2086 : if (n_font != -1)
625 2086 : mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
626 2086 : if (p_bbox->width >= 0 && p_bbox->height >= 0)
627 2086 : return n_font;
628 : }
629 0 : if (n_char != '?')
630 0 : return getCharMetric (rFont, '?', p_bbox);
631 :
632 0 : return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
633 : }
634 :
635 : sal_Int32
636 2086 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
637 : {
638 2086 : Font2 aFont(*this);
639 2086 : if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
640 : {
641 0 : nFrom += 0xF000;
642 0 : nTo += 0xF000;
643 : }
644 :
645 4172 : for( int n = 0; n < (nTo - nFrom + 1); n++ )
646 : {
647 2086 : CharacterMetric aBBox;
648 : // coverity[callee_ptr_arith]
649 2086 : getCharMetric(aFont, n + nFrom, &aBBox);
650 2086 : pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
651 : }
652 :
653 : // returned metrics have postscript precision
654 2086 : return 1000;
655 : }
656 :
657 : /*
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
662 : */
663 :
664 : void
665 0 : PrinterGfx::OnEndJob ()
666 : {
667 0 : maPS3Font.clear();
668 0 : maPS1Font.clear();
669 0 : }
670 :
671 : void
672 0 : PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
673 : {
674 : // write all type 1 fonts
675 0 : std::list< sal_Int32 >::iterator aFont;
676 : // already in the document header ?
677 0 : for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
678 : {
679 0 : const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
680 0 : OUString aUNCPath;
681 0 : osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
682 0 : osl::File aFontFile (aUNCPath);
683 :
684 : // provide the pfb or pfa font as a (pfa-)font resource
685 : OString aPostScriptName =
686 0 : OUStringToOString ( mrFontMgr.getPSName(*aFont),
687 0 : RTL_TEXTENCODING_ASCII_US );
688 :
689 0 : WritePS (pFile, "%%BeginResource: font ");
690 0 : WritePS (pFile, aPostScriptName.getStr());
691 0 : WritePS (pFile, "\n");
692 :
693 0 : osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
694 0 : if (nError == osl::File::E_None)
695 : {
696 0 : convertPfbToPfa (aFontFile, *pFile);
697 0 : aFontFile.close ();
698 :
699 0 : char lastchar = '\n';
700 :
701 0 : if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
702 : {
703 0 : sal_uInt64 uBytes(1);
704 0 : pFile->read(static_cast<void *>(&lastchar), uBytes, uBytes);
705 : }
706 :
707 0 : if (lastchar != '\n')
708 0 : WritePS (pFile, "\n");
709 : }
710 0 : WritePS (pFile, "%%EndResource\n");
711 0 : rSuppliedFonts.push_back( aPostScriptName );
712 0 : }
713 :
714 : // write glyphsets and reencodings
715 0 : std::list< GlyphSet >::iterator aIter;
716 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
717 : {
718 0 : if (aIter->GetFontType() == fonttype::TrueType)
719 : {
720 0 : aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts, rSuppliedFonts );
721 : }
722 : else
723 : {
724 0 : aIter->PSUploadEncoding (pFile, *this);
725 : }
726 : }
727 801 : }
728 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|