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