1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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>
47 GlyphSet::GlyphSet (sal_Int32 nFontID
, bool bVertical
)
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 ??? */
67 unsigned char* nOutGlyphID
,
68 sal_Int32
* nOutGlyphSetID
71 return LookupCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
)
72 || AddCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
);
76 GlyphSet::GetGlyphID (
79 unsigned char* nOutGlyphID
,
80 sal_Int32
* nOutGlyphSetID
83 return LookupGlyphID (nGlyph
, nOutGlyphID
, nOutGlyphSetID
)
84 || AddGlyphID (nGlyph
, nUnicode
, nOutGlyphID
, nOutGlyphSetID
);
88 GlyphSet::LookupCharID (
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
;
113 *nOutGlyphSetID
= -1;
119 GlyphSet::LookupGlyphID (
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
;
144 *nOutGlyphSetID
= -1;
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
);
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;
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
;
182 GlyphSet::AddNotdef (char_map_t
&rCharMap
)
184 if (rCharMap
.empty())
189 GlyphSet::AddNotdef (glyph_map_t
&rGlyphMap
)
191 if (rGlyphMap
.empty())
195 GlyphSet::AddCharID (
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
);
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))
222 maCharList
.push_back (aMap
);
225 // insert a new glyph in the font subset
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
;
234 *nOutGlyphID
= nMappedChar
;
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
];
253 GlyphSet::AddGlyphID (
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))
279 maGlyphList
.push_back (aMap
);
282 // insert a new glyph in the font subset
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
;
291 *nOutGlyphID
= nMappedChar
;
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
];
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();
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();
348 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID
)
350 if (meBaseType
== fonttype::TrueType
)
351 return RTL_TEXTENCODING_DONTKNOW
;
354 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
355 return RTL_TEXTENCODING_SYMBOL
;
357 return nGlyphSetID
== 1 ? RTL_TEXTENCODING_MS_1252
358 : RTL_TEXTENCODING_USER_START
+ nGlyphSetID
;
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");
371 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
375 + OString::number ((nEnc
- RTL_TEXTENCODING_USER_START
));
384 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID
)
386 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
390 GlyphSet::PSDefineReencodedFont (osl::File
* pOutFile
, sal_Int32 nGlyphSetID
)
393 if (meBaseType
!= fonttype::Type1
)
396 sal_Char pEncodingVector
[256];
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
);
415 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc
, const OString
&rFontName
)
417 if ( nEnc
== RTL_TEXTENCODING_MS_1252
418 || nEnc
== RTL_TEXTENCODING_ISO_8859_1
)
421 + OString("-iso1252");
424 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
428 + OString::number ((nEnc
- RTL_TEXTENCODING_USER_START
));
437 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID
)
439 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
442 void GlyphSet::DrawGlyphs(
445 const sal_GlyphId
* pGlyphIds
,
446 const sal_Unicode
* pUnicodes
,
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
++)
459 GetGlyphID (pGlyphIds
[nChar
], pUnicodes
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
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;
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
)
500 pDeltaSubset
[nGlyphs
] = pDeltaArray
[nChar
] - nOffset
;
506 // show the text using the PrinterGfx text api
507 aPoint
.Move (nOffset
, 0);
509 OString aGlyphSetName
;
511 aGlyphSetName
= GetGlyphSetName(*aSet
);
513 aGlyphSetName
= GetCharSetName(*aSet
);
515 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(*aSet
));
516 rGfx
.PSMoveTo (aPoint
);
517 rGfx
.PSShowText (pGlyphSubset
, nGlyphs
, nGlyphs
, nGlyphs
> 1 ? pDeltaSubset
: NULL
);
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
);
529 ImplDrawText (rGfx
, rPoint
, pStr
, nLen
, pDeltaArray
);
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() );
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
)
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
);
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
);
592 DrawGlyphs( rGfx
, rPoint
, NULL
, pStr
, nLen
, pDeltaArray
, false);
596 GlyphSet::PSUploadEncoding(osl::File
* pOutFile
, PrinterGfx
&rGfx
)
599 if (meBaseType
!= fonttype::Type1
)
601 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
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
)
613 if (nGlyphSetID
== 1) // latin1 page uses global reencoding table
615 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
618 if ((*aGlyphSet
).empty()) // empty set, doesn't need reencoding
623 // create reencoding table
625 sal_Char pEncodingVector
[256];
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();
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();
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
);
663 nSize
+= psp::appendStr (".notdef", pEncodingVector
+ nSize
);
664 nSize
+= psp::appendStr (" ", pEncodingVector
+ nSize
);
668 psp::appendStr ("\n", pEncodingVector
+ nSize
);
669 psp::WritePS (pOutFile
, pEncodingVector
);
674 nSize
+= psp::appendStr ("] def\n", pEncodingVector
+ nSize
);
675 psp::WritePS (pOutFile
, pEncodingVector
);
677 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
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
;
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
);
731 GlyphSet::PSUploadFont (osl::File
& rOutFile
, PrinterGfx
&rGfx
, bool bAllowType42
, std::list
< OString
>& rSuppliedFonts
)
733 // only for truetype fonts
734 if (meBaseType
!= fonttype::TrueType
)
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
)
745 utl::TempFile aTmpFile
;
746 aTmpFile
.EnableKillingFile();
747 FILE* pTmpFile
= fopen(OUStringToOString(aTmpFile
.GetFileName(), osl_getThreadTextEncoding()).getStr(), "w+b");
748 if (pTmpFile
== NULL
)
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())
770 // loop through all the chars in the subset
771 char_map_t::const_iterator aChar
;
773 for (aChar
= (*aCharSet
).begin(); aChar
!= (*aCharSet
).end(); ++aChar
)
775 pUChars
[n
] = (*aChar
).first
;
776 pEncoding
[n
] = (*aChar
).second
;
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())
802 // loop through all the glyphs in the subset
803 glyph_map_t::const_iterator aGlyph
;
805 for (aGlyph
= (*aGlyphSet
).begin(); aGlyph
!= (*aGlyphSet
).end(); ++aGlyph
)
807 pTTGlyphMapping
[n
] = (*aGlyph
).first
;
808 pEncoding
[n
] = (*aGlyph
).second
;
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
825 unsigned char pBuffer
[0x2000];
830 nIn
= fread(pBuffer
, 1, sizeof(pBuffer
), pTmpFile
);
831 rOutFile
.write (pBuffer
, nIn
, nOut
);
833 while ((nIn
== nOut
) && !feof(pTmpFile
));
836 CloseTTFont (pTTFont
);
841 (void)rOutFile
; (void)rGfx
; (void)bAllowType42
; (void)rSuppliedFonts
;
842 # warning FIXME: Missing OpenTTFontFile outside of Unix ...
847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */