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