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