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