1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
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"
41 #include "coretext/salgdi2.h"
44 #include "aqua/salframe.h"
48 #include "saldatabasic.hxx"
49 #include <basebmp/scanlineformats.hxx>
52 #include "ctfonts.hxx"
54 #include "fontsubset.hxx"
55 #include "impfont.hxx"
56 #include "sallayout.hxx"
62 // =======================================================================
64 SystemFontList::~SystemFontList( void )
68 // =======================================================================
70 ImplMacTextStyle::ImplMacTextStyle( const FontSelectPattern
& rReqFont
)
71 : mpFontData( (ImplMacFontData
*)rReqFont
.mpFontData
)
72 , mfFontStretch( 1.0 )
73 , mfFontRotation( 0.0 )
76 // -----------------------------------------------------------------------
78 ImplMacTextStyle::~ImplMacTextStyle( void )
81 // =======================================================================
83 ImplMacFontData::ImplMacFontData( const ImplMacFontData
& rSrc
)
84 : PhysicalFontFace( rSrc
)
85 , mnFontId( rSrc
.mnFontId
)
86 , mpCharMap( rSrc
.mpCharMap
)
87 , mbOs2Read( rSrc
.mbOs2Read
)
88 , mbHasOs2Table( rSrc
.mbHasOs2Table
)
89 , mbCmapEncodingRead( rSrc
.mbCmapEncodingRead
)
92 mpCharMap
->AddReference();
95 // -----------------------------------------------------------------------
97 ImplMacFontData::ImplMacFontData( const ImplDevFontAttributes
& rDFA
, sal_IntPtr nFontId
)
98 : PhysicalFontFace( rDFA
, 0 )
102 , mbHasOs2Table( false )
103 , mbCmapEncodingRead( false )
104 , mbFontCapabilitiesRead( false )
107 // -----------------------------------------------------------------------
109 ImplMacFontData::~ImplMacFontData()
112 mpCharMap
->DeReference();
115 // -----------------------------------------------------------------------
117 sal_IntPtr
ImplMacFontData::GetFontId() const
119 return (sal_IntPtr
)mnFontId
;
122 // -----------------------------------------------------------------------
124 ImplFontEntry
* ImplMacFontData::CreateFontInstance(FontSelectPattern
& rFSD
) const
126 return new ImplFontEntry(rFSD
);
129 // -----------------------------------------------------------------------
131 static unsigned GetUShort( const unsigned char* p
){return((p
[0]<<8)+p
[1]);}
133 const ImplFontCharMap
* ImplMacFontData::GetImplFontCharMap() const
135 // return the cached charmap
139 // set the default charmap
140 mpCharMap
= ImplFontCharMap::GetDefaultMap();
141 mpCharMap
->AddReference();
143 // get the CMAP byte size
144 // allocate a buffer for the CMAP raw data
145 const int nBufSize
= GetFontTable( "cmap", NULL
);
146 DBG_ASSERT( (nBufSize
> 0), "ImplMacFontData::GetImplFontCharMap : GetFontTable1 failed!\n");
150 // get the CMAP raw data
151 ByteVector
aBuffer( nBufSize
);
152 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
153 DBG_ASSERT( (nRawLength
> 0), "ImplMacFontData::GetImplFontCharMap : GetFontTable2 failed!\n");
154 if( nRawLength
<= 0 )
156 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::GetImplFontCharMap : ByteCount mismatch!\n");
159 CmapResult aCmapResult
;
160 if( ParseCMAP( &aBuffer
[0], nRawLength
, aCmapResult
) )
162 // create the matching charmap
163 mpCharMap
->DeReference();
164 mpCharMap
= new ImplFontCharMap( aCmapResult
);
165 mpCharMap
->AddReference();
171 bool ImplMacFontData::GetImplFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
173 // read this only once per font
174 if( mbFontCapabilitiesRead
)
176 rFontCapabilities
= maFontCapabilities
;
177 return !rFontCapabilities
.maUnicodeRange
.empty() || !rFontCapabilities
.maCodePageRange
.empty();
179 mbFontCapabilitiesRead
= true;
182 // prepare to get the GSUB table raw data
183 nBufSize
= GetFontTable( "GSUB", NULL
);
186 // allocate a buffer for the GSUB raw data
187 ByteVector
aBuffer( nBufSize
);
188 // get the GSUB raw data
189 const int nRawLength
= GetFontTable( "GSUB", &aBuffer
[0] );
192 const unsigned char* pGSUBTable
= &aBuffer
[0];
193 vcl::getTTScripts(maFontCapabilities
.maGSUBScriptTags
, pGSUBTable
, nRawLength
);
196 nBufSize
= GetFontTable( "OS/2", NULL
);
199 // allocate a buffer for the OS/2 raw data
200 ByteVector
aBuffer( nBufSize
);
201 // get the OS/2 raw data
202 const int nRawLength
= GetFontTable( "OS/2", &aBuffer
[0] );
205 const unsigned char* pOS2Table
= &aBuffer
[0];
207 maFontCapabilities
.maUnicodeRange
,
208 maFontCapabilities
.maCodePageRange
,
209 pOS2Table
, nRawLength
);
212 rFontCapabilities
= maFontCapabilities
;
213 return !rFontCapabilities
.maUnicodeRange
.empty() || !rFontCapabilities
.maCodePageRange
.empty();
216 // -----------------------------------------------------------------------
218 void ImplMacFontData::ReadOs2Table( void ) const
220 // read this only once per font
224 mbHasOs2Table
= false;
226 // prepare to get the OS/2 table raw data
227 const int nBufSize
= GetFontTable( "OS/2", NULL
);
228 DBG_ASSERT( (nBufSize
> 0), "ImplMacFontData::ReadOs2Table : GetFontTable1 failed!\n");
232 // get the OS/2 raw data
233 ByteVector
aBuffer( nBufSize
);
234 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
235 DBG_ASSERT( (nRawLength
> 0), "ImplMacFontData::ReadOs2Table : GetFontTable2 failed!\n");
236 if( nRawLength
<= 0 )
238 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::ReadOs2Table : ByteCount mismatch!\n");
239 mbHasOs2Table
= true;
241 // parse the OS/2 raw data
242 // TODO: also analyze panose info, etc.
245 void ImplMacFontData::ReadMacCmapEncoding( void ) const
247 // read this only once per font
248 if( mbCmapEncodingRead
)
250 mbCmapEncodingRead
= true;
252 const int nBufSize
= GetFontTable( "cmap", NULL
);
256 // get the CMAP raw data
257 ByteVector
aBuffer( nBufSize
);
258 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
259 if( nRawLength
< 24 )
261 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::ReadMacCmapEncoding : ByteCount mismatch!\n");
263 const unsigned char* pCmap
= &aBuffer
[0];
264 if( GetUShort( pCmap
) != 0x0000 )
268 // -----------------------------------------------------------------------
270 AquaSalGraphics::AquaSalGraphics()
275 , mpXorEmulation( NULL
)
282 , mfFakeDPIScale( 1.0 )
284 , maLineColor( COL_WHITE
)
285 , maFillColor( COL_BLACK
)
286 , mpMacFontData( NULL
)
287 , mpMacTextStyle( NULL
)
288 , maTextColor( COL_BLACK
)
289 , mbNonAntialiasedText( false )
295 , mfFakeDPIScale( 1.0 )
296 , mpMacFontData( NULL
)
297 , mpMacTextStyle( NULL
)
298 , maTextColor( COL_BLACK
)
299 , mbNonAntialiasedText( false )
303 // -----------------------------------------------------------------------
305 AquaSalGraphics::~AquaSalGraphics()
308 CGPathRelease( mxClipPath
);
309 delete mpMacTextStyle
;
312 delete mpXorEmulation
;
315 CGLayerRelease( mxLayer
);
316 else if( mrContext
&& mbWindow
)
318 // destroy backbuffer bitmap context that we created ourself
319 CGContextRelease( mrContext
);
321 // memory is freed automatically by maOwnContextMemory
326 // =======================================================================
328 void AquaSalGraphics::SetTextColor( SalColor nSalColor
)
330 maTextColor
= RGBAColor( nSalColor
);
332 mpMacTextStyle
->SetTextColor( maTextColor
);
335 // -----------------------------------------------------------------------
337 void AquaSalGraphics::GetFontMetric( ImplFontMetricData
* pMetric
, int /*nFallbackLevel*/ )
339 mpMacTextStyle
->GetFontMetric( mfFakeDPIScale
, *pMetric
);
342 // -----------------------------------------------------------------------
344 static bool AddTempDevFont(const OUString
& rFontFileURL
)
346 OUString aUSytemPath
;
347 OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL
, aUSytemPath
) );
348 OString aCFileName
= OUStringToOString( aUSytemPath
, RTL_TEXTENCODING_UTF8
);
350 CFStringRef rFontPath
= CFStringCreateWithCString(NULL
, aCFileName
.getStr(), kCFStringEncodingUTF8
);
351 CFURLRef rFontURL
= CFURLCreateWithFileSystemPath(NULL
, rFontPath
, kCFURLPOSIXPathStyle
, true);
354 bool success
= CTFontManagerRegisterFontsForURL(rFontURL
, kCTFontManagerScopeProcess
, &error
);
365 static void AddTempFontDir( const OUString
&rFontDirUrl
)
367 osl::Directory
aFontDir( rFontDirUrl
);
368 osl::FileBase::RC rcOSL
= aFontDir
.open();
369 if( rcOSL
== osl::FileBase::E_None
)
371 osl::DirectoryItem aDirItem
;
373 while( aFontDir
.getNextItem( aDirItem
, 10 ) == osl::FileBase::E_None
)
375 osl::FileStatus
aFileStatus( osl_FileStatus_Mask_FileURL
);
376 rcOSL
= aDirItem
.getFileStatus( aFileStatus
);
377 if ( rcOSL
== osl::FileBase::E_None
)
378 AddTempDevFont(aFileStatus
.getFileURL());
383 static void AddLocalTempFontDirs()
385 static bool bFirst
= true;
390 // add private font files
392 OUString
aBrandStr( "$BRAND_BASE_DIR" );
393 rtl_bootstrap_expandMacros( &aBrandStr
.pData
);
394 AddTempFontDir( aBrandStr
+ "/" LIBO_SHARE_FOLDER
"/fonts/truetype/" );
397 void AquaSalGraphics::GetDevFontList( ImplDevFontList
* pFontList
)
399 DBG_ASSERT( pFontList
, "AquaSalGraphics::GetDevFontList(NULL) !");
401 AddLocalTempFontDirs();
403 // The idea is to cache the list of system fonts once it has been generated.
404 // SalData seems to be a good place for this caching. However we have to
405 // carefully make the access to the font list thread-safe. If we register
406 // a font-change event handler to update the font list in case fonts have
407 // changed on the system we have to lock access to the list. The right
408 // way to do that is the solar mutex since GetDevFontList is protected
409 // through it as should be all event handlers
411 SalData
* pSalData
= GetSalData();
412 if( !pSalData
->mpFontList
)
413 pSalData
->mpFontList
= GetCoretextFontList();
415 // Copy all PhysicalFontFace objects contained in the SystemFontList
416 pSalData
->mpFontList
->AnnounceFonts( *pFontList
);
419 void AquaSalGraphics::ClearDevFontCache()
421 SalData
* pSalData
= GetSalData();
422 delete pSalData
->mpFontList
;
423 pSalData
->mpFontList
= NULL
;
426 // -----------------------------------------------------------------------
428 bool AquaSalGraphics::AddTempDevFont( ImplDevFontList
*,
429 const OUString
& rFontFileURL
, const OUString
& /*rFontName*/ )
431 return ::AddTempDevFont(rFontFileURL
);
434 // -----------------------------------------------------------------------
436 sal_Bool
AquaSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphId
, basegfx::B2DPolyPolygon
& rPolyPoly
)
438 const bool bRC
= mpMacTextStyle
->GetGlyphOutline( nGlyphId
, rPolyPoly
);
442 // -----------------------------------------------------------------------
444 sal_Bool
AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphId
, Rectangle
& rRect
)
446 const bool bRC
= mpMacTextStyle
->GetGlyphBoundRect( nGlyphId
, rRect
);
450 // -----------------------------------------------------------------------
452 void AquaSalGraphics::GetDevFontSubstList( OutputDevice
* )
454 // nothing to do since there are no device-specific fonts on Aqua
457 // -----------------------------------------------------------------------
459 void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout
& )
463 // -----------------------------------------------------------------------
465 sal_uInt16
AquaSalGraphics::SetFont( FontSelectPattern
* pReqFont
, int /*nFallbackLevel*/ )
467 // release the text style
468 delete mpMacTextStyle
;
469 mpMacTextStyle
= NULL
;
471 // handle NULL request meaning: release-font-resources request
474 mpMacFontData
= NULL
;
478 // update the text style
479 mpMacFontData
= static_cast<const ImplMacFontData
*>( pReqFont
->mpFontData
);
480 mpMacTextStyle
= mpMacFontData
->CreateMacTextStyle( *pReqFont
);
481 mpMacTextStyle
->SetTextColor( maTextColor
);
483 SAL_INFO("vcl.coretext",
485 << " to " << mpMacFontData
->GetFamilyName()
486 << ", " << mpMacFontData
->GetStyleName()
487 << " fontid=" << mpMacFontData
->GetFontId()
488 << " for " << pReqFont
->GetFamilyName()
489 << ", " << pReqFont
->GetStyleName()
490 << " weight=" << pReqFont
->GetWeight()
491 << " slant=" << pReqFont
->GetSlant()
492 << " size=" << pReqFont
->mnHeight
<< "x" << pReqFont
->mnWidth
493 << " orientation=" << pReqFont
->mnOrientation
499 // -----------------------------------------------------------------------
501 SalLayout
* AquaSalGraphics::GetTextLayout( ImplLayoutArgs
& /*rArgs*/, int /*nFallbackLevel*/ )
503 SalLayout
* pSalLayout
= mpMacTextStyle
->GetTextLayout();
507 // -----------------------------------------------------------------------
509 const ImplFontCharMap
* AquaSalGraphics::GetImplFontCharMap() const
512 return ImplFontCharMap::GetDefaultMap();
514 return mpMacFontData
->GetImplFontCharMap();
517 bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
522 return mpMacFontData
->GetImplFontCapabilities(rFontCapabilities
);
525 // -----------------------------------------------------------------------
527 // fake a SFNT font directory entry for a font table
528 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory
529 static void FakeDirEntry( const char aTag
[5], ByteCount nOfs
, ByteCount nLen
,
530 const unsigned char* /*pData*/, unsigned char*& rpDest
)
533 rpDest
[ 0] = aTag
[0];
534 rpDest
[ 1] = aTag
[1];
535 rpDest
[ 2] = aTag
[2];
536 rpDest
[ 3] = aTag
[3];
537 // TODO: get entry checksum and write it
538 // not too important since the subsetter doesn't care currently
539 // for( pData+nOfs ... pData+nOfs+nLen )
540 // write entry offset
541 rpDest
[ 8] = (char)(nOfs
>> 24);
542 rpDest
[ 9] = (char)(nOfs
>> 16);
543 rpDest
[10] = (char)(nOfs
>> 8);
544 rpDest
[11] = (char)(nOfs
>> 0);
545 // write entry length
546 rpDest
[12] = (char)(nLen
>> 24);
547 rpDest
[13] = (char)(nLen
>> 16);
548 rpDest
[14] = (char)(nLen
>> 8);
549 rpDest
[15] = (char)(nLen
>> 0);
550 // advance to next entry
554 // fake a TTF or CFF font as directly accessing font file is not possible
555 // when only the fontid is known. This approach also handles *.dfont fonts.
556 bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace
* pFontData
,
557 ByteVector
& rBuffer
, bool* pJustCFF
)
559 const ImplMacFontData
* pMacFont
= static_cast<const ImplMacFontData
*>(pFontData
);
561 // short circuit for CFF-only fonts
562 const int nCffSize
= pMacFont
->GetFontTable( "CFF ", NULL
);
563 if( pJustCFF
!= NULL
)
565 *pJustCFF
= (nCffSize
> 0);
568 rBuffer
.resize( nCffSize
);
569 const int nCffRead
= pMacFont
->GetFontTable( "CFF ", &rBuffer
[0]);
570 if( nCffRead
!= nCffSize
)
576 // get font table availability and size in bytes
577 const int nHeadSize
= pMacFont
->GetFontTable( "head", NULL
);
580 const int nMaxpSize
= pMacFont
->GetFontTable( "maxp", NULL
);
583 const int nCmapSize
= pMacFont
->GetFontTable( "cmap", NULL
);
586 const int nNameSize
= pMacFont
->GetFontTable( "name", NULL
);
589 const int nHheaSize
= pMacFont
->GetFontTable( "hhea", NULL
);
592 const int nHmtxSize
= pMacFont
->GetFontTable( "hmtx", NULL
);
596 // get the ttf-glyf outline tables
601 nLocaSize
= pMacFont
->GetFontTable( "loca", NULL
);
604 nGlyfSize
= pMacFont
->GetFontTable( "glyf", NULL
);
609 int nPrepSize
= 0, nCvtSize
= 0, nFpgmSize
= 0;
610 if( nGlyfSize
) // TODO: reduce PDF size by making hint subsetting optional
612 nPrepSize
= pMacFont
->GetFontTable( "prep", NULL
);
613 nCvtSize
= pMacFont
->GetFontTable( "cvt ", NULL
);
614 nFpgmSize
= pMacFont
->GetFontTable( "fpgm", NULL
);
617 // prepare a byte buffer for a fake font
619 nTableCount
+= (nPrepSize
>0) + (nCvtSize
>0) + (nFpgmSize
>0) + (nGlyfSize
>0);
620 const ByteCount nFdirSize
= 12 + 16*nTableCount
;
621 ByteCount nTotalSize
= nFdirSize
;
622 nTotalSize
+= nHeadSize
+ nMaxpSize
+ nNameSize
+ nCmapSize
;
624 nTotalSize
+= nLocaSize
+ nGlyfSize
;
626 nTotalSize
+= nCffSize
;
627 nTotalSize
+= nHheaSize
+ nHmtxSize
;
628 nTotalSize
+= nPrepSize
+ nCvtSize
+ nFpgmSize
;
629 rBuffer
.resize( nTotalSize
);
631 // fake a SFNT font directory header
632 if( nTableCount
< 16 )
635 while( (nTableCount
>> nLog2
) > 1 ) ++nLog2
;
636 rBuffer
[ 1] = 1; // Win-TTF style scaler
637 rBuffer
[ 5] = nTableCount
; // table count
638 rBuffer
[ 7] = nLog2
*16; // searchRange
639 rBuffer
[ 9] = nLog2
; // entrySelector
640 rBuffer
[11] = (nTableCount
-nLog2
)*16; // rangeShift
643 // get font table raw data and update the fake directory entries
644 ByteCount nOfs
= nFdirSize
;
645 unsigned char* pFakeEntry
= &rBuffer
[12];
646 if( nCmapSize
!= pMacFont
->GetFontTable( "cmap", &rBuffer
[nOfs
]))
648 FakeDirEntry( "cmap", nOfs
, nCmapSize
, &rBuffer
[0], pFakeEntry
);
651 if( nCvtSize
!= pMacFont
->GetFontTable( "cvt ", &rBuffer
[nOfs
]))
653 FakeDirEntry( "cvt ", nOfs
, nCvtSize
, &rBuffer
[0], pFakeEntry
);
657 if( nFpgmSize
!= pMacFont
->GetFontTable( "fpgm", &rBuffer
[nOfs
]))
659 FakeDirEntry( "fpgm", nOfs
, nFpgmSize
, &rBuffer
[0], pFakeEntry
);
663 if( nCffSize
!= pMacFont
->GetFontTable( "CFF ", &rBuffer
[nOfs
]))
665 FakeDirEntry( "CFF ", nOfs
, nCffSize
, &rBuffer
[0], pFakeEntry
);
668 if( nGlyfSize
!= pMacFont
->GetFontTable( "glyf", &rBuffer
[nOfs
]))
670 FakeDirEntry( "glyf", nOfs
, nGlyfSize
, &rBuffer
[0], pFakeEntry
);
672 if( nLocaSize
!= pMacFont
->GetFontTable( "loca", &rBuffer
[nOfs
]))
674 FakeDirEntry( "loca", nOfs
, nLocaSize
, &rBuffer
[0], pFakeEntry
);
677 if( nHeadSize
!= pMacFont
->GetFontTable( "head", &rBuffer
[nOfs
]))
679 FakeDirEntry( "head", nOfs
, nHeadSize
, &rBuffer
[0], pFakeEntry
);
681 if( nHheaSize
!= pMacFont
->GetFontTable( "hhea", &rBuffer
[nOfs
]))
683 FakeDirEntry( "hhea", nOfs
, nHheaSize
, &rBuffer
[0], pFakeEntry
);
685 if( nHmtxSize
!= pMacFont
->GetFontTable( "hmtx", &rBuffer
[nOfs
]))
687 FakeDirEntry( "hmtx", nOfs
, nHmtxSize
, &rBuffer
[0], pFakeEntry
);
689 if( nMaxpSize
!= pMacFont
->GetFontTable( "maxp", &rBuffer
[nOfs
]))
691 FakeDirEntry( "maxp", nOfs
, nMaxpSize
, &rBuffer
[0], pFakeEntry
);
693 if( nNameSize
!= pMacFont
->GetFontTable( "name", &rBuffer
[nOfs
]))
695 FakeDirEntry( "name", nOfs
, nNameSize
, &rBuffer
[0], pFakeEntry
);
698 if( nPrepSize
!= pMacFont
->GetFontTable( "prep", &rBuffer
[nOfs
]))
700 FakeDirEntry( "prep", nOfs
, nPrepSize
, &rBuffer
[0], pFakeEntry
);
704 DBG_ASSERT( (nOfs
==nTotalSize
), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)");
709 // -----------------------------------------------------------------------
711 void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace
* pFontData
, bool bVertical
,
712 Int32Vector
& rGlyphWidths
, Ucs2UIntMap
& rUnicodeEnc
)
714 rGlyphWidths
.clear();
717 if( pFontData
->IsSubsettable() )
720 if( !GetRawFontData( pFontData
, aBuffer
, NULL
) )
723 // TODO: modernize psprint's horrible fontsubset C-API
724 // this probably only makes sense after the switch to another SCM
725 // that can preserve change history after file renames
727 // use the font subsetter to get the widths
728 TrueTypeFont
* pSftFont
= NULL
;
729 int nRC
= ::OpenTTFontBuffer( (void*)&aBuffer
[0], aBuffer
.size(), 0, &pSftFont
);
733 const int nGlyphCount
= ::GetTTGlyphCount( pSftFont
);
734 if( nGlyphCount
> 0 )
737 rGlyphWidths
.resize(nGlyphCount
);
738 std::vector
<sal_uInt16
> aGlyphIds(nGlyphCount
);
739 for( int i
= 0; i
< nGlyphCount
; i
++ )
740 aGlyphIds
[i
] = static_cast<sal_uInt16
>(i
);
741 const TTSimpleGlyphMetrics
* pGlyphMetrics
= ::GetTTSimpleGlyphMetrics(
742 pSftFont
, &aGlyphIds
[0], nGlyphCount
, bVertical
);
745 for( int i
= 0; i
< nGlyphCount
; ++i
)
746 rGlyphWidths
[i
] = pGlyphMetrics
[i
].adv
;
747 free( (void*)pGlyphMetrics
);
750 const ImplFontCharMap
* pMap
= mpMacFontData
->GetImplFontCharMap();
751 DBG_ASSERT( pMap
&& pMap
->GetCharCount(), "no charmap" );
752 pMap
->AddReference(); // TODO: add and use RAII object instead
754 // get unicode<->glyph encoding
755 // TODO? avoid sft mapping by using the pMap itself
756 int nCharCount
= pMap
->GetCharCount();
757 sal_uInt32 nChar
= pMap
->GetFirstChar();
758 for(; --nCharCount
>= 0; nChar
= pMap
->GetNextChar( nChar
) )
760 if( nChar
> 0xFFFF ) // TODO: allow UTF-32 chars
762 sal_Ucs nUcsChar
= static_cast<sal_Ucs
>(nChar
);
763 sal_uInt32 nGlyph
= ::MapChar( pSftFont
, nUcsChar
, bVertical
);
765 rUnicodeEnc
[ nUcsChar
] = nGlyph
;
768 pMap
->DeReference(); // TODO: add and use RAII object instead
771 ::CloseTTFont( pSftFont
);
773 else if( pFontData
->IsEmbeddable() )
775 // get individual character widths
776 OSL_FAIL("not implemented for non-subsettable fonts!\n");
780 // -----------------------------------------------------------------------
782 const Ucs2SIntMap
* AquaSalGraphics::GetFontEncodingVector(
783 const PhysicalFontFace
*, const Ucs2OStrMap
** /*ppNonEncoded*/ )
788 // -----------------------------------------------------------------------
790 const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace
*,
791 const sal_Ucs
* /*pUnicodes*/,
792 sal_Int32
* /*pWidths*/,
799 // -----------------------------------------------------------------------
801 void AquaSalGraphics::FreeEmbedFontData( const void* pData
, long /*nDataLen*/ )
803 // TODO: implementing this only makes sense when the implementation of
804 // AquaSalGraphics::GetEmbedFontData() returns non-NULL
806 DBG_ASSERT( (pData
!=NULL
), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n");
809 // -----------------------------------------------------------------------
811 SystemFontData
AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const
813 SystemFontData aSysFontData
;
814 aSysFontData
.nSize
= sizeof( SystemFontData
);
816 aSysFontData
.bAntialias
= !mbNonAntialiasedText
;
823 // Note that "SvpSalGraphics" is actually called AquaSalGraphics for iOS
825 bool SvpSalGraphics::CheckContext()
827 const basegfx::B2IVector size
= m_aDevice
->getSize();
828 const basegfx::B2IVector bufferSize
= m_aDevice
->getBufferSize();
829 const sal_Int32 scanlineStride
= m_aDevice
->getScanlineStride();
830 basebmp::RawMemorySharedArray pixelBuffer
= m_aDevice
->getBuffer();
834 "CheckContext: device=" << m_aDevice
.get() <<
835 " size=" << size
.getX() << "x" << size
.getY() <<
836 (m_aDevice
->isTopDown() ? " top-down" : " bottom-up") <<
837 " stride=" << scanlineStride
<<
838 " bufferSize=(" << bufferSize
.getX() << "," << bufferSize
.getY() << ")" );
840 switch( m_aDevice
->getScanlineFormat() ) {
841 case basebmp::FORMAT_EIGHT_BIT_PAL
:
842 mrContext
= CGBitmapContextCreate(pixelBuffer
.get(),
843 bufferSize
.getX(), bufferSize
.getY(),
845 CGColorSpaceCreateDeviceGray(),
848 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_RGBA
:
849 mrContext
= CGBitmapContextCreate(pixelBuffer
.get(),
850 bufferSize
.getX(), bufferSize
.getY(),
852 CGColorSpaceCreateDeviceRGB(),
853 kCGImageAlphaNoneSkipLast
);
855 case basebmp::FORMAT_THIRTYTWO_BIT_TC_MASK_BGRA
:
856 mrContext
= CGBitmapContextCreate(pixelBuffer
.get(),
857 bufferSize
.getX(), bufferSize
.getY(),
859 CGColorSpaceCreateDeviceRGB(),
860 kCGImageAlphaNoneSkipFirst
| kCGBitmapByteOrder32Little
);
863 SAL_WARN( "vcl.ios", "CheckContext: unsupported color format " << basebmp::formatName( m_aDevice
->getScanlineFormat() ) );
867 SAL_WARN_IF( mrContext
== NULL
&& !warned
, "vcl.ios", "CheckContext: CGBitmapContextCreate() failed" );
869 // Should we also clip the context? (Then we need to add a
870 // getBounds() function to BitmapDevice.)
872 if( mrContext
!= NULL
&& m_aDevice
->isTopDown() )
874 CGContextTranslateCTM( mrContext
, 0, bufferSize
.getY() );
875 CGContextScaleCTM( mrContext
, 1, -1 );
881 RectangleVector aRectangles
;
882 m_aClipRegion
.GetRegionRectangles(aRectangles
);
884 CGContextBeginPath( mrContext
);
886 for(RectangleVector::const_iterator
aRectIter(aRectangles
.begin()); aRectIter
!= aRectangles
.end(); ++aRectIter
)
888 const long nW(aRectIter
->Right() - aRectIter
->Left() + 1); // uses +1 logic in original
892 const long nH(aRectIter
->Bottom() - aRectIter
->Top() + 1); // uses +1 logic in original
896 CGRect aRect
= {{ (CGFloat
) aRectIter
->Left(), (CGFloat
) aRectIter
->Top() }, { (CGFloat
) nW
, (CGFloat
) nH
}};
897 CGContextAddRect( mrContext
, aRect
);
902 if (!CGContextIsPathEmpty(mrContext
))
903 CGContextClip(mrContext
);
907 SAL_INFO( "vcl.ios", "CheckContext: context=" << mrContext
);
909 return ( mrContext
!= NULL
);
912 CGContextRef
SvpSalGraphics::GetContext()
922 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */