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 .
21 #include "glyphset.hxx"
22 #include "psputil.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"
44 using ::rtl::OUString
;
46 using ::rtl::OStringBuffer
;
47 using ::rtl::OUStringToOString
;
49 GlyphSet::GlyphSet (sal_Int32 nFontID
, sal_Bool bVertical
)
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 ??? */
67 GlyphSet::GetFontID ()
73 GlyphSet::GetFontType ()
79 GlyphSet::IsVertical ()
87 sal_uChar
* nOutGlyphID
,
88 sal_Int32
* nOutGlyphSetID
91 return LookupCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
)
92 || AddCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
);
96 GlyphSet::GetGlyphID (
99 sal_uChar
* nOutGlyphID
,
100 sal_Int32
* nOutGlyphSetID
103 return LookupGlyphID (nGlyph
, nOutGlyphID
, nOutGlyphSetID
)
104 || AddGlyphID (nGlyph
, nUnicode
, nOutGlyphID
, nOutGlyphSetID
);
108 GlyphSet::LookupCharID (
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
;
133 *nOutGlyphSetID
= -1;
139 GlyphSet::LookupGlyphID (
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
;
164 *nOutGlyphSetID
= -1;
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
);
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;
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
;
202 GlyphSet::AddNotdef (char_map_t
&rCharMap
)
204 if (rCharMap
.empty())
209 GlyphSet::AddNotdef (glyph_map_t
&rGlyphMap
)
211 if (rGlyphMap
.empty())
215 GlyphSet::AddCharID (
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
);
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))
242 maCharList
.push_back (aMap
);
245 // insert a new glyph in the font subset
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
;
254 *nOutGlyphID
= nMappedChar
;
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
];
273 GlyphSet::AddGlyphID (
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
);
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))
301 maGlyphList
.push_back (aMap
);
304 // insert a new glyph in the font subset
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
;
313 *nOutGlyphID
= nMappedChar
;
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
];
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();
345 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
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();
365 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
372 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID
)
374 if (meBaseType
== fonttype::TrueType
)
375 return RTL_TEXTENCODING_DONTKNOW
;
378 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
379 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
380 return RTL_TEXTENCODING_SYMBOL
;
382 return nGlyphSetID
== 1 ? RTL_TEXTENCODING_MS_1252
383 : RTL_TEXTENCODING_USER_START
+ nGlyphSetID
;
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");
396 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
400 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
409 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID
)
411 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
415 GlyphSet::PSDefineReencodedFont (osl::File
* pOutFile
, sal_Int32 nGlyphSetID
)
418 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
421 sal_Char pEncodingVector
[256];
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
);
440 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc
, const OString
&rFontName
)
442 if ( nEnc
== RTL_TEXTENCODING_MS_1252
443 || nEnc
== RTL_TEXTENCODING_ISO_8859_1
)
446 + OString("-iso1252");
449 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
453 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
462 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID
)
464 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
467 void GlyphSet::DrawGlyphs(
470 const sal_uInt32
* pGlyphIds
,
471 const sal_Unicode
* pUnicodes
,
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
++)
484 GetGlyphID (pGlyphIds
[nChar
], pUnicodes
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
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;
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
)
525 pDeltaSubset
[nGlyphs
] = pDeltaArray
[nChar
] - nOffset
;
531 // show the text using the PrinterGfx text api
532 aPoint
.Move (nOffset
, 0);
534 OString aGlyphSetName
;
536 aGlyphSetName
= GetGlyphSetName(*aSet
);
538 aGlyphSetName
= GetCharSetName(*aSet
);
540 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(*aSet
));
541 rGfx
.PSMoveTo (aPoint
);
542 rGfx
.PSShowText (pGlyphSubset
, nGlyphs
, nGlyphs
, nGlyphs
> 1 ? pDeltaSubset
: NULL
);
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
);
554 ImplDrawText (rGfx
, rPoint
, pStr
, nLen
, pDeltaArray
);
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() );
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
)
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
);
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
);
617 DrawGlyphs( rGfx
, rPoint
, NULL
, pStr
, nLen
, pDeltaArray
, sal_False
);
621 GlyphSet::PSUploadEncoding(osl::File
* pOutFile
, PrinterGfx
&rGfx
)
624 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
626 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
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
)
638 if (nGlyphSetID
== 1) // latin1 page uses global reencoding table
640 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
643 if ((*aGlyphSet
).empty()) // empty set, doesn't need reencoding
648 // create reencoding table
650 sal_Char pEncodingVector
[256];
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();
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();
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
);
688 nSize
+= psp::appendStr (".notdef", pEncodingVector
+ nSize
);
689 nSize
+= psp::appendStr (" ", pEncodingVector
+ nSize
);
693 nSize
+= psp::appendStr ("\n", pEncodingVector
+ nSize
);
694 psp::WritePS (pOutFile
, pEncodingVector
);
699 nSize
+= psp::appendStr ("] def\n", pEncodingVector
+ nSize
);
700 psp::WritePS (pOutFile
, pEncodingVector
);
702 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
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
;
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
);
756 GlyphSet::PSUploadFont (osl::File
& rOutFile
, PrinterGfx
&rGfx
, bool bAllowType42
, std::list
< OString
>& rSuppliedFonts
)
758 // only for truetype fonts
759 if (meBaseType
!= fonttype::TrueType
)
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
)
769 FILE* pTmpFile
= tmpfile();
770 if (pTmpFile
== NULL
)
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())
792 // loop thru all the chars in the subset
793 char_map_t::const_iterator aChar
;
795 for (aChar
= (*aCharSet
).begin(); aChar
!= (*aCharSet
).end(); ++aChar
)
797 pUChars
[n
] = (*aChar
).first
;
798 pEncoding
[n
] = (*aChar
).second
;
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())
824 // loop thru all the glyphs in the subset
825 glyph_map_t::const_iterator aGlyph
;
827 for (aGlyph
= (*aGlyphSet
).begin(); aGlyph
!= (*aGlyphSet
).end(); ++aGlyph
)
829 pTTGlyphMapping
[n
] = (*aGlyph
).first
;
830 pEncoding
[n
] = (*aGlyph
).second
;
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
847 sal_uChar pBuffer
[0x2000];
852 nIn
= fread(pBuffer
, 1, sizeof(pBuffer
), pTmpFile
);
853 rOutFile
.write (pBuffer
, nIn
, nOut
);
855 while ((nIn
== nOut
) && !feof(pTmpFile
));
858 CloseTTFont (pTTFont
);
863 (void)rOutFile
; (void)rGfx
; (void)bAllowType42
; (void)rSuppliedFonts
;
864 # warning FIXME: Missing OpenTTFontFile outside of Unix ...
869 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */