1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include "glyphset.hxx"
32 #include "psputil.hxx"
36 #include "vcl/printergfx.hxx"
37 #include "vcl/fontmanager.hxx"
38 #include "vcl/fontsubset.hxx"
40 #include "osl/thread.h"
42 #include "sal/alloca.h"
44 #include "rtl/ustring.hxx"
45 #include "rtl/strbuf.hxx"
57 mbUseFontEncoding (false)
60 GlyphSet::GlyphSet (sal_Int32 nFontID
, sal_Bool bVertical
)
62 mbVertical (bVertical
)
64 PrintFontManager
&rMgr
= PrintFontManager::get();
65 meBaseType
= rMgr
.getFontType (mnFontID
);
66 maBaseName
= OUStringToOString (rMgr
.getPSName(mnFontID
),
67 RTL_TEXTENCODING_ASCII_US
);
68 mnBaseEncoding
= rMgr
.getFontEncoding(mnFontID
);
69 mbUseFontEncoding
= rMgr
.getUseOnlyFontEncoding(mnFontID
);
72 GlyphSet::~GlyphSet ()
74 /* FIXME delete the glyphlist ??? */
78 GlyphSet::GetFontID ()
84 GlyphSet::GetFontType ()
90 GlyphSet::IsVertical ()
96 GlyphSet::SetFont (sal_Int32 nFontID
, sal_Bool bVertical
)
102 mbVertical
= bVertical
;
104 PrintFontManager
&rMgr
= PrintFontManager::get();
105 meBaseType
= rMgr
.getFontType (mnFontID
);
106 maBaseName
= OUStringToOString (rMgr
.getPSName(mnFontID
),
107 RTL_TEXTENCODING_ASCII_US
);
108 mnBaseEncoding
= rMgr
.getFontEncoding(mnFontID
);
109 mbUseFontEncoding
= rMgr
.getUseOnlyFontEncoding(mnFontID
);
115 GlyphSet::GetCharID (
117 sal_uChar
* nOutGlyphID
,
118 sal_Int32
* nOutGlyphSetID
121 return LookupCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
)
122 || AddCharID (nChar
, nOutGlyphID
, nOutGlyphSetID
);
126 GlyphSet::GetGlyphID (
128 sal_Unicode nUnicode
,
129 sal_uChar
* nOutGlyphID
,
130 sal_Int32
* nOutGlyphSetID
133 return LookupGlyphID (nGlyph
, nOutGlyphID
, nOutGlyphSetID
)
134 || AddGlyphID (nGlyph
, nUnicode
, nOutGlyphID
, nOutGlyphSetID
);
138 GlyphSet::LookupCharID (
140 sal_uChar
* nOutGlyphID
,
141 sal_Int32
* nOutGlyphSetID
144 char_list_t::iterator aGlyphSet
;
145 sal_Int32 nGlyphSetID
;
147 // loop thru all the font subsets
148 for (aGlyphSet
= maCharList
.begin(), nGlyphSetID
= 1;
149 aGlyphSet
!= maCharList
.end();
150 ++aGlyphSet
, nGlyphSetID
++)
152 // check every subset if it contains the queried unicode char
153 char_map_t::const_iterator aGlyph
= (*aGlyphSet
).find (nChar
);
154 if (aGlyph
!= (*aGlyphSet
).end())
156 // success: found the unicode char, return the glyphid and the glyphsetid
157 *nOutGlyphSetID
= nGlyphSetID
;
158 *nOutGlyphID
= (*aGlyph
).second
;
163 *nOutGlyphSetID
= -1;
169 GlyphSet::LookupGlyphID (
171 sal_uChar
* nOutGlyphID
,
172 sal_Int32
* nOutGlyphSetID
175 glyph_list_t::iterator aGlyphSet
;
176 sal_Int32 nGlyphSetID
;
178 // loop thru all the font subsets
179 for (aGlyphSet
= maGlyphList
.begin(), nGlyphSetID
= 1;
180 aGlyphSet
!= maGlyphList
.end();
181 ++aGlyphSet
, nGlyphSetID
++)
183 // check every subset if it contains the queried unicode char
184 glyph_map_t::const_iterator aGlyph
= (*aGlyphSet
).find (nGlyph
);
185 if (aGlyph
!= (*aGlyphSet
).end())
187 // success: found the glyph id, return the mapped glyphid and the glyphsetid
188 *nOutGlyphSetID
= nGlyphSetID
;
189 *nOutGlyphID
= (*aGlyph
).second
;
194 *nOutGlyphSetID
= -1;
200 GlyphSet::GetAnsiMapping (sal_Unicode nUnicodeChar
)
202 static rtl_UnicodeToTextConverter aConverter
=
203 rtl_createUnicodeToTextConverter(RTL_TEXTENCODING_MS_1252
);
204 static rtl_UnicodeToTextContext aContext
=
205 rtl_createUnicodeToTextContext( aConverter
);
210 const sal_uInt32 nCvtFlags
= RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
211 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
;
213 sal_Size nSize
= rtl_convertUnicodeToText( aConverter
, aContext
,
214 &nUnicodeChar
, 1, &nAnsiChar
, 1,
215 nCvtFlags
, &nCvtInfo
, &nCvtChars
);
217 return nSize
== 1 ? (sal_uChar
)nAnsiChar
: (sal_uChar
)0;
221 GlyphSet::GetSymbolMapping (sal_Unicode nUnicodeChar
)
223 if (0x0000 < nUnicodeChar
&& nUnicodeChar
< 0x0100)
224 return (sal_uChar
)nUnicodeChar
;
225 if (0xf000 < nUnicodeChar
&& nUnicodeChar
< 0xf100)
226 return (sal_uChar
)nUnicodeChar
;
232 GlyphSet::AddNotdef (char_map_t
&rCharMap
)
234 if (rCharMap
.size() == 0)
239 GlyphSet::AddNotdef (glyph_map_t
&rGlyphMap
)
241 if (rGlyphMap
.size() == 0)
245 GlyphSet::AddCharID (
247 sal_uChar
* nOutGlyphID
,
248 sal_Int32
* nOutGlyphSetID
251 sal_uChar nMappedChar
;
253 // XXX important: avoid to reencode type1 symbol fonts
254 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
255 nMappedChar
= GetSymbolMapping (nChar
);
257 nMappedChar
= GetAnsiMapping (nChar
);
259 // create an empty glyphmap that is reserved for iso1252 encoded glyphs
260 // (or -- unencoded -- symbol glyphs) and a second map that takes any other
261 if (maCharList
.empty())
263 char_map_t aMap
, aMapp
;
265 maCharList
.push_back (aMap
);
266 maCharList
.push_back (aMapp
);
268 // if the last map is full, create a new one
269 if ((!nMappedChar
) && (maCharList
.back().size() == 255))
272 maCharList
.push_back (aMap
);
275 // insert a new glyph in the font subset
278 // always put iso1252 chars into the first map, map them on itself
279 char_map_t
& aGlyphSet
= maCharList
.front();
280 AddNotdef (aGlyphSet
);
282 aGlyphSet
[nChar
] = nMappedChar
;
284 *nOutGlyphID
= nMappedChar
;
288 // other chars are just appended to the list
289 char_map_t
& aGlyphSet
= maCharList
.back();
290 AddNotdef (aGlyphSet
);
292 int nSize
= aGlyphSet
.size();
294 aGlyphSet
[nChar
] = nSize
;
295 *nOutGlyphSetID
= maCharList
.size();
296 *nOutGlyphID
= aGlyphSet
[nChar
];
303 GlyphSet::AddGlyphID (
305 sal_Unicode nUnicode
,
306 sal_uChar
* nOutGlyphID
,
307 sal_Int32
* nOutGlyphSetID
310 sal_uChar nMappedChar
;
312 // XXX important: avoid to reencode type1 symbol fonts
313 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
314 nMappedChar
= GetSymbolMapping (nUnicode
);
316 nMappedChar
= GetAnsiMapping (nUnicode
);
318 // create an empty glyphmap that is reserved for iso1252 encoded glyphs
319 // (or -- unencoded -- symbol glyphs) and a second map that takes any other
320 if (maGlyphList
.empty())
322 glyph_map_t aMap
, aMapp
;
324 maGlyphList
.push_back (aMap
);
325 maGlyphList
.push_back (aMapp
);
327 // if the last map is full, create a new one
328 if ((!nMappedChar
) && (maGlyphList
.back().size() == 255))
331 maGlyphList
.push_back (aMap
);
334 // insert a new glyph in the font subset
337 // always put iso1252 chars into the first map, map them on itself
338 glyph_map_t
& aGlyphSet
= maGlyphList
.front();
339 AddNotdef (aGlyphSet
);
341 aGlyphSet
[nGlyph
] = nMappedChar
;
343 *nOutGlyphID
= nMappedChar
;
347 // other chars are just appended to the list
348 glyph_map_t
& aGlyphSet
= maGlyphList
.back();
349 AddNotdef (aGlyphSet
);
351 int nSize
= aGlyphSet
.size();
353 aGlyphSet
[nGlyph
] = nSize
;
354 *nOutGlyphSetID
= maGlyphList
.size();
355 *nOutGlyphID
= aGlyphSet
[nGlyph
];
362 GlyphSet::GetCharSetName (sal_Int32 nGlyphSetID
)
364 if (meBaseType
== fonttype::TrueType
)
366 OStringBuffer
aSetName( maBaseName
.getLength() + 32 );
367 aSetName
.append( maBaseName
);
368 aSetName
.append( "FID" );
369 aSetName
.append( mnFontID
);
370 aSetName
.append( mbVertical
? "VCSet" : "HCSet" );
371 aSetName
.append( nGlyphSetID
);
372 return aSetName
.makeStringAndClear();
375 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
382 GlyphSet::GetGlyphSetName (sal_Int32 nGlyphSetID
)
384 if (meBaseType
== fonttype::TrueType
)
386 OStringBuffer
aSetName( maBaseName
.getLength() + 32 );
387 aSetName
.append( maBaseName
);
388 aSetName
.append( "FID" );
389 aSetName
.append( mnFontID
);
390 aSetName
.append( mbVertical
? "VGSet" : "HGSet" );
391 aSetName
.append( nGlyphSetID
);
392 return aSetName
.makeStringAndClear();
395 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
402 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID
)
404 if (meBaseType
== fonttype::TrueType
)
405 return RTL_TEXTENCODING_DONTKNOW
;
408 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
409 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
410 return RTL_TEXTENCODING_SYMBOL
;
412 return nGlyphSetID
== 1 ? RTL_TEXTENCODING_MS_1252
413 : RTL_TEXTENCODING_USER_START
+ nGlyphSetID
;
418 GlyphSet::GetGlyphSetEncodingName (rtl_TextEncoding nEnc
, const OString
&rFontName
)
420 if ( nEnc
== RTL_TEXTENCODING_MS_1252
421 || nEnc
== RTL_TEXTENCODING_ISO_8859_1
)
423 return OString("ISO1252Encoding");
426 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
430 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
439 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID
)
441 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
445 GlyphSet::PSDefineReencodedFont (osl::File
* pOutFile
, sal_Int32 nGlyphSetID
)
448 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
451 sal_Char pEncodingVector
[256];
454 nSize
+= psp::appendStr ("(", pEncodingVector
+ nSize
);
455 nSize
+= psp::appendStr (GetReencodedFontName(nGlyphSetID
),
456 pEncodingVector
+ nSize
);
457 nSize
+= psp::appendStr (") cvn (", pEncodingVector
+ nSize
);
458 nSize
+= psp::appendStr (maBaseName
.getStr(),
459 pEncodingVector
+ nSize
);
460 nSize
+= psp::appendStr (") cvn ", pEncodingVector
+ nSize
);
461 nSize
+= psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID
),
462 pEncodingVector
+ nSize
);
463 nSize
+= psp::appendStr (" psp_definefont\n",
464 pEncodingVector
+ nSize
);
466 psp::WritePS (pOutFile
, pEncodingVector
);
470 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc
, const OString
&rFontName
)
472 if ( nEnc
== RTL_TEXTENCODING_MS_1252
473 || nEnc
== RTL_TEXTENCODING_ISO_8859_1
)
476 + OString("-iso1252");
479 if (nEnc
>= RTL_TEXTENCODING_USER_START
&& nEnc
<= RTL_TEXTENCODING_USER_END
)
483 + OString::valueOf ((sal_Int32
)(nEnc
- RTL_TEXTENCODING_USER_START
));
492 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID
)
494 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID
), maBaseName
);
497 void GlyphSet::DrawGlyphs(
500 const sal_uInt32
* pGlyphIds
,
501 const sal_Unicode
* pUnicodes
,
503 const sal_Int32
* pDeltaArray
)
505 sal_uChar
*pGlyphID
= (sal_uChar
*)alloca (nLen
* sizeof(sal_uChar
));
506 sal_Int32
*pGlyphSetID
= (sal_Int32
*)alloca (nLen
* sizeof(sal_Int32
));
507 std::set
< sal_Int32
> aGlyphSet
;
509 // convert unicode to font glyph id and font subset
510 for (int nChar
= 0; nChar
< nLen
; nChar
++)
512 GetGlyphID (pGlyphIds
[nChar
], pUnicodes
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
513 aGlyphSet
.insert (pGlyphSetID
[nChar
]);
516 // loop over all glyph sets to detect substrings that can be xshown together
517 // without changing the postscript font
518 sal_Int32
*pDeltaSubset
= (sal_Int32
*)alloca (nLen
* sizeof(sal_Int32
));
519 sal_uChar
*pGlyphSubset
= (sal_uChar
*)alloca (nLen
* sizeof(sal_uChar
));
521 std::set
< sal_Int32
>::iterator aSet
;
522 for (aSet
= aGlyphSet
.begin(); aSet
!= aGlyphSet
.end(); ++aSet
)
524 Point aPoint
= rPoint
;
525 sal_Int32 nOffset
= 0;
526 sal_Int32 nGlyphs
= 0;
529 // get offset to first glyph
530 for (nChar
= 0; (nChar
< nLen
) && (pGlyphSetID
[nChar
] != *aSet
); nChar
++)
532 nOffset
= pDeltaArray
[nChar
];
535 // loop over all chars to extract those that share the current glyph set
536 for (nChar
= 0; nChar
< nLen
; nChar
++)
538 if (pGlyphSetID
[nChar
] == *aSet
)
540 pGlyphSubset
[nGlyphs
] = pGlyphID
[nChar
];
541 // the offset to the next glyph is determined by the glyph in
542 // front of the next glyph with the same glyphset id
543 // most often, this will be the current glyph
544 while ((nChar
+ 1) < nLen
)
546 if (pGlyphSetID
[nChar
+ 1] == *aSet
)
551 pDeltaSubset
[nGlyphs
] = pDeltaArray
[nChar
] - nOffset
;
557 // show the text using the PrinterGfx text api
558 aPoint
.Move (nOffset
, 0);
560 OString
aGlyphSetName(GetGlyphSetName(*aSet
));
561 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(*aSet
));
562 rGfx
.PSMoveTo (aPoint
);
563 rGfx
.PSShowText (pGlyphSubset
, nGlyphs
, nGlyphs
, nGlyphs
> 1 ? pDeltaSubset
: NULL
);
568 GlyphSet::DrawText (PrinterGfx
&rGfx
, const Point
& rPoint
,
569 const sal_Unicode
* pStr
, sal_Int16 nLen
, const sal_Int32
* pDeltaArray
)
571 // dispatch to the impl method
572 if (pDeltaArray
== NULL
)
573 ImplDrawText (rGfx
, rPoint
, pStr
, nLen
);
575 ImplDrawText (rGfx
, rPoint
, pStr
, nLen
, pDeltaArray
);
579 GlyphSet::ImplDrawText (PrinterGfx
&rGfx
, const Point
& rPoint
,
580 const sal_Unicode
* pStr
, sal_Int16 nLen
)
582 rGfx
.PSMoveTo (rPoint
);
584 if( mbUseFontEncoding
)
586 OString
aPSName( OUStringToOString( rGfx
.GetFontMgr().getPSName( mnFontID
), RTL_TEXTENCODING_ISO_8859_1
) );
587 OString
aBytes( OUStringToOString( OUString( pStr
, nLen
), mnBaseEncoding
) );
588 rGfx
.PSSetFont( aPSName
, mnBaseEncoding
);
589 rGfx
.PSShowText( (const unsigned char*)aBytes
.getStr(), nLen
, aBytes
.getLength() );
594 sal_uChar
*pGlyphID
= (sal_uChar
*)alloca (nLen
* sizeof(sal_uChar
));
595 sal_Int32
*pGlyphSetID
= (sal_Int32
*)alloca (nLen
* sizeof(sal_Int32
));
597 // convert unicode to glyph id and char set (font subset)
598 for (nChar
= 0; nChar
< nLen
; nChar
++)
599 GetCharID (pStr
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
601 // loop over the string to draw subsequent pieces of chars
602 // with the same postscript font
603 for (nChar
= 0; nChar
< nLen
; /* atend */)
605 sal_Int32 nGlyphSetID
= pGlyphSetID
[nChar
];
606 sal_Int32 nGlyphs
= 1;
607 for (int nNextChar
= nChar
+ 1; nNextChar
< nLen
; nNextChar
++)
609 if (pGlyphSetID
[nNextChar
] == nGlyphSetID
)
615 // show the text using the PrinterGfx text api
616 OString
aGlyphSetName(GetCharSetName(nGlyphSetID
));
617 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(nGlyphSetID
));
618 rGfx
.PSShowText (pGlyphID
+ nChar
, nGlyphs
, nGlyphs
);
625 GlyphSet::ImplDrawText (PrinterGfx
&rGfx
, const Point
& rPoint
,
626 const sal_Unicode
* pStr
, sal_Int16 nLen
, const sal_Int32
* pDeltaArray
)
628 if( mbUseFontEncoding
)
630 OString
aPSName( OUStringToOString( rGfx
.GetFontMgr().getPSName( mnFontID
), RTL_TEXTENCODING_ISO_8859_1
) );
631 OString
aBytes( OUStringToOString( OUString( pStr
, nLen
), mnBaseEncoding
) );
632 rGfx
.PSMoveTo( rPoint
);
633 rGfx
.PSSetFont( aPSName
, mnBaseEncoding
);
634 rGfx
.PSShowText( (const unsigned char*)aBytes
.getStr(), nLen
, aBytes
.getLength(), pDeltaArray
);
638 sal_uChar
*pGlyphID
= (sal_uChar
*)alloca (nLen
* sizeof(sal_uChar
));
639 sal_Int32
*pGlyphSetID
= (sal_Int32
*)alloca (nLen
* sizeof(sal_Int32
));
640 std::set
< sal_Int32
> aGlyphSet
;
642 // convert unicode to font glyph id and font subset
643 for (int nChar
= 0; nChar
< nLen
; nChar
++)
645 GetCharID (pStr
[nChar
], pGlyphID
+ nChar
, pGlyphSetID
+ nChar
);
646 aGlyphSet
.insert (pGlyphSetID
[nChar
]);
649 // loop over all glyph sets to detect substrings that can be xshown together
650 // without changing the postscript font
651 sal_Int32
*pDeltaSubset
= (sal_Int32
*)alloca (nLen
* sizeof(sal_Int32
));
652 sal_uChar
*pGlyphSubset
= (sal_uChar
*)alloca (nLen
* sizeof(sal_uChar
));
654 std::set
< sal_Int32
>::iterator aSet
;
655 for (aSet
= aGlyphSet
.begin(); aSet
!= aGlyphSet
.end(); ++aSet
)
657 Point aPoint
= rPoint
;
658 sal_Int32 nOffset
= 0;
659 sal_Int32 nGlyphs
= 0;
662 // get offset to first glyph
663 for (nChar
= 0; (nChar
< nLen
) && (pGlyphSetID
[nChar
] != *aSet
); nChar
++)
665 nOffset
= pDeltaArray
[nChar
];
668 // loop over all chars to extract those that share the current glyph set
669 for (nChar
= 0; nChar
< nLen
; nChar
++)
671 if (pGlyphSetID
[nChar
] == *aSet
)
673 pGlyphSubset
[nGlyphs
] = pGlyphID
[nChar
];
674 // the offset to the next glyph is determined by the glyph in
675 // front of the next glyph with the same glyphset id
676 // most often, this will be the current glyph
677 while ((nChar
+ 1) < nLen
)
679 if (pGlyphSetID
[nChar
+ 1] == *aSet
)
684 pDeltaSubset
[nGlyphs
] = pDeltaArray
[nChar
] - nOffset
;
690 // show the text using the PrinterGfx text api
691 aPoint
.Move (nOffset
, 0);
693 OString
aGlyphSetName(GetCharSetName(*aSet
));
694 rGfx
.PSSetFont (aGlyphSetName
, GetGlyphSetEncoding(*aSet
));
695 rGfx
.PSMoveTo (aPoint
);
696 rGfx
.PSShowText (pGlyphSubset
, nGlyphs
, nGlyphs
, nGlyphs
> 1 ? pDeltaSubset
: NULL
);
701 GlyphSet::PSUploadEncoding(osl::File
* pOutFile
, PrinterGfx
&rGfx
)
704 if ((meBaseType
!= fonttype::Builtin
) && (meBaseType
!= fonttype::Type1
))
706 if (mnBaseEncoding
== RTL_TEXTENCODING_SYMBOL
)
709 PrintFontManager
&rMgr
= rGfx
.GetFontMgr();
711 // loop thru all the font subsets
712 sal_Int32 nGlyphSetID
= 0;
713 char_list_t::iterator aGlyphSet
;
714 for (aGlyphSet
= maCharList
.begin(); aGlyphSet
!= maCharList
.end(); aGlyphSet
++)
718 if (nGlyphSetID
== 1) // latin1 page uses global reencoding table
720 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
723 if ((*aGlyphSet
).size() == 0) // empty set, doesn't need reencoding
728 // create reencoding table
730 sal_Char pEncodingVector
[256];
733 nSize
+= psp::appendStr ("/",
734 pEncodingVector
+ nSize
);
735 nSize
+= psp::appendStr (GetGlyphSetEncodingName(nGlyphSetID
),
736 pEncodingVector
+ nSize
);
737 nSize
+= psp::appendStr (" [ ",
738 pEncodingVector
+ nSize
);
740 // need a list of glyphs, sorted by glyphid
741 typedef std::map
< sal_uInt8
, sal_Unicode
> ps_mapping_t
;
742 typedef ps_mapping_t::value_type ps_value_t
;
743 ps_mapping_t aSortedGlyphSet
;
745 char_map_t::const_iterator aUnsortedGlyph
;
746 for (aUnsortedGlyph
= (*aGlyphSet
).begin();
747 aUnsortedGlyph
!= (*aGlyphSet
).end();
750 aSortedGlyphSet
.insert(ps_value_t((*aUnsortedGlyph
).second
,
751 (*aUnsortedGlyph
).first
));
754 ps_mapping_t::const_iterator aSortedGlyph
;
755 // loop thru all the glyphs in the subset
756 for (aSortedGlyph
= (aSortedGlyphSet
).begin();
757 aSortedGlyph
!= (aSortedGlyphSet
).end();
760 nSize
+= psp::appendStr ("/",
761 pEncodingVector
+ nSize
);
763 std::list
< OString
> aName( rMgr
.getAdobeNameFromUnicode((*aSortedGlyph
).second
) );
765 if( aName
.begin() != aName
.end() )
766 nSize
+= psp::appendStr ( aName
.front(), pEncodingVector
+ nSize
);
768 nSize
+= psp::appendStr (".notdef", pEncodingVector
+ nSize
);
769 nSize
+= psp::appendStr (" ", pEncodingVector
+ nSize
);
773 nSize
+= psp::appendStr ("\n", pEncodingVector
+ nSize
);
774 psp::WritePS (pOutFile
, pEncodingVector
);
779 nSize
+= psp::appendStr ("] def\n", pEncodingVector
+ nSize
);
780 psp::WritePS (pOutFile
, pEncodingVector
);
782 PSDefineReencodedFont (pOutFile
, nGlyphSetID
);
788 static void CreatePSUploadableFont( TrueTypeFont
* pSrcFont
, FILE* pTmpFile
,
789 const char* pGlyphSetName
, int nGlyphCount
,
790 /*const*/ sal_uInt16
* pRequestedGlyphs
, /*const*/ sal_uChar
* pEncoding
,
791 bool bAllowType42
, bool /*bAllowCID*/ )
793 // match the font-subset to the printer capabilities
794 // TODO: allow CFF for capable printers
795 int nTargetMask
= FontSubsetInfo::TYPE1_PFA
| FontSubsetInfo::TYPE3_FONT
;
797 nTargetMask
|= FontSubsetInfo::TYPE42_FONT
;
799 FontSubsetInfo aInfo
;
800 aInfo
.LoadFont( pSrcFont
);
802 #if 1 // TODO: remove 16bit->long conversion when input args has been changed
803 long aRequestedGlyphs
[256];
804 for( int i
= 0; i
< nGlyphCount
; ++i
)
805 aRequestedGlyphs
[i
] = pRequestedGlyphs
[i
];
808 aInfo
.CreateFontSubset( nTargetMask
, pTmpFile
, pGlyphSetName
,
809 aRequestedGlyphs
, pEncoding
, nGlyphCount
, NULL
);
813 GlyphSet::PSUploadFont (osl::File
& rOutFile
, PrinterGfx
&rGfx
, bool bAllowType42
, std::list
< OString
>& rSuppliedFonts
)
815 // only for truetype fonts
816 if (meBaseType
!= fonttype::TrueType
)
819 TrueTypeFont
*pTTFont
;
820 OString
aTTFileName (rGfx
.GetFontMgr().getFontFileSysPath(mnFontID
));
821 int nFace
= rGfx
.GetFontMgr().getFontFaceNumber(mnFontID
);
822 sal_Int32 nSuccess
= OpenTTFontFile(aTTFileName
.getStr(), nFace
< 0 ? 0 : nFace
, &pTTFont
);
823 if (nSuccess
!= SF_OK
)
825 FILE* pTmpFile
= tmpfile();
826 if (pTmpFile
== NULL
)
829 // array of unicode source characters
830 sal_Unicode pUChars
[256];
832 // encoding vector maps character encoding to the ordinal number
833 // of the glyph in the output file
834 sal_uChar pEncoding
[256];
835 sal_uInt16 pTTGlyphMapping
[256];
836 const bool bAllowCID
= false; // TODO: nPSLanguageLevel>=3
838 // loop thru all the font subsets
839 sal_Int32 nCharSetID
;
840 char_list_t::iterator aCharSet
;
841 for (aCharSet
= maCharList
.begin(), nCharSetID
= 1;
842 aCharSet
!= maCharList
.end();
843 ++aCharSet
, nCharSetID
++)
845 if ((*aCharSet
).size() == 0)
848 // loop thru all the chars in the subset
849 char_map_t::const_iterator aChar
;
851 for (aChar
= (*aCharSet
).begin(); aChar
!= (*aCharSet
).end(); aChar
++)
853 pUChars
[n
] = (*aChar
).first
;
854 pEncoding
[n
] = (*aChar
).second
;
857 // create a mapping from the unicode chars to the char encoding in
858 // source TrueType font
859 MapString (pTTFont
, pUChars
, (*aCharSet
).size(), pTTGlyphMapping
, mbVertical
);
861 // create the current subset
862 OString aCharSetName
= GetCharSetName(nCharSetID
);
863 fprintf( pTmpFile
, "%%%%BeginResource: font %s\n", aCharSetName
.getStr() );
864 CreatePSUploadableFont( pTTFont
, pTmpFile
, aCharSetName
.getStr(), (*aCharSet
).size(),
865 pTTGlyphMapping
, pEncoding
, bAllowType42
, bAllowCID
);
866 fprintf( pTmpFile
, "%%%%EndResource\n" );
867 rSuppliedFonts
.push_back( aCharSetName
);
870 // loop thru all the font glyph subsets
871 sal_Int32 nGlyphSetID
;
872 glyph_list_t::iterator aGlyphSet
;
873 for (aGlyphSet
= maGlyphList
.begin(), nGlyphSetID
= 1;
874 aGlyphSet
!= maGlyphList
.end();
875 ++aGlyphSet
, nGlyphSetID
++)
877 if ((*aGlyphSet
).size() == 0)
880 // loop thru all the glyphs in the subset
881 glyph_map_t::const_iterator aGlyph
;
883 for (aGlyph
= (*aGlyphSet
).begin(); aGlyph
!= (*aGlyphSet
).end(); aGlyph
++)
885 pTTGlyphMapping
[n
] = (*aGlyph
).first
;
886 pEncoding
[n
] = (*aGlyph
).second
;
890 // create the current subset
891 OString aGlyphSetName
= GetGlyphSetName(nGlyphSetID
);
892 fprintf( pTmpFile
, "%%%%BeginResource: font %s\n", aGlyphSetName
.getStr() );
893 CreatePSUploadableFont( pTTFont
, pTmpFile
, aGlyphSetName
.getStr(), (*aGlyphSet
).size(),
894 pTTGlyphMapping
, pEncoding
, bAllowType42
, bAllowCID
);
895 fprintf( pTmpFile
, "%%%%EndResource\n" );
896 rSuppliedFonts
.push_back( aGlyphSetName
);
899 // copy the file into the page header
903 sal_uChar pBuffer
[0x2000];
908 nIn
= fread(pBuffer
, 1, sizeof(pBuffer
), pTmpFile
);
909 rOutFile
.write (pBuffer
, nIn
, nOut
);
911 while ((nIn
== nOut
) && !feof(pTmpFile
));
914 CloseTTFont (pTTFont
);