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 "sal/config.h"
22 #include "osl/file.hxx"
23 #include "osl/process.h"
25 #include "osl/mutex.hxx"
27 #include "rtl/bootstrap.h"
28 #include "rtl/strbuf.hxx"
30 #include "basegfx/range/b2drectangle.hxx"
31 #include "basegfx/polygon/b2dpolygon.hxx"
32 #include "basegfx/polygon/b2dpolygontools.hxx"
33 #include "basegfx/matrix/b2dhommatrix.hxx"
34 #include "basegfx/matrix/b2dhommatrixtools.hxx"
36 #include "vcl/sysdata.hxx"
37 #include "vcl/svapp.hxx"
39 #include "coretext/salgdi2.h"
42 #include "aqua/salframe.h"
46 #include "saldatabasic.hxx"
47 #include <basebmp/scanlineformats.hxx>
50 #include "ctfonts.hxx"
52 #include "fontsubset.hxx"
53 #include "impfont.hxx"
54 #include "sallayout.hxx"
60 // =======================================================================
62 SystemFontList::~SystemFontList( void )
66 // =======================================================================
68 ImplMacTextStyle::ImplMacTextStyle( const FontSelectPattern
& rReqFont
)
69 : mpFontData( (ImplMacFontData
*)rReqFont
.mpFontData
)
70 , mfFontStretch( 1.0 )
71 , mfFontRotation( 0.0 )
74 // -----------------------------------------------------------------------
76 ImplMacTextStyle::~ImplMacTextStyle( void )
79 // =======================================================================
81 ImplMacFontData::ImplMacFontData( const ImplMacFontData
& rSrc
)
82 : PhysicalFontFace( rSrc
)
83 , mnFontId( rSrc
.mnFontId
)
84 , mpCharMap( rSrc
.mpCharMap
)
85 , mbOs2Read( rSrc
.mbOs2Read
)
86 , mbHasOs2Table( rSrc
.mbHasOs2Table
)
87 , mbCmapEncodingRead( rSrc
.mbCmapEncodingRead
)
90 mpCharMap
->AddReference();
93 // -----------------------------------------------------------------------
95 ImplMacFontData::ImplMacFontData( const ImplDevFontAttributes
& rDFA
, sal_IntPtr nFontId
)
96 : PhysicalFontFace( rDFA
, 0 )
100 , mbHasOs2Table( false )
101 , mbCmapEncodingRead( false )
102 , mbFontCapabilitiesRead( false )
105 // -----------------------------------------------------------------------
107 ImplMacFontData::~ImplMacFontData()
110 mpCharMap
->DeReference();
113 // -----------------------------------------------------------------------
115 sal_IntPtr
ImplMacFontData::GetFontId() const
117 return (sal_IntPtr
)mnFontId
;
120 // -----------------------------------------------------------------------
122 ImplFontEntry
* ImplMacFontData::CreateFontInstance(FontSelectPattern
& rFSD
) const
124 return new ImplFontEntry(rFSD
);
127 // -----------------------------------------------------------------------
129 static unsigned GetUShort( const unsigned char* p
){return((p
[0]<<8)+p
[1]);}
131 const ImplFontCharMap
* ImplMacFontData::GetImplFontCharMap() const
133 // return the cached charmap
137 // set the default charmap
138 mpCharMap
= ImplFontCharMap::GetDefaultMap();
139 mpCharMap
->AddReference();
141 // get the CMAP byte size
142 // allocate a buffer for the CMAP raw data
143 const int nBufSize
= GetFontTable( "cmap", NULL
);
144 DBG_ASSERT( (nBufSize
> 0), "ImplMacFontData::GetImplFontCharMap : GetFontTable1 failed!\n");
148 // get the CMAP raw data
149 ByteVector
aBuffer( nBufSize
);
150 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
151 DBG_ASSERT( (nRawLength
> 0), "ImplMacFontData::GetImplFontCharMap : GetFontTable2 failed!\n");
152 if( nRawLength
<= 0 )
154 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::GetImplFontCharMap : ByteCount mismatch!\n");
157 CmapResult aCmapResult
;
158 if( ParseCMAP( &aBuffer
[0], nRawLength
, aCmapResult
) )
160 // create the matching charmap
161 mpCharMap
->DeReference();
162 mpCharMap
= new ImplFontCharMap( aCmapResult
);
163 mpCharMap
->AddReference();
169 bool ImplMacFontData::GetImplFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
171 // read this only once per font
172 if( mbFontCapabilitiesRead
)
174 rFontCapabilities
= maFontCapabilities
;
175 return !rFontCapabilities
.maUnicodeRange
.empty() || !rFontCapabilities
.maCodePageRange
.empty();
177 mbFontCapabilitiesRead
= true;
180 // prepare to get the GSUB table raw data
181 nBufSize
= GetFontTable( "GSUB", NULL
);
184 // allocate a buffer for the GSUB raw data
185 ByteVector
aBuffer( nBufSize
);
186 // get the GSUB raw data
187 const int nRawLength
= GetFontTable( "GSUB", &aBuffer
[0] );
190 const unsigned char* pGSUBTable
= &aBuffer
[0];
191 vcl::getTTScripts(maFontCapabilities
.maGSUBScriptTags
, pGSUBTable
, nRawLength
);
194 nBufSize
= GetFontTable( "OS/2", NULL
);
197 // allocate a buffer for the OS/2 raw data
198 ByteVector
aBuffer( nBufSize
);
199 // get the OS/2 raw data
200 const int nRawLength
= GetFontTable( "OS/2", &aBuffer
[0] );
203 const unsigned char* pOS2Table
= &aBuffer
[0];
205 maFontCapabilities
.maUnicodeRange
,
206 maFontCapabilities
.maCodePageRange
,
207 pOS2Table
, nRawLength
);
210 rFontCapabilities
= maFontCapabilities
;
211 return !rFontCapabilities
.maUnicodeRange
.empty() || !rFontCapabilities
.maCodePageRange
.empty();
214 // -----------------------------------------------------------------------
216 void ImplMacFontData::ReadOs2Table( void ) const
218 // read this only once per font
222 mbHasOs2Table
= false;
224 // prepare to get the OS/2 table raw data
225 const int nBufSize
= GetFontTable( "OS/2", NULL
);
226 DBG_ASSERT( (nBufSize
> 0), "ImplMacFontData::ReadOs2Table : GetFontTable1 failed!\n");
230 // get the OS/2 raw data
231 ByteVector
aBuffer( nBufSize
);
232 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
233 DBG_ASSERT( (nRawLength
> 0), "ImplMacFontData::ReadOs2Table : GetFontTable2 failed!\n");
234 if( nRawLength
<= 0 )
236 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::ReadOs2Table : ByteCount mismatch!\n");
237 mbHasOs2Table
= true;
239 // parse the OS/2 raw data
240 // TODO: also analyze panose info, etc.
243 void ImplMacFontData::ReadMacCmapEncoding( void ) const
245 // read this only once per font
246 if( mbCmapEncodingRead
)
248 mbCmapEncodingRead
= true;
250 const int nBufSize
= GetFontTable( "cmap", NULL
);
254 // get the CMAP raw data
255 ByteVector
aBuffer( nBufSize
);
256 const int nRawLength
= GetFontTable( "cmap", &aBuffer
[0] );
257 if( nRawLength
< 24 )
259 DBG_ASSERT( (nBufSize
==nRawLength
), "ImplMacFontData::ReadMacCmapEncoding : ByteCount mismatch!\n");
261 const unsigned char* pCmap
= &aBuffer
[0];
262 if( GetUShort( pCmap
) != 0x0000 )
266 // -----------------------------------------------------------------------
268 AquaSalGraphics::AquaSalGraphics()
273 , mpXorEmulation( NULL
)
280 , mfFakeDPIScale( 1.0 )
282 , maLineColor( COL_WHITE
)
283 , maFillColor( COL_BLACK
)
284 , mpMacFontData( NULL
)
285 , mpMacTextStyle( NULL
)
286 , maTextColor( COL_BLACK
)
287 , mbNonAntialiasedText( false )
293 , mfFakeDPIScale( 1.0 )
294 , mpMacFontData( NULL
)
295 , mpMacTextStyle( NULL
)
296 , maTextColor( COL_BLACK
)
297 , mbNonAntialiasedText( false )
301 // -----------------------------------------------------------------------
303 AquaSalGraphics::~AquaSalGraphics()
306 CGPathRelease( mxClipPath
);
307 delete mpMacTextStyle
;
310 delete mpXorEmulation
;
313 CGLayerRelease( mxLayer
);
314 else if( mrContext
&& mbWindow
)
316 // destroy backbuffer bitmap context that we created ourself
317 CGContextRelease( mrContext
);
319 // memory is freed automatically by maOwnContextMemory
324 // =======================================================================
326 void AquaSalGraphics::SetTextColor( SalColor nSalColor
)
328 maTextColor
= RGBAColor( nSalColor
);
330 mpMacTextStyle
->SetTextColor( maTextColor
);
333 // -----------------------------------------------------------------------
335 void AquaSalGraphics::GetFontMetric( ImplFontMetricData
* pMetric
, int /*nFallbackLevel*/ )
337 mpMacTextStyle
->GetFontMetric( mfFakeDPIScale
, *pMetric
);
340 // -----------------------------------------------------------------------
342 sal_uLong
AquaSalGraphics::GetKernPairs( sal_uLong
, ImplKernPairData
* )
347 // -----------------------------------------------------------------------
349 static bool AddTempDevFont(const OUString
& rFontFileURL
)
351 OUString aUSytemPath
;
352 OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL
, aUSytemPath
) );
353 OString aCFileName
= OUStringToOString( aUSytemPath
, RTL_TEXTENCODING_UTF8
);
355 CFStringRef rDir
= CFStringCreateWithCString(NULL
, aCFileName
.getStr(), kCFStringEncodingUTF8
);
356 CFURLRef rDirURL
= CFURLCreateWithFileSystemPath(NULL
, rDir
, kCFURLPOSIXPathStyle
, true);
359 bool success
= CTFontManagerRegisterFontsForURL(rDirURL
, kCTFontManagerScopeProcess
, &error
);
370 static void AddTempFontDir( const OUString
&rFontDirUrl
)
372 osl::Directory
aFontDir( rFontDirUrl
);
373 osl::FileBase::RC rcOSL
= aFontDir
.open();
374 if( rcOSL
== osl::FileBase::E_None
)
376 osl::DirectoryItem aDirItem
;
378 while( aFontDir
.getNextItem( aDirItem
, 10 ) == osl::FileBase::E_None
)
380 osl::FileStatus
aFileStatus( osl_FileStatus_Mask_FileURL
);
381 rcOSL
= aDirItem
.getFileStatus( aFileStatus
);
382 if ( rcOSL
== osl::FileBase::E_None
)
383 AddTempDevFont(aFileStatus
.getFileURL());
388 static void AddLocalTempFontDirs()
390 static bool bFirst
= true;
395 // add private font files
397 OUString
aBrandStr( "$BRAND_BASE_DIR" );
398 rtl_bootstrap_expandMacros( &aBrandStr
.pData
);
399 AddTempFontDir( aBrandStr
+ "/share/fonts/truetype/" );
402 void AquaSalGraphics::GetDevFontList( ImplDevFontList
* pFontList
)
404 DBG_ASSERT( pFontList
, "AquaSalGraphics::GetDevFontList(NULL) !");
406 AddLocalTempFontDirs();
408 // The idea is to cache the list of system fonts once it has been generated.
409 // SalData seems to be a good place for this caching. However we have to
410 // carefully make the access to the font list thread-safe. If we register
411 // a font-change event handler to update the font list in case fonts have
412 // changed on the system we have to lock access to the list. The right
413 // way to do that is the solar mutex since GetDevFontList is protected
414 // through it as should be all event handlers
416 SalData
* pSalData
= GetSalData();
417 if( !pSalData
->mpFontList
)
418 pSalData
->mpFontList
= GetCoretextFontList();
420 // Copy all PhysicalFontFace objects contained in the SystemFontList
421 pSalData
->mpFontList
->AnnounceFonts( *pFontList
);
424 void AquaSalGraphics::ClearDevFontCache()
426 SalData
* pSalData
= GetSalData();
427 delete pSalData
->mpFontList
;
428 pSalData
->mpFontList
= NULL
;
431 // -----------------------------------------------------------------------
433 bool AquaSalGraphics::AddTempDevFont( ImplDevFontList
*,
434 const OUString
& rFontFileURL
, const OUString
& /*rFontName*/ )
436 return ::AddTempDevFont(rFontFileURL
);
439 // -----------------------------------------------------------------------
441 sal_Bool
AquaSalGraphics::GetGlyphOutline( sal_GlyphId nGlyphId
, basegfx::B2DPolyPolygon
& rPolyPoly
)
443 const bool bRC
= mpMacTextStyle
->GetGlyphOutline( nGlyphId
, rPolyPoly
);
447 // -----------------------------------------------------------------------
449 sal_Bool
AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId nGlyphId
, Rectangle
& rRect
)
451 const bool bRC
= mpMacTextStyle
->GetGlyphBoundRect( nGlyphId
, rRect
);
455 // -----------------------------------------------------------------------
457 void AquaSalGraphics::GetDevFontSubstList( OutputDevice
* )
459 // nothing to do since there are no device-specific fonts on Aqua
462 // -----------------------------------------------------------------------
464 void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout
& )
468 // -----------------------------------------------------------------------
470 sal_uInt16
AquaSalGraphics::SetFont( FontSelectPattern
* pReqFont
, int /*nFallbackLevel*/ )
472 // release the text style
473 delete mpMacTextStyle
;
474 mpMacTextStyle
= NULL
;
476 // handle NULL request meaning: release-font-resources request
479 mpMacFontData
= NULL
;
483 // update the text style
484 mpMacFontData
= static_cast<const ImplMacFontData
*>( pReqFont
->mpFontData
);
485 mpMacTextStyle
= mpMacFontData
->CreateMacTextStyle( *pReqFont
);
486 mpMacTextStyle
->SetTextColor( maTextColor
);
488 #if OSL_DEBUG_LEVEL > 3
489 fprintf( stderr
, "SetFont to (\"%s\", \"%s\", fontid=%d) for (\"%s\" \"%s\" weight=%d, slant=%d size=%dx%d orientation=%d)\n",
490 OUStringToOString( mpMacFontData
->GetFamilyName(), RTL_TEXTENCODING_UTF8
).getStr(),
491 OUStringToOString( mpMacFontData
->GetStyleName(), RTL_TEXTENCODING_UTF8
).getStr(),
493 OUStringToOString( pReqFont
->GetFamilyName(), RTL_TEXTENCODING_UTF8
).getStr(),
494 OUStringToOString( pReqFont
->GetStyleName(), RTL_TEXTENCODING_UTF8
).getStr(),
495 pReqFont
->GetWeight(),
496 pReqFont
->GetSlant(),
499 pReqFont
->mnOrientation
);
505 // -----------------------------------------------------------------------
507 SalLayout
* AquaSalGraphics::GetTextLayout( ImplLayoutArgs
& /*rArgs*/, int /*nFallbackLevel*/ )
509 SalLayout
* pSalLayout
= mpMacTextStyle
->GetTextLayout();
513 // -----------------------------------------------------------------------
515 const ImplFontCharMap
* AquaSalGraphics::GetImplFontCharMap() const
518 return ImplFontCharMap::GetDefaultMap();
520 return mpMacFontData
->GetImplFontCharMap();
523 bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities
&rFontCapabilities
) const
528 return mpMacFontData
->GetImplFontCapabilities(rFontCapabilities
);
531 // -----------------------------------------------------------------------
533 // fake a SFNT font directory entry for a font table
534 // see http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html#Directory
535 static void FakeDirEntry( const char aTag
[5], ByteCount nOfs
, ByteCount nLen
,
536 const unsigned char* /*pData*/, unsigned char*& rpDest
)
539 rpDest
[ 0] = aTag
[0];
540 rpDest
[ 1] = aTag
[1];
541 rpDest
[ 2] = aTag
[2];
542 rpDest
[ 3] = aTag
[3];
543 // TODO: get entry checksum and write it
544 // not too important since the subsetter doesn't care currently
545 // for( pData+nOfs ... pData+nOfs+nLen )
546 // write entry offset
547 rpDest
[ 8] = (char)(nOfs
>> 24);
548 rpDest
[ 9] = (char)(nOfs
>> 16);
549 rpDest
[10] = (char)(nOfs
>> 8);
550 rpDest
[11] = (char)(nOfs
>> 0);
551 // write entry length
552 rpDest
[12] = (char)(nLen
>> 24);
553 rpDest
[13] = (char)(nLen
>> 16);
554 rpDest
[14] = (char)(nLen
>> 8);
555 rpDest
[15] = (char)(nLen
>> 0);
556 // advance to next entry
560 // fake a TTF or CFF font as directly accessing font file is not possible
561 // when only the fontid is known. This approach also handles *.dfont fonts.
562 bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace
* pFontData
,
563 ByteVector
& rBuffer
, bool* pJustCFF
)
565 const ImplMacFontData
* pMacFont
= static_cast<const ImplMacFontData
*>(pFontData
);
567 // short circuit for CFF-only fonts
568 const int nCffSize
= pMacFont
->GetFontTable( "CFF ", NULL
);
569 if( pJustCFF
!= NULL
)
571 *pJustCFF
= (nCffSize
> 0);
574 rBuffer
.resize( nCffSize
);
575 const int nCffRead
= pMacFont
->GetFontTable( "CFF ", &rBuffer
[0]);
576 if( nCffRead
!= nCffSize
)
582 // get font table availability and size in bytes
583 const int nHeadSize
= pMacFont
->GetFontTable( "head", NULL
);
586 const int nMaxpSize
= pMacFont
->GetFontTable( "maxp", NULL
);
589 const int nCmapSize
= pMacFont
->GetFontTable( "cmap", NULL
);
592 const int nNameSize
= pMacFont
->GetFontTable( "name", NULL
);
595 const int nHheaSize
= pMacFont
->GetFontTable( "hhea", NULL
);
598 const int nHmtxSize
= pMacFont
->GetFontTable( "hmtx", NULL
);
602 // get the ttf-glyf outline tables
607 nLocaSize
= pMacFont
->GetFontTable( "loca", NULL
);
610 nGlyfSize
= pMacFont
->GetFontTable( "glyf", NULL
);
615 int nPrepSize
= 0, nCvtSize
= 0, nFpgmSize
= 0;
616 if( nGlyfSize
) // TODO: reduce PDF size by making hint subsetting optional
618 nPrepSize
= pMacFont
->GetFontTable( "prep", NULL
);
619 nCvtSize
= pMacFont
->GetFontTable( "cvt ", NULL
);
620 nFpgmSize
= pMacFont
->GetFontTable( "fpgm", NULL
);
623 // prepare a byte buffer for a fake font
625 nTableCount
+= (nPrepSize
>0) + (nCvtSize
>0) + (nFpgmSize
>0) + (nGlyfSize
>0);
626 const ByteCount nFdirSize
= 12 + 16*nTableCount
;
627 ByteCount nTotalSize
= nFdirSize
;
628 nTotalSize
+= nHeadSize
+ nMaxpSize
+ nNameSize
+ nCmapSize
;
630 nTotalSize
+= nLocaSize
+ nGlyfSize
;
632 nTotalSize
+= nCffSize
;
633 nTotalSize
+= nHheaSize
+ nHmtxSize
;
634 nTotalSize
+= nPrepSize
+ nCvtSize
+ nFpgmSize
;
635 rBuffer
.resize( nTotalSize
);
637 // fake a SFNT font directory header
638 if( nTableCount
< 16 )
641 while( (nTableCount
>> nLog2
) > 1 ) ++nLog2
;
642 rBuffer
[ 1] = 1; // Win-TTF style scaler
643 rBuffer
[ 5] = nTableCount
; // table count
644 rBuffer
[ 7] = nLog2
*16; // searchRange
645 rBuffer
[ 9] = nLog2
; // entrySelector
646 rBuffer
[11] = (nTableCount
-nLog2
)*16; // rangeShift
649 // get font table raw data and update the fake directory entries
650 ByteCount nOfs
= nFdirSize
;
651 unsigned char* pFakeEntry
= &rBuffer
[12];
652 if( nCmapSize
!= pMacFont
->GetFontTable( "cmap", &rBuffer
[nOfs
]))
654 FakeDirEntry( "cmap", nOfs
, nCmapSize
, &rBuffer
[0], pFakeEntry
);
657 if( nCvtSize
!= pMacFont
->GetFontTable( "cvt ", &rBuffer
[nOfs
]))
659 FakeDirEntry( "cvt ", nOfs
, nCvtSize
, &rBuffer
[0], pFakeEntry
);
663 if( nFpgmSize
!= pMacFont
->GetFontTable( "fpgm", &rBuffer
[nOfs
]))
665 FakeDirEntry( "fpgm", nOfs
, nFpgmSize
, &rBuffer
[0], pFakeEntry
);
669 if( nCffSize
!= pMacFont
->GetFontTable( "CFF ", &rBuffer
[nOfs
]))
671 FakeDirEntry( "CFF ", nOfs
, nCffSize
, &rBuffer
[0], pFakeEntry
);
674 if( nGlyfSize
!= pMacFont
->GetFontTable( "glyf", &rBuffer
[nOfs
]))
676 FakeDirEntry( "glyf", nOfs
, nGlyfSize
, &rBuffer
[0], pFakeEntry
);
678 if( nLocaSize
!= pMacFont
->GetFontTable( "loca", &rBuffer
[nOfs
]))
680 FakeDirEntry( "loca", nOfs
, nLocaSize
, &rBuffer
[0], pFakeEntry
);
683 if( nHeadSize
!= pMacFont
->GetFontTable( "head", &rBuffer
[nOfs
]))
685 FakeDirEntry( "head", nOfs
, nHeadSize
, &rBuffer
[0], pFakeEntry
);
687 if( nHheaSize
!= pMacFont
->GetFontTable( "hhea", &rBuffer
[nOfs
]))
689 FakeDirEntry( "hhea", nOfs
, nHheaSize
, &rBuffer
[0], pFakeEntry
);
691 if( nHmtxSize
!= pMacFont
->GetFontTable( "hmtx", &rBuffer
[nOfs
]))
693 FakeDirEntry( "hmtx", nOfs
, nHmtxSize
, &rBuffer
[0], pFakeEntry
);
695 if( nMaxpSize
!= pMacFont
->GetFontTable( "maxp", &rBuffer
[nOfs
]))
697 FakeDirEntry( "maxp", nOfs
, nMaxpSize
, &rBuffer
[0], pFakeEntry
);
699 if( nNameSize
!= pMacFont
->GetFontTable( "name", &rBuffer
[nOfs
]))
701 FakeDirEntry( "name", nOfs
, nNameSize
, &rBuffer
[0], pFakeEntry
);
704 if( nPrepSize
!= pMacFont
->GetFontTable( "prep", &rBuffer
[nOfs
]))
706 FakeDirEntry( "prep", nOfs
, nPrepSize
, &rBuffer
[0], pFakeEntry
);
710 DBG_ASSERT( (nOfs
==nTotalSize
), "AquaSalGraphics::CreateFontSubset (nOfs!=nTotalSize)");
715 // -----------------------------------------------------------------------
717 void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace
* pFontData
, bool bVertical
,
718 Int32Vector
& rGlyphWidths
, Ucs2UIntMap
& rUnicodeEnc
)
720 rGlyphWidths
.clear();
723 if( pFontData
->IsSubsettable() )
726 if( !GetRawFontData( pFontData
, aBuffer
, NULL
) )
729 // TODO: modernize psprint's horrible fontsubset C-API
730 // this probably only makes sense after the switch to another SCM
731 // that can preserve change history after file renames
733 // use the font subsetter to get the widths
734 TrueTypeFont
* pSftFont
= NULL
;
735 int nRC
= ::OpenTTFontBuffer( (void*)&aBuffer
[0], aBuffer
.size(), 0, &pSftFont
);
739 const int nGlyphCount
= ::GetTTGlyphCount( pSftFont
);
740 if( nGlyphCount
> 0 )
743 rGlyphWidths
.resize(nGlyphCount
);
744 std::vector
<sal_uInt16
> aGlyphIds(nGlyphCount
);
745 for( int i
= 0; i
< nGlyphCount
; i
++ )
746 aGlyphIds
[i
] = static_cast<sal_uInt16
>(i
);
747 const TTSimpleGlyphMetrics
* pGlyphMetrics
= ::GetTTSimpleGlyphMetrics(
748 pSftFont
, &aGlyphIds
[0], nGlyphCount
, bVertical
);
751 for( int i
= 0; i
< nGlyphCount
; ++i
)
752 rGlyphWidths
[i
] = pGlyphMetrics
[i
].adv
;
753 free( (void*)pGlyphMetrics
);
756 const ImplFontCharMap
* pMap
= mpMacFontData
->GetImplFontCharMap();
757 DBG_ASSERT( pMap
&& pMap
->GetCharCount(), "no charmap" );
758 pMap
->AddReference(); // TODO: add and use RAII object instead
760 // get unicode<->glyph encoding
761 // TODO? avoid sft mapping by using the pMap itself
762 int nCharCount
= pMap
->GetCharCount();
763 sal_uInt32 nChar
= pMap
->GetFirstChar();
764 for(; --nCharCount
>= 0; nChar
= pMap
->GetNextChar( nChar
) )
766 if( nChar
> 0xFFFF ) // TODO: allow UTF-32 chars
768 sal_Ucs nUcsChar
= static_cast<sal_Ucs
>(nChar
);
769 sal_uInt32 nGlyph
= ::MapChar( pSftFont
, nUcsChar
, bVertical
);
771 rUnicodeEnc
[ nUcsChar
] = nGlyph
;
774 pMap
->DeReference(); // TODO: add and use RAII object instead
777 ::CloseTTFont( pSftFont
);
779 else if( pFontData
->IsEmbeddable() )
781 // get individual character widths
782 OSL_FAIL("not implemented for non-subsettable fonts!\n");
786 // -----------------------------------------------------------------------
788 const Ucs2SIntMap
* AquaSalGraphics::GetFontEncodingVector(
789 const PhysicalFontFace
*, const Ucs2OStrMap
** /*ppNonEncoded*/ )
794 // -----------------------------------------------------------------------
796 const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace
*,
797 const sal_Ucs
* /*pUnicodes*/,
798 sal_Int32
* /*pWidths*/,
805 // -----------------------------------------------------------------------
807 void AquaSalGraphics::FreeEmbedFontData( const void* pData
, long /*nDataLen*/ )
809 // TODO: implementing this only makes sense when the implementation of
810 // AquaSalGraphics::GetEmbedFontData() returns non-NULL
812 DBG_ASSERT( (pData
!=NULL
), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n");
815 // -----------------------------------------------------------------------
817 SystemFontData
AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const
819 SystemFontData aSysFontData
;
820 aSysFontData
.nSize
= sizeof( SystemFontData
);
822 aSysFontData
.bAntialias
= !mbNonAntialiasedText
;
827 // -----------------------------------------------------------------------
831 // Note that "SvpSalGraphics" is actually called AquaSalGraphics for iOS
833 bool SvpSalGraphics::CheckContext()
835 const basegfx::B2IVector size
= m_aDevice
->getSize();
836 const basegfx::B2IVector bufferSize
= m_aDevice
->getBufferSize();
837 const sal_Int32 scanlineStride
= m_aDevice
->getScanlineStride();
838 basebmp::RawMemorySharedArray pixelBuffer
= m_aDevice
->getBuffer();
841 "CheckContext: device=" << m_aDevice
.get() <<
842 " size=" << size
.getX() << "x" << size
.getY() <<
843 (m_aDevice
->isTopDown() ? " top-down" : " bottom-up") <<
844 " stride=" << scanlineStride
<<
845 " bufferSize=(" << bufferSize
.getX() << "," << bufferSize
.getY() << ")" );
847 switch( m_aDevice
->getScanlineFormat() ) {
848 case basebmp::Format::EIGHT_BIT_PAL
:
849 mrContext
= CGBitmapContextCreate(pixelBuffer
.get(),
850 bufferSize
.getX(), bufferSize
.getY(),
852 CGColorSpaceCreateDeviceGray(),
855 case basebmp::Format::THIRTYTWO_BIT_TC_MASK_RGBA
:
856 mrContext
= CGBitmapContextCreate(pixelBuffer
.get(),
857 bufferSize
.getX(), bufferSize
.getY(),
859 CGColorSpaceCreateDeviceRGB(),
860 kCGImageAlphaNoneSkipLast
);
863 SAL_INFO( "vcl.ios", "CheckContext: unsupported color format " << basebmp::Format::formatName( m_aDevice
->getScanlineFormat() ) );
866 SAL_WARN_IF( mrContext
== NULL
, "vcl.ios", "CheckContext() failed" );
868 // Should we also clip the context? (Then we need to add a
869 // getBounds() function to BitmapDevice.)
871 if( mrContext
!= NULL
&& m_aDevice
->isTopDown() )
873 CGContextTranslateCTM( mrContext
, 0, bufferSize
.getY() );
874 CGContextScaleCTM( mrContext
, 1, -1 );
877 SAL_INFO( "vcl.ios", "CheckContext: context=" << mrContext
);
879 return ( mrContext
!= NULL
);
882 CGContextRef
SvpSalGraphics::GetContext()
892 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */