bump product version to 5.0.4.1
[LibreOffice.git] / vcl / quartz / salgdi.cxx
blob52cf48acf816681d3bbdf87b5e6e075487ed593e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <config_folders.h>
22 #include "sal/config.h"
24 #include "osl/file.hxx"
25 #include "osl/process.h"
27 #include "osl/mutex.hxx"
29 #include "rtl/bootstrap.h"
30 #include "rtl/strbuf.hxx"
32 #include "basegfx/range/b2drectangle.hxx"
33 #include "basegfx/polygon/b2dpolygon.hxx"
34 #include "basegfx/polygon/b2dpolygontools.hxx"
35 #include "basegfx/matrix/b2dhommatrix.hxx"
36 #include "basegfx/matrix/b2dhommatrixtools.hxx"
38 #include "vcl/sysdata.hxx"
39 #include "vcl/svapp.hxx"
40 #include "vcl/metric.hxx"
42 #include "impfont.hxx"
44 #include "quartz/salgdi.h"
45 #include "quartz/utils.h"
47 #ifdef MACOSX
48 #include "osx/salframe.h"
49 #endif
51 #ifdef IOS
52 #include "saldatabasic.hxx"
53 #include <basebmp/scanlineformats.hxx>
54 #endif
56 #include "ctfonts.hxx"
58 #include "fontsubset.hxx"
59 #include "sallayout.hxx"
60 #include "sft.hxx"
62 using namespace vcl;
64 CoreTextFontData::CoreTextFontData( const CoreTextFontData& rSrc )
65 : PhysicalFontFace( rSrc )
66 , mnFontId( rSrc.mnFontId )
67 , mbOs2Read( rSrc.mbOs2Read )
68 , mbHasOs2Table( rSrc.mbHasOs2Table )
69 , mbCmapEncodingRead( rSrc.mbCmapEncodingRead )
71 if( rSrc.mpCharMap )
72 mpCharMap = rSrc.mpCharMap;
75 CoreTextFontData::CoreTextFontData( const ImplDevFontAttributes& rDFA, sal_IntPtr nFontId )
76 : PhysicalFontFace( rDFA, 0 )
77 , mnFontId( nFontId )
78 , mbOs2Read( false )
79 , mbHasOs2Table( false )
80 , mbCmapEncodingRead( false )
81 , mbFontCapabilitiesRead( false )
85 CoreTextFontData::~CoreTextFontData()
87 if( mpCharMap )
88 mpCharMap = 0;
91 sal_IntPtr CoreTextFontData::GetFontId() const
93 return (sal_IntPtr)mnFontId;
96 static unsigned GetUShort( const unsigned char* p ){return((p[0]<<8)+p[1]);}
98 const FontCharMapPtr CoreTextFontData::GetFontCharMap() const
100 // return the cached charmap
101 if( mpCharMap )
102 return mpCharMap;
104 // set the default charmap
105 FontCharMapPtr pCharMap( new FontCharMap() );
106 mpCharMap = pCharMap;
108 // get the CMAP byte size
109 // allocate a buffer for the CMAP raw data
110 const int nBufSize = GetFontTable( "cmap", NULL );
111 DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::GetFontCharMap : GetFontTable1 failed!\n");
112 if( nBufSize <= 0 )
113 return mpCharMap;
115 // get the CMAP raw data
116 ByteVector aBuffer( nBufSize );
117 const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
118 DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::GetFontCharMap : GetFontTable2 failed!\n");
119 if( nRawLength <= 0 )
120 return mpCharMap;
121 DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::GetFontCharMap : ByteCount mismatch!\n");
123 // parse the CMAP
124 CmapResult aCmapResult;
125 if( ParseCMAP( &aBuffer[0], nRawLength, aCmapResult ) )
127 FontCharMapPtr pDefFontCharMap( new FontCharMap(aCmapResult) );
128 // create the matching charmap
129 mpCharMap = pDefFontCharMap;
132 return mpCharMap;
135 bool CoreTextFontData::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
137 // read this only once per font
138 if( mbFontCapabilitiesRead )
140 rFontCapabilities = maFontCapabilities;
141 return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
143 mbFontCapabilitiesRead = true;
145 int nBufSize = 0;
146 // prepare to get the GSUB table raw data
147 nBufSize = GetFontTable( "GSUB", NULL );
148 if( nBufSize > 0 )
150 // allocate a buffer for the GSUB raw data
151 ByteVector aBuffer( nBufSize );
152 // get the GSUB raw data
153 const int nRawLength = GetFontTable( "GSUB", &aBuffer[0] );
154 if( nRawLength > 0 )
156 const unsigned char* pGSUBTable = &aBuffer[0];
157 vcl::getTTScripts(maFontCapabilities.maGSUBScriptTags, pGSUBTable, nRawLength);
160 nBufSize = GetFontTable( "OS/2", NULL );
161 if( nBufSize > 0 )
163 // allocate a buffer for the OS/2 raw data
164 ByteVector aBuffer( nBufSize );
165 // get the OS/2 raw data
166 const int nRawLength = GetFontTable( "OS/2", &aBuffer[0] );
167 if( nRawLength > 0 )
169 const unsigned char* pOS2Table = &aBuffer[0];
170 vcl::getTTCoverage(
171 maFontCapabilities.maUnicodeRange,
172 maFontCapabilities.maCodePageRange,
173 pOS2Table, nRawLength);
176 rFontCapabilities = maFontCapabilities;
177 return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
180 void CoreTextFontData::ReadOs2Table() const
182 // read this only once per font
183 if( mbOs2Read )
184 return;
185 mbOs2Read = true;
186 mbHasOs2Table = false;
188 // prepare to get the OS/2 table raw data
189 const int nBufSize = GetFontTable( "OS/2", NULL );
190 DBG_ASSERT( (nBufSize > 0), "CoreTextFontData::ReadOs2Table : GetFontTable1 failed!\n");
191 if( nBufSize <= 0 )
192 return;
194 // get the OS/2 raw data
195 ByteVector aBuffer( nBufSize );
196 const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
197 DBG_ASSERT( (nRawLength > 0), "CoreTextFontData::ReadOs2Table : GetFontTable2 failed!\n");
198 if( nRawLength <= 0 )
199 return;
200 DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadOs2Table : ByteCount mismatch!\n");
201 mbHasOs2Table = true;
203 // parse the OS/2 raw data
204 // TODO: also analyze panose info, etc.
207 void CoreTextFontData::ReadMacCmapEncoding() const
209 // read this only once per font
210 if( mbCmapEncodingRead )
211 return;
212 mbCmapEncodingRead = true;
214 const int nBufSize = GetFontTable( "cmap", NULL );
215 if( nBufSize <= 0 )
216 return;
218 // get the CMAP raw data
219 ByteVector aBuffer( nBufSize );
220 const int nRawLength = GetFontTable( "cmap", &aBuffer[0] );
221 if( nRawLength < 24 )
222 return;
223 DBG_ASSERT( (nBufSize==nRawLength), "CoreTextFontData::ReadMacCmapEncoding : ByteCount mismatch!\n");
225 const unsigned char* pCmap = &aBuffer[0];
226 if( GetUShort( pCmap ) != 0x0000 )
227 return;
230 AquaSalGraphics::AquaSalGraphics():
231 #ifdef MACOSX
232 mpFrame( NULL ),
233 #endif
234 mxLayer( NULL )
235 , mrContext( NULL )
236 #if OSL_DEBUG_LEVEL > 0
237 , mnContextStackDepth( 0 )
238 #endif
239 , mpXorEmulation( NULL )
240 , mnXorMode( 0 )
241 , mnWidth( 0 )
242 , mnHeight( 0 )
243 , mnBitmapDepth( 0 )
244 , mnRealDPIX( 0 )
245 , mnRealDPIY( 0 )
246 , mxClipPath( NULL )
247 , maLineColor( COL_WHITE )
248 , maFillColor( COL_BLACK )
249 , mpFontData( NULL )
250 , mpTextStyle( NULL )
251 , maTextColor( COL_BLACK )
252 , mbNonAntialiasedText( false )
253 , mbPrinter( false )
254 , mbVirDev( false )
255 #ifdef MACOSX
256 , mbWindow( false )
257 #else
258 , mbForeignContext( false )
259 #endif
261 SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this );
264 AquaSalGraphics::~AquaSalGraphics()
266 SAL_INFO( "vcl.quartz", "AquaSalGraphics::~AquaSalGraphics() this=" << this );
268 if( mxClipPath )
270 CG_TRACE( "CGPathRelease(" << mxClipPath << ")" );
271 CGPathRelease( mxClipPath );
274 delete mpTextStyle;
276 if( mpXorEmulation )
277 delete mpXorEmulation;
279 #ifdef IOS
280 if (mbForeignContext)
281 return;
282 #endif
283 if( mxLayer )
285 CG_TRACE( "CGLayerRelease(" << mxLayer << ")" );
286 CGLayerRelease( mxLayer );
288 else if( mrContext
289 #ifdef MACOSX
290 && mbWindow
291 #endif
294 // destroy backbuffer bitmap context that we created ourself
295 CG_TRACE( "CGContextRelease(" << mrContext << ")" );
296 CGContextRelease( mrContext );
297 mrContext = NULL;
301 SalGraphicsImpl* AquaSalGraphics::GetImpl() const
303 return NULL;
306 void AquaSalGraphics::SetTextColor( SalColor nSalColor )
308 maTextColor = RGBAColor( nSalColor );
309 // SAL_ DEBUG(std::hex << nSalColor << std::dec << "={" << maTextColor.GetRed() << ", " << maTextColor.GetGreen() << ", " << maTextColor.GetBlue() << ", " << maTextColor.GetAlpha() << "}");
312 void AquaSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int /*nFallbackLevel*/ )
314 mpTextStyle->GetFontMetric( *pMetric );
317 static bool AddTempDevFont(const OUString& rFontFileURL)
319 OUString aUSytemPath;
320 OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, aUSytemPath ) );
321 OString aCFileName = OUStringToOString( aUSytemPath, RTL_TEXTENCODING_UTF8 );
323 CFStringRef rFontPath = CFStringCreateWithCString(NULL, aCFileName.getStr(), kCFStringEncodingUTF8);
324 CFURLRef rFontURL = CFURLCreateWithFileSystemPath(NULL, rFontPath, kCFURLPOSIXPathStyle, true);
326 bool success = false;
328 CFErrorRef error;
329 success = CTFontManagerRegisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, &error);
330 if (!success)
332 CFRelease(error);
335 return success;
338 static void AddTempFontDir( const OUString &rFontDirUrl )
340 osl::Directory aFontDir( rFontDirUrl );
341 osl::FileBase::RC rcOSL = aFontDir.open();
342 if( rcOSL == osl::FileBase::E_None )
344 osl::DirectoryItem aDirItem;
346 while( aFontDir.getNextItem( aDirItem, 10 ) == osl::FileBase::E_None )
348 osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
349 rcOSL = aDirItem.getFileStatus( aFileStatus );
350 if ( rcOSL == osl::FileBase::E_None )
351 AddTempDevFont(aFileStatus.getFileURL());
356 static void AddLocalTempFontDirs()
358 static bool bFirst = true;
359 if( !bFirst )
360 return;
361 bFirst = false;
363 // add private font files
365 OUString aBrandStr( "$BRAND_BASE_DIR" );
366 rtl_bootstrap_expandMacros( &aBrandStr.pData );
367 AddTempFontDir( aBrandStr + "/" LIBO_SHARE_FOLDER "/fonts/truetype/" );
370 void AquaSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection )
372 DBG_ASSERT( pFontCollection, "AquaSalGraphics::GetDevFontList(NULL) !");
374 AddLocalTempFontDirs();
376 // The idea is to cache the list of system fonts once it has been generated.
377 // SalData seems to be a good place for this caching. However we have to
378 // carefully make the access to the font list thread-safe. If we register
379 // a font-change event handler to update the font list in case fonts have
380 // changed on the system we have to lock access to the list. The right
381 // way to do that is the solar mutex since GetDevFontList is protected
382 // through it as should be all event handlers
384 SalData* pSalData = GetSalData();
385 if( !pSalData->mpFontList )
386 pSalData->mpFontList = GetCoretextFontList();
388 // Copy all PhysicalFontFace objects contained in the SystemFontList
389 pSalData->mpFontList->AnnounceFonts( *pFontCollection );
392 void AquaSalGraphics::ClearDevFontCache()
394 SalData* pSalData = GetSalData();
395 delete pSalData->mpFontList;
396 pSalData->mpFontList = NULL;
399 bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*,
400 const OUString& rFontFileURL, const OUString& /*rFontName*/ )
402 return ::AddTempDevFont(rFontFileURL);
405 bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId, basegfx::B2DPolyPolygon& rPolyPoly )
407 const bool bRC = mpTextStyle->GetGlyphOutline( aGlyphId, rPolyPoly );
408 return bRC;
411 bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
413 const bool bRC = mpTextStyle->GetGlyphBoundRect( aGlyphId, rRect );
414 return bRC;
417 void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout& )
421 sal_uInt16 AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ )
423 // release the text style
424 delete mpTextStyle;
425 mpTextStyle = NULL;
427 // handle NULL request meaning: release-font-resources request
428 if( !pReqFont )
430 mpFontData = NULL;
431 return 0;
434 // update the text style
435 mpFontData = static_cast<const CoreTextFontData*>( pReqFont->mpFontData );
436 mpTextStyle = new CoreTextStyle( *pReqFont );
438 SAL_INFO("vcl.ct",
439 "SetFont"
440 " to " << mpFontData->GetFamilyName()
441 << ", " << mpFontData->GetStyleName()
442 << " fontid=" << mpFontData->GetFontId()
443 << " for " << pReqFont->GetFamilyName()
444 << ", " << pReqFont->GetStyleName()
445 << " weight=" << pReqFont->GetWeight()
446 << " slant=" << pReqFont->GetSlant()
447 << " size=" << pReqFont->mnHeight << "x" << pReqFont->mnWidth
448 << " orientation=" << pReqFont->mnOrientation
451 return 0;
454 SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int /*nFallbackLevel*/ )
456 SalLayout* pSalLayout = mpTextStyle->GetTextLayout();
457 return pSalLayout;
460 const FontCharMapPtr AquaSalGraphics::GetFontCharMap() const
462 if( !mpFontData )
464 FontCharMapPtr pFontCharMap( new FontCharMap() );
465 return pFontCharMap;
468 return mpFontData->GetFontCharMap();
471 bool AquaSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
473 if( !mpFontData )
474 return false;
476 return mpFontData->GetFontCapabilities(rFontCapabilities);
479 // fake a SFNT font directory entry for a font table
480 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory
481 static void FakeDirEntry( const char aTag[5], ByteCount nOfs, ByteCount nLen,
482 const unsigned char* /*pData*/, unsigned char*& rpDest )
484 // write entry tag
485 rpDest[ 0] = aTag[0];
486 rpDest[ 1] = aTag[1];
487 rpDest[ 2] = aTag[2];
488 rpDest[ 3] = aTag[3];
489 // TODO: get entry checksum and write it
490 // not too important since the subsetter doesn't care currently
491 // for( pData+nOfs ... pData+nOfs+nLen )
492 // write entry offset
493 rpDest[ 8] = (char)(nOfs >> 24);
494 rpDest[ 9] = (char)(nOfs >> 16);
495 rpDest[10] = (char)(nOfs >> 8);
496 rpDest[11] = (char)(nOfs >> 0);
497 // write entry length
498 rpDest[12] = (char)(nLen >> 24);
499 rpDest[13] = (char)(nLen >> 16);
500 rpDest[14] = (char)(nLen >> 8);
501 rpDest[15] = (char)(nLen >> 0);
502 // advance to next entry
503 rpDest += 16;
506 // fake a TTF or CFF font as directly accessing font file is not possible
507 // when only the fontid is known. This approach also handles *.dfont fonts.
508 bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData,
509 ByteVector& rBuffer, bool* pJustCFF )
511 const CoreTextFontData* pMacFont = static_cast<const CoreTextFontData*>(pFontData);
513 // short circuit for CFF-only fonts
514 const int nCffSize = pMacFont->GetFontTable( "CFF ", NULL);
515 if( pJustCFF != NULL )
517 *pJustCFF = (nCffSize > 0);
518 if( *pJustCFF)
520 rBuffer.resize( nCffSize);
521 const int nCffRead = pMacFont->GetFontTable( "CFF ", &rBuffer[0]);
522 if( nCffRead != nCffSize)
523 return false;
524 return true;
528 // get font table availability and size in bytes
529 const int nHeadSize = pMacFont->GetFontTable( "head", NULL);
530 if( nHeadSize <= 0)
531 return false;
532 const int nMaxpSize = pMacFont->GetFontTable( "maxp", NULL);
533 if( nMaxpSize <= 0)
534 return false;
535 const int nCmapSize = pMacFont->GetFontTable( "cmap", NULL);
536 if( nCmapSize <= 0)
537 return false;
538 const int nNameSize = pMacFont->GetFontTable( "name", NULL);
539 if( nNameSize <= 0)
540 return false;
541 const int nHheaSize = pMacFont->GetFontTable( "hhea", NULL);
542 if( nHheaSize <= 0)
543 return false;
544 const int nHmtxSize = pMacFont->GetFontTable( "hmtx", NULL);
545 if( nHmtxSize <= 0)
546 return false;
548 // get the ttf-glyf outline tables
549 int nLocaSize = 0;
550 int nGlyfSize = 0;
551 if( nCffSize <= 0)
553 nLocaSize = pMacFont->GetFontTable( "loca", NULL);
554 if( nLocaSize <= 0)
555 return false;
556 nGlyfSize = pMacFont->GetFontTable( "glyf", NULL);
557 if( nGlyfSize <= 0)
558 return false;
561 int nPrepSize = 0, nCvtSize = 0, nFpgmSize = 0;
562 if( nGlyfSize) // TODO: reduce PDF size by making hint subsetting optional
564 nPrepSize = pMacFont->GetFontTable( "prep", NULL);
565 nCvtSize = pMacFont->GetFontTable( "cvt ", NULL);
566 nFpgmSize = pMacFont->GetFontTable( "fpgm", NULL);
569 // prepare a byte buffer for a fake font
570 int nTableCount = 7;
571 nTableCount += (nPrepSize>0?1:0) + (nCvtSize>0?1:0) + (nFpgmSize>0?1:0) + (nGlyfSize>0?1:0);
572 const ByteCount nFdirSize = 12 + 16*nTableCount;
573 ByteCount nTotalSize = nFdirSize;
574 nTotalSize += nHeadSize + nMaxpSize + nNameSize + nCmapSize;
575 if( nGlyfSize )
576 nTotalSize += nLocaSize + nGlyfSize;
577 else
578 nTotalSize += nCffSize;
579 nTotalSize += nHheaSize + nHmtxSize;
580 nTotalSize += nPrepSize + nCvtSize + nFpgmSize;
581 rBuffer.resize( nTotalSize );
583 // fake a SFNT font directory header
584 if( nTableCount < 16 )
586 int nLog2 = 0;
587 while( (nTableCount >> nLog2) > 1 ) ++nLog2;
588 rBuffer[ 1] = 1; // Win-TTF style scaler
589 rBuffer[ 5] = nTableCount; // table count
590 rBuffer[ 7] = nLog2*16; // searchRange
591 rBuffer[ 9] = nLog2; // entrySelector
592 rBuffer[11] = (nTableCount-nLog2)*16; // rangeShift
595 // get font table raw data and update the fake directory entries
596 ByteCount nOfs = nFdirSize;
597 unsigned char* pFakeEntry = &rBuffer[12];
598 if( nCmapSize != pMacFont->GetFontTable( "cmap", &rBuffer[nOfs]))
599 return false;
600 FakeDirEntry( "cmap", nOfs, nCmapSize, &rBuffer[0], pFakeEntry );
601 nOfs += nCmapSize;
602 if( nCvtSize ) {
603 if( nCvtSize != pMacFont->GetFontTable( "cvt ", &rBuffer[nOfs]))
604 return false;
605 FakeDirEntry( "cvt ", nOfs, nCvtSize, &rBuffer[0], pFakeEntry );
606 nOfs += nCvtSize;
608 if( nFpgmSize ) {
609 if( nFpgmSize != pMacFont->GetFontTable( "fpgm", &rBuffer[nOfs]))
610 return false;
611 FakeDirEntry( "fpgm", nOfs, nFpgmSize, &rBuffer[0], pFakeEntry );
612 nOfs += nFpgmSize;
614 if( nCffSize ) {
615 if( nCffSize != pMacFont->GetFontTable( "CFF ", &rBuffer[nOfs]))
616 return false;
617 FakeDirEntry( "CFF ", nOfs, nCffSize, &rBuffer[0], pFakeEntry );
618 nOfs += nGlyfSize;
619 } else {
620 if( nGlyfSize != pMacFont->GetFontTable( "glyf", &rBuffer[nOfs]))
621 return false;
622 FakeDirEntry( "glyf", nOfs, nGlyfSize, &rBuffer[0], pFakeEntry );
623 nOfs += nGlyfSize;
624 if( nLocaSize != pMacFont->GetFontTable( "loca", &rBuffer[nOfs]))
625 return false;
626 FakeDirEntry( "loca", nOfs, nLocaSize, &rBuffer[0], pFakeEntry );
627 nOfs += nLocaSize;
629 if( nHeadSize != pMacFont->GetFontTable( "head", &rBuffer[nOfs]))
630 return false;
631 FakeDirEntry( "head", nOfs, nHeadSize, &rBuffer[0], pFakeEntry );
632 nOfs += nHeadSize;
633 if( nHheaSize != pMacFont->GetFontTable( "hhea", &rBuffer[nOfs]))
634 return false;
635 FakeDirEntry( "hhea", nOfs, nHheaSize, &rBuffer[0], pFakeEntry );
636 nOfs += nHheaSize;
637 if( nHmtxSize != pMacFont->GetFontTable( "hmtx", &rBuffer[nOfs]))
638 return false;
639 FakeDirEntry( "hmtx", nOfs, nHmtxSize, &rBuffer[0], pFakeEntry );
640 nOfs += nHmtxSize;
641 if( nMaxpSize != pMacFont->GetFontTable( "maxp", &rBuffer[nOfs]))
642 return false;
643 FakeDirEntry( "maxp", nOfs, nMaxpSize, &rBuffer[0], pFakeEntry );
644 nOfs += nMaxpSize;
645 if( nNameSize != pMacFont->GetFontTable( "name", &rBuffer[nOfs]))
646 return false;
647 FakeDirEntry( "name", nOfs, nNameSize, &rBuffer[0], pFakeEntry );
648 nOfs += nNameSize;
649 if( nPrepSize ) {
650 if( nPrepSize != pMacFont->GetFontTable( "prep", &rBuffer[nOfs]))
651 return false;
652 FakeDirEntry( "prep", nOfs, nPrepSize, &rBuffer[0], pFakeEntry );
653 nOfs += nPrepSize;
656 DBG_ASSERT( (nOfs==nTotalSize), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)");
658 return true;
661 void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bVertical,
662 Int32Vector& rGlyphWidths, Ucs2UIntMap& rUnicodeEnc )
664 rGlyphWidths.clear();
665 rUnicodeEnc.clear();
667 if( pFontData->IsSubsettable() )
669 ByteVector aBuffer;
670 if( !GetRawFontData( pFontData, aBuffer, NULL ) )
671 return;
673 // TODO: modernize psprint's horrible fontsubset C-API
674 // this probably only makes sense after the switch to another SCM
675 // that can preserve change history after file renames
677 // use the font subsetter to get the widths
678 TrueTypeFont* pSftFont = NULL;
679 int nRC = ::OpenTTFontBuffer( (void*)&aBuffer[0], aBuffer.size(), 0, &pSftFont);
680 if( nRC != SF_OK )
681 return;
683 const int nGlyphCount = ::GetTTGlyphCount( pSftFont );
684 if( nGlyphCount > 0 )
686 // get glyph metrics
687 rGlyphWidths.resize(nGlyphCount);
688 std::vector<sal_uInt16> aGlyphIds(nGlyphCount);
689 for( int i = 0; i < nGlyphCount; i++ )
690 aGlyphIds[i] = static_cast<sal_uInt16>(i);
691 const TTSimpleGlyphMetrics* pGlyphMetrics = ::GetTTSimpleGlyphMetrics(
692 pSftFont, &aGlyphIds[0], nGlyphCount, bVertical );
693 if( pGlyphMetrics )
695 for( int i = 0; i < nGlyphCount; ++i )
696 rGlyphWidths[i] = pGlyphMetrics[i].adv;
697 free( (void*)pGlyphMetrics );
700 FontCharMapPtr pMap = mpFontData->GetFontCharMap();
701 DBG_ASSERT( pMap && pMap->GetCharCount(), "no charmap" );
703 // get unicode<->glyph encoding
704 // TODO? avoid sft mapping by using the pMap itself
705 int nCharCount = pMap->GetCharCount();
706 sal_uInt32 nChar = pMap->GetFirstChar();
707 for(; --nCharCount >= 0; nChar = pMap->GetNextChar( nChar ) )
709 if( nChar > 0xFFFF ) // TODO: allow UTF-32 chars
710 break;
711 sal_Ucs nUcsChar = static_cast<sal_Ucs>(nChar);
712 sal_uInt32 nGlyph = ::MapChar( pSftFont, nUcsChar, bVertical );
713 if( nGlyph > 0 )
714 rUnicodeEnc[ nUcsChar ] = nGlyph;
717 pMap = 0;
720 ::CloseTTFont( pSftFont );
722 else if( pFontData->IsEmbeddable() )
724 // get individual character widths
725 OSL_FAIL("not implemented for non-subsettable fonts!\n");
729 const Ucs2SIntMap* AquaSalGraphics::GetFontEncodingVector(
730 const PhysicalFontFace*, const Ucs2OStrMap** /*ppNonEncoded*/, std::set<sal_Unicode> const** )
732 return NULL;
735 const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace*,
736 const sal_Ucs* /*pUnicodes*/,
737 sal_Int32* /*pWidths*/,
738 size_t /*nLen*/,
739 FontSubsetInfo&,
740 long* /*pDataLen*/ )
742 return NULL;
745 void AquaSalGraphics::FreeEmbedFontData( const void* pData, long /*nDataLen*/ )
747 // TODO: implementing this only makes sense when the implementation of
748 // AquaSalGraphics::GetEmbedFontData() returns non-NULL
749 (void)pData;
750 DBG_ASSERT( (pData!=NULL), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n");
753 SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const
755 SystemFontData aSysFontData;
756 aSysFontData.nSize = sizeof( SystemFontData );
758 aSysFontData.bAntialias = !mbNonAntialiasedText;
760 return aSysFontData;
763 bool AquaSalGraphics::IsFlipped() const
765 #ifdef MACOSX
766 return mbWindow;
767 #else
768 return false;
769 #endif
772 void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight)
774 #ifdef MACOSX
775 if( ! mbWindow ) // view only on Window graphics
776 return;
778 if( mpFrame )
780 // update a little more around the designated rectangle
781 // this helps with antialiased rendering
782 // Rounding down x and width can accumulate a rounding error of up to 2
783 // The decrementing of x, the rounding error and the antialiasing border
784 // require that the width and the height need to be increased by four
785 const Rectangle aVclRect(Point(static_cast<long int>(lX-1),
786 static_cast<long int>(lY-1) ),
787 Size( static_cast<long int>(lWidth+4),
788 static_cast<long int>(lHeight+4) ) );
789 mpFrame->maInvalidRect.Union( aVclRect );
791 #else
792 (void) lX;
793 (void) lY;
794 (void) lWidth;
795 (void) lHeight;
796 return;
797 #endif
800 #ifdef IOS
802 bool AquaSalGraphics::CheckContext()
804 if (mbForeignContext)
806 SAL_INFO("vcl.ios", "CheckContext() this=" << this << ", mbForeignContext, return true");
807 return true;
810 SAL_INFO( "vcl.ios", "CheckContext() this=" << this << ", not foreign, return false");
811 return false;
814 CGContextRef AquaSalGraphics::GetContext()
816 if ( !mrContext )
817 CheckContext();
819 return mrContext;
822 #endif
824 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */