Bump for 4.0-15
[LibreOffice.git] / vcl / generic / print / glyphset.cxx
blob5c90618c2087e9f4e688d4370aa5dafdb641a9ba
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 "osl/thread.h"
32 #include "sal/alloca.h"
34 #include "rtl/ustring.hxx"
35 #include "rtl/strbuf.hxx"
37 #include <set>
38 #include <map>
39 #include <algorithm>
41 using namespace vcl;
42 using namespace psp;
44 using ::rtl::OUString;
45 using ::rtl::OString;
46 using ::rtl::OStringBuffer;
47 using ::rtl::OUStringToOString;
49 GlyphSet::GlyphSet (sal_Int32 nFontID, sal_Bool bVertical)
50 : mnFontID (nFontID),
51 mbVertical (bVertical)
53 PrintFontManager &rMgr = PrintFontManager::get();
54 meBaseType = rMgr.getFontType (mnFontID);
55 maBaseName = OUStringToOString (rMgr.getPSName(mnFontID),
56 RTL_TEXTENCODING_ASCII_US);
57 mnBaseEncoding = rMgr.getFontEncoding(mnFontID);
58 mbUseFontEncoding = rMgr.getUseOnlyFontEncoding(mnFontID);
61 GlyphSet::~GlyphSet ()
63 /* FIXME delete the glyphlist ??? */
66 sal_Int32
67 GlyphSet::GetFontID ()
69 return mnFontID;
72 fonttype::type
73 GlyphSet::GetFontType ()
75 return meBaseType;
78 sal_Bool
79 GlyphSet::IsVertical ()
81 return mbVertical;
84 sal_Bool
85 GlyphSet::GetCharID (
86 sal_Unicode nChar,
87 sal_uChar* nOutGlyphID,
88 sal_Int32* nOutGlyphSetID
91 return LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
92 || AddCharID (nChar, nOutGlyphID, nOutGlyphSetID);
95 sal_Bool
96 GlyphSet::GetGlyphID (
97 sal_uInt32 nGlyph,
98 sal_Unicode nUnicode,
99 sal_uChar* nOutGlyphID,
100 sal_Int32* nOutGlyphSetID
103 return LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
104 || AddGlyphID (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
107 sal_Bool
108 GlyphSet::LookupCharID (
109 sal_Unicode nChar,
110 sal_uChar* nOutGlyphID,
111 sal_Int32* nOutGlyphSetID
114 char_list_t::iterator aGlyphSet;
115 sal_Int32 nGlyphSetID;
117 // loop thru all the font subsets
118 for (aGlyphSet = maCharList.begin(), nGlyphSetID = 1;
119 aGlyphSet != maCharList.end();
120 ++aGlyphSet, nGlyphSetID++)
122 // check every subset if it contains the queried unicode char
123 char_map_t::const_iterator aGlyph = (*aGlyphSet).find (nChar);
124 if (aGlyph != (*aGlyphSet).end())
126 // success: found the unicode char, return the glyphid and the glyphsetid
127 *nOutGlyphSetID = nGlyphSetID;
128 *nOutGlyphID = (*aGlyph).second;
129 return sal_True;
133 *nOutGlyphSetID = -1;
134 *nOutGlyphID = 0;
135 return sal_False;
138 sal_Bool
139 GlyphSet::LookupGlyphID (
140 sal_uInt32 nGlyph,
141 sal_uChar* nOutGlyphID,
142 sal_Int32* nOutGlyphSetID
145 glyph_list_t::iterator aGlyphSet;
146 sal_Int32 nGlyphSetID;
148 // loop thru all the font subsets
149 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
150 aGlyphSet != maGlyphList.end();
151 ++aGlyphSet, nGlyphSetID++)
153 // check every subset if it contains the queried unicode char
154 glyph_map_t::const_iterator aGlyph = (*aGlyphSet).find (nGlyph);
155 if (aGlyph != (*aGlyphSet).end())
157 // success: found the glyph id, return the mapped glyphid and the glyphsetid
158 *nOutGlyphSetID = nGlyphSetID;
159 *nOutGlyphID = (*aGlyph).second;
160 return sal_True;
164 *nOutGlyphSetID = -1;
165 *nOutGlyphID = 0;
166 return sal_False;
169 sal_uChar
170 GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar)
172 static rtl_UnicodeToTextConverter aConverter =
173 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252);
174 static rtl_UnicodeToTextContext aContext =
175 rtl_createUnicodeToTextContext( aConverter );
177 sal_Char nAnsiChar;
178 sal_uInt32 nCvtInfo;
179 sal_Size nCvtChars;
180 const sal_uInt32 nCvtFlags = RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
181 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
183 sal_Size nSize = rtl_convertUnicodeToText( aConverter, aContext,
184 &nUnicodeChar, 1, &nAnsiChar, 1,
185 nCvtFlags, &nCvtInfo, &nCvtChars );
187 return nSize == 1 ? (sal_uChar)nAnsiChar : (sal_uChar)0;
190 sal_uChar
191 GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar)
193 if (0x0000 < nUnicodeChar && nUnicodeChar < 0x0100)
194 return (sal_uChar)nUnicodeChar;
195 if (0xf000 < nUnicodeChar && nUnicodeChar < 0xf100)
196 return (sal_uChar)nUnicodeChar;
198 return 0;
201 void
202 GlyphSet::AddNotdef (char_map_t &rCharMap)
204 if (rCharMap.empty())
205 rCharMap[0] = 0;
208 void
209 GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
211 if (rGlyphMap.empty())
212 rGlyphMap[0] = 0;
214 sal_Bool
215 GlyphSet::AddCharID (
216 sal_Unicode nChar,
217 sal_uChar* nOutGlyphID,
218 sal_Int32* nOutGlyphSetID
221 sal_uChar nMappedChar;
223 // XXX important: avoid to reencode type1 symbol fonts
224 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
225 nMappedChar = GetSymbolMapping (nChar);
226 else
227 nMappedChar = GetAnsiMapping (nChar);
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 if (maCharList.empty())
233 char_map_t aMap, aMapp;
235 maCharList.push_back (aMap);
236 maCharList.push_back (aMapp);
238 // if the last map is full, create a new one
239 if ((!nMappedChar) && (maCharList.back().size() == 255))
241 char_map_t aMap;
242 maCharList.push_back (aMap);
245 // insert a new glyph in the font subset
246 if (nMappedChar)
248 // always put iso1252 chars into the first map, map them on itself
249 char_map_t& aGlyphSet = maCharList.front();
250 AddNotdef (aGlyphSet);
252 aGlyphSet [nChar] = nMappedChar;
253 *nOutGlyphSetID = 1;
254 *nOutGlyphID = nMappedChar;
256 else
258 // other chars are just appended to the list
259 char_map_t& aGlyphSet = maCharList.back();
260 AddNotdef (aGlyphSet);
262 int nSize = aGlyphSet.size();
264 aGlyphSet [nChar] = nSize;
265 *nOutGlyphSetID = maCharList.size();
266 *nOutGlyphID = aGlyphSet [nChar];
269 return sal_True;
272 sal_Bool
273 GlyphSet::AddGlyphID (
274 sal_uInt32 nGlyph,
275 sal_Unicode nUnicode,
276 sal_uChar* nOutGlyphID,
277 sal_Int32* nOutGlyphSetID
280 sal_uChar nMappedChar;
282 // XXX important: avoid to reencode type1 symbol fonts
283 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
284 nMappedChar = GetSymbolMapping (nUnicode);
285 else
286 nMappedChar = GetAnsiMapping (nUnicode);
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 if (maGlyphList.empty())
292 glyph_map_t aMap, aMapp;
294 maGlyphList.push_back (aMap);
295 maGlyphList.push_back (aMapp);
297 // if the last map is full, create a new one
298 if ((!nMappedChar) && (maGlyphList.back().size() == 255))
300 glyph_map_t aMap;
301 maGlyphList.push_back (aMap);
304 // insert a new glyph in the font subset
305 if (nMappedChar)
307 // always put iso1252 chars into the first map, map them on itself
308 glyph_map_t& aGlyphSet = maGlyphList.front();
309 AddNotdef (aGlyphSet);
311 aGlyphSet [nGlyph] = nMappedChar;
312 *nOutGlyphSetID = 1;
313 *nOutGlyphID = nMappedChar;
315 else
317 // other chars are just appended to the list
318 glyph_map_t& aGlyphSet = maGlyphList.back();
319 AddNotdef (aGlyphSet);
321 int nSize = aGlyphSet.size();
323 aGlyphSet [nGlyph] = nSize;
324 *nOutGlyphSetID = maGlyphList.size();
325 *nOutGlyphID = aGlyphSet [nGlyph];
328 return sal_True;
331 OString
332 GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID)
334 if (meBaseType == fonttype::TrueType)
336 OStringBuffer aSetName( maBaseName.getLength() + 32 );
337 aSetName.append( maBaseName );
338 aSetName.append( "FID" );
339 aSetName.append( mnFontID );
340 aSetName.append( mbVertical ? "VCSet" : "HCSet" );
341 aSetName.append( nGlyphSetID );
342 return aSetName.makeStringAndClear();
344 else
345 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
347 return maBaseName;
351 OString
352 GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID)
354 if (meBaseType == fonttype::TrueType)
356 OStringBuffer aSetName( maBaseName.getLength() + 32 );
357 aSetName.append( maBaseName );
358 aSetName.append( "FID" );
359 aSetName.append( mnFontID );
360 aSetName.append( mbVertical ? "VGSet" : "HGSet" );
361 aSetName.append( nGlyphSetID );
362 return aSetName.makeStringAndClear();
364 else
365 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
367 return maBaseName;
371 sal_Int32
372 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
374 if (meBaseType == fonttype::TrueType)
375 return RTL_TEXTENCODING_DONTKNOW;
376 else
378 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
379 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
380 return RTL_TEXTENCODING_SYMBOL;
381 else
382 return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
383 : RTL_TEXTENCODING_USER_START + nGlyphSetID;
387 OString
388 GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc, const OString &rFontName)
390 if ( nEnc == RTL_TEXTENCODING_MS_1252
391 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
393 return OString("ISO1252Encoding");
395 else
396 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
398 return rFontName
399 + OString("Enc")
400 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
402 else
404 return OString();
408 OString
409 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
411 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
414 void
415 GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
417 // only for ps fonts
418 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
419 return;
421 sal_Char pEncodingVector [256];
422 sal_Int32 nSize = 0;
424 nSize += psp::appendStr ("(", pEncodingVector + nSize);
425 nSize += psp::appendStr (GetReencodedFontName(nGlyphSetID).getStr(),
426 pEncodingVector + nSize);
427 nSize += psp::appendStr (") cvn (", pEncodingVector + nSize);
428 nSize += psp::appendStr (maBaseName.getStr(),
429 pEncodingVector + nSize);
430 nSize += psp::appendStr (") cvn ", pEncodingVector + nSize);
431 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
432 pEncodingVector + nSize);
433 nSize += psp::appendStr (" psp_definefont\n",
434 pEncodingVector + nSize);
436 psp::WritePS (pOutFile, pEncodingVector);
439 OString
440 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
442 if ( nEnc == RTL_TEXTENCODING_MS_1252
443 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
445 return rFontName
446 + OString("-iso1252");
448 else
449 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
451 return rFontName
452 + OString("-enc")
453 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
455 else
457 return OString();
461 OString
462 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
464 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
467 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)
476 sal_uChar *pGlyphID = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
477 sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
478 std::set< sal_Int32 > aGlyphSet;
480 // convert unicode to font glyph id and font subset
481 for (int nChar = 0; nChar < nLen; nChar++)
483 if (bUseGlyphs)
484 GetGlyphID (pGlyphIds[nChar], pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
485 else
486 GetCharID (pUnicodes[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
487 aGlyphSet.insert (pGlyphSetID[nChar]);
490 // loop over all glyph sets to detect substrings that can be xshown together
491 // without changing the postscript font
492 sal_Int32 *pDeltaSubset = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
493 sal_uChar *pGlyphSubset = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
495 std::set< sal_Int32 >::iterator aSet;
496 for (aSet = aGlyphSet.begin(); aSet != aGlyphSet.end(); ++aSet)
498 Point aPoint = rPoint;
499 sal_Int32 nOffset = 0;
500 sal_Int32 nGlyphs = 0;
501 sal_Int32 nChar;
503 // get offset to first glyph
504 for (nChar = 0; (nChar < nLen) && (pGlyphSetID[nChar] != *aSet); nChar++)
506 nOffset = pDeltaArray [nChar];
509 // loop over all chars to extract those that share the current glyph set
510 for (nChar = 0; nChar < nLen; nChar++)
512 if (pGlyphSetID[nChar] == *aSet)
514 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 while ((nChar + 1) < nLen)
520 if (pGlyphSetID[nChar + 1] == *aSet)
521 break;
522 else
523 nChar += 1;
525 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
527 nGlyphs += 1;
531 // show the text using the PrinterGfx text api
532 aPoint.Move (nOffset, 0);
534 OString aGlyphSetName;
535 if (bUseGlyphs)
536 aGlyphSetName = GetGlyphSetName(*aSet);
537 else
538 aGlyphSetName = GetCharSetName(*aSet);
540 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(*aSet));
541 rGfx.PSMoveTo (aPoint);
542 rGfx.PSShowText (pGlyphSubset, nGlyphs, nGlyphs, nGlyphs > 1 ? pDeltaSubset : NULL);
546 void
547 GlyphSet::DrawText (PrinterGfx &rGfx, const Point& rPoint,
548 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
550 // dispatch to the impl method
551 if (pDeltaArray == NULL)
552 ImplDrawText (rGfx, rPoint, pStr, nLen);
553 else
554 ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
557 void
558 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
559 const sal_Unicode* pStr, sal_Int16 nLen)
561 rGfx.PSMoveTo (rPoint);
563 if( mbUseFontEncoding )
565 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
566 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
567 rGfx.PSSetFont( aPSName, mnBaseEncoding );
568 rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength() );
569 return;
572 int nChar;
573 sal_uChar *pGlyphID = (sal_uChar*)alloca (nLen * sizeof(sal_uChar));
574 sal_Int32 *pGlyphSetID = (sal_Int32*)alloca (nLen * sizeof(sal_Int32));
576 // convert unicode to glyph id and char set (font subset)
577 for (nChar = 0; nChar < nLen; nChar++)
578 GetCharID (pStr[nChar], pGlyphID + nChar, pGlyphSetID + nChar);
580 // loop over the string to draw subsequent pieces of chars
581 // with the same postscript font
582 for (nChar = 0; nChar < nLen; /* atend */)
584 sal_Int32 nGlyphSetID = pGlyphSetID [nChar];
585 sal_Int32 nGlyphs = 1;
586 for (int nNextChar = nChar + 1; nNextChar < nLen; nNextChar++)
588 if (pGlyphSetID[nNextChar] == nGlyphSetID)
589 nGlyphs++;
590 else
591 break;
594 // show the text using the PrinterGfx text api
595 OString aGlyphSetName(GetCharSetName(nGlyphSetID));
596 rGfx.PSSetFont (aGlyphSetName, GetGlyphSetEncoding(nGlyphSetID));
597 rGfx.PSShowText (pGlyphID + nChar, nGlyphs, nGlyphs);
599 nChar += nGlyphs;
603 void
604 GlyphSet::ImplDrawText (PrinterGfx &rGfx, const Point& rPoint,
605 const sal_Unicode* pStr, sal_Int16 nLen, const sal_Int32* pDeltaArray)
607 if( mbUseFontEncoding )
609 OString aPSName( OUStringToOString( rGfx.GetFontMgr().getPSName( mnFontID ), RTL_TEXTENCODING_ISO_8859_1 ) );
610 OString aBytes( OUStringToOString( OUString( pStr, nLen ), mnBaseEncoding ) );
611 rGfx.PSMoveTo( rPoint );
612 rGfx.PSSetFont( aPSName, mnBaseEncoding );
613 rGfx.PSShowText( (const unsigned char*)aBytes.getStr(), nLen, aBytes.getLength(), pDeltaArray );
614 return;
617 DrawGlyphs( rGfx, rPoint, NULL, pStr, nLen, pDeltaArray, sal_False);
620 sal_Bool
621 GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
623 // only for ps fonts
624 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
625 return sal_False;
626 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
627 return sal_False;
629 PrintFontManager &rMgr = rGfx.GetFontMgr();
631 // loop thru all the font subsets
632 sal_Int32 nGlyphSetID = 0;
633 char_list_t::iterator aGlyphSet;
634 for (aGlyphSet = maCharList.begin(); aGlyphSet != maCharList.end(); ++aGlyphSet)
636 ++nGlyphSetID;
638 if (nGlyphSetID == 1) // latin1 page uses global reencoding table
640 PSDefineReencodedFont (pOutFile, nGlyphSetID);
641 continue;
643 if ((*aGlyphSet).empty()) // empty set, doesn't need reencoding
645 continue;
648 // create reencoding table
650 sal_Char pEncodingVector [256];
651 sal_Int32 nSize = 0;
653 nSize += psp::appendStr ("/",
654 pEncodingVector + nSize);
655 nSize += psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID).getStr(),
656 pEncodingVector + nSize);
657 nSize += psp::appendStr (" [ ",
658 pEncodingVector + nSize);
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 ps_mapping_t aSortedGlyphSet;
665 char_map_t::const_iterator aUnsortedGlyph;
666 for (aUnsortedGlyph = (*aGlyphSet).begin();
667 aUnsortedGlyph != (*aGlyphSet).end();
668 ++aUnsortedGlyph)
670 aSortedGlyphSet.insert(ps_value_t((*aUnsortedGlyph).second,
671 (*aUnsortedGlyph).first));
674 ps_mapping_t::const_iterator aSortedGlyph;
675 // loop thru all the glyphs in the subset
676 for (aSortedGlyph = (aSortedGlyphSet).begin();
677 aSortedGlyph != (aSortedGlyphSet).end();
678 ++aSortedGlyph)
680 nSize += psp::appendStr ("/",
681 pEncodingVector + nSize);
683 std::list< OString > aName( rMgr.getAdobeNameFromUnicode((*aSortedGlyph).second) );
685 if( aName.begin() != aName.end() )
686 nSize += psp::appendStr ( aName.front().getStr(), pEncodingVector + nSize);
687 else
688 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
689 nSize += psp::appendStr (" ", pEncodingVector + nSize);
690 // flush line
691 if (nSize >= 70)
693 nSize += psp::appendStr ("\n", pEncodingVector + nSize);
694 psp::WritePS (pOutFile, pEncodingVector);
695 nSize = 0;
699 nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
700 psp::WritePS (pOutFile, pEncodingVector);
702 PSDefineReencodedFont (pOutFile, nGlyphSetID);
705 return sal_True;
708 struct EncEntry
710 sal_uChar aEnc;
711 long aGID;
713 EncEntry() : aEnc( 0 ), aGID( 0 ) {}
715 bool operator<( const EncEntry& rRight ) const
716 { return aEnc < rRight.aEnc; }
719 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*/ )
724 // match the font-subset to the printer capabilities
725 // TODO: allow CFF for capable printers
726 int nTargetMask = FontSubsetInfo::TYPE1_PFA | FontSubsetInfo::TYPE3_FONT;
727 if( bAllowType42 )
728 nTargetMask |= FontSubsetInfo::TYPE42_FONT;
730 std::vector< EncEntry > aSorted( nGlyphCount, EncEntry() );
731 for( int i = 0; i < nGlyphCount; i++ )
733 aSorted[i].aEnc = pEncoding[i];
734 aSorted[i].aGID = pRequestedGlyphs[i];
737 std::stable_sort( aSorted.begin(), aSorted.end() );
739 std::vector< sal_uChar > aEncoding( nGlyphCount );
740 std::vector< long > aRequestedGlyphs( nGlyphCount );
742 for( int i = 0; i < nGlyphCount; i++ )
744 aEncoding[i] = aSorted[i].aEnc;
745 aRequestedGlyphs[i] = aSorted[i].aGID;
748 FontSubsetInfo aInfo;
749 aInfo.LoadFont( pSrcFont );
751 aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
752 &aRequestedGlyphs[0], &aEncoding[0], nGlyphCount, NULL );
755 sal_Bool
756 GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
758 // only for truetype fonts
759 if (meBaseType != fonttype::TrueType)
760 return sal_False;
762 #if defined( UNX )
763 TrueTypeFont *pTTFont;
764 OString aTTFileName (rGfx.GetFontMgr().getFontFileSysPath(mnFontID));
765 int nFace = rGfx.GetFontMgr().getFontFaceNumber(mnFontID);
766 sal_Int32 nSuccess = OpenTTFontFile(aTTFileName.getStr(), nFace, &pTTFont);
767 if (nSuccess != SF_OK)
768 return sal_False;
769 FILE* pTmpFile = tmpfile();
770 if (pTmpFile == NULL)
771 return sal_False;
773 // array of unicode source characters
774 sal_Unicode pUChars[256];
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 const bool bAllowCID = false; // TODO: nPSLanguageLevel>=3
782 // loop thru all the font subsets
783 sal_Int32 nCharSetID;
784 char_list_t::iterator aCharSet;
785 for (aCharSet = maCharList.begin(), nCharSetID = 1;
786 aCharSet != maCharList.end();
787 ++aCharSet, nCharSetID++)
789 if ((*aCharSet).empty())
790 continue;
792 // loop thru all the chars in the subset
793 char_map_t::const_iterator aChar;
794 sal_Int32 n = 0;
795 for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); ++aChar)
797 pUChars [n] = (*aChar).first;
798 pEncoding [n] = (*aChar).second;
799 n++;
801 // create a mapping from the unicode chars to the char encoding in
802 // source TrueType font
803 MapString (pTTFont, pUChars, (*aCharSet).size(), pTTGlyphMapping, mbVertical);
805 // create the current subset
806 OString aCharSetName = GetCharSetName(nCharSetID);
807 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aCharSetName.getStr() );
808 CreatePSUploadableFont( pTTFont, pTmpFile, aCharSetName.getStr(), (*aCharSet).size(),
809 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
810 fprintf( pTmpFile, "%%%%EndResource\n" );
811 rSuppliedFonts.push_back( aCharSetName );
814 // loop thru all the font glyph subsets
815 sal_Int32 nGlyphSetID;
816 glyph_list_t::iterator aGlyphSet;
817 for (aGlyphSet = maGlyphList.begin(), nGlyphSetID = 1;
818 aGlyphSet != maGlyphList.end();
819 ++aGlyphSet, nGlyphSetID++)
821 if ((*aGlyphSet).empty())
822 continue;
824 // loop thru all the glyphs in the subset
825 glyph_map_t::const_iterator aGlyph;
826 sal_Int32 n = 0;
827 for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); ++aGlyph)
829 pTTGlyphMapping [n] = (*aGlyph).first;
830 pEncoding [n] = (*aGlyph).second;
831 n++;
834 // create the current subset
835 OString aGlyphSetName = GetGlyphSetName(nGlyphSetID);
836 fprintf( pTmpFile, "%%%%BeginResource: font %s\n", aGlyphSetName.getStr() );
837 CreatePSUploadableFont( pTTFont, pTmpFile, aGlyphSetName.getStr(), (*aGlyphSet).size(),
838 pTTGlyphMapping, pEncoding, bAllowType42, bAllowCID );
839 fprintf( pTmpFile, "%%%%EndResource\n" );
840 rSuppliedFonts.push_back( aGlyphSetName );
843 // copy the file into the page header
844 rewind(pTmpFile);
845 fflush(pTmpFile);
847 sal_uChar pBuffer[0x2000];
848 sal_uInt64 nIn;
849 sal_uInt64 nOut;
852 nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
853 rOutFile.write (pBuffer, nIn, nOut);
855 while ((nIn == nOut) && !feof(pTmpFile));
857 // cleanup
858 CloseTTFont (pTTFont);
859 fclose (pTmpFile);
861 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
869 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */