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