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