Bump version to 4.1-6
[LibreOffice.git] / vcl / generic / print / glyphset.cxx
blobbb43ef52fa696b9f1977759da2c17c43f85b3fc2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "glyphset.hxx"
22 #include "psputil.hxx"
24 #include "sft.hxx"
26 #include "generic/printergfx.hxx"
27 #include "fontsubset.hxx"
28 #include "vcl/fontmanager.hxx"
30 #include <tools/gen.hxx>
32 #include "osl/thread.h"
34 #include "sal/alloca.h"
36 #include "rtl/ustring.hxx"
37 #include "rtl/strbuf.hxx"
39 #include <set>
40 #include <map>
41 #include <algorithm>
43 using namespace vcl;
44 using namespace psp;
47 GlyphSet::GlyphSet (sal_Int32 nFontID, sal_Bool bVertical)
48 : mnFontID (nFontID),
49 mbVertical (bVertical)
51 PrintFontManager &rMgr = PrintFontManager::get();
52 meBaseType = rMgr.getFontType (mnFontID);
53 maBaseName = OUStringToOString (rMgr.getPSName(mnFontID),
54 RTL_TEXTENCODING_ASCII_US);
55 mnBaseEncoding = rMgr.getFontEncoding(mnFontID);
56 mbUseFontEncoding = rMgr.getUseOnlyFontEncoding(mnFontID);
59 GlyphSet::~GlyphSet ()
61 /* FIXME delete the glyphlist ??? */
64 sal_Int32
65 GlyphSet::GetFontID ()
67 return mnFontID;
70 fonttype::type
71 GlyphSet::GetFontType ()
73 return meBaseType;
76 sal_Bool
77 GlyphSet::IsVertical ()
79 return mbVertical;
82 sal_Bool
83 GlyphSet::GetCharID (
84 sal_Unicode nChar,
85 sal_uChar* nOutGlyphID,
86 sal_Int32* nOutGlyphSetID
89 return LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
90 || AddCharID (nChar, nOutGlyphID, nOutGlyphSetID);
93 sal_Bool
94 GlyphSet::GetGlyphID (
95 sal_uInt32 nGlyph,
96 sal_Unicode nUnicode,
97 sal_uChar* nOutGlyphID,
98 sal_Int32* nOutGlyphSetID
101 return LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
102 || AddGlyphID (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
105 sal_Bool
106 GlyphSet::LookupCharID (
107 sal_Unicode nChar,
108 sal_uChar* nOutGlyphID,
109 sal_Int32* nOutGlyphSetID
112 char_list_t::iterator aGlyphSet;
113 sal_Int32 nGlyphSetID;
115 // loop thru all the font subsets
116 for (aGlyphSet = maCharList.begin(), nGlyphSetID = 1;
117 aGlyphSet != maCharList.end();
118 ++aGlyphSet, nGlyphSetID++)
120 // check every subset if it contains the queried unicode char
121 char_map_t::const_iterator aGlyph = (*aGlyphSet).find (nChar);
122 if (aGlyph != (*aGlyphSet).end())
124 // success: found the unicode char, return the glyphid and the glyphsetid
125 *nOutGlyphSetID = nGlyphSetID;
126 *nOutGlyphID = (*aGlyph).second;
127 return sal_True;
131 *nOutGlyphSetID = -1;
132 *nOutGlyphID = 0;
133 return sal_False;
136 sal_Bool
137 GlyphSet::LookupGlyphID (
138 sal_uInt32 nGlyph,
139 sal_uChar* nOutGlyphID,
140 sal_Int32* nOutGlyphSetID
143 glyph_list_t::iterator aGlyphSet;
144 sal_Int32 nGlyphSetID;
146 // loop thru all the font subsets
147 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
148 aGlyphSet != maGlyphList.end();
149 ++aGlyphSet, nGlyphSetID++)
151 // check every subset if it contains the queried unicode char
152 glyph_map_t::const_iterator aGlyph = (*aGlyphSet).find (nGlyph);
153 if (aGlyph != (*aGlyphSet).end())
155 // success: found the glyph id, return the mapped glyphid and the glyphsetid
156 *nOutGlyphSetID = nGlyphSetID;
157 *nOutGlyphID = (*aGlyph).second;
158 return sal_True;
162 *nOutGlyphSetID = -1;
163 *nOutGlyphID = 0;
164 return sal_False;
167 sal_uChar
168 GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar)
170 static rtl_UnicodeToTextConverter aConverter =
171 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252);
172 static rtl_UnicodeToTextContext aContext =
173 rtl_createUnicodeToTextContext( aConverter );
175 sal_Char nAnsiChar;
176 sal_uInt32 nCvtInfo;
177 sal_Size nCvtChars;
178 const sal_uInt32 nCvtFlags = RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
179 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
181 sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
182 &nUnicodeChar, 1, &nAnsiChar, 1,
183 nCvtFlags, &nCvtInfo, &nCvtChars );
185 return nSize == 1 ? (sal_uChar)nAnsiChar : (sal_uChar)0;
188 sal_uChar
189 GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar)
191 if (0x0000 < nUnicodeChar && nUnicodeChar < 0x0100)
192 return (sal_uChar)nUnicodeChar;
193 if (0xf000 < nUnicodeChar && nUnicodeChar < 0xf100)
194 return (sal_uChar)nUnicodeChar;
196 return 0;
199 void
200 GlyphSet::AddNotdef (char_map_t &rCharMap)
202 if (rCharMap.empty())
203 rCharMap[0] = 0;
206 void
207 GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
209 if (rGlyphMap.empty())
210 rGlyphMap[0] = 0;
212 sal_Bool
213 GlyphSet::AddCharID (
214 sal_Unicode nChar,
215 sal_uChar* nOutGlyphID,
216 sal_Int32* nOutGlyphSetID
219 sal_uChar nMappedChar;
221 // XXX important: avoid to reencode type1 symbol fonts
222 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
223 nMappedChar = GetSymbolMapping (nChar);
224 else
225 nMappedChar = GetAnsiMapping (nChar);
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 if (maCharList.empty())
231 char_map_t aMap, aMapp;
233 maCharList.push_back (aMap);
234 maCharList.push_back (aMapp);
236 // if the last map is full, create a new one
237 if ((!nMappedChar) && (maCharList.back().size() == 255))
239 char_map_t aMap;
240 maCharList.push_back (aMap);
243 // insert a new glyph in the font subset
244 if (nMappedChar)
246 // always put iso1252 chars into the first map, map them on itself
247 char_map_t& aGlyphSet = maCharList.front();
248 AddNotdef (aGlyphSet);
250 aGlyphSet [nChar] = nMappedChar;
251 *nOutGlyphSetID = 1;
252 *nOutGlyphID = nMappedChar;
254 else
256 // other chars are just appended to the list
257 char_map_t& aGlyphSet = maCharList.back();
258 AddNotdef (aGlyphSet);
260 int nSize = aGlyphSet.size();
262 aGlyphSet [nChar] = nSize;
263 *nOutGlyphSetID = maCharList.size();
264 *nOutGlyphID = aGlyphSet [nChar];
267 return sal_True;
270 sal_Bool
271 GlyphSet::AddGlyphID (
272 sal_uInt32 nGlyph,
273 sal_Unicode nUnicode,
274 sal_uChar* nOutGlyphID,
275 sal_Int32* nOutGlyphSetID
278 sal_uChar nMappedChar = 0;
280 // XXX important: avoid to reencode type1 symbol fonts
281 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
282 nMappedChar = GetSymbolMapping (nUnicode);
284 // create an empty glyphmap that is reserved for unencoded symbol glyphs,
285 // and a second map that takes any other
286 if (maGlyphList.empty())
288 glyph_map_t aMap, aMapp;
290 maGlyphList.push_back (aMap);
291 maGlyphList.push_back (aMapp);
293 // if the last map is full, create a new one
294 if ((!nMappedChar) && (maGlyphList.back().size() == 255))
296 glyph_map_t aMap;
297 maGlyphList.push_back (aMap);
300 // insert a new glyph in the font subset
301 if (nMappedChar)
303 // always put symbol glyphs into the first map, map them on itself
304 glyph_map_t& aGlyphSet = maGlyphList.front();
305 AddNotdef (aGlyphSet);
307 aGlyphSet [nGlyph] = nMappedChar;
308 *nOutGlyphSetID = 1;
309 *nOutGlyphID = nMappedChar;
311 else
313 // other glyphs are just appended to the list
314 glyph_map_t& aGlyphSet = maGlyphList.back();
315 AddNotdef (aGlyphSet);
317 int nSize = aGlyphSet.size();
319 aGlyphSet [nGlyph] = nSize;
320 *nOutGlyphSetID = maGlyphList.size();
321 *nOutGlyphID = aGlyphSet [nGlyph];
324 return sal_True;
327 OString
328 GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID)
330 if (meBaseType == fonttype::TrueType)
332 OStringBuffer aSetName( maBaseName.getLength() + 32 );
333 aSetName.append( maBaseName );
334 aSetName.append( "FID" );
335 aSetName.append( mnFontID );
336 aSetName.append( mbVertical ? "VCSet" : "HCSet" );
337 aSetName.append( nGlyphSetID );
338 return aSetName.makeStringAndClear();
340 else
341 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
343 return maBaseName;
347 OString
348 GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
350 if (meBaseType == fonttype::TrueType)
352 OStringBuffer aSetName( maBaseName.getLength() + 32 );
353 aSetName.append( maBaseName );
354 aSetName.append( "FID" );
355 aSetName.append( mnFontID );
356 aSetName.append( mbVertical ? "VGSet" : "HGSet" );
357 aSetName.append( nGlyphSetID );
358 return aSetName.makeStringAndClear();
360 else
361 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
363 return maBaseName;
367 sal_Int32
368 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
370 if (meBaseType == fonttype::TrueType)
371 return RTL_TEXTENCODING_DONTKNOW;
372 else
374 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
375 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
376 return RTL_TEXTENCODING_SYMBOL;
377 else
378 return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
379 : RTL_TEXTENCODING_USER_START + nGlyphSetID;
383 OString
384 GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc, const OString &rFontName)
386 if ( nEnc == RTL_TEXTENCODING_MS_1252
387 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
389 return OString("ISO1252Encoding");
391 else
392 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
394 return rFontName
395 + OString("Enc")
396 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
398 else
400 return OString();
404 OString
405 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
407 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
410 void
411 GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
413 // only for ps fonts
414 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
415 return;
417 sal_Char pEncodingVector [256];
418 sal_Int32 nSize = 0;
420 nSize += psp::appendStr ("(", pEncodingVector + nSize);
421 nSize += psp::appendStr (GetReencodedFontName(nGlyphSetID).getStr(),
422 pEncodingVector + nSize);
423 nSize += psp::appendStr (") cvn (", pEncodingVector + nSize);
424 nSize += psp::appendStr (maBaseName.getStr(),
425 pEncodingVector + nSize);
426 nSize += psp::appendStr (") cvn ", pEncodingVector + nSize);
427 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
428 pEncodingVector + nSize);
429 nSize += psp::appendStr (" psp_definefont\n",
430 pEncodingVector + nSize);
432 psp::WritePS (pOutFile, pEncodingVector);
435 OString
436 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
438 if ( nEnc == RTL_TEXTENCODING_MS_1252
439 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
441 return rFontName
442 + OString("-iso1252");
444 else
445 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
447 return rFontName
448 + OString("-enc")
449 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
451 else
453 return OString();
457 OString
458 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
460 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
463 void GlyphSet::DrawGlyphs(
464 PrinterGfx& rGfx,
465 const Point& rPoint,
466 const sal_uInt32* pGlyphIds,
467 const sal_Unicode* pUnicodes,
468 sal_Int16 nLen,
469 const sal_Int32* pDeltaArray,
470 const sal_Bool bUseGlyphs)
472 sal_uChar *pGlyphID = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
473 sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
474 std::set< sal_Int32 > aGlyphSet;
476 // convert unicode to font glyph id and font subset
477 for (int nChar = 0; nChar < nLen; nChar++)
479 if (bUseGlyphs)
480 GetGlyphID (pGlyphIds[nChar], pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
481 else
482 GetCharID (pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
483 aGlyphSet.insert (pGlyphSetID[nChar]);
486 // loop over all glyph sets to detect substrings that can be xshown together
487 // without changing the postscript font
488 sal_Int32 *pDeltaSubset = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
489 sal_uChar *pGlyphSubset = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
491 std::set< sal_Int32 >::iterator aSet;
492 for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
494 Point aPoint = rPoint;
495 sal_Int32 nOffset = 0;
496 sal_Int32 nGlyphs = 0;
497 sal_Int32 nChar;
499 // get offset to first glyph
500 for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
502 nOffset = pDeltaArray [nChar];
505 // loop over all chars to extract those that share the current glyph set
506 for (nChar = 0; nChar < nLen; nChar++)
508 if (pGlyphSetID[nChar] == *aSet)
510 pGlyphSubset [nGlyphs] = pGlyphID [nChar];
511 // the offset to the next glyph is determined by the glyph in
512 // front of the next glyph with the same glyphset id
513 // most often, this will be the current glyph
514 while ((nChar + 1) < nLen)
516 if (pGlyphSetID[nChar + 1] == *aSet)
517 break;
518 else
519 nChar += 1;
521 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
523 nGlyphs += 1;
527 // show the text using the PrinterGfx text api
528 aPoint.Move (nOffset, 0);
530 OString aGlyphSetName;
531 if (bUseGlyphs)
532 aGlyphSetName = GetGlyphSetName(*aSet);
533 else
534 aGlyphSetName = GetCharSetName(*aSet);
536 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(*aSet));
537 rGfx.PSMoveTo (aPoint);
538 rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
542 void
543 GlyphSet::DrawText (PrinterGfx &rGfx, const Point& rPoint,
544 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
546 // dispatch to the impl method
547 if (pDeltaArray == NULL)
548 ImplDrawText (rGfx, rPoint, pStr, nLen);
549 else
550 ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
553 void
554 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
555 const sal_Unicode* pStr, sal_Int16 nLen)
557 rGfx.PSMoveTo (rPoint);
559 if( mbUseFontEncoding )
561 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
562 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
563 rGfx.PSSetFont( aPSName, mnBaseEncoding );
564 rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength() );
565 return;
568 int nChar;
569 sal_uChar *pGlyphID = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
570 sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
572 // convert unicode to glyph id and char set (font subset)
573 for (nChar = 0; nChar < nLen; nChar++)
574 GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
576 // loop over the string to draw subsequent pieces of chars
577 // with the same postscript font
578 for (nChar = 0; nChar < nLen; /* atend */)
580 sal_Int32 nGlyphSetID = pGlyphSetID [nChar];
581 sal_Int32 nGlyphs = 1;
582 for (int nNextChar = nChar + 1; nNextChar < nLen; nNextChar++)
584 if (pGlyphSetID[nNextChar] == nGlyphSetID)
585 nGlyphs++;
586 else
587 break;
590 // show the text using the PrinterGfx text api
591 OString aGlyphSetName(GetCharSetName(nGlyphSetID));
592 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(nGlyphSetID));
593 rGfx.PSShowText (pGlyphID + nChar, nGlyphs, nGlyphs);
595 nChar += nGlyphs;
599 void
600 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
601 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
603 if( mbUseFontEncoding )
605 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
606 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
607 rGfx.PSMoveTo( rPoint );
608 rGfx.PSSetFont( aPSName, mnBaseEncoding );
609 rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength(), pDeltaArray );
610 return;
613 DrawGlyphs( rGfx, rPoint, NULL, pStr, nLen, pDeltaArray, sal_False);
616 sal_Bool
617 GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
619 // only for ps fonts
620 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
621 return sal_False;
622 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
623 return sal_False;
625 PrintFontManager &rMgr = rGfx.GetFontMgr();
627 // loop thru all the font subsets
628 sal_Int32 nGlyphSetID = 0;
629 char_list_t::iterator aGlyphSet;
630 for (aGlyphSet = maCharList.begin(); aGlyphSet != maCharList.end(); ++aGlyphSet)
632 ++nGlyphSetID;
634 if (nGlyphSetID == 1) // latin1 page uses global reencoding table
636 PSDefineReencodedFont (pOutFile, nGlyphSetID);
637 continue;
639 if ((*aGlyphSet).empty()) // empty set, doesn't need reencoding
641 continue;
644 // create reencoding table
646 sal_Char pEncodingVector [256];
647 sal_Int32 nSize = 0;
649 nSize += psp::appendStr ("/",
650 pEncodingVector + nSize);
651 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
652 pEncodingVector + nSize);
653 nSize += psp::appendStr (" [ ",
654 pEncodingVector + nSize);
656 // need a list of glyphs, sorted by glyphid
657 typedef std::map< sal_uInt8, sal_Unicode > ps_mapping_t;
658 typedef ps_mapping_t::value_type ps_value_t;
659 ps_mapping_t aSortedGlyphSet;
661 char_map_t::const_iterator aUnsortedGlyph;
662 for (aUnsortedGlyph = (*aGlyphSet).begin();
663 aUnsortedGlyph != (*aGlyphSet).end();
664 ++aUnsortedGlyph)
666 aSortedGlyphSet.insert(ps_value_t((*aUnsortedGlyph).second,
667 (*aUnsortedGlyph).first));
670 ps_mapping_t::const_iterator aSortedGlyph;
671 // loop thru all the glyphs in the subset
672 for (aSortedGlyph = (aSortedGlyphSet).begin();
673 aSortedGlyph != (aSortedGlyphSet).end();
674 ++aSortedGlyph)
676 nSize += psp::appendStr ("/",
677 pEncodingVector + nSize);
679 std::list< OString > aName( rMgr.getAdobeNameFromUnicode((*aSortedGlyph).second) );
681 if( aName.begin() != aName.end() )
682 nSize += psp::appendStr ( aName.front().getStr(), pEncodingVector + nSize);
683 else
684 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
685 nSize += psp::appendStr (" ", pEncodingVector + nSize);
686 // flush line
687 if (nSize >= 70)
689 nSize += psp::appendStr ("\n", pEncodingVector + nSize);
690 psp::WritePS (pOutFile, pEncodingVector);
691 nSize = 0;
695 nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
696 psp::WritePS (pOutFile, pEncodingVector);
698 PSDefineReencodedFont (pOutFile, nGlyphSetID);
701 return sal_True;
704 struct EncEntry
706 sal_uChar aEnc;
707 long aGID;
709 EncEntry() : aEnc( 0 ), aGID( 0 ) {}
711 bool operator<( const EncEntry& rRight ) const
712 { return aEnc < rRight.aEnc; }
715 static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile,
716 const char* pGlyphSetName, int nGlyphCount,
717 /*const*/ sal_uInt16* pRequestedGlyphs, /*const*/ sal_uChar* pEncoding,
718 bool bAllowType42, bool /*bAllowCID*/ )
720 // match the font-subset to the printer capabilities
721 // TODO: allow CFF for capable printers
722 int nTargetMask = FontSubsetInfo::TYPE1_PFA | FontSubsetInfo::TYPE3_FONT;
723 if( bAllowType42 )
724 nTargetMask |= FontSubsetInfo::TYPE42_FONT;
726 std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
727 for( int i = 0; i < nGlyphCount; i++ )
729 aSorted[i].aEnc = pEncoding[i];
730 aSorted[i].aGID = pRequestedGlyphs[i];
733 std::stable_sort( aSorted.begin(), aSorted.end() );
735 std::vector< sal_uChar > aEncoding( nGlyphCount );
736 std::vector< long > aRequestedGlyphs( nGlyphCount );
738 for( int i = 0; i < nGlyphCount; i++ )
740 aEncoding[i] = aSorted[i].aEnc;
741 aRequestedGlyphs[i] = aSorted[i].aGID;
744 FontSubsetInfo aInfo;
745 aInfo.LoadFont( pSrcFont );
747 aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
748 &aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL );
751 sal_Bool
752 GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
754 // only for truetype fonts
755 if (meBaseType != fonttype::TrueType)
756 return sal_False;
758 #if defined( UNX )
759 TrueTypeFont *pTTFont;
760 OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
761 int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
762 sal_Int32 nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace, &pTTFont);
763 if (nSuccess != SF_OK)
764 return sal_False;
765 FILE* pTmpFile = tmpfile();
766 if (pTmpFile == NULL)
767 return sal_False;
769 // array of unicode source characters
770 sal_Unicode pUChars[256];
772 // encoding vector maps character encoding to the ordinal number
773 // of the glyph in the output file
774 sal_uChar pEncoding[256];
775 sal_uInt16 pTTGlyphMapping[256];
776 const bool bAllowCID = false; // TODO: nPSLanguageLevel>=3
778 // loop thru all the font subsets
779 sal_Int32 nCharSetID;
780 char_list_t::iterator aCharSet;
781 for (aCharSet = maCharList.begin(), nCharSetID = 1;
782 aCharSet != maCharList.end();
783 ++aCharSet, nCharSetID++)
785 if ((*aCharSet).empty())
786 continue;
788 // loop thru all the chars in the subset
789 char_map_t::const_iterator aChar;
790 sal_Int32 n = 0;
791 for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); ++aChar)
793 pUChars [n] = (*aChar).first;
794 pEncoding [n] = (*aChar).second;
795 n++;
797 // create a mapping from the unicode chars to the char encoding in
798 // source TrueType font
799 MapString (pTTFont, pUChars, (*aCharSet).size(), pTTGlyphMapping, mbVertical);
801 // create the current subset
802 OString aCharSetName = GetCharSetName(nCharSetID);
803 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aCharSetName.getStr() );
804 CreatePSUploadableFont( pTTFont, pTmpFile, aCharSetName.getStr(), (*aCharSet).size(),
805 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
806 fprintf( pTmpFile, "%%%%EndResource\n" );
807 rSuppliedFonts.push_back( aCharSetName );
810 // loop thru all the font glyph subsets
811 sal_Int32 nGlyphSetID;
812 glyph_list_t::iterator aGlyphSet;
813 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
814 aGlyphSet != maGlyphList.end();
815 ++aGlyphSet, nGlyphSetID++)
817 if ((*aGlyphSet).empty())
818 continue;
820 // loop thru all the glyphs in the subset
821 glyph_map_t::const_iterator aGlyph;
822 sal_Int32 n = 0;
823 for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); ++aGlyph)
825 pTTGlyphMapping [n] = (*aGlyph).first;
826 pEncoding [n] = (*aGlyph).second;
827 n++;
830 // create the current subset
831 OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
832 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
833 CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), (*aGlyphSet).size(),
834 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
835 fprintf( pTmpFile, "%%%%EndResource\n" );
836 rSuppliedFonts.push_back( aGlyphSetName );
839 // copy the file into the page header
840 rewind(pTmpFile);
841 fflush(pTmpFile);
843 sal_uChar pBuffer[0x2000];
844 sal_uInt64 nIn;
845 sal_uInt64 nOut;
848 nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
849 rOutFile.write (pBuffer, nIn, nOut);
851 while ((nIn == nOut) && !feof(pTmpFile));
853 // cleanup
854 CloseTTFont (pTTFont);
855 fclose (pTmpFile);
857 return sal_True;
858 #else
859 (void)rOutFile; (void)rGfx; (void)bAllowType42; (void)rSuppliedFonts;
860 # warning FIXME: Missing OpenTTFontFile outside of Unix ...
861 return sal_False;
862 #endif
865 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */