Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / generic / print / glyphset.cxx
blob37bd752525f8dc10aaa5c7f8903760d530c25c5a
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 .
20 #include "glyphset.hxx"
21 #include "psputil.hxx"
23 #include "sft.hxx"
25 #include "generic/printergfx.hxx"
26 #include "fontsubset.hxx"
27 #include "fontmanager.hxx"
29 #include <tools/gen.hxx>
31 #include "osl/thread.h"
33 #include "sal/alloca.h"
35 #include "rtl/ustring.hxx"
36 #include "rtl/strbuf.hxx"
38 #include <unotools/tempfile.hxx>
40 #include <set>
41 #include <map>
42 #include <algorithm>
44 using namespace vcl;
45 using namespace psp;
47 GlyphSet::GlyphSet (sal_Int32 nFontID, 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 bool
65 GlyphSet::GetCharID (
66 sal_Unicode nChar,
67 unsigned char* nOutGlyphID,
68 sal_Int32* nOutGlyphSetID
71 return LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
72 || AddCharID (nChar, nOutGlyphID, nOutGlyphSetID);
75 bool
76 GlyphSet::GetGlyphID (
77 sal_GlyphId nGlyph,
78 sal_Unicode nUnicode,
79 unsigned char* nOutGlyphID,
80 sal_Int32* nOutGlyphSetID
83 return LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
84 || AddGlyphID (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
87 bool
88 GlyphSet::LookupCharID (
89 sal_Unicode nChar,
90 unsigned char* nOutGlyphID,
91 sal_Int32* nOutGlyphSetID
94 char_list_t::iterator aGlyphSet;
95 sal_Int32 nGlyphSetID;
97 // loop through all the font subsets
98 for (aGlyphSet = maCharList.begin(), nGlyphSetID = 1;
99 aGlyphSet != maCharList.end();
100 ++aGlyphSet, nGlyphSetID++)
102 // check every subset if it contains the queried unicode char
103 char_map_t::const_iterator aGlyph = (*aGlyphSet).find (nChar);
104 if (aGlyph != (*aGlyphSet).end())
106 // success: found the unicode char, return the glyphid and the glyphsetid
107 *nOutGlyphSetID = nGlyphSetID;
108 *nOutGlyphID = (*aGlyph).second;
109 return true;
113 *nOutGlyphSetID = -1;
114 *nOutGlyphID = 0;
115 return false;
118 bool
119 GlyphSet::LookupGlyphID (
120 sal_GlyphId nGlyph,
121 unsigned char* nOutGlyphID,
122 sal_Int32* nOutGlyphSetID
125 glyph_list_t::iterator aGlyphSet;
126 sal_Int32 nGlyphSetID;
128 // loop through all the font subsets
129 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
130 aGlyphSet != maGlyphList.end();
131 ++aGlyphSet, nGlyphSetID++)
133 // check every subset if it contains the queried unicode char
134 glyph_map_t::const_iterator aGlyph = (*aGlyphSet).find (nGlyph);
135 if (aGlyph != (*aGlyphSet).end())
137 // success: found the glyph id, return the mapped glyphid and the glyphsetid
138 *nOutGlyphSetID = nGlyphSetID;
139 *nOutGlyphID = (*aGlyph).second;
140 return true;
144 *nOutGlyphSetID = -1;
145 *nOutGlyphID = 0;
146 return false;
149 unsigned char
150 GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar)
152 static rtl_UnicodeToTextConverter aConverter =
153 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252);
154 static rtl_UnicodeToTextContext aContext =
155 rtl_createUnicodeToTextContext( aConverter );
157 sal_Char nAnsiChar;
158 sal_uInt32 nCvtInfo;
159 sal_Size nCvtChars;
160 const sal_uInt32 nCvtFlags = RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
161 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
163 sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
164 &nUnicodeChar, 1, &nAnsiChar, 1,
165 nCvtFlags, &nCvtInfo, &nCvtChars );
167 return nSize == 1 ? (unsigned char)nAnsiChar : (unsigned char)0;
170 unsigned char
171 GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar)
173 if (0x0000 < nUnicodeChar && nUnicodeChar < 0x0100)
174 return (unsigned char)nUnicodeChar;
175 if (0xf000 < nUnicodeChar && nUnicodeChar < 0xf100)
176 return (unsigned char)nUnicodeChar;
178 return 0;
181 void
182 GlyphSet::AddNotdef (char_map_t &rCharMap)
184 if (rCharMap.empty())
185 rCharMap[0] = 0;
188 void
189 GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
191 if (rGlyphMap.empty())
192 rGlyphMap[0] = 0;
194 bool
195 GlyphSet::AddCharID (
196 sal_Unicode nChar,
197 unsigned char* nOutGlyphID,
198 sal_Int32* nOutGlyphSetID
201 unsigned char nMappedChar;
203 // XXX important: avoid to reencode type1 symbol fonts
204 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
205 nMappedChar = GetSymbolMapping (nChar);
206 else
207 nMappedChar = GetAnsiMapping (nChar);
209 // create an empty glyphmap that is reserved for iso1252 encoded glyphs
210 // (or -- unencoded -- symbol glyphs) and a second map that takes any other
211 if (maCharList.empty())
213 char_map_t aMap, aMapp;
215 maCharList.push_back (aMap);
216 maCharList.push_back (aMapp);
218 // if the last map is full, create a new one
219 if ((!nMappedChar) && (maCharList.back().size() == 255))
221 char_map_t aMap;
222 maCharList.push_back (aMap);
225 // insert a new glyph in the font subset
226 if (nMappedChar)
228 // always put iso1252 chars into the first map, map them on itself
229 char_map_t& aGlyphSet = maCharList.front();
230 AddNotdef (aGlyphSet);
232 aGlyphSet [nChar] = nMappedChar;
233 *nOutGlyphSetID = 1;
234 *nOutGlyphID = nMappedChar;
236 else
238 // other chars are just appended to the list
239 char_map_t& aGlyphSet = maCharList.back();
240 AddNotdef (aGlyphSet);
242 int nSize = aGlyphSet.size();
244 aGlyphSet [nChar] = nSize;
245 *nOutGlyphSetID = maCharList.size();
246 *nOutGlyphID = aGlyphSet [nChar];
249 return true;
252 bool
253 GlyphSet::AddGlyphID (
254 sal_GlyphId nGlyph,
255 sal_Unicode nUnicode,
256 unsigned char* nOutGlyphID,
257 sal_Int32* nOutGlyphSetID
260 unsigned char nMappedChar = 0;
262 // XXX important: avoid to reencode type1 symbol fonts
263 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
264 nMappedChar = GetSymbolMapping (nUnicode);
266 // create an empty glyphmap that is reserved for unencoded symbol glyphs,
267 // and a second map that takes any other
268 if (maGlyphList.empty())
270 glyph_map_t aMap, aMapp;
272 maGlyphList.push_back (aMap);
273 maGlyphList.push_back (aMapp);
275 // if the last map is full, create a new one
276 if ((!nMappedChar) && (maGlyphList.back().size() == 255))
278 glyph_map_t aMap;
279 maGlyphList.push_back (aMap);
282 // insert a new glyph in the font subset
283 if (nMappedChar)
285 // always put symbol glyphs into the first map, map them on itself
286 glyph_map_t& aGlyphSet = maGlyphList.front();
287 AddNotdef (aGlyphSet);
289 aGlyphSet [nGlyph] = nMappedChar;
290 *nOutGlyphSetID = 1;
291 *nOutGlyphID = nMappedChar;
293 else
295 // other glyphs are just appended to the list
296 glyph_map_t& aGlyphSet = maGlyphList.back();
297 AddNotdef (aGlyphSet);
299 int nSize = aGlyphSet.size();
301 aGlyphSet [nGlyph] = nSize;
302 *nOutGlyphSetID = maGlyphList.size();
303 *nOutGlyphID = aGlyphSet [nGlyph];
306 return true;
309 OString
310 GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID)
312 if (meBaseType == fonttype::TrueType)
314 OStringBuffer aSetName( maBaseName.getLength() + 32 );
315 aSetName.append( maBaseName );
316 aSetName.append( "FID" );
317 aSetName.append( mnFontID );
318 aSetName.append( mbVertical ? "VCSet" : "HCSet" );
319 aSetName.append( nGlyphSetID );
320 return aSetName.makeStringAndClear();
322 else
324 return maBaseName;
328 OString
329 GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
331 if (meBaseType == fonttype::TrueType)
333 OStringBuffer aSetName( maBaseName.getLength() + 32 );
334 aSetName.append( maBaseName );
335 aSetName.append( "FID" );
336 aSetName.append( mnFontID );
337 aSetName.append( mbVertical ? "VGSet" : "HGSet" );
338 aSetName.append( nGlyphSetID );
339 return aSetName.makeStringAndClear();
341 else
343 return maBaseName;
347 sal_Int32
348 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
350 if (meBaseType == fonttype::TrueType)
351 return RTL_TEXTENCODING_DONTKNOW;
352 else
354 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
355 return RTL_TEXTENCODING_SYMBOL;
356 else
357 return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
358 : RTL_TEXTENCODING_USER_START + nGlyphSetID;
362 OString
363 GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc, const OString &rFontName)
365 if ( nEnc == RTL_TEXTENCODING_MS_1252
366 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
368 return OString("ISO1252Encoding");
370 else
371 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
373 return rFontName
374 + OString("Enc")
375 + OString::number ((nEnc - RTL_TEXTENCODING_USER_START));
377 else
379 return OString();
383 OString
384 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
386 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
389 void
390 GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
392 // only for ps fonts
393 if (meBaseType != fonttype::Type1)
394 return;
396 sal_Char pEncodingVector [256];
397 sal_Int32 nSize = 0;
399 nSize += psp::appendStr ("(", pEncodingVector + nSize);
400 nSize += psp::appendStr (GetReencodedFontName(nGlyphSetID).getStr(),
401 pEncodingVector + nSize);
402 nSize += psp::appendStr (") cvn (", pEncodingVector + nSize);
403 nSize += psp::appendStr (maBaseName.getStr(),
404 pEncodingVector + nSize);
405 nSize += psp::appendStr (") cvn ", pEncodingVector + nSize);
406 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
407 pEncodingVector + nSize);
408 nSize += psp::appendStr (" psp_definefont\n",
409 pEncodingVector + nSize);
411 psp::WritePS (pOutFile, pEncodingVector);
414 OString
415 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
417 if ( nEnc == RTL_TEXTENCODING_MS_1252
418 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
420 return rFontName
421 + OString("-iso1252");
423 else
424 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
426 return rFontName
427 + OString("-enc")
428 + OString::number ((nEnc - RTL_TEXTENCODING_USER_START));
430 else
432 return OString();
436 OString
437 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
439 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
442 void GlyphSet::DrawGlyphs(
443 PrinterGfx& rGfx,
444 const Point& rPoint,
445 const sal_GlyphId* pGlyphIds,
446 const sal_Unicode* pUnicodes,
447 sal_Int16 nLen,
448 const sal_Int32* pDeltaArray,
449 const bool bUseGlyphs)
451 unsigned char *pGlyphID = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
452 sal_Int32 *pGlyphSetID = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
453 std::set< sal_Int32 > aGlyphSet;
455 // convert unicode to font glyph id and font subset
456 for (int nChar = 0; nChar < nLen; nChar++)
458 if (bUseGlyphs)
459 GetGlyphID (pGlyphIds[nChar], pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
460 else
461 GetCharID (pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
462 aGlyphSet.insert (pGlyphSetID[nChar]);
465 // loop over all glyph sets to detect substrings that can be xshown together
466 // without changing the postscript font
467 sal_Int32 *pDeltaSubset = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
468 unsigned char *pGlyphSubset = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
470 std::set< sal_Int32 >::iterator aSet;
471 for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
473 Point aPoint = rPoint;
474 sal_Int32 nOffset = 0;
475 sal_Int32 nGlyphs = 0;
476 sal_Int32 nChar;
478 // get offset to first glyph
479 for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
481 nOffset = pDeltaArray [nChar];
484 // loop over all chars to extract those that share the current glyph set
485 for (nChar = 0; nChar < nLen; nChar++)
487 if (pGlyphSetID[nChar] == *aSet)
489 pGlyphSubset [nGlyphs] = pGlyphID [nChar];
490 // the offset to the next glyph is determined by the glyph in
491 // front of the next glyph with the same glyphset id
492 // most often, this will be the current glyph
493 while ((nChar + 1) < nLen)
495 if (pGlyphSetID[nChar + 1] == *aSet)
496 break;
497 else
498 nChar += 1;
500 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
502 nGlyphs += 1;
506 // show the text using the PrinterGfx text api
507 aPoint.Move (nOffset, 0);
509 OString aGlyphSetName;
510 if (bUseGlyphs)
511 aGlyphSetName = GetGlyphSetName(*aSet);
512 else
513 aGlyphSetName = GetCharSetName(*aSet);
515 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(*aSet));
516 rGfx.PSMoveTo (aPoint);
517 rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
521 void
522 GlyphSet::DrawText (PrinterGfx &rGfx, const Point& rPoint,
523 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
525 // dispatch to the impl method
526 if (pDeltaArray == NULL)
527 ImplDrawText (rGfx, rPoint, pStr, nLen);
528 else
529 ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
532 void
533 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
534 const sal_Unicode* pStr, sal_Int16 nLen)
536 rGfx.PSMoveTo (rPoint);
538 if( mbUseFontEncoding )
540 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
541 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
542 rGfx.PSSetFont( aPSName, mnBaseEncoding );
543 rGfx.PSShowText( reinterpret_cast<const unsigned char*>(aBytes.getStr()), nLen, aBytes.getLength() );
544 return;
547 int nChar;
548 unsigned char *pGlyphID = static_cast<unsigned char*>(alloca (nLen * sizeof(unsigned char)));
549 sal_Int32 *pGlyphSetID = static_cast<sal_Int32*>(alloca (nLen * sizeof(sal_Int32)));
551 // convert unicode to glyph id and char set (font subset)
552 for (nChar = 0; nChar < nLen; nChar++)
553 GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
555 // loop over the string to draw subsequent pieces of chars
556 // with the same postscript font
557 for (nChar = 0; nChar < nLen; /* atend */)
559 sal_Int32 nGlyphSetID = pGlyphSetID [nChar];
560 sal_Int32 nGlyphs = 1;
561 for (int nNextChar = nChar + 1; nNextChar < nLen; nNextChar++)
563 if (pGlyphSetID[nNextChar] == nGlyphSetID)
564 nGlyphs++;
565 else
566 break;
569 // show the text using the PrinterGfx text api
570 OString aGlyphSetName(GetCharSetName(nGlyphSetID));
571 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(nGlyphSetID));
572 rGfx.PSShowText (pGlyphID + nChar, nGlyphs, nGlyphs);
574 nChar += nGlyphs;
578 void
579 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
580 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
582 if( mbUseFontEncoding )
584 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
585 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
586 rGfx.PSMoveTo( rPoint );
587 rGfx.PSSetFont( aPSName, mnBaseEncoding );
588 rGfx.PSShowText( reinterpret_cast<const unsigned char*>(aBytes.getStr()), nLen, aBytes.getLength(), pDeltaArray );
589 return;
592 DrawGlyphs( rGfx, rPoint, NULL, pStr, nLen, pDeltaArray, false);
595 bool
596 GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
598 // only for ps fonts
599 if (meBaseType != fonttype::Type1)
600 return false;
601 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
602 return false;
604 PrintFontManager &rMgr = rGfx.GetFontMgr();
606 // loop through all the font subsets
607 sal_Int32 nGlyphSetID = 0;
608 char_list_t::iterator aGlyphSet;
609 for (aGlyphSet = maCharList.begin(); aGlyphSet != maCharList.end(); ++aGlyphSet)
611 ++nGlyphSetID;
613 if (nGlyphSetID == 1) // latin1 page uses global reencoding table
615 PSDefineReencodedFont (pOutFile, nGlyphSetID);
616 continue;
618 if ((*aGlyphSet).empty()) // empty set, doesn't need reencoding
620 continue;
623 // create reencoding table
625 sal_Char pEncodingVector [256];
626 sal_Int32 nSize = 0;
628 nSize += psp::appendStr ("/",
629 pEncodingVector + nSize);
630 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
631 pEncodingVector + nSize);
632 nSize += psp::appendStr (" [ ",
633 pEncodingVector + nSize);
635 // need a list of glyphs, sorted by glyphid
636 typedef std::map< sal_uInt8, sal_Unicode > ps_mapping_t;
637 typedef ps_mapping_t::value_type ps_value_t;
638 ps_mapping_t aSortedGlyphSet;
640 char_map_t::const_iterator aUnsortedGlyph;
641 for (aUnsortedGlyph = (*aGlyphSet).begin();
642 aUnsortedGlyph != (*aGlyphSet).end();
643 ++aUnsortedGlyph)
645 aSortedGlyphSet.insert(ps_value_t((*aUnsortedGlyph).second,
646 (*aUnsortedGlyph).first));
649 ps_mapping_t::const_iterator aSortedGlyph;
650 // loop through all the glyphs in the subset
651 for (aSortedGlyph = (aSortedGlyphSet).begin();
652 aSortedGlyph != (aSortedGlyphSet).end();
653 ++aSortedGlyph)
655 nSize += psp::appendStr ("/",
656 pEncodingVector + nSize);
658 std::list< OString > aName( rMgr.getAdobeNameFromUnicode((*aSortedGlyph).second) );
660 if( aName.begin() != aName.end() )
661 nSize += psp::appendStr ( aName.front().getStr(), pEncodingVector + nSize);
662 else
663 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
664 nSize += psp::appendStr (" ", pEncodingVector + nSize);
665 // flush line
666 if (nSize >= 70)
668 psp::appendStr ("\n", pEncodingVector + nSize);
669 psp::WritePS (pOutFile, pEncodingVector);
670 nSize = 0;
674 nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
675 psp::WritePS (pOutFile, pEncodingVector);
677 PSDefineReencodedFont (pOutFile, nGlyphSetID);
680 return true;
683 struct EncEntry
685 unsigned char aEnc;
686 long aGID;
688 EncEntry() : aEnc( 0 ), aGID( 0 ) {}
690 bool operator<( const EncEntry& rRight ) const
691 { return aEnc < rRight.aEnc; }
694 static void CreatePSUploadableFont( TrueTypeFont* pSrcFont, FILE* pTmpFile,
695 const char* pGlyphSetName, int nGlyphCount,
696 /*const*/ sal_uInt16* pRequestedGlyphs, /*const*/ unsigned char* pEncoding,
697 bool bAllowType42, bool /*bAllowCID*/ )
699 // match the font-subset to the printer capabilities
700 // TODO: allow CFF for capable printers
701 int nTargetMask = FontSubsetInfo::TYPE1_PFA | FontSubsetInfo::TYPE3_FONT;
702 if( bAllowType42 )
703 nTargetMask |= FontSubsetInfo::TYPE42_FONT;
705 std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
706 for( int i = 0; i < nGlyphCount; i++ )
708 aSorted[i].aEnc = pEncoding[i];
709 aSorted[i].aGID = pRequestedGlyphs[i];
712 std::stable_sort( aSorted.begin(), aSorted.end() );
714 std::vector< unsigned char > aEncoding( nGlyphCount );
715 std::vector< sal_GlyphId > aRequestedGlyphs( nGlyphCount );
717 for( int i = 0; i < nGlyphCount; i++ )
719 aEncoding[i] = aSorted[i].aEnc;
720 aRequestedGlyphs[i] = aSorted[i].aGID;
723 FontSubsetInfo aInfo;
724 aInfo.LoadFont( pSrcFont );
726 aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
727 &aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL );
730 bool
731 GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
733 // only for truetype fonts
734 if (meBaseType != fonttype::TrueType)
735 return false;
737 #if defined( UNX )
738 TrueTypeFont *pTTFont;
739 OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
740 int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
741 sal_Int32 nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace, &pTTFont);
742 if (nSuccess != SF_OK)
743 return false;
745 utl::TempFile aTmpFile;
746 aTmpFile.EnableKillingFile();
747 FILE* pTmpFile = fopen(OUStringToOString(aTmpFile.GetFileName(), osl_getThreadTextEncoding()).getStr(), "w+b");
748 if (pTmpFile == NULL)
749 return false;
751 // array of unicode source characters
752 sal_Unicode pUChars[256];
754 // encoding vector maps character encoding to the ordinal number
755 // of the glyph in the output file
756 unsigned char pEncoding[256];
757 sal_uInt16 pTTGlyphMapping[256];
758 const bool bAllowCID = false; // TODO: nPSLanguageLevel>=3
760 // loop through all the font subsets
761 sal_Int32 nCharSetID;
762 char_list_t::iterator aCharSet;
763 for (aCharSet = maCharList.begin(), nCharSetID = 1;
764 aCharSet != maCharList.end();
765 ++aCharSet, nCharSetID++)
767 if ((*aCharSet).empty())
768 continue;
770 // loop through all the chars in the subset
771 char_map_t::const_iterator aChar;
772 sal_Int32 n = 0;
773 for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); ++aChar)
775 pUChars [n] = (*aChar).first;
776 pEncoding [n] = (*aChar).second;
777 n++;
779 // create a mapping from the unicode chars to the char encoding in
780 // source TrueType font
781 MapString (pTTFont, pUChars, (*aCharSet).size(), pTTGlyphMapping, mbVertical);
783 // create the current subset
784 OString aCharSetName = GetCharSetName(nCharSetID);
785 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aCharSetName.getStr() );
786 CreatePSUploadableFont( pTTFont, pTmpFile, aCharSetName.getStr(), (*aCharSet).size(),
787 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
788 fprintf( pTmpFile, "%%%%EndResource\n" );
789 rSuppliedFonts.push_back( aCharSetName );
792 // loop through all the font glyph subsets
793 sal_Int32 nGlyphSetID;
794 glyph_list_t::iterator aGlyphSet;
795 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
796 aGlyphSet != maGlyphList.end();
797 ++aGlyphSet, nGlyphSetID++)
799 if ((*aGlyphSet).empty())
800 continue;
802 // loop through all the glyphs in the subset
803 glyph_map_t::const_iterator aGlyph;
804 sal_Int32 n = 0;
805 for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); ++aGlyph)
807 pTTGlyphMapping [n] = (*aGlyph).first;
808 pEncoding [n] = (*aGlyph).second;
809 n++;
812 // create the current subset
813 OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
814 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
815 CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), (*aGlyphSet).size(),
816 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
817 fprintf( pTmpFile, "%%%%EndResource\n" );
818 rSuppliedFonts.push_back( aGlyphSetName );
821 // copy the file into the page header
822 rewind(pTmpFile);
823 fflush(pTmpFile);
825 unsigned char pBuffer[0x2000];
826 sal_uInt64 nIn;
827 sal_uInt64 nOut;
830 nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
831 rOutFile.write (pBuffer, nIn, nOut);
833 while ((nIn == nOut) && !feof(pTmpFile));
835 // cleanup
836 CloseTTFont (pTTFont);
837 fclose (pTmpFile);
839 return true;
840 #else
841 (void)rOutFile; (void)rGfx; (void)bAllowType42; (void)rSuppliedFonts;
842 # warning FIXME: Missing OpenTTFontFile outside of Unix ...
843 return false;
844 #endif
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */