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 "glyphset.hxx"
28cdf0e10cSrcweir #include "psputil.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include "sft.hxx"
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include "printergfx.hxx"
33cdf0e10cSrcweir #include "fontsubset.hxx"
34cdf0e10cSrcweir #include "vcl/fontmanager.hxx"
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include "osl/thread.h"
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include "sal/alloca.h"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "rtl/ustring.hxx"
41cdf0e10cSrcweir #include "rtl/strbuf.hxx"
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include <set>
44cdf0e10cSrcweir #include <map>
45cdf0e10cSrcweir #include <algorithm>
46cdf0e10cSrcweir 
47cdf0e10cSrcweir using namespace vcl;
48cdf0e10cSrcweir using namespace psp;
49cdf0e10cSrcweir using namespace rtl;
50cdf0e10cSrcweir 
GlyphSet()51cdf0e10cSrcweir GlyphSet::GlyphSet ()
52cdf0e10cSrcweir         : mnFontID   (-1),
53cdf0e10cSrcweir           mbVertical (0),
54cdf0e10cSrcweir           mbUseFontEncoding (false)
55cdf0e10cSrcweir {}
56cdf0e10cSrcweir 
GlyphSet(sal_Int32 nFontID,sal_Bool bVertical)57cdf0e10cSrcweir GlyphSet::GlyphSet (sal_Int32 nFontID, sal_Bool bVertical)
58cdf0e10cSrcweir         : mnFontID (nFontID),
59cdf0e10cSrcweir           mbVertical (bVertical)
60cdf0e10cSrcweir {
61cdf0e10cSrcweir     PrintFontManager &rMgr = PrintFontManager::get();
62cdf0e10cSrcweir     meBaseType      	= rMgr.getFontType (mnFontID);
63cdf0e10cSrcweir     maBaseName      	= OUStringToOString (rMgr.getPSName(mnFontID),
64cdf0e10cSrcweir                                            RTL_TEXTENCODING_ASCII_US);
65cdf0e10cSrcweir     mnBaseEncoding  	= rMgr.getFontEncoding(mnFontID);
66cdf0e10cSrcweir     mbUseFontEncoding	= rMgr.getUseOnlyFontEncoding(mnFontID);
67cdf0e10cSrcweir }
68cdf0e10cSrcweir 
~GlyphSet()69cdf0e10cSrcweir GlyphSet::~GlyphSet ()
70cdf0e10cSrcweir {
71cdf0e10cSrcweir     /* FIXME delete the glyphlist ??? */
72cdf0e10cSrcweir }
73cdf0e10cSrcweir 
74cdf0e10cSrcweir sal_Int32
GetFontID()75cdf0e10cSrcweir GlyphSet::GetFontID ()
76cdf0e10cSrcweir {
77cdf0e10cSrcweir     return mnFontID;
78cdf0e10cSrcweir }
79cdf0e10cSrcweir 
80cdf0e10cSrcweir fonttype::type
GetFontType()81cdf0e10cSrcweir GlyphSet::GetFontType ()
82cdf0e10cSrcweir {
83cdf0e10cSrcweir     return meBaseType;
84cdf0e10cSrcweir }
85cdf0e10cSrcweir 
86cdf0e10cSrcweir sal_Bool
IsVertical()87cdf0e10cSrcweir GlyphSet::IsVertical ()
88cdf0e10cSrcweir {
89cdf0e10cSrcweir     return mbVertical;
90cdf0e10cSrcweir }
91cdf0e10cSrcweir 
92cdf0e10cSrcweir sal_Bool
SetFont(sal_Int32 nFontID,sal_Bool bVertical)93cdf0e10cSrcweir GlyphSet::SetFont (sal_Int32 nFontID, sal_Bool bVertical)
94cdf0e10cSrcweir {
95cdf0e10cSrcweir     if (mnFontID != -1)
96cdf0e10cSrcweir         return sal_False;
97cdf0e10cSrcweir 
98cdf0e10cSrcweir     mnFontID   = nFontID;
99cdf0e10cSrcweir     mbVertical = bVertical;
100cdf0e10cSrcweir 
101cdf0e10cSrcweir     PrintFontManager &rMgr = PrintFontManager::get();
102cdf0e10cSrcweir     meBaseType      = rMgr.getFontType (mnFontID);
103cdf0e10cSrcweir     maBaseName      = OUStringToOString (rMgr.getPSName(mnFontID),
104cdf0e10cSrcweir                                            RTL_TEXTENCODING_ASCII_US);
105cdf0e10cSrcweir     mnBaseEncoding  = rMgr.getFontEncoding(mnFontID);
106cdf0e10cSrcweir     mbUseFontEncoding	= rMgr.getUseOnlyFontEncoding(mnFontID);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir     return sal_True;
109cdf0e10cSrcweir }
110cdf0e10cSrcweir 
111cdf0e10cSrcweir sal_Bool
GetCharID(sal_Unicode nChar,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)112cdf0e10cSrcweir GlyphSet::GetCharID (
113cdf0e10cSrcweir                      sal_Unicode nChar,
114cdf0e10cSrcweir                      sal_uChar* nOutGlyphID,
115cdf0e10cSrcweir                      sal_Int32* nOutGlyphSetID
116cdf0e10cSrcweir                      )
117cdf0e10cSrcweir {
118cdf0e10cSrcweir     return    LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
119cdf0e10cSrcweir            || AddCharID    (nChar, nOutGlyphID, nOutGlyphSetID);
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir sal_Bool
GetGlyphID(sal_GlyphId nGlyph,sal_Unicode nUnicode,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)123cdf0e10cSrcweir GlyphSet::GetGlyphID (
124*248a599fSHerbert Dürr                       sal_GlyphId nGlyph,
125cdf0e10cSrcweir                       sal_Unicode nUnicode,
126cdf0e10cSrcweir                       sal_uChar* nOutGlyphID,
127cdf0e10cSrcweir                       sal_Int32* nOutGlyphSetID
128cdf0e10cSrcweir                      )
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     return    LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
131cdf0e10cSrcweir            || AddGlyphID    (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
132cdf0e10cSrcweir }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir sal_Bool
LookupCharID(sal_Unicode nChar,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)135cdf0e10cSrcweir GlyphSet::LookupCharID (
136cdf0e10cSrcweir                         sal_Unicode nChar,
137cdf0e10cSrcweir                         sal_uChar* nOutGlyphID,
138cdf0e10cSrcweir                         sal_Int32* nOutGlyphSetID
139cdf0e10cSrcweir                         )
140cdf0e10cSrcweir {
141cdf0e10cSrcweir     char_list_t::iterator aGlyphSet;
142cdf0e10cSrcweir     sal_Int32             nGlyphSetID;
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     // loop thru all the font subsets
145cdf0e10cSrcweir     for (aGlyphSet  = maCharList.begin(), nGlyphSetID = 1;
146cdf0e10cSrcweir          aGlyphSet != maCharList.end();
147cdf0e10cSrcweir          ++aGlyphSet, nGlyphSetID++)
148cdf0e10cSrcweir     {
149cdf0e10cSrcweir         // check every subset if it contains the queried unicode char
150cdf0e10cSrcweir         char_map_t::const_iterator aGlyph = (*aGlyphSet).find (nChar);
151cdf0e10cSrcweir         if (aGlyph != (*aGlyphSet).end())
152cdf0e10cSrcweir         {
153cdf0e10cSrcweir             // success: found the unicode char, return the glyphid and the glyphsetid
154cdf0e10cSrcweir             *nOutGlyphSetID = nGlyphSetID;
155cdf0e10cSrcweir             *nOutGlyphID    = (*aGlyph).second;
156cdf0e10cSrcweir             return sal_True;
157cdf0e10cSrcweir         }
158cdf0e10cSrcweir     }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir     *nOutGlyphSetID = -1;
161cdf0e10cSrcweir     *nOutGlyphID    =  0;
162cdf0e10cSrcweir     return sal_False;
163cdf0e10cSrcweir }
164cdf0e10cSrcweir 
165cdf0e10cSrcweir sal_Bool
LookupGlyphID(sal_GlyphId nGlyph,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)166cdf0e10cSrcweir GlyphSet::LookupGlyphID (
167*248a599fSHerbert Dürr                         sal_GlyphId nGlyph,
168cdf0e10cSrcweir                         sal_uChar* nOutGlyphID,
169cdf0e10cSrcweir                         sal_Int32* nOutGlyphSetID
170cdf0e10cSrcweir                         )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir     glyph_list_t::iterator aGlyphSet;
173cdf0e10cSrcweir     sal_Int32             nGlyphSetID;
174cdf0e10cSrcweir 
175cdf0e10cSrcweir     // loop thru all the font subsets
176cdf0e10cSrcweir     for (aGlyphSet  = maGlyphList.begin(), nGlyphSetID = 1;
177cdf0e10cSrcweir          aGlyphSet != maGlyphList.end();
178cdf0e10cSrcweir          ++aGlyphSet, nGlyphSetID++)
179cdf0e10cSrcweir     {
180cdf0e10cSrcweir         // check every subset if it contains the queried unicode char
181cdf0e10cSrcweir         glyph_map_t::const_iterator aGlyph = (*aGlyphSet).find (nGlyph);
182cdf0e10cSrcweir         if (aGlyph != (*aGlyphSet).end())
183cdf0e10cSrcweir         {
184cdf0e10cSrcweir             // success: found the glyph id, return the mapped glyphid and the glyphsetid
185cdf0e10cSrcweir             *nOutGlyphSetID = nGlyphSetID;
186cdf0e10cSrcweir             *nOutGlyphID    = (*aGlyph).second;
187cdf0e10cSrcweir             return sal_True;
188cdf0e10cSrcweir         }
189cdf0e10cSrcweir     }
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     *nOutGlyphSetID = -1;
192cdf0e10cSrcweir     *nOutGlyphID    =  0;
193cdf0e10cSrcweir     return sal_False;
194cdf0e10cSrcweir }
195cdf0e10cSrcweir 
196cdf0e10cSrcweir sal_uChar
GetAnsiMapping(sal_Unicode nUnicodeChar)197cdf0e10cSrcweir GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar)
198cdf0e10cSrcweir {
199cdf0e10cSrcweir     static rtl_UnicodeToTextConverter aConverter =
200cdf0e10cSrcweir                 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252);
201cdf0e10cSrcweir 	static rtl_UnicodeToTextContext aContext =
202cdf0e10cSrcweir 		 	rtl_createUnicodeToTextContext( aConverter );
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     sal_Char            nAnsiChar;
205cdf0e10cSrcweir 	sal_uInt32          nCvtInfo;
206cdf0e10cSrcweir 	sal_Size            nCvtChars;
207cdf0e10cSrcweir    	const sal_uInt32    nCvtFlags =  RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
208cdf0e10cSrcweir                                    | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
209cdf0e10cSrcweir 
210cdf0e10cSrcweir 	sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
211cdf0e10cSrcweir 				&nUnicodeChar, 1, &nAnsiChar, 1,
212cdf0e10cSrcweir 				nCvtFlags, &nCvtInfo, &nCvtChars );
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     return nSize == 1 ? (sal_uChar)nAnsiChar : (sal_uChar)0;
215cdf0e10cSrcweir }
216cdf0e10cSrcweir 
217cdf0e10cSrcweir sal_uChar
GetSymbolMapping(sal_Unicode nUnicodeChar)218cdf0e10cSrcweir GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar)
219cdf0e10cSrcweir {
220cdf0e10cSrcweir     if (0x0000 < nUnicodeChar && nUnicodeChar < 0x0100)
221cdf0e10cSrcweir         return (sal_uChar)nUnicodeChar;
222cdf0e10cSrcweir     if (0xf000 < nUnicodeChar && nUnicodeChar < 0xf100)
223cdf0e10cSrcweir         return (sal_uChar)nUnicodeChar;
224cdf0e10cSrcweir 
225cdf0e10cSrcweir     return 0;
226cdf0e10cSrcweir }
227cdf0e10cSrcweir 
228cdf0e10cSrcweir void
AddNotdef(char_map_t & rCharMap)229cdf0e10cSrcweir GlyphSet::AddNotdef (char_map_t &rCharMap)
230cdf0e10cSrcweir {
231cdf0e10cSrcweir     if (rCharMap.size() == 0)
232cdf0e10cSrcweir         rCharMap[0] = 0;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir 
235cdf0e10cSrcweir void
AddNotdef(glyph_map_t & rGlyphMap)236cdf0e10cSrcweir GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
237cdf0e10cSrcweir {
238cdf0e10cSrcweir     if (rGlyphMap.size() == 0)
239cdf0e10cSrcweir         rGlyphMap[0] = 0;
240cdf0e10cSrcweir }
241cdf0e10cSrcweir sal_Bool
AddCharID(sal_Unicode nChar,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)242cdf0e10cSrcweir GlyphSet::AddCharID (
243cdf0e10cSrcweir                      sal_Unicode nChar,
244cdf0e10cSrcweir                      sal_uChar* nOutGlyphID,
245cdf0e10cSrcweir                      sal_Int32* nOutGlyphSetID
246cdf0e10cSrcweir                      )
247cdf0e10cSrcweir {
248cdf0e10cSrcweir     sal_uChar nMappedChar;
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     // XXX important: avoid to reencode type1 symbol fonts
251cdf0e10cSrcweir     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
252cdf0e10cSrcweir         nMappedChar = GetSymbolMapping (nChar);
253cdf0e10cSrcweir     else
254cdf0e10cSrcweir         nMappedChar = GetAnsiMapping (nChar);
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     // create an empty glyphmap that is reserved for iso1252 encoded glyphs
257cdf0e10cSrcweir     // (or -- unencoded -- symbol glyphs) and a second map that takes any other
258cdf0e10cSrcweir     if (maCharList.empty())
259cdf0e10cSrcweir     {
260cdf0e10cSrcweir         char_map_t aMap, aMapp;
261cdf0e10cSrcweir 
262cdf0e10cSrcweir         maCharList.push_back (aMap);
263cdf0e10cSrcweir         maCharList.push_back (aMapp);
264cdf0e10cSrcweir     }
265cdf0e10cSrcweir     // if the last map is full, create a new one
266cdf0e10cSrcweir     if ((!nMappedChar) && (maCharList.back().size() == 255))
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir         char_map_t aMap;
269cdf0e10cSrcweir         maCharList.push_back (aMap);
270cdf0e10cSrcweir     }
271cdf0e10cSrcweir 
272cdf0e10cSrcweir     // insert a new glyph in the font subset
273cdf0e10cSrcweir     if (nMappedChar)
274cdf0e10cSrcweir     {
275cdf0e10cSrcweir         // always put iso1252 chars into the first map, map them on itself
276cdf0e10cSrcweir         char_map_t& aGlyphSet = maCharList.front();
277cdf0e10cSrcweir         AddNotdef (aGlyphSet);
278cdf0e10cSrcweir 
279cdf0e10cSrcweir         aGlyphSet [nChar] = nMappedChar;
280cdf0e10cSrcweir         *nOutGlyphSetID   = 1;
281cdf0e10cSrcweir         *nOutGlyphID      = nMappedChar;
282cdf0e10cSrcweir     }
283cdf0e10cSrcweir     else
284cdf0e10cSrcweir     {
285cdf0e10cSrcweir         // other chars are just appended to the list
286cdf0e10cSrcweir         char_map_t& aGlyphSet = maCharList.back();
287cdf0e10cSrcweir         AddNotdef (aGlyphSet);
288cdf0e10cSrcweir 
289cdf0e10cSrcweir         int nSize         = aGlyphSet.size();
290cdf0e10cSrcweir 
291cdf0e10cSrcweir         aGlyphSet [nChar] = nSize;
292cdf0e10cSrcweir         *nOutGlyphSetID   = maCharList.size();
293cdf0e10cSrcweir         *nOutGlyphID      = aGlyphSet [nChar];
294cdf0e10cSrcweir     }
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     return sal_True;
297cdf0e10cSrcweir }
298cdf0e10cSrcweir 
299cdf0e10cSrcweir sal_Bool
AddGlyphID(sal_GlyphId nGlyph,sal_Unicode nUnicode,sal_uChar * nOutGlyphID,sal_Int32 * nOutGlyphSetID)300cdf0e10cSrcweir GlyphSet::AddGlyphID (
301*248a599fSHerbert Dürr                      sal_GlyphId nGlyph,
302cdf0e10cSrcweir                      sal_Unicode nUnicode,
303cdf0e10cSrcweir                      sal_uChar* nOutGlyphID,
304cdf0e10cSrcweir                      sal_Int32* nOutGlyphSetID
305cdf0e10cSrcweir                      )
306cdf0e10cSrcweir {
307cdf0e10cSrcweir     sal_uChar nMappedChar;
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     // XXX important: avoid to reencode type1 symbol fonts
310cdf0e10cSrcweir     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
311cdf0e10cSrcweir         nMappedChar = GetSymbolMapping (nUnicode);
312cdf0e10cSrcweir     else
313cdf0e10cSrcweir         nMappedChar = GetAnsiMapping (nUnicode);
314cdf0e10cSrcweir 
315cdf0e10cSrcweir     // create an empty glyphmap that is reserved for iso1252 encoded glyphs
316cdf0e10cSrcweir     // (or -- unencoded -- symbol glyphs) and a second map that takes any other
317cdf0e10cSrcweir     if (maGlyphList.empty())
318cdf0e10cSrcweir     {
319cdf0e10cSrcweir         glyph_map_t aMap, aMapp;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir         maGlyphList.push_back (aMap);
322cdf0e10cSrcweir         maGlyphList.push_back (aMapp);
323cdf0e10cSrcweir     }
324cdf0e10cSrcweir     // if the last map is full, create a new one
325cdf0e10cSrcweir     if ((!nMappedChar) && (maGlyphList.back().size() == 255))
326cdf0e10cSrcweir     {
327cdf0e10cSrcweir         glyph_map_t aMap;
328cdf0e10cSrcweir         maGlyphList.push_back (aMap);
329cdf0e10cSrcweir     }
330cdf0e10cSrcweir 
331cdf0e10cSrcweir     // insert a new glyph in the font subset
332cdf0e10cSrcweir     if (nMappedChar)
333cdf0e10cSrcweir     {
334cdf0e10cSrcweir         // always put iso1252 chars into the first map, map them on itself
335cdf0e10cSrcweir         glyph_map_t& aGlyphSet = maGlyphList.front();
336cdf0e10cSrcweir         AddNotdef (aGlyphSet);
337cdf0e10cSrcweir 
338cdf0e10cSrcweir         aGlyphSet [nGlyph] = nMappedChar;
339cdf0e10cSrcweir         *nOutGlyphSetID    = 1;
340cdf0e10cSrcweir         *nOutGlyphID       = nMappedChar;
341cdf0e10cSrcweir     }
342cdf0e10cSrcweir     else
343cdf0e10cSrcweir     {
344cdf0e10cSrcweir         // other chars are just appended to the list
345cdf0e10cSrcweir         glyph_map_t& aGlyphSet = maGlyphList.back();
346cdf0e10cSrcweir         AddNotdef (aGlyphSet);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir         int nSize         = aGlyphSet.size();
349cdf0e10cSrcweir 
350cdf0e10cSrcweir         aGlyphSet [nGlyph] = nSize;
351cdf0e10cSrcweir         *nOutGlyphSetID   = maGlyphList.size();
352cdf0e10cSrcweir         *nOutGlyphID      = aGlyphSet [nGlyph];
353cdf0e10cSrcweir     }
354cdf0e10cSrcweir 
355cdf0e10cSrcweir     return sal_True;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir 
358cdf0e10cSrcweir OString
GetCharSetName(sal_Int32 nGlyphSetID)359cdf0e10cSrcweir GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID)
360cdf0e10cSrcweir {
361cdf0e10cSrcweir     if (meBaseType == fonttype::TrueType)
362cdf0e10cSrcweir     {
363cdf0e10cSrcweir         OStringBuffer aSetName( maBaseName.getLength() + 32 );
364cdf0e10cSrcweir         aSetName.append( maBaseName );
365cdf0e10cSrcweir         aSetName.append( "FID" );
366cdf0e10cSrcweir         aSetName.append( mnFontID );
367cdf0e10cSrcweir         aSetName.append( mbVertical ? "VCSet" : "HCSet" );
368cdf0e10cSrcweir         aSetName.append( nGlyphSetID );
369cdf0e10cSrcweir         return aSetName.makeStringAndClear();
370cdf0e10cSrcweir     }
371cdf0e10cSrcweir     else
372cdf0e10cSrcweir     /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
373cdf0e10cSrcweir     {
374cdf0e10cSrcweir         return maBaseName;
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir }
377cdf0e10cSrcweir 
378cdf0e10cSrcweir OString
GetGlyphSetName(sal_Int32 nGlyphSetID)379cdf0e10cSrcweir GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
380cdf0e10cSrcweir {
381cdf0e10cSrcweir     if (meBaseType == fonttype::TrueType)
382cdf0e10cSrcweir     {
383cdf0e10cSrcweir         OStringBuffer aSetName( maBaseName.getLength() + 32 );
384cdf0e10cSrcweir         aSetName.append( maBaseName );
385cdf0e10cSrcweir         aSetName.append( "FID" );
386cdf0e10cSrcweir         aSetName.append( mnFontID );
387cdf0e10cSrcweir         aSetName.append( mbVertical ? "VGSet" : "HGSet" );
388cdf0e10cSrcweir         aSetName.append( nGlyphSetID );
389cdf0e10cSrcweir         return aSetName.makeStringAndClear();
390cdf0e10cSrcweir     }
391cdf0e10cSrcweir     else
392cdf0e10cSrcweir     /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
393cdf0e10cSrcweir     {
394cdf0e10cSrcweir         return maBaseName;
395cdf0e10cSrcweir     }
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir sal_Int32
GetGlyphSetEncoding(sal_Int32 nGlyphSetID)399cdf0e10cSrcweir GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
400cdf0e10cSrcweir {
401cdf0e10cSrcweir     if (meBaseType == fonttype::TrueType)
402cdf0e10cSrcweir         return RTL_TEXTENCODING_DONTKNOW;
403cdf0e10cSrcweir     else
404cdf0e10cSrcweir     {
405cdf0e10cSrcweir     /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
406cdf0e10cSrcweir         if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
407cdf0e10cSrcweir             return RTL_TEXTENCODING_SYMBOL;
408cdf0e10cSrcweir         else
409cdf0e10cSrcweir             return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
410cdf0e10cSrcweir                                     : RTL_TEXTENCODING_USER_START + nGlyphSetID;
411cdf0e10cSrcweir     }
412cdf0e10cSrcweir }
413cdf0e10cSrcweir 
414cdf0e10cSrcweir OString
GetGlyphSetEncodingName(rtl_TextEncoding nEnc,const OString & rFontName)415cdf0e10cSrcweir GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc, const OString &rFontName)
416cdf0e10cSrcweir {
417cdf0e10cSrcweir     if (   nEnc == RTL_TEXTENCODING_MS_1252
418cdf0e10cSrcweir         || nEnc == RTL_TEXTENCODING_ISO_8859_1)
419cdf0e10cSrcweir     {
420cdf0e10cSrcweir         return OString("ISO1252Encoding");
421cdf0e10cSrcweir     }
422cdf0e10cSrcweir     else
423cdf0e10cSrcweir     if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
424cdf0e10cSrcweir     {
425cdf0e10cSrcweir         return  rFontName
426cdf0e10cSrcweir                 + OString("Enc")
427cdf0e10cSrcweir                 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
428cdf0e10cSrcweir     }
429cdf0e10cSrcweir     else
430cdf0e10cSrcweir     {
431cdf0e10cSrcweir         return OString();
432cdf0e10cSrcweir     }
433cdf0e10cSrcweir }
434cdf0e10cSrcweir 
435cdf0e10cSrcweir OString
GetGlyphSetEncodingName(sal_Int32 nGlyphSetID)436cdf0e10cSrcweir GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
437cdf0e10cSrcweir {
438cdf0e10cSrcweir     return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
439cdf0e10cSrcweir }
440cdf0e10cSrcweir 
441cdf0e10cSrcweir void
PSDefineReencodedFont(osl::File * pOutFile,sal_Int32 nGlyphSetID)442cdf0e10cSrcweir GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
443cdf0e10cSrcweir {
444cdf0e10cSrcweir     // only for ps fonts
445cdf0e10cSrcweir     if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
446cdf0e10cSrcweir         return;
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     sal_Char  pEncodingVector [256];
449cdf0e10cSrcweir     sal_Int32 nSize = 0;
450cdf0e10cSrcweir 
451cdf0e10cSrcweir     nSize += psp::appendStr ("(", pEncodingVector + nSize);
452cdf0e10cSrcweir     nSize += psp::appendStr (GetReencodedFontName(nGlyphSetID),
453cdf0e10cSrcweir                                   pEncodingVector + nSize);
454cdf0e10cSrcweir     nSize += psp::appendStr (") cvn (", pEncodingVector + nSize);
455cdf0e10cSrcweir     nSize += psp::appendStr (maBaseName.getStr(),
456cdf0e10cSrcweir                                   pEncodingVector + nSize);
457cdf0e10cSrcweir     nSize += psp::appendStr (") cvn ", pEncodingVector + nSize);
458cdf0e10cSrcweir     nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID),
459cdf0e10cSrcweir                                   pEncodingVector + nSize);
460cdf0e10cSrcweir     nSize += psp::appendStr (" psp_definefont\n",
461cdf0e10cSrcweir                                   pEncodingVector + nSize);
462cdf0e10cSrcweir 
463cdf0e10cSrcweir     psp::WritePS (pOutFile, pEncodingVector);
464cdf0e10cSrcweir }
465cdf0e10cSrcweir 
466cdf0e10cSrcweir OString
GetReencodedFontName(rtl_TextEncoding nEnc,const OString & rFontName)467cdf0e10cSrcweir GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
468cdf0e10cSrcweir {
469cdf0e10cSrcweir     if (   nEnc == RTL_TEXTENCODING_MS_1252
470cdf0e10cSrcweir         || nEnc == RTL_TEXTENCODING_ISO_8859_1)
471cdf0e10cSrcweir     {
472cdf0e10cSrcweir         return rFontName
473cdf0e10cSrcweir                + OString("-iso1252");
474cdf0e10cSrcweir     }
475cdf0e10cSrcweir     else
476cdf0e10cSrcweir     if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
477cdf0e10cSrcweir     {
478cdf0e10cSrcweir         return rFontName
479cdf0e10cSrcweir                + OString("-enc")
480cdf0e10cSrcweir                + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
481cdf0e10cSrcweir     }
482cdf0e10cSrcweir     else
483cdf0e10cSrcweir     {
484cdf0e10cSrcweir         return OString();
485cdf0e10cSrcweir     }
486cdf0e10cSrcweir }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir OString
GetReencodedFontName(sal_Int32 nGlyphSetID)489cdf0e10cSrcweir GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
490cdf0e10cSrcweir {
491cdf0e10cSrcweir     return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
492cdf0e10cSrcweir }
493cdf0e10cSrcweir 
DrawGlyphs(PrinterGfx & rGfx,const Point & rPoint,const sal_GlyphId * pGlyphIds,const sal_Unicode * pUnicodes,sal_Int16 nLen,const sal_Int32 * pDeltaArray)494cdf0e10cSrcweir void GlyphSet::DrawGlyphs(
495cdf0e10cSrcweir                           PrinterGfx& rGfx,
496cdf0e10cSrcweir                           const Point& rPoint,
497*248a599fSHerbert Dürr                           const sal_GlyphId* pGlyphIds,
498cdf0e10cSrcweir                           const sal_Unicode* pUnicodes,
499cdf0e10cSrcweir                           sal_Int16 nLen,
500cdf0e10cSrcweir                           const sal_Int32* pDeltaArray )
501cdf0e10cSrcweir {
502cdf0e10cSrcweir     sal_uChar *pGlyphID    = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
503cdf0e10cSrcweir     sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
504cdf0e10cSrcweir     std::set< sal_Int32 > aGlyphSet;
505cdf0e10cSrcweir 
506cdf0e10cSrcweir     // convert unicode to font glyph id and font subset
507cdf0e10cSrcweir     for (int nChar = 0; nChar < nLen; nChar++)
508cdf0e10cSrcweir     {
509cdf0e10cSrcweir         GetGlyphID (pGlyphIds[nChar], pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
510cdf0e10cSrcweir         aGlyphSet.insert (pGlyphSetID[nChar]);
511cdf0e10cSrcweir     }
512cdf0e10cSrcweir 
513cdf0e10cSrcweir     // loop over all glyph sets to detect substrings that can be xshown together
514cdf0e10cSrcweir     // without changing the postscript font
515cdf0e10cSrcweir     sal_Int32 *pDeltaSubset = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
516cdf0e10cSrcweir     sal_uChar *pGlyphSubset = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     std::set< sal_Int32 >::iterator aSet;
519cdf0e10cSrcweir     for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
520cdf0e10cSrcweir     {
521cdf0e10cSrcweir         Point     aPoint  = rPoint;
522cdf0e10cSrcweir         sal_Int32 nOffset = 0;
523cdf0e10cSrcweir         sal_Int32 nGlyphs = 0;
524cdf0e10cSrcweir         sal_Int32 nChar;
525cdf0e10cSrcweir 
526cdf0e10cSrcweir         // get offset to first glyph
527cdf0e10cSrcweir         for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
528cdf0e10cSrcweir         {
529cdf0e10cSrcweir             nOffset = pDeltaArray [nChar];
530cdf0e10cSrcweir         }
531cdf0e10cSrcweir 
532cdf0e10cSrcweir         // loop over all chars to extract those that share the current glyph set
533cdf0e10cSrcweir         for (nChar = 0; nChar < nLen; nChar++)
534cdf0e10cSrcweir         {
535cdf0e10cSrcweir             if (pGlyphSetID[nChar] == *aSet)
536cdf0e10cSrcweir             {
537cdf0e10cSrcweir                 pGlyphSubset [nGlyphs] = pGlyphID [nChar];
538cdf0e10cSrcweir                 // the offset to the next glyph is determined by the glyph in
539cdf0e10cSrcweir                 // front of the next glyph with the same glyphset id
540cdf0e10cSrcweir                 // most often, this will be the current glyph
541cdf0e10cSrcweir                 while ((nChar + 1) < nLen)
542cdf0e10cSrcweir                 {
543cdf0e10cSrcweir                     if (pGlyphSetID[nChar + 1] == *aSet)
544cdf0e10cSrcweir                         break;
545cdf0e10cSrcweir                     else
546cdf0e10cSrcweir                         nChar += 1;
547cdf0e10cSrcweir                 }
548cdf0e10cSrcweir                 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
549cdf0e10cSrcweir 
550cdf0e10cSrcweir                 nGlyphs += 1;
551cdf0e10cSrcweir             }
552cdf0e10cSrcweir         }
553cdf0e10cSrcweir 
554cdf0e10cSrcweir         // show the text using the PrinterGfx text api
555cdf0e10cSrcweir         aPoint.Move (nOffset, 0);
556cdf0e10cSrcweir 
557cdf0e10cSrcweir         OString aGlyphSetName(GetGlyphSetName(*aSet));
558cdf0e10cSrcweir         rGfx.PSSetFont  (aGlyphSetName, GetGlyphSetEncoding(*aSet));
559cdf0e10cSrcweir         rGfx.PSMoveTo   (aPoint);
560cdf0e10cSrcweir         rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
561cdf0e10cSrcweir     }
562cdf0e10cSrcweir }
563cdf0e10cSrcweir 
564cdf0e10cSrcweir void
DrawText(PrinterGfx & rGfx,const Point & rPoint,const sal_Unicode * pStr,sal_Int16 nLen,const sal_Int32 * pDeltaArray)565cdf0e10cSrcweir GlyphSet::DrawText (PrinterGfx &rGfx, const Point& rPoint,
566cdf0e10cSrcweir                     const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
567cdf0e10cSrcweir {
568cdf0e10cSrcweir     // dispatch to the impl method
569cdf0e10cSrcweir     if (pDeltaArray == NULL)
570cdf0e10cSrcweir         ImplDrawText (rGfx, rPoint, pStr, nLen);
571cdf0e10cSrcweir     else
572cdf0e10cSrcweir         ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
573cdf0e10cSrcweir }
574cdf0e10cSrcweir 
575cdf0e10cSrcweir void
ImplDrawText(PrinterGfx & rGfx,const Point & rPoint,const sal_Unicode * pStr,sal_Int16 nLen)576cdf0e10cSrcweir GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
577cdf0e10cSrcweir                         const sal_Unicode* pStr, sal_Int16 nLen)
578cdf0e10cSrcweir {
579cdf0e10cSrcweir     rGfx.PSMoveTo (rPoint);
580cdf0e10cSrcweir 
581cdf0e10cSrcweir     if( mbUseFontEncoding )
582cdf0e10cSrcweir     {
583cdf0e10cSrcweir         OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
584cdf0e10cSrcweir         OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
585cdf0e10cSrcweir         rGfx.PSSetFont( aPSName, mnBaseEncoding );
586cdf0e10cSrcweir         rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength() );
587cdf0e10cSrcweir         return;
588cdf0e10cSrcweir     }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir     int nChar;
591cdf0e10cSrcweir     sal_uChar *pGlyphID    = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
592cdf0e10cSrcweir     sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
593cdf0e10cSrcweir 
594cdf0e10cSrcweir     // convert unicode to glyph id and char set (font subset)
595cdf0e10cSrcweir     for (nChar = 0; nChar < nLen; nChar++)
596cdf0e10cSrcweir         GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
597cdf0e10cSrcweir 
598cdf0e10cSrcweir     // loop over the string to draw subsequent pieces of chars
599cdf0e10cSrcweir     // with the same postscript font
600cdf0e10cSrcweir     for (nChar = 0; nChar < nLen; /* atend */)
601cdf0e10cSrcweir     {
602cdf0e10cSrcweir         sal_Int32 nGlyphSetID = pGlyphSetID [nChar];
603cdf0e10cSrcweir         sal_Int32 nGlyphs     = 1;
604cdf0e10cSrcweir         for (int nNextChar = nChar + 1; nNextChar < nLen; nNextChar++)
605cdf0e10cSrcweir         {
606cdf0e10cSrcweir             if (pGlyphSetID[nNextChar] == nGlyphSetID)
607cdf0e10cSrcweir                 nGlyphs++;
608cdf0e10cSrcweir             else
609cdf0e10cSrcweir                 break;
610cdf0e10cSrcweir         }
611cdf0e10cSrcweir 
612cdf0e10cSrcweir         // show the text using the PrinterGfx text api
613cdf0e10cSrcweir         OString aGlyphSetName(GetCharSetName(nGlyphSetID));
614cdf0e10cSrcweir         rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(nGlyphSetID));
615cdf0e10cSrcweir         rGfx.PSShowText (pGlyphID + nChar, nGlyphs, nGlyphs);
616cdf0e10cSrcweir 
617cdf0e10cSrcweir         nChar += nGlyphs;
618cdf0e10cSrcweir     }
619cdf0e10cSrcweir }
620cdf0e10cSrcweir 
621cdf0e10cSrcweir void
ImplDrawText(PrinterGfx & rGfx,const Point & rPoint,const sal_Unicode * pStr,sal_Int16 nLen,const sal_Int32 * pDeltaArray)622cdf0e10cSrcweir GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
623cdf0e10cSrcweir                         const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
624cdf0e10cSrcweir {
625cdf0e10cSrcweir     if( mbUseFontEncoding )
626cdf0e10cSrcweir     {
627cdf0e10cSrcweir         OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
628cdf0e10cSrcweir         OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
629cdf0e10cSrcweir         rGfx.PSMoveTo( rPoint );
630cdf0e10cSrcweir         rGfx.PSSetFont( aPSName, mnBaseEncoding );
631cdf0e10cSrcweir         rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength(), pDeltaArray );
632cdf0e10cSrcweir         return;
633cdf0e10cSrcweir     }
634cdf0e10cSrcweir 
635cdf0e10cSrcweir     sal_uChar *pGlyphID    = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
636cdf0e10cSrcweir     sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
637cdf0e10cSrcweir     std::set< sal_Int32 > aGlyphSet;
638cdf0e10cSrcweir 
639cdf0e10cSrcweir     // convert unicode to font glyph id and font subset
640cdf0e10cSrcweir     for (int nChar = 0; nChar < nLen; nChar++)
641cdf0e10cSrcweir     {
642cdf0e10cSrcweir         GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
643cdf0e10cSrcweir         aGlyphSet.insert (pGlyphSetID[nChar]);
644cdf0e10cSrcweir     }
645cdf0e10cSrcweir 
646cdf0e10cSrcweir     // loop over all glyph sets to detect substrings that can be xshown together
647cdf0e10cSrcweir     // without changing the postscript font
648cdf0e10cSrcweir     sal_Int32 *pDeltaSubset = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
649cdf0e10cSrcweir     sal_uChar *pGlyphSubset = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
650cdf0e10cSrcweir 
651cdf0e10cSrcweir     std::set< sal_Int32 >::iterator aSet;
652cdf0e10cSrcweir     for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
653cdf0e10cSrcweir     {
654cdf0e10cSrcweir         Point     aPoint  = rPoint;
655cdf0e10cSrcweir         sal_Int32 nOffset = 0;
656cdf0e10cSrcweir         sal_Int32 nGlyphs = 0;
657cdf0e10cSrcweir         sal_Int32 nChar;
658cdf0e10cSrcweir 
659cdf0e10cSrcweir         // get offset to first glyph
660cdf0e10cSrcweir         for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
661cdf0e10cSrcweir         {
662cdf0e10cSrcweir             nOffset = pDeltaArray [nChar];
663cdf0e10cSrcweir         }
664cdf0e10cSrcweir 
665cdf0e10cSrcweir         // loop over all chars to extract those that share the current glyph set
666cdf0e10cSrcweir         for (nChar = 0; nChar < nLen; nChar++)
667cdf0e10cSrcweir         {
668cdf0e10cSrcweir             if (pGlyphSetID[nChar] == *aSet)
669cdf0e10cSrcweir             {
670cdf0e10cSrcweir                 pGlyphSubset [nGlyphs] = pGlyphID [nChar];
671cdf0e10cSrcweir                 // the offset to the next glyph is determined by the glyph in
672cdf0e10cSrcweir                 // front of the next glyph with the same glyphset id
673cdf0e10cSrcweir                 // most often, this will be the current glyph
674cdf0e10cSrcweir                 while ((nChar + 1) < nLen)
675cdf0e10cSrcweir                 {
676cdf0e10cSrcweir                     if (pGlyphSetID[nChar + 1] == *aSet)
677cdf0e10cSrcweir                         break;
678cdf0e10cSrcweir                     else
679cdf0e10cSrcweir                         nChar += 1;
680cdf0e10cSrcweir                 }
681cdf0e10cSrcweir                 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
682cdf0e10cSrcweir 
683cdf0e10cSrcweir                 nGlyphs += 1;
684cdf0e10cSrcweir             }
685cdf0e10cSrcweir         }
686cdf0e10cSrcweir 
687cdf0e10cSrcweir         // show the text using the PrinterGfx text api
688cdf0e10cSrcweir         aPoint.Move (nOffset, 0);
689cdf0e10cSrcweir 
690cdf0e10cSrcweir         OString aGlyphSetName(GetCharSetName(*aSet));
691cdf0e10cSrcweir         rGfx.PSSetFont  (aGlyphSetName, GetGlyphSetEncoding(*aSet));
692cdf0e10cSrcweir         rGfx.PSMoveTo   (aPoint);
693cdf0e10cSrcweir         rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
694cdf0e10cSrcweir     }
695cdf0e10cSrcweir }
696cdf0e10cSrcweir 
697cdf0e10cSrcweir sal_Bool
PSUploadEncoding(osl::File * pOutFile,PrinterGfx & rGfx)698cdf0e10cSrcweir GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
699cdf0e10cSrcweir {
700cdf0e10cSrcweir     // only for ps fonts
701cdf0e10cSrcweir     if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
702cdf0e10cSrcweir         return sal_False;
703cdf0e10cSrcweir     if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
704cdf0e10cSrcweir         return sal_False;
705cdf0e10cSrcweir 
706cdf0e10cSrcweir     PrintFontManager &rMgr = rGfx.GetFontMgr();
707cdf0e10cSrcweir 
708cdf0e10cSrcweir     // loop thru all the font subsets
709cdf0e10cSrcweir     sal_Int32               nGlyphSetID = 0;
710cdf0e10cSrcweir     char_list_t::iterator   aGlyphSet;
711cdf0e10cSrcweir     for (aGlyphSet = maCharList.begin(); aGlyphSet != maCharList.end(); aGlyphSet++)
712cdf0e10cSrcweir     {
713cdf0e10cSrcweir         ++nGlyphSetID;
714cdf0e10cSrcweir 
715cdf0e10cSrcweir         if (nGlyphSetID == 1) // latin1 page uses global reencoding table
716cdf0e10cSrcweir         {
717cdf0e10cSrcweir             PSDefineReencodedFont (pOutFile, nGlyphSetID);
718cdf0e10cSrcweir             continue;
719cdf0e10cSrcweir         }
720cdf0e10cSrcweir         if ((*aGlyphSet).size() == 0) // empty set, doesn't need reencoding
721cdf0e10cSrcweir         {
722cdf0e10cSrcweir             continue;
723cdf0e10cSrcweir         }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir         // create reencoding table
726cdf0e10cSrcweir 
727cdf0e10cSrcweir         sal_Char  pEncodingVector [256];
728cdf0e10cSrcweir         sal_Int32 nSize = 0;
729cdf0e10cSrcweir 
730cdf0e10cSrcweir         nSize += psp::appendStr ("/",
731cdf0e10cSrcweir                                  pEncodingVector + nSize);
732cdf0e10cSrcweir         nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID),
733cdf0e10cSrcweir                                  pEncodingVector + nSize);
734cdf0e10cSrcweir         nSize += psp::appendStr (" [ ",
735cdf0e10cSrcweir                                  pEncodingVector + nSize);
736cdf0e10cSrcweir 
737cdf0e10cSrcweir         // need a list of glyphs, sorted by glyphid
738cdf0e10cSrcweir         typedef std::map< sal_uInt8, sal_Unicode > ps_mapping_t;
739cdf0e10cSrcweir         typedef ps_mapping_t::value_type ps_value_t;
740cdf0e10cSrcweir         ps_mapping_t aSortedGlyphSet;
741cdf0e10cSrcweir 
742cdf0e10cSrcweir         char_map_t::const_iterator aUnsortedGlyph;
743cdf0e10cSrcweir         for (aUnsortedGlyph  = (*aGlyphSet).begin();
744cdf0e10cSrcweir              aUnsortedGlyph != (*aGlyphSet).end();
745cdf0e10cSrcweir              ++aUnsortedGlyph)
746cdf0e10cSrcweir         {
747cdf0e10cSrcweir             aSortedGlyphSet.insert(ps_value_t((*aUnsortedGlyph).second,
748cdf0e10cSrcweir                                              (*aUnsortedGlyph).first));
749cdf0e10cSrcweir         }
750cdf0e10cSrcweir 
751cdf0e10cSrcweir         ps_mapping_t::const_iterator aSortedGlyph;
752cdf0e10cSrcweir         // loop thru all the glyphs in the subset
753cdf0e10cSrcweir         for (aSortedGlyph  = (aSortedGlyphSet).begin();
754cdf0e10cSrcweir              aSortedGlyph != (aSortedGlyphSet).end();
755cdf0e10cSrcweir              ++aSortedGlyph)
756cdf0e10cSrcweir         {
757cdf0e10cSrcweir             nSize += psp::appendStr ("/",
758cdf0e10cSrcweir                                      pEncodingVector + nSize);
759cdf0e10cSrcweir 
760cdf0e10cSrcweir             std::list< OString > aName( rMgr.getAdobeNameFromUnicode((*aSortedGlyph).second) );
761cdf0e10cSrcweir 
762cdf0e10cSrcweir             if( aName.begin() != aName.end() )
763cdf0e10cSrcweir                 nSize += psp::appendStr ( aName.front(), pEncodingVector + nSize);
764cdf0e10cSrcweir             else
765cdf0e10cSrcweir                 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
766cdf0e10cSrcweir             nSize += psp::appendStr (" ",  pEncodingVector + nSize);
767cdf0e10cSrcweir             // flush line
768cdf0e10cSrcweir             if (nSize >= 70)
769cdf0e10cSrcweir             {
770cdf0e10cSrcweir                 nSize += psp::appendStr ("\n", pEncodingVector + nSize);
771cdf0e10cSrcweir                 psp::WritePS (pOutFile, pEncodingVector);
772cdf0e10cSrcweir                 nSize = 0;
773cdf0e10cSrcweir             }
774cdf0e10cSrcweir         }
775cdf0e10cSrcweir 
776cdf0e10cSrcweir         nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
777cdf0e10cSrcweir         psp::WritePS (pOutFile, pEncodingVector);
778cdf0e10cSrcweir 
779cdf0e10cSrcweir         PSDefineReencodedFont (pOutFile, nGlyphSetID);
780cdf0e10cSrcweir     }
781cdf0e10cSrcweir 
782cdf0e10cSrcweir     return sal_True;
783cdf0e10cSrcweir }
784cdf0e10cSrcweir 
785cdf0e10cSrcweir struct EncEntry
786cdf0e10cSrcweir {
787cdf0e10cSrcweir     sal_uChar  aEnc;
788cdf0e10cSrcweir     long       aGID;
789cdf0e10cSrcweir 
EncEntryEncEntry790cdf0e10cSrcweir     EncEntry() : aEnc( 0 ), aGID( 0 ) {}
791cdf0e10cSrcweir 
operator <EncEntry792cdf0e10cSrcweir     bool operator<( const EncEntry& rRight ) const
793cdf0e10cSrcweir     { return aEnc < rRight.aEnc; }
794cdf0e10cSrcweir };
795cdf0e10cSrcweir 
CreatePSUploadableFont(TrueTypeFont * pSrcFont,FILE * pTmpFile,const char * pGlyphSetName,int nGlyphCount,sal_uInt16 * pRequestedGlyphs,sal_uChar * pEncoding,bool bAllowType42,bool)796cdf0e10cSrcweir static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile,
797cdf0e10cSrcweir 	const char* pGlyphSetName, int nGlyphCount,
798cdf0e10cSrcweir 	/*const*/ sal_uInt16* pRequestedGlyphs, /*const*/ sal_uChar* pEncoding,
799cdf0e10cSrcweir 	bool bAllowType42, bool /*bAllowCID*/ )
800cdf0e10cSrcweir {
801cdf0e10cSrcweir 	// match the font-subset to the printer capabilities
802cdf0e10cSrcweir  	// TODO: allow CFF for capable printers
803cdf0e10cSrcweir 	int nTargetMask = FontSubsetInfo::TYPE1_PFA | FontSubsetInfo::TYPE3_FONT;
804cdf0e10cSrcweir 	if( bAllowType42 )
805cdf0e10cSrcweir 		nTargetMask |= FontSubsetInfo::TYPE42_FONT;
806cdf0e10cSrcweir 
807cdf0e10cSrcweir     std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
808cdf0e10cSrcweir     for( int i = 0; i < nGlyphCount; i++ )
809cdf0e10cSrcweir     {
810cdf0e10cSrcweir         aSorted[i].aEnc = pEncoding[i];
811cdf0e10cSrcweir         aSorted[i].aGID = pRequestedGlyphs[i];
812cdf0e10cSrcweir     }
813cdf0e10cSrcweir 
814cdf0e10cSrcweir     std::stable_sort( aSorted.begin(), aSorted.end() );
815cdf0e10cSrcweir 
816cdf0e10cSrcweir     std::vector< sal_uChar > aEncoding( nGlyphCount );
817*248a599fSHerbert Dürr     std::vector< sal_GlyphId> aRequestedGlyphs( nGlyphCount );
818cdf0e10cSrcweir 
819cdf0e10cSrcweir     for( int i = 0; i < nGlyphCount; i++ )
820cdf0e10cSrcweir     {
821cdf0e10cSrcweir         aEncoding[i]        = aSorted[i].aEnc;
822cdf0e10cSrcweir         aRequestedGlyphs[i] = aSorted[i].aGID;
823cdf0e10cSrcweir     }
824cdf0e10cSrcweir 
825cdf0e10cSrcweir 	FontSubsetInfo aInfo;
826cdf0e10cSrcweir 	aInfo.LoadFont( pSrcFont );
827cdf0e10cSrcweir 
828cdf0e10cSrcweir 	aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
829cdf0e10cSrcweir 		&aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL );
830cdf0e10cSrcweir }
831cdf0e10cSrcweir 
832cdf0e10cSrcweir sal_Bool
PSUploadFont(osl::File & rOutFile,PrinterGfx & rGfx,bool bAllowType42,std::list<OString> & rSuppliedFonts)833cdf0e10cSrcweir GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
834cdf0e10cSrcweir {
835cdf0e10cSrcweir     // only for truetype fonts
836cdf0e10cSrcweir     if (meBaseType != fonttype::TrueType)
837cdf0e10cSrcweir         return sal_False;
838cdf0e10cSrcweir 
839cdf0e10cSrcweir     TrueTypeFont *pTTFont;
840cdf0e10cSrcweir     OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
841cdf0e10cSrcweir     int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
842cdf0e10cSrcweir     sal_Int32 nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace < 0 ? 0 : nFace, &pTTFont);
843cdf0e10cSrcweir     if (nSuccess != SF_OK)
844cdf0e10cSrcweir         return sal_False;
845cdf0e10cSrcweir     FILE* pTmpFile = tmpfile();
846cdf0e10cSrcweir     if (pTmpFile == NULL)
847cdf0e10cSrcweir         return sal_False;
848cdf0e10cSrcweir 
849cdf0e10cSrcweir     // array of unicode source characters
850cdf0e10cSrcweir     sal_Unicode pUChars[256];
851cdf0e10cSrcweir 
852cdf0e10cSrcweir     // encoding vector maps character encoding to the ordinal number
853cdf0e10cSrcweir     // of the glyph in the output file
854cdf0e10cSrcweir     sal_uChar  pEncoding[256];
855cdf0e10cSrcweir     sal_uInt16 pTTGlyphMapping[256];
856cdf0e10cSrcweir 	const bool bAllowCID = false; // TODO: nPSLanguageLevel>=3
857cdf0e10cSrcweir 
858cdf0e10cSrcweir     // loop thru all the font subsets
859cdf0e10cSrcweir     sal_Int32 nCharSetID;
860cdf0e10cSrcweir     char_list_t::iterator aCharSet;
861cdf0e10cSrcweir     for (aCharSet = maCharList.begin(), nCharSetID = 1;
862cdf0e10cSrcweir          aCharSet != maCharList.end();
863cdf0e10cSrcweir          ++aCharSet, nCharSetID++)
864cdf0e10cSrcweir     {
865cdf0e10cSrcweir         if ((*aCharSet).size() == 0)
866cdf0e10cSrcweir             continue;
867cdf0e10cSrcweir 
868cdf0e10cSrcweir         // loop thru all the chars in the subset
869cdf0e10cSrcweir         char_map_t::const_iterator aChar;
870cdf0e10cSrcweir         sal_Int32 n = 0;
871cdf0e10cSrcweir         for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); aChar++)
872cdf0e10cSrcweir         {
873cdf0e10cSrcweir             pUChars [n]   = (*aChar).first;
874cdf0e10cSrcweir             pEncoding [n] = (*aChar).second;
875cdf0e10cSrcweir             n++;
876cdf0e10cSrcweir         }
877cdf0e10cSrcweir         // create a mapping from the unicode chars to the char encoding in
878cdf0e10cSrcweir         // source TrueType font
879cdf0e10cSrcweir         MapString (pTTFont, pUChars, (*aCharSet).size(), pTTGlyphMapping, mbVertical);
880cdf0e10cSrcweir 
881cdf0e10cSrcweir         // create the current subset
882cdf0e10cSrcweir         OString aCharSetName = GetCharSetName(nCharSetID);
883cdf0e10cSrcweir         fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aCharSetName.getStr() );
884cdf0e10cSrcweir         CreatePSUploadableFont( pTTFont, pTmpFile, aCharSetName.getStr(), (*aCharSet).size(),
885cdf0e10cSrcweir 								pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
886cdf0e10cSrcweir         fprintf( pTmpFile, "%%%%EndResource\n" );
887cdf0e10cSrcweir         rSuppliedFonts.push_back( aCharSetName );
888cdf0e10cSrcweir     }
889cdf0e10cSrcweir 
890cdf0e10cSrcweir     // loop thru all the font glyph subsets
891cdf0e10cSrcweir     sal_Int32 nGlyphSetID;
892cdf0e10cSrcweir     glyph_list_t::iterator aGlyphSet;
893cdf0e10cSrcweir     for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
894cdf0e10cSrcweir          aGlyphSet != maGlyphList.end();
895cdf0e10cSrcweir          ++aGlyphSet, nGlyphSetID++)
896cdf0e10cSrcweir     {
897cdf0e10cSrcweir         if ((*aGlyphSet).size() == 0)
898cdf0e10cSrcweir             continue;
899cdf0e10cSrcweir 
900cdf0e10cSrcweir         // loop thru all the glyphs in the subset
901cdf0e10cSrcweir         glyph_map_t::const_iterator aGlyph;
902cdf0e10cSrcweir         sal_Int32 n = 0;
903cdf0e10cSrcweir         for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); aGlyph++)
904cdf0e10cSrcweir         {
905cdf0e10cSrcweir             pTTGlyphMapping [n] = (*aGlyph).first;
906cdf0e10cSrcweir             pEncoding 		[n] = (*aGlyph).second;
907cdf0e10cSrcweir             n++;
908cdf0e10cSrcweir         }
909cdf0e10cSrcweir 
910cdf0e10cSrcweir         // create the current subset
911cdf0e10cSrcweir         OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
912cdf0e10cSrcweir         fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
913cdf0e10cSrcweir         CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), (*aGlyphSet).size(),
914cdf0e10cSrcweir 								pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
915cdf0e10cSrcweir         fprintf( pTmpFile, "%%%%EndResource\n" );
916cdf0e10cSrcweir         rSuppliedFonts.push_back( aGlyphSetName );
917cdf0e10cSrcweir     }
918cdf0e10cSrcweir 
919cdf0e10cSrcweir     // copy the file into the page header
920cdf0e10cSrcweir     rewind(pTmpFile);
921cdf0e10cSrcweir     fflush(pTmpFile);
922cdf0e10cSrcweir 
923cdf0e10cSrcweir     sal_uChar  pBuffer[0x2000];
924cdf0e10cSrcweir     sal_uInt64 nIn;
925cdf0e10cSrcweir     sal_uInt64 nOut;
926cdf0e10cSrcweir     do
927cdf0e10cSrcweir     {
928cdf0e10cSrcweir         nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
929cdf0e10cSrcweir         rOutFile.write (pBuffer, nIn, nOut);
930cdf0e10cSrcweir     }
931cdf0e10cSrcweir     while ((nIn == nOut) && !feof(pTmpFile));
932cdf0e10cSrcweir 
933cdf0e10cSrcweir     // cleanup
934cdf0e10cSrcweir     CloseTTFont (pTTFont);
935cdf0e10cSrcweir     fclose (pTmpFile);
936cdf0e10cSrcweir 
937cdf0e10cSrcweir     return sal_True;
938cdf0e10cSrcweir }
939