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 <tools/gen.hxx>
32 #include "osl/thread.h"
34 #include "sal/alloca.h"
36 #include "rtl/ustring.hxx"
37 #include "rtl/strbuf.hxx"
47 GlyphSet::GlyphSet (sal_Int32 nFontID
, sal_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 ??? */
65 GlyphSet::GetFontID ()
71 GlyphSet::GetFontType ()
77 GlyphSet::IsVertical ()
85 sal_uChar
* nOutGlyphID
,
86 sal_Int32
* nOutGlyphSetID
89 return LookupCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
)
90 || AddCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
);
94 GlyphSet::GetGlyphID (
97 sal_uChar
* nOutGlyphID
,
98 sal_Int32
* nOutGlyphSetID
101 return LookupGlyphID (nGlyph
, nOutGlyphID
, nOutGlyphSetID
)
102 || AddGlyphID (nGlyph
, nUnicode
, nOutGlyphID
, nOutGlyphSetID
);
106 GlyphSet::LookupCharID (
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
;
131 *nOutGlyphSetID
= -1;
137 GlyphSet::LookupGlyphID (
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
;
162 *nOutGlyphSetID
= -1;
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
);
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;
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
;
200 GlyphSet::AddNotdef (char_map_t
&rCharMap
)
202 if (rCharMap
.empty())
207 GlyphSet::AddNotdef (glyph_map_t
&rGlyphMap
)
209 if (rGlyphMap
.empty())
213 GlyphSet::AddCharID (
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
);
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))
240 maCharList
.push_back (aMap
);
243 // insert a new glyph in the font subset
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
;
252 *nOutGlyphID
= nMappedChar
;
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
];
271 GlyphSet::AddGlyphID (
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))
297 maGlyphList
.push_back (aMap
);
300 // insert a new glyph in the font subset
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
;
309 *nOutGlyphID
= nMappedChar
;
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
];
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();
341 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
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();
361 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
368 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID
)
370 if (meBaseType
== fonttype::TrueType
)
371 return RTL_TEXTENCODING_DONTKNOW
;
374 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
375 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
376 return RTL_TEXTENCODING_SYMBOL
;
378 return nGlyphSetID
== 1 ? RTL_TEXTENCODING_MS_1252
379 : RTL_TEXTENCODING_USER_START
+ nGlyphSetID
;
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");
392 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
396 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
405 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID
)
407 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
411 GlyphSet::PSDefineReencodedFont (osl::File
* pOutFile
, sal_Int32 nGlyphSetID
)
414 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
417 sal_Char pEncodingVector
[256];
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
);
436 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc
, const OString
&rFontName
)
438 if ( nEnc
== RTL_TEXTENCODING_MS_1252
439 || nEnc
== RTL_TEXTENCODING_ISO_8859_1
)
442 + OString("-iso1252");
445 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
449 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
458 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID
)
460 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
463 void GlyphSet::DrawGlyphs(
466 const sal_uInt32
* pGlyphIds
,
467 const sal_Unicode
* pUnicodes
,
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
++)
480 GetGlyphID (pGlyphIds
[nChar
], pUnicodes
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
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;
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
)
521 pDeltaSubset
[nGlyphs
] = pDeltaArray
[nChar
] - nOffset
;
527 // show the text using the PrinterGfx text api
528 aPoint
.Move (nOffset
, 0);
530 OString aGlyphSetName
;
532 aGlyphSetName
= GetGlyphSetName(*aSet
);
534 aGlyphSetName
= GetCharSetName(*aSet
);
536 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(*aSet
));
537 rGfx
.PSMoveTo (aPoint
);
538 rGfx
.PSShowText (pGlyphSubset
, nGlyphs
, nGlyphs
, nGlyphs
> 1 ? pDeltaSubset
: NULL
);
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
);
550 ImplDrawText (rGfx
, rPoint
, pStr
, nLen
, pDeltaArray
);
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() );
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
)
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
);
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
);
613 DrawGlyphs( rGfx
, rPoint
, NULL
, pStr
, nLen
, pDeltaArray
, sal_False
);
617 GlyphSet::PSUploadEncoding(osl::File
* pOutFile
, PrinterGfx
&rGfx
)
620 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
622 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
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
)
634 if (nGlyphSetID
== 1) // latin1 page uses global reencoding table
636 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
639 if ((*aGlyphSet
).empty()) // empty set, doesn't need reencoding
644 // create reencoding table
646 sal_Char pEncodingVector
[256];
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();
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();
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
);
684 nSize
+= psp::appendStr (".notdef", pEncodingVector
+ nSize
);
685 nSize
+= psp::appendStr (" ", pEncodingVector
+ nSize
);
689 nSize
+= psp::appendStr ("\n", pEncodingVector
+ nSize
);
690 psp::WritePS (pOutFile
, pEncodingVector
);
695 nSize
+= psp::appendStr ("] def\n", pEncodingVector
+ nSize
);
696 psp::WritePS (pOutFile
, pEncodingVector
);
698 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
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
;
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
);
752 GlyphSet::PSUploadFont (osl::File
& rOutFile
, PrinterGfx
&rGfx
, bool bAllowType42
, std::list
< OString
>& rSuppliedFonts
)
754 // only for truetype fonts
755 if (meBaseType
!= fonttype::TrueType
)
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
)
765 FILE* pTmpFile
= tmpfile();
766 if (pTmpFile
== NULL
)
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())
788 // loop thru all the chars in the subset
789 char_map_t::const_iterator aChar
;
791 for (aChar
= (*aCharSet
).begin(); aChar
!= (*aCharSet
).end(); ++aChar
)
793 pUChars
[n
] = (*aChar
).first
;
794 pEncoding
[n
] = (*aChar
).second
;
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())
820 // loop thru all the glyphs in the subset
821 glyph_map_t::const_iterator aGlyph
;
823 for (aGlyph
= (*aGlyphSet
).begin(); aGlyph
!= (*aGlyphSet
).end(); ++aGlyph
)
825 pTTGlyphMapping
[n
] = (*aGlyph
).first
;
826 pEncoding
[n
] = (*aGlyph
).second
;
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
843 sal_uChar pBuffer
[0x2000];
848 nIn
= fread(pBuffer
, 1, sizeof(pBuffer
), pTmpFile
);
849 rOutFile
.write (pBuffer
, nIn
, nOut
);
851 while ((nIn
== nOut
) && !feof(pTmpFile
));
854 CloseTTFont (pTTFont
);
859 (void)rOutFile
; (void)rGfx
; (void)bAllowType42
; (void)rSuppliedFonts
;
860 # warning FIXME: Missing OpenTTFontFile outside of Unix ...
865 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */