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 4172 : fontID GetFont (int nIdx) const
55 4172 : { return nIdx < Font2Size ? mpFont[nIdx] : -1 ; }
56 4172 : bool IsSymbolFont () const
57 4172 : { return mbSymbol; }
58 :
59 : Font2 (const PrinterGfx &rGfx);
60 4172 : ~Font2 () {}
61 : };
62 :
63 4172 : Font2::Font2(const PrinterGfx &rGfx)
64 : {
65 4172 : mpFont[0] = rGfx.GetFontID();
66 4172 : mpFont[1] = rGfx.getFallbackID();
67 :
68 4172 : PrintFontManager &rMgr = PrintFontManager::get();
69 8344 : mbSymbol = mpFont[0] != -1 &&
70 8344 : rMgr.getFontEncoding(mpFont[0]) == RTL_TEXTENCODING_SYMBOL;
71 4172 : }
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 1092 : 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 1092 : mnFontID = nFontID;
117 1092 : maVirtualStatus.maFont = OString();
118 1092 : maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW;
119 1092 : maVirtualStatus.mnTextHeight = nHeight;
120 1092 : maVirtualStatus.mnTextWidth = nWidth;
121 1092 : maVirtualStatus.mbArtItalic = bArtItalic;
122 1092 : maVirtualStatus.mbArtBold = bArtBold;
123 1092 : mnTextAngle = nAngle;
124 1092 : mbTextVertical = bVertical;
125 :
126 1092 : 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 : 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 = (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 = (fontID*) alloca(nLen * sizeof(fontID));
327 0 : sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32));
328 :
329 0 : for( int n = 0; n < nLen; n++ )
330 : {
331 0 : CharacterMetric aBBox;
332 : // coverity[array_vs_singleton]
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 = (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 = (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 nDeltaAngle, 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 = (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 0 : while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen )
457 0 : i++;
458 0 : if( i <= nLen && i > nLastPos )
459 : {
460 0 : for( int n = nLastPos; n < i; n++ )
461 0 : pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() );
462 :
463 : SetFont( mnFontID,
464 : maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth,
465 : nNormalAngle, mbTextVertical,
466 : maVirtualStatus.mbArtItalic,
467 0 : maVirtualStatus.mbArtBold );
468 0 : drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos );
469 :
470 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos));
471 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin));
472 : }
473 0 : if( i < nLen )
474 : {
475 0 : int nOldWidth = maVirtualStatus.mnTextWidth;
476 0 : int nOldHeight = maVirtualStatus.mnTextHeight;
477 : SetFont( mnFontID,
478 : nTextScale,
479 : maVirtualStatus.mnTextHeight,
480 : nNormalAngle + nDeltaAngle,
481 : mbTextVertical,
482 : maVirtualStatus.mbArtItalic,
483 0 : maVirtualStatus.mbArtBold );
484 :
485 0 : double nA = nTextScale * aInfo.m_nAscend / 1000.0;
486 0 : double nD = nTextScale * aInfo.m_nDescend / 1000.0;
487 0 : double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight;
488 0 : if( !pGsubFlags[i] )
489 0 : nD *= fStretch;
490 :
491 0 : Point aPos( aPoint );
492 0 : switch( nDeltaAngle )
493 : {
494 : case +900:
495 0 : aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin);
496 0 : aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos);
497 0 : break;
498 : case -900:
499 0 : aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos);
500 0 : aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos);
501 0 : break;
502 : }
503 0 : drawText( aPos, pStr+i, 1, NULL );
504 0 : if( i < nLen-1 && pDeltaArray )
505 : {
506 0 : aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos));
507 0 : aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin));
508 : }
509 :
510 : // swap text width/height again
511 : SetFont( mnFontID,
512 : nOldHeight,
513 : nOldWidth,
514 : nNormalAngle,
515 : mbTextVertical,
516 : maVirtualStatus.mbArtItalic,
517 0 : maVirtualStatus.mbArtBold );
518 : }
519 0 : i++;
520 0 : nLastPos = i;
521 : }
522 0 : mnTextAngle = nNormalAngle;
523 0 : return true;
524 : }
525 :
526 : void
527 0 : PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr,
528 : sal_Int16 nLen, const sal_Int32* pDeltaArray)
529 : {
530 : // treat it like a builtin font in case a user has that font also in the
531 : // printer. This is not so unlikely as it may seem; no print embedding
532 : // licensed fonts are often used (or so they say) in companies:
533 : // they are installed on displays and printers, but get not embedded in
534 : // print files or documents because they are not licensed for use outside
535 : // the company.
536 0 : OString aMessage( "The font " );
537 0 : aMessage += OUStringToOString( mrFontMgr.getPSName(mnFontID),
538 0 : RTL_TEXTENCODING_ASCII_US );
539 0 : aMessage += " could not be downloaded\nbecause its license does not allow for that";
540 0 : PSComment( aMessage.getStr() );
541 :
542 : OString aFontName = OUStringToOString(
543 0 : mrFontMgr.getPSName(mnFontID),
544 0 : RTL_TEXTENCODING_ASCII_US);
545 0 : PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1);
546 :
547 0 : sal_Size nSize = 4 * nLen;
548 0 : unsigned char* pBuffer = (unsigned char*)alloca (nSize* sizeof(unsigned char));
549 :
550 0 : ConverterFactory &rCvt = GetConverterFactory ();
551 0 : nSize = rCvt.Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1);
552 :
553 0 : PSMoveTo (rPoint);
554 0 : PSShowText (pBuffer, nLen, nSize, pDeltaArray);
555 0 : }
556 :
557 : void
558 0 : PrinterGfx::drawText(
559 : const Point& rPoint,
560 : const sal_Unicode* pStr,
561 : sal_Int16 nLen,
562 : const sal_Int32* pDeltaArray
563 : )
564 : {
565 0 : if (!(nLen > 0))
566 0 : return;
567 :
568 0 : fonttype::type eType = mrFontMgr.getFontType (mnFontID);
569 :
570 0 : if (eType == fonttype::Type1)
571 0 : PSUploadPS1Font (mnFontID);
572 :
573 0 : if ( eType == fonttype::TrueType
574 0 : && !mrFontMgr.isFontDownloadingAllowedForPrinting(mnFontID))
575 : {
576 0 : LicenseWarning(rPoint, pStr, nLen, pDeltaArray);
577 0 : return;
578 : }
579 :
580 0 : if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) )
581 : {
582 0 : GlyphSet aGSet( mnFontID, mbTextVertical );
583 0 : aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray );
584 0 : return;
585 : }
586 :
587 : // search for a glyph set matching the set font
588 0 : std::list< GlyphSet >::iterator aIter;
589 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
590 0 : if ( ((*aIter).GetFontID() == mnFontID)
591 0 : && ((*aIter).IsVertical() == mbTextVertical))
592 : {
593 0 : (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
594 0 : break;
595 : }
596 :
597 : // not found ? create a new one
598 0 : if (aIter == maPS3Font.end())
599 : {
600 0 : maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical));
601 0 : maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray);
602 : }
603 : }
604 :
605 : int
606 4172 : PrinterGfx::getCharWidth (bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox)
607 : {
608 4172 : b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0);
609 4172 : int w = b_vert ? p_bbox->height : p_bbox->width;
610 4172 : w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight;
611 4172 : return w;
612 : }
613 :
614 : fontID
615 4172 : PrinterGfx::getCharMetric (const Font2 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox)
616 : {
617 4172 : p_bbox->width = -1;
618 4172 : p_bbox->height = -1;
619 :
620 4172 : for (fontID n = 0; n < Font2Size; n++)
621 : {
622 4172 : fontID n_font = rFont.GetFont(n);
623 4172 : if (n_font != -1)
624 4172 : mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox );
625 4172 : if (p_bbox->width >= 0 && p_bbox->height >= 0)
626 4172 : return n_font;
627 : }
628 0 : if (n_char != '?')
629 0 : return getCharMetric (rFont, '?', p_bbox);
630 :
631 0 : return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1);
632 : }
633 :
634 : sal_Int32
635 4172 : PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray)
636 : {
637 4172 : Font2 aFont(*this);
638 4172 : if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256))
639 : {
640 0 : nFrom += 0xF000;
641 0 : nTo += 0xF000;
642 : }
643 :
644 8344 : for( int n = 0; n < (nTo - nFrom + 1); n++ )
645 : {
646 4172 : CharacterMetric aBBox;
647 : // coverity[array_vs_singleton]
648 4172 : getCharMetric (aFont, n + nFrom, &aBBox);
649 4172 : pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox);
650 : }
651 :
652 : // returned metrics have postscript precision
653 4172 : return 1000;
654 : }
655 :
656 : /*
657 : * spool the converted truetype fonts to the page header after the page body is
658 : * complete
659 : * for Type1 fonts spool additional reencoding vectors that are necessary to access the
660 : * whole font
661 : */
662 :
663 : void
664 0 : PrinterGfx::OnEndPage ()
665 : {
666 0 : }
667 :
668 : void
669 0 : PrinterGfx::OnEndJob ()
670 : {
671 0 : maPS3Font.clear();
672 0 : maPS1Font.clear();
673 0 : }
674 :
675 : void
676 0 : PrinterGfx::writeResources( osl::File* pFile, std::list< OString >& rSuppliedFonts )
677 : {
678 : // write all type 1 fonts
679 0 : std::list< sal_Int32 >::iterator aFont;
680 : // already in the document header ?
681 0 : for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont)
682 : {
683 0 : const OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) );
684 0 : OUString aUNCPath;
685 0 : osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath);
686 0 : osl::File aFontFile (aUNCPath);
687 :
688 : // provide the pfb or pfa font as a (pfa-)font resource
689 : OString aPostScriptName =
690 0 : OUStringToOString ( mrFontMgr.getPSName(*aFont),
691 0 : RTL_TEXTENCODING_ASCII_US );
692 :
693 0 : WritePS (pFile, "%%BeginResource: font ");
694 0 : WritePS (pFile, aPostScriptName.getStr());
695 0 : WritePS (pFile, "\n");
696 :
697 0 : osl::File::RC nError = aFontFile.open(osl_File_OpenFlag_Read);
698 0 : if (nError == osl::File::E_None)
699 : {
700 0 : convertPfbToPfa (aFontFile, *pFile);
701 0 : aFontFile.close ();
702 :
703 0 : char lastchar = '\n';
704 :
705 0 : if (pFile->setPos(osl_Pos_Current, -1) == osl::FileBase::E_None)
706 : {
707 0 : sal_uInt64 uBytes(1);
708 0 : pFile->read((void *)(&lastchar), uBytes, uBytes);
709 : }
710 :
711 0 : if (lastchar != '\n')
712 0 : WritePS (pFile, "\n");
713 : }
714 0 : WritePS (pFile, "%%EndResource\n");
715 0 : rSuppliedFonts.push_back( aPostScriptName );
716 0 : }
717 :
718 : // write glyphsets and reencodings
719 0 : std::list< GlyphSet >::iterator aIter;
720 0 : for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter)
721 : {
722 0 : if (aIter->GetFontType() == fonttype::TrueType)
723 : {
724 0 : aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts, rSuppliedFonts );
725 : }
726 : else
727 : {
728 0 : aIter->PSUploadEncoding (pFile, *this);
729 : }
730 : }
731 1233 : }
732 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|