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