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