1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <math.h> 28 29 #include "psputil.hxx" 30 #include "glyphset.hxx" 31 32 #include "printergfx.hxx" 33 #include "vcl/fontmanager.hxx" 34 #include "vcl/helper.hxx" 35 36 #include "osl/thread.h" 37 38 #include "sal/alloca.h" 39 40 using namespace psp ; 41 42 namespace psp { 43 /* 44 container for a font and its helper fonts: 45 1st font is the font substitute e.g. helvetica substitutes arial on the printer 46 2nd is the font itself 47 3rd is a fallback font, usually a font with unicode glyph repertoir (e.g. andale) 48 symbol fonts (adobe-fontspecific) may need special glyphmapping 49 (symbol page vc. latin page) 50 */ 51 class Font3 52 { 53 private: 54 55 #define Font3Size 3 56 57 fontID mpFont [Font3Size]; 58 bool mbSymbol; 59 60 public: 61 62 fontID GetFont (int nIdx) const 63 { return nIdx < Font3Size ? mpFont[nIdx] : -1 ; } 64 bool IsSymbolFont () const 65 { return mbSymbol; } 66 67 Font3 (const PrinterGfx &rGfx); 68 ~Font3 () {} 69 }; 70 71 Font3::Font3(const PrinterGfx &rGfx) 72 { 73 mpFont[0] = rGfx.getFontSubstitute(); 74 mpFont[1] = rGfx.GetFontID(); 75 mpFont[2] = rGfx.getFallbackID(); 76 // mpFont[2] = rGfx.GetFontID(); 77 78 PrintFontManager &rMgr = PrintFontManager::get(); 79 mbSymbol = mpFont[1] != -1 ? 80 rMgr.getFontEncoding(mpFont[1]) == RTL_TEXTENCODING_SYMBOL : false; 81 } 82 83 } // namespace psp 84 85 static int getVerticalDeltaAngle( sal_Unicode nChar ) 86 { 87 int nAngle = 0; 88 if( ( nChar >= 0x1100 && nChar < 0x11fa ) || 89 ( nChar >= 0x3000 && nChar < 0xfb00 ) || 90 ( nChar >= 0xfe20 && nChar < 0xfe70 ) || 91 ( nChar >= 0xff00 && nChar < 0xff64 ) 92 ) 93 { 94 /* #i52932# remember: 95 nChar == 0x2010 || nChar == 0x2015 96 nChar == 0x2016 || nChar == 0x2026 97 98 are nAngle = 0 also, but already handled in the first if 99 */ 100 if( ( nChar >= 0x3008 && nChar < 0x3019 && nChar != 0x3012 ) || 101 nChar == 0xff3b || nChar == 0xff3d || 102 (nChar >= 0xff6b && nChar < 0xff64 ) || 103 nChar == 0xffe3 104 ) 105 nAngle = 0; 106 else if( nChar == 0x30fc ) 107 nAngle = -900; 108 else 109 nAngle = 900; 110 } 111 return nAngle; 112 } 113 114 void 115 PrinterGfx::PSUploadPS1Font (sal_Int32 nFontID) 116 { 117 std::list< sal_Int32 >::iterator aFont; 118 // already in the document header ? 119 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont ) 120 if( nFontID == *aFont ) 121 return; 122 123 // no occurrenc yet, mark for download 124 // add the fontid to the list 125 maPS1Font.push_back (nFontID); 126 } 127 128 /* 129 * implement text handling printer routines, 130 */ 131 132 sal_uInt16 133 PrinterGfx::SetFont( 134 sal_Int32 nFontID, 135 sal_Int32 nHeight, 136 sal_Int32 nWidth, 137 sal_Int32 nAngle, 138 bool bVertical, 139 bool bArtItalic, 140 bool bArtBold 141 ) 142 { 143 // font and encoding will be set by drawText again immediately 144 // before PSShowText 145 mnFontID = nFontID; 146 maVirtualStatus.maFont = rtl::OString(); 147 maVirtualStatus.maEncoding = RTL_TEXTENCODING_DONTKNOW; 148 maVirtualStatus.mnTextHeight = nHeight; 149 maVirtualStatus.mnTextWidth = nWidth; 150 maVirtualStatus.mbArtItalic = bArtItalic; 151 maVirtualStatus.mbArtBold = bArtBold; 152 mnTextAngle = nAngle; 153 mbTextVertical = bVertical; 154 155 return 0; 156 } 157 158 sal_uInt16 159 PrinterGfx::SetFallbackFont ( sal_Int32 nFontID ) 160 { 161 mnFallbackID = nFontID; 162 return 0; 163 } 164 165 void PrinterGfx::drawGlyphs( 166 const Point& rPoint, 167 sal_uInt32* pGlyphIds, 168 sal_Unicode* pUnicodes, 169 sal_Int16 nLen, 170 sal_Int32* pDeltaArray 171 ) 172 { 173 174 // draw the string 175 // search for a glyph set matching the set font 176 std::list< GlyphSet >::iterator aIter; 177 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); aIter++) 178 if ( ((*aIter).GetFontID() == mnFontID) 179 && ((*aIter).IsVertical() == mbTextVertical)) 180 { 181 (*aIter).DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray); 182 break; 183 } 184 185 // not found ? create a new one 186 if (aIter == maPS3Font.end()) 187 { 188 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical)); 189 maPS3Font.back().DrawGlyphs (*this, rPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray); 190 } 191 } 192 193 void PrinterGfx::DrawGlyphs( 194 const Point& rPoint, 195 sal_GlyphId* pGlyphIds, 196 sal_Unicode* pUnicodes, 197 sal_Int16 nLen, 198 sal_Int32* pDeltaArray 199 ) 200 { 201 if( nLen <= 0 ) 202 return; 203 204 if ( !mrFontMgr.isFontDownloadingAllowed( mnFontID ) ) 205 { 206 LicenseWarning(rPoint, pUnicodes, nLen, pDeltaArray); 207 return; 208 } 209 210 if( mrFontMgr.getFontType( mnFontID ) != fonttype::TrueType ) 211 { 212 DrawText( rPoint, pUnicodes, nLen, pDeltaArray ); 213 return; 214 } 215 216 // move and rotate the user coordinate system 217 // avoid the gsave/grestore for the simple cases since it allows 218 // reuse of the current font if it hasn't changed 219 sal_Int32 nCurrentTextAngle = mnTextAngle; 220 Point aPoint( rPoint ); 221 222 if (nCurrentTextAngle != 0) 223 { 224 PSGSave (); 225 PSTranslate (rPoint); 226 PSRotate (nCurrentTextAngle); 227 mnTextAngle = 0; 228 aPoint = Point( 0, 0 ); 229 } 230 231 if( mbTextVertical ) 232 { 233 // vertical glyphs can have an additional rotation ... sigh. 234 // so break up text in chunks of normal glyphs and print out 235 // specially rotated glyphs extra 236 sal_uInt32* pTempGlyphIds = (sal_uInt32*)alloca(sizeof(sal_Int32)*nLen); 237 sal_Int32* pTempDelta = (sal_Int32*)alloca(sizeof(sal_Int32)*nLen); 238 sal_Unicode* pTempUnicodes = (sal_Unicode*)alloca(sizeof(sal_Unicode)*nLen); 239 sal_Int16 nTempLen = 0; 240 sal_Int32 nTempFirstDelta = 0; 241 Point aRotPoint; 242 sal_Int32 nTextHeight = maVirtualStatus.mnTextHeight; 243 sal_Int32 nTextWidth = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight; 244 sal_Int32 nAscend = mrFontMgr.getFontAscend( mnFontID ); 245 sal_Int32 nDescend = mrFontMgr.getFontDescend( mnFontID ); 246 247 nDescend = nDescend * nTextHeight / 1000; 248 nAscend = nAscend * nTextHeight / 1000; 249 250 for( sal_Int16 i = 0; i < nLen; i++ ) 251 { 252 const sal_GlyphId nRot = pGlyphIds[i] & GF_ROTMASK; 253 if( nRot == GF_NONE ) 254 { 255 pTempUnicodes[nTempLen] = pUnicodes[i]; 256 pTempGlyphIds[nTempLen] = pGlyphIds[i]; 257 if( nTempLen > 0 ) 258 pTempDelta[nTempLen-1] = pDeltaArray[i-1]-nTempFirstDelta; 259 else 260 { 261 // the first element in pDeltaArray shows 262 // the offset of the second character 263 // so if the first glyph is normal 264 // then we do not need to move the delta indices 265 // else we have to move them down by one and 266 // recalculate aPoint and all deltas 267 if( i != 0 ) 268 nTempFirstDelta = pDeltaArray[ i-1 ]; 269 } 270 nTempLen++; 271 } 272 else 273 { 274 sal_Int32 nOffset = i > 0 ? pDeltaArray[i-1] : 0; 275 sal_Int32 nRotAngle = 0; 276 switch( nRot ) 277 { 278 case GF_ROTR: 279 nRotAngle = 2700; 280 aRotPoint = Point( -nAscend*nTextWidth/nTextHeight, -nDescend*nTextWidth/nTextHeight - nOffset ); 281 break; 282 case GF_VERT: 283 nRotAngle = 1800; 284 aRotPoint = Point( -nOffset, (nAscend+nDescend) ); 285 break; 286 case GF_ROTL: 287 nRotAngle = 900; 288 aRotPoint = Point( -nDescend*nTextWidth/nTextHeight, nOffset + nAscend*nTextWidth/nTextHeight ); 289 break; 290 } 291 sal_GlyphId nRotGlyphId = pGlyphIds[i]; 292 sal_Unicode nRotUnicode = pUnicodes[i]; 293 sal_Int32 nRotDelta = 0; 294 295 // transform matrix to new individual direction 296 PSGSave (); 297 GraphicsStatus aSaveStatus = maVirtualStatus; 298 if( nRot != 2 ) // switch font aspect 299 { 300 maVirtualStatus.mnTextWidth = nTextHeight; 301 maVirtualStatus.mnTextHeight = nTextWidth; 302 } 303 if( aPoint.X() || aPoint.Y() ) 304 PSTranslate( aPoint ); 305 PSRotate (nRotAngle); 306 // draw the rotated glyph 307 drawGlyphs( aRotPoint, &nRotGlyphId, &nRotUnicode, 1, &nRotDelta ); 308 309 // restore previous state 310 maVirtualStatus = aSaveStatus; 311 PSGRestore(); 312 } 313 } 314 315 pGlyphIds = pTempGlyphIds; 316 pUnicodes = pTempUnicodes; 317 pDeltaArray = pTempDelta; 318 nLen = nTempLen; 319 320 aPoint.X() += nTempFirstDelta; 321 } 322 323 if( nLen > 0 ) 324 drawGlyphs( aPoint, pGlyphIds, pUnicodes, nLen, pDeltaArray ); 325 326 // restore the user coordinate system 327 if (nCurrentTextAngle != 0) 328 { 329 PSGRestore (); 330 mnTextAngle = nCurrentTextAngle; 331 } 332 } 333 334 void 335 PrinterGfx::DrawText ( 336 const Point& rPoint, 337 const sal_Unicode* pStr, 338 sal_Int16 nLen, 339 const sal_Int32* pDeltaArray 340 ) 341 { 342 fontID nRestoreFont = mnFontID; 343 344 // setup font[substitutes] and map the string into the symbol area in case of 345 // symbol font 346 Font3 aFont(*this); 347 sal_Unicode *pEffectiveStr; 348 if ( aFont.IsSymbolFont() ) 349 { 350 pEffectiveStr = (sal_Unicode*)alloca(nLen * sizeof(pStr[0])); 351 for (int i = 0; i < nLen; i++) 352 pEffectiveStr[i] = pStr[i] < 256 ? pStr[i] + 0xF000 : pStr[i]; 353 } 354 else 355 { 356 pEffectiveStr = const_cast<sal_Unicode*>(pStr); 357 } 358 359 fontID *pFontMap = (fontID*) alloca(nLen * sizeof(fontID)); 360 sal_Int32 *pCharWidth = (sal_Int32*) alloca(nLen * sizeof(sal_Int32)); 361 362 for( int n = 0; n < nLen; n++ ) 363 { 364 CharacterMetric aBBox; 365 pFontMap[n] = getCharMetric (aFont, pEffectiveStr[n], &aBBox); 366 pCharWidth[n] = getCharWidth (mbTextVertical, pEffectiveStr[n], &aBBox); 367 } 368 369 // setup a new delta array, use virtual resolution of 1000 370 sal_Int32* pNewDeltaArray = (sal_Int32*)alloca( sizeof( sal_Int32 )*nLen ); 371 if ( pDeltaArray != 0) 372 { 373 for (int i = 0; i < nLen - 1; i++) 374 pNewDeltaArray[i] = 1000 * pDeltaArray[i]; 375 pNewDeltaArray[nLen - 1] = 0; 376 } 377 else 378 { 379 pNewDeltaArray[0] = pCharWidth[0]; 380 for (int i = 1; i < nLen; i++) 381 pNewDeltaArray[i] = pNewDeltaArray[i-1] + pCharWidth[i]; 382 } 383 384 // move and rotate the user coordinate system 385 // avoid the gsave/grestore for the simple cases since it allows 386 // reuse of the current font if it hasn't changed 387 sal_Int32 nCurrentTextAngle = mnTextAngle; 388 sal_Int32 nCurrentPointX; 389 sal_Int32 nCurrentPointY; 390 391 if (nCurrentTextAngle != 0) 392 { 393 PSGSave (); 394 PSTranslate (rPoint); 395 PSRotate (nCurrentTextAngle); 396 mnTextAngle = 0; 397 398 nCurrentPointX = 0; 399 nCurrentPointY = 0; 400 } 401 else 402 { 403 nCurrentPointX = rPoint.X(); 404 nCurrentPointY = rPoint.Y(); 405 } 406 407 // draw the string 408 sal_Int32 nDelta = 0; 409 for (int nTo = 0; nTo < nLen; ) 410 { 411 int nFrom = nTo; 412 fontID nFont = pFontMap[ nFrom ]; 413 414 while ((nTo < nLen) && (nFont == pFontMap[nTo])) 415 { 416 pNewDeltaArray[ nTo ] = (sal_Int32)(((0.5 + pNewDeltaArray[ nTo ]) / 1000.0) - nDelta); 417 nTo++ ; 418 } 419 420 SetFont( nFont, 421 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth, 422 mnTextAngle, 423 mbTextVertical, 424 maVirtualStatus.mbArtItalic, 425 maVirtualStatus.mbArtBold 426 ); 427 428 if (mbTextVertical) 429 { 430 drawVerticalizedText( 431 Point(nCurrentPointX + nDelta, nCurrentPointY), 432 pEffectiveStr + nFrom, nTo - nFrom, 433 pNewDeltaArray + nFrom ); 434 } 435 else 436 { 437 drawText( 438 Point(nCurrentPointX + nDelta, nCurrentPointY), 439 pEffectiveStr + nFrom, nTo - nFrom, 440 pDeltaArray == NULL ? NULL : pNewDeltaArray + nFrom ); 441 } 442 nDelta += pNewDeltaArray[ nTo - 1 ]; 443 } 444 445 // restore the user coordinate system 446 if (nCurrentTextAngle != 0) 447 { 448 PSGRestore (); 449 mnTextAngle = nCurrentTextAngle; 450 } 451 452 // restore the original font settings 453 SetFont( nRestoreFont, 454 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth, 455 mnTextAngle, mbTextVertical, 456 maVirtualStatus.mbArtItalic, 457 maVirtualStatus.mbArtBold 458 ); 459 } 460 461 void PrinterGfx::drawVerticalizedText( 462 const Point& rPoint, 463 const sal_Unicode* pStr, 464 sal_Int16 nLen, 465 const sal_Int32* pDeltaArray 466 ) 467 { 468 sal_Int32* pDelta = (sal_Int32*)alloca( nLen * sizeof(sal_Int32) ); 469 470 int nTextScale = maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight; 471 int nNormalAngle = mnTextAngle; 472 int nDeltaAngle, nLastPos = 0; 473 474 double fSin = sin( -2.0*M_PI*nNormalAngle/3600 ); 475 double fCos = cos( -2.0*M_PI*nNormalAngle/3600 ); 476 477 PrintFontManager &rMgr = PrintFontManager::get(); 478 PrintFontInfo aInfo; 479 rMgr.getFontInfo( mnFontID, aInfo ); 480 481 bool* pGsubFlags = (bool*)alloca( nLen * sizeof(bool) ); 482 rMgr.hasVerticalSubstitutions( mnFontID, pStr, nLen, pGsubFlags ); 483 484 Point aPoint( rPoint ); 485 for( int i = 0; i < nLen; ) 486 { 487 while( ( nDeltaAngle = getVerticalDeltaAngle( pStr[i] ) ) == 0 && i < nLen ) 488 i++; 489 if( i <= nLen && i > nLastPos ) 490 { 491 for( int n = nLastPos; n < i; n++ ) 492 pDelta[n] = pDeltaArray[n] - (aPoint.X() - rPoint.X() ); 493 494 SetFont( mnFontID, 495 maVirtualStatus.mnTextHeight, maVirtualStatus.mnTextWidth, 496 nNormalAngle, mbTextVertical, 497 maVirtualStatus.mbArtItalic, 498 maVirtualStatus.mbArtBold ); 499 drawText( aPoint, pStr + nLastPos, i - nLastPos, pDelta + nLastPos ); 500 501 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i-1] * fCos)); 502 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i-1] * fSin)); 503 } 504 if( i < nLen ) 505 { 506 int nOldWidth = maVirtualStatus.mnTextWidth; 507 int nOldHeight = maVirtualStatus.mnTextHeight; 508 SetFont( mnFontID, 509 nTextScale, 510 maVirtualStatus.mnTextHeight, 511 nNormalAngle + nDeltaAngle, 512 mbTextVertical, 513 maVirtualStatus.mbArtItalic, 514 maVirtualStatus.mbArtBold ); 515 516 double nA = nTextScale * aInfo.m_nAscend / 1000.0; 517 double nD = nTextScale * aInfo.m_nDescend / 1000.0; 518 double fStretch = (double)maVirtualStatus.mnTextWidth / maVirtualStatus.mnTextHeight; 519 if( !pGsubFlags[i] ) 520 nD *= fStretch; 521 522 Point aPos( aPoint ); 523 switch( nDeltaAngle ) 524 { 525 case +900: 526 aPos.X() += (sal_Int32)(+nA * fCos + nD * fSin); 527 aPos.Y() += (sal_Int32)(-nA * fSin + nD * fCos); 528 break; 529 case -900: 530 aPos.X() += (sal_Int32)(+nA * fSin + nD * fCos); 531 aPos.Y() += (sal_Int32)(-(nTextScale*fStretch - nD) * fCos); 532 break; 533 } 534 drawText( aPos, pStr+i, 1, NULL ); 535 if( i < nLen-1 && pDeltaArray ) 536 { 537 aPoint.X() = (sal_Int32)(rPoint.X() + ((double)pDeltaArray[i] * fCos)); 538 aPoint.Y() = (sal_Int32)(rPoint.Y() + ((double)pDeltaArray[i] * fSin)); 539 } 540 541 // swap text width/height again 542 SetFont( mnFontID, 543 nOldHeight, 544 nOldWidth, 545 nNormalAngle, 546 mbTextVertical, 547 maVirtualStatus.mbArtItalic, 548 maVirtualStatus.mbArtBold ); 549 } 550 i++; 551 nLastPos = i; 552 } 553 mnTextAngle = nNormalAngle; 554 } 555 556 void 557 PrinterGfx::LicenseWarning(const Point& rPoint, const sal_Unicode* pStr, 558 sal_Int16 nLen, const sal_Int32* pDeltaArray) 559 { 560 // treat it like a builtin font in case a user has that font also in the 561 // printer. This is not so unlikely as it may seem; no print embedding 562 // licensed fonts are often used (or so they say) in companies: 563 // they are installed on displays and printers, but get not embedded in 564 // they are installed on displays and printers, but get not embedded in 565 // print files or documents because they are not licensed for use outside 566 // the company. 567 rtl::OString aMessage( "The font " ); 568 aMessage += rtl::OUStringToOString( mrFontMgr.getPSName(mnFontID), 569 RTL_TEXTENCODING_ASCII_US ); 570 aMessage += " could not be downloaded\nbecause its license does not allow for that"; 571 PSComment( aMessage.getStr() ); 572 573 rtl::OString aFontName = rtl::OUStringToOString( 574 mrFontMgr.getPSName(mnFontID), 575 RTL_TEXTENCODING_ASCII_US); 576 PSSetFont (aFontName, RTL_TEXTENCODING_ISO_8859_1); 577 578 sal_Size nSize = 4 * nLen; 579 sal_uChar* pBuffer = (sal_uChar*)alloca (nSize* sizeof(sal_uChar)); 580 581 ConverterFactory* pCvt = GetConverterFactory (); 582 nSize = pCvt->Convert (pStr, nLen, pBuffer, nSize, RTL_TEXTENCODING_ISO_8859_1); 583 584 PSMoveTo (rPoint); 585 PSShowText (pBuffer, nLen, nSize, pDeltaArray); 586 } 587 588 void 589 PrinterGfx::drawText( 590 const Point& rPoint, 591 const sal_Unicode* pStr, 592 sal_Int16 nLen, 593 const sal_Int32* pDeltaArray 594 ) 595 { 596 if (!(nLen > 0)) 597 return; 598 599 fonttype::type eType = mrFontMgr.getFontType (mnFontID); 600 601 if (eType == fonttype::Type1) 602 PSUploadPS1Font (mnFontID); 603 604 if ( eType == fonttype::TrueType 605 && !mrFontMgr.isFontDownloadingAllowed(mnFontID)) 606 { 607 LicenseWarning(rPoint, pStr, nLen, pDeltaArray); 608 return; 609 } 610 611 if( mrFontMgr.getUseOnlyFontEncoding( mnFontID ) ) 612 { 613 GlyphSet aGSet( mnFontID, mbTextVertical ); 614 aGSet.DrawText( *this, rPoint, pStr, nLen, pDeltaArray ); 615 return; 616 } 617 618 // search for a glyph set matching the set font 619 std::list< GlyphSet >::iterator aIter; 620 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); aIter++) 621 if ( ((*aIter).GetFontID() == mnFontID) 622 && ((*aIter).IsVertical() == mbTextVertical)) 623 { 624 (*aIter).DrawText (*this, rPoint, pStr, nLen, pDeltaArray); 625 break; 626 } 627 628 // not found ? create a new one 629 if (aIter == maPS3Font.end()) 630 { 631 maPS3Font.push_back (GlyphSet(mnFontID, mbTextVertical)); 632 maPS3Font.back().DrawText (*this, rPoint, pStr, nLen, pDeltaArray); 633 } 634 } 635 636 int 637 PrinterGfx::getCharWidth (sal_Bool b_vert, sal_Unicode n_char, CharacterMetric *p_bbox) 638 { 639 b_vert = b_vert && (getVerticalDeltaAngle(n_char) != 0); 640 int w = b_vert ? p_bbox->height : p_bbox->width; 641 w *= maVirtualStatus.mnTextWidth ? maVirtualStatus.mnTextWidth : maVirtualStatus.mnTextHeight; 642 return w; 643 } 644 645 fontID 646 PrinterGfx::getCharMetric (const Font3 &rFont, sal_Unicode n_char, CharacterMetric *p_bbox) 647 { 648 p_bbox->width = -1; 649 p_bbox->height = -1; 650 651 for (fontID n = 0; n < 3; n++) 652 { 653 fontID n_font = rFont.GetFont(n); 654 if (n_font != -1) 655 { 656 if( mbStrictSO52Compatibility ) 657 { 658 fonttype::type eType = mrFontMgr.getFontType( n_font ); 659 if( (eType == fonttype::Builtin || eType == fonttype::Type1) ) 660 { 661 // note: any character exchanged here MUST also be changed 662 // in the compatibility ISO encoding vector in the prolog 663 // in printerjob.cxx 664 sal_Unicode aRepl = 0; 665 if( n_char == 0x2d ) 666 aRepl = 0x2212; 667 else if( n_char == 0x27 ) 668 aRepl = 0x2019; 669 /* 670 additional characters that may need backwards compatibility: 671 ISO5589 StdEnc Unicode suggested n_char -> aRepl 672 0264 0302 0x00B4 0x00B4 (acute) -> 0x2019 (quiteright) 673 0246 - 0x00A6 0x00A6 (brokenbar) -> 0x007C (bar) 674 0225 0267 0x0095 0x0095 () -> 0x2022 (bullet) 675 0140 0301 0x0060 0x0060 (grave) -> ? 676 */ 677 if( aRepl ) 678 { 679 mrFontMgr.getMetrics( n_font, aRepl, aRepl, p_bbox ); 680 if (p_bbox->width >= 0 && p_bbox->height >= 0) 681 return n_font; 682 } 683 } 684 } 685 mrFontMgr.getMetrics( n_font, n_char, n_char, p_bbox ); 686 } 687 if (p_bbox->width >= 0 && p_bbox->height >= 0) 688 return n_font; 689 } 690 if (n_char != '?') 691 return getCharMetric (rFont, '?', p_bbox); 692 693 return rFont.GetFont(0) != -1 ? rFont.GetFont(0) : rFont.GetFont(1); 694 } 695 696 fontID 697 PrinterGfx::getFontSubstitute () const 698 { 699 if( mpFontSubstitutes ) 700 { 701 ::std::hash_map< fontID, fontID >::const_iterator it = 702 mpFontSubstitutes->find( mnFontID ); 703 if( it != mpFontSubstitutes->end() ) 704 return it->second; 705 } 706 707 return -1; 708 } 709 710 sal_Int32 711 PrinterGfx::GetCharWidth (sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray) 712 { 713 Font3 aFont(*this); 714 if (aFont.IsSymbolFont() && (nFrom < 256) && (nTo < 256)) 715 { 716 nFrom += 0xF000; 717 nTo += 0xF000; 718 } 719 720 for( int n = 0; n < (nTo - nFrom + 1); n++ ) 721 { 722 CharacterMetric aBBox; 723 getCharMetric (aFont, n + nFrom, &aBBox); 724 pWidthArray[n] = getCharWidth (mbTextVertical, n + nFrom, &aBBox); 725 } 726 727 // returned metrics have postscript precision 728 return 1000; 729 } 730 731 const ::std::list< KernPair >& PrinterGfx::getKernPairs( bool bVertical ) const 732 { 733 /* 734 * Note: this is only a 80% solution: if a font is only 735 * partially substituted in a string due to missing glyphs 736 * the results may not be perfect; the more so the more the 737 * substitution differs from the original metricwise. But 738 * vcl only asks for KernPairs for each font once and NOT 739 * in a string context this is the best we can do. 740 * In future the kerning should be done on a per string basis. 741 */ 742 fontID nFont = mnFontID; 743 if( mpFontSubstitutes ) 744 { 745 ::std::hash_map< fontID, fontID >::const_iterator it = 746 mpFontSubstitutes->find( mnFontID ); 747 if( it != mpFontSubstitutes->end() ) 748 nFont = it->second; 749 } 750 return mrFontMgr.getKernPairs( nFont, bVertical ); 751 } 752 753 /* 754 * advanced glyph handling 755 */ 756 757 sal_Bool 758 PrinterGfx::GetGlyphBoundRect (sal_Unicode /*c*/, Rectangle& /*rOutRect*/) 759 { 760 return 0; 761 } 762 763 sal_uInt32 764 PrinterGfx::GetGlyphOutline (sal_Unicode /*c*/, 765 sal_uInt16 **/*ppPolySizes*/, Point **/*ppPoints*/, sal_uInt8 **/*ppFlags*/) 766 { 767 return 0; 768 } 769 770 /* 771 * spool the converted truetype fonts to the page header after the page body is 772 * complete 773 * for Type1 fonts spool additional reencoding vectors that are necessary to access the 774 * whole font 775 */ 776 777 void 778 PrinterGfx::OnEndPage () 779 { 780 } 781 782 void 783 PrinterGfx::OnEndJob () 784 { 785 maPS3Font.clear(); 786 maPS1Font.clear(); 787 } 788 789 void 790 PrinterGfx::writeResources( osl::File* pFile, std::list< rtl::OString >& rSuppliedFonts, std::list< rtl::OString >& rNeededFonts ) 791 { 792 // write all type 1 fonts 793 std::list< sal_Int32 >::iterator aFont; 794 // already in the document header ? 795 for (aFont = maPS1Font.begin(); aFont != maPS1Font.end(); ++aFont) 796 { 797 const rtl::OString& rSysPath (mrFontMgr.getFontFileSysPath(*aFont) ); 798 rtl::OUString aUNCPath; 799 osl::File::getFileURLFromSystemPath (OStringToOUString (rSysPath, osl_getThreadTextEncoding()), aUNCPath); 800 osl::File aFontFile (aUNCPath); 801 802 // provide the pfb or pfa font as a (pfa-)font resource 803 rtl::OString aPostScriptName = 804 rtl::OUStringToOString ( mrFontMgr.getPSName(*aFont), 805 RTL_TEXTENCODING_ASCII_US ); 806 807 WritePS (pFile, "%%BeginResource: font "); 808 WritePS (pFile, aPostScriptName.getStr()); 809 WritePS (pFile, "\n"); 810 811 osl::File::RC nError = aFontFile.open (OpenFlag_Read); 812 if (nError == osl::File::E_None) 813 { 814 convertPfbToPfa (aFontFile, *pFile); 815 aFontFile.close (); 816 817 pFile->setPos(osl_Pos_Current, -1); 818 char lastchar = '\n'; 819 sal_uInt64 uBytes(1); 820 pFile->read((void *)(&lastchar), uBytes, uBytes); 821 if (lastchar != '\n') 822 WritePS (pFile, "\n"); 823 } 824 WritePS (pFile, "%%EndResource\n"); 825 rSuppliedFonts.push_back( aPostScriptName ); 826 } 827 828 // write glyphsets and reencodings 829 std::list< GlyphSet >::iterator aIter; 830 for (aIter = maPS3Font.begin(); aIter != maPS3Font.end(); ++aIter) 831 { 832 if (aIter->GetFontType() == fonttype::TrueType) 833 { 834 aIter->PSUploadFont (*pFile, *this, mbUploadPS42Fonts ? true : false, rSuppliedFonts ); 835 } 836 else 837 // ( aIter->GetFontType() == fonttype::Type1 838 // || aIter->GetFontType() == fonttype::Builtin ) 839 { 840 aIter->PSUploadEncoding (pFile, *this); 841 if( aIter->GetFontType() == fonttype::Builtin ) 842 rNeededFonts.push_back( 843 rtl::OUStringToOString( 844 mrFontMgr.getPSName( aIter->GetFontID() ), 845 RTL_TEXTENCODING_ASCII_US ) ); 846 } 847 } 848 } 849 850 bool PrinterGfx::getStrictSO52Compatibility() const 851 { 852 return mbStrictSO52Compatibility; 853 } 854 855 void PrinterGfx::setStrictSO52Compatibility( bool bCompat) 856 { 857 mbStrictSO52Compatibility = bCompat; 858 } 859