merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / printergfx / glyphset.cxx
blob24ca7916acab5169f7319f67adfda7deb5a94be2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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"
34 #include "sft.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"
47 #include <set>
48 #include <map>
50 using namespace vcl;
51 using namespace psp;
52 using namespace rtl;
54 GlyphSet::GlyphSet ()
55 : mnFontID (-1),
56 mbVertical (0),
57 mbUseFontEncoding (false)
60 GlyphSet::GlyphSet (sal_Int32 nFontID, sal_Bool bVertical)
61 : mnFontID (nFontID),
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 ??? */
77 sal_Int32
78 GlyphSet::GetFontID ()
80 return mnFontID;
83 fonttype::type
84 GlyphSet::GetFontType ()
86 return meBaseType;
89 sal_Bool
90 GlyphSet::IsVertical ()
92 return mbVertical;
95 sal_Bool
96 GlyphSet::SetFont (sal_Int32 nFontID, sal_Bool bVertical)
98 if (mnFontID != -1)
99 return sal_False;
101 mnFontID = nFontID;
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);
111 return sal_True;
114 sal_Bool
115 GlyphSet::GetCharID (
116 sal_Unicode nChar,
117 sal_uChar* nOutGlyphID,
118 sal_Int32* nOutGlyphSetID
121 return LookupCharID (nChar, nOutGlyphID, nOutGlyphSetID)
122 || AddCharID (nChar, nOutGlyphID, nOutGlyphSetID);
125 sal_Bool
126 GlyphSet::GetGlyphID (
127 sal_uInt32 nGlyph,
128 sal_Unicode nUnicode,
129 sal_uChar* nOutGlyphID,
130 sal_Int32* nOutGlyphSetID
133 return LookupGlyphID (nGlyph, nOutGlyphID, nOutGlyphSetID)
134 || AddGlyphID (nGlyph, nUnicode, nOutGlyphID, nOutGlyphSetID);
137 sal_Bool
138 GlyphSet::LookupCharID (
139 sal_Unicode nChar,
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;
159 return sal_True;
163 *nOutGlyphSetID = -1;
164 *nOutGlyphID = 0;
165 return sal_False;
168 sal_Bool
169 GlyphSet::LookupGlyphID (
170 sal_uInt32 nGlyph,
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;
190 return sal_True;
194 *nOutGlyphSetID = -1;
195 *nOutGlyphID = 0;
196 return sal_False;
199 sal_uChar
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 );
207 sal_Char nAnsiChar;
208 sal_uInt32 nCvtInfo;
209 sal_Size nCvtChars;
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;
220 sal_uChar
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;
228 return 0;
231 void
232 GlyphSet::AddNotdef (char_map_t &rCharMap)
234 if (rCharMap.size() == 0)
235 rCharMap[0] = 0;
238 void
239 GlyphSet::AddNotdef (glyph_map_t &rGlyphMap)
241 if (rGlyphMap.size() == 0)
242 rGlyphMap[0] = 0;
244 sal_Bool
245 GlyphSet::AddCharID (
246 sal_Unicode nChar,
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);
256 else
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))
271 char_map_t aMap;
272 maCharList.push_back (aMap);
275 // insert a new glyph in the font subset
276 if (nMappedChar)
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;
283 *nOutGlyphSetID = 1;
284 *nOutGlyphID = nMappedChar;
286 else
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];
299 return sal_True;
302 sal_Bool
303 GlyphSet::AddGlyphID (
304 sal_uInt32 nGlyph,
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);
315 else
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))
330 glyph_map_t aMap;
331 maGlyphList.push_back (aMap);
334 // insert a new glyph in the font subset
335 if (nMappedChar)
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;
342 *nOutGlyphSetID = 1;
343 *nOutGlyphID = nMappedChar;
345 else
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];
358 return sal_True;
361 OString
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();
374 else
375 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
377 return maBaseName;
381 OString
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();
394 else
395 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
397 return maBaseName;
401 sal_Int32
402 GlyphSet::GetGlyphSetEncoding (sal_Int32 nGlyphSetID)
404 if (meBaseType == fonttype::TrueType)
405 return RTL_TEXTENCODING_DONTKNOW;
406 else
408 /* (meBaseType == fonttype::Type1 || meBaseType == fonttype::Builtin) */
409 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
410 return RTL_TEXTENCODING_SYMBOL;
411 else
412 return nGlyphSetID == 1 ? RTL_TEXTENCODING_MS_1252
413 : RTL_TEXTENCODING_USER_START + nGlyphSetID;
417 OString
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");
425 else
426 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
428 return rFontName
429 + OString("Enc")
430 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
432 else
434 return OString();
438 OString
439 GlyphSet::GetGlyphSetEncodingName (sal_Int32 nGlyphSetID)
441 return GetGlyphSetEncodingName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
444 void
445 GlyphSet::PSDefineReencodedFont (osl::File* pOutFile, sal_Int32 nGlyphSetID)
447 // only for ps fonts
448 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
449 return;
451 sal_Char pEncodingVector [256];
452 sal_Int32 nSize = 0;
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);
469 OString
470 GlyphSet::GetReencodedFontName (rtl_TextEncoding nEnc, const OString &rFontName)
472 if ( nEnc == RTL_TEXTENCODING_MS_1252
473 || nEnc == RTL_TEXTENCODING_ISO_8859_1)
475 return rFontName
476 + OString("-iso1252");
478 else
479 if (nEnc >= RTL_TEXTENCODING_USER_START && nEnc <= RTL_TEXTENCODING_USER_END)
481 return rFontName
482 + OString("-enc")
483 + OString::valueOf ((sal_Int32)(nEnc - RTL_TEXTENCODING_USER_START));
485 else
487 return OString();
491 OString
492 GlyphSet::GetReencodedFontName (sal_Int32 nGlyphSetID)
494 return GetReencodedFontName (GetGlyphSetEncoding(nGlyphSetID), maBaseName);
497 void GlyphSet::DrawGlyphs(
498 PrinterGfx& rGfx,
499 const Point& rPoint,
500 const sal_uInt32* pGlyphIds,
501 const sal_Unicode* pUnicodes,
502 sal_Int16 nLen,
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;
527 sal_Int32 nChar;
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)
547 break;
548 else
549 nChar += 1;
551 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
553 nGlyphs += 1;
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);
567 void
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);
574 else
575 ImplDrawText (rGfx, rPoint, pStr, nLen, pDeltaArray);
578 void
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() );
590 return;
593 int nChar;
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)
610 nGlyphs++;
611 else
612 break;
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);
620 nChar += nGlyphs;
624 void
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 );
635 return;
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;
660 sal_Int32 nChar;
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)
680 break;
681 else
682 nChar += 1;
684 pDeltaSubset [nGlyphs] = pDeltaArray[nChar] - nOffset;
686 nGlyphs += 1;
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);
700 sal_Bool
701 GlyphSet::PSUploadEncoding(osl::File* pOutFile, PrinterGfx &rGfx)
703 // only for ps fonts
704 if ((meBaseType != fonttype::Builtin) && (meBaseType != fonttype::Type1))
705 return sal_False;
706 if (mnBaseEncoding == RTL_TEXTENCODING_SYMBOL)
707 return sal_False;
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++)
716 ++nGlyphSetID;
718 if (nGlyphSetID == 1) // latin1 page uses global reencoding table
720 PSDefineReencodedFont (pOutFile, nGlyphSetID);
721 continue;
723 if ((*aGlyphSet).size() == 0) // empty set, doesn't need reencoding
725 continue;
728 // create reencoding table
730 sal_Char pEncodingVector [256];
731 sal_Int32 nSize = 0;
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();
748 ++aUnsortedGlyph)
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();
758 ++aSortedGlyph)
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);
767 else
768 nSize += psp::appendStr (".notdef", pEncodingVector + nSize );
769 nSize += psp::appendStr (" ", pEncodingVector + nSize);
770 // flush line
771 if (nSize >= 70)
773 nSize += psp::appendStr ("\n", pEncodingVector + nSize);
774 psp::WritePS (pOutFile, pEncodingVector);
775 nSize = 0;
779 nSize += psp::appendStr ("] def\n", pEncodingVector + nSize);
780 psp::WritePS (pOutFile, pEncodingVector);
782 PSDefineReencodedFont (pOutFile, nGlyphSetID);
785 return sal_True;
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;
796 if( bAllowType42 )
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];
806 #endif
808 aInfo.CreateFontSubset( nTargetMask, pTmpFile, pGlyphSetName,
809 aRequestedGlyphs, pEncoding, nGlyphCount, NULL );
812 sal_Bool
813 GlyphSet::PSUploadFont (osl::File& rOutFile, PrinterGfx &rGfx, bool bAllowType42, std::list< OString >& rSuppliedFonts )
815 // only for truetype fonts
816 if (meBaseType != fonttype::TrueType)
817 return sal_False;
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)
824 return sal_False;
825 FILE* pTmpFile = tmpfile();
826 if (pTmpFile == NULL)
827 return sal_False;
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)
846 continue;
848 // loop thru all the chars in the subset
849 char_map_t::const_iterator aChar;
850 sal_Int32 n = 0;
851 for (aChar = (*aCharSet).begin(); aChar != (*aCharSet).end(); aChar++)
853 pUChars [n] = (*aChar).first;
854 pEncoding [n] = (*aChar).second;
855 n++;
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)
878 continue;
880 // loop thru all the glyphs in the subset
881 glyph_map_t::const_iterator aGlyph;
882 sal_Int32 n = 0;
883 for (aGlyph = (*aGlyphSet).begin(); aGlyph != (*aGlyphSet).end(); aGlyph++)
885 pTTGlyphMapping [n] = (*aGlyph).first;
886 pEncoding [n] = (*aGlyph).second;
887 n++;
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
900 rewind(pTmpFile);
901 fflush(pTmpFile);
903 sal_uChar pBuffer[0x2000];
904 sal_uInt64 nIn;
905 sal_uInt64 nOut;
908 nIn = fread(pBuffer, 1, sizeof(pBuffer), pTmpFile);
909 rOutFile.write (pBuffer, nIn, nOut);
911 while ((nIn == nOut) && !feof(pTmpFile));
913 // cleanup
914 CloseTTFont (pTTFont);
915 fclose (pTmpFile);
917 return sal_True;