bump product version to 7.2.5.1
[LibreOffice.git] / vcl / quartz / salgdi.cxx
blobc938cf7720304f8d1008694d9f4c3010dd446695
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 <sal/config.h>
21 #include <sal/log.hxx>
22 #include <config_folders.h>
24 #include <basegfx/matrix/b2dhommatrix.hxx>
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <basegfx/polygon/b2dpolygon.hxx>
27 #include <basegfx/polygon/b2dpolygontools.hxx>
28 #include <basegfx/range/b2drectangle.hxx>
29 #include <osl/file.hxx>
30 #include <osl/process.h>
31 #include <rtl/bootstrap.h>
32 #include <rtl/strbuf.hxx>
33 #include <tools/long.hxx>
34 #include <comphelper/lok.hxx>
36 #include <vcl/metric.hxx>
37 #include <vcl/fontcharmap.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/sysdata.hxx>
41 #include <quartz/ctfonts.hxx>
42 #include <fontsubset.hxx>
43 #include <impfont.hxx>
44 #include <impfontcharmap.hxx>
45 #include <impfontmetricdata.hxx>
46 #include <outdev.h>
47 #include <PhysicalFontCollection.hxx>
49 #ifdef MACOSX
50 #include <osx/salframe.h>
51 #endif
52 #include <quartz/utils.h>
53 #ifdef IOS
54 #include "saldatabasic.hxx"
55 #endif
56 #include <sallayout.hxx>
57 #include <sft.hxx>
59 using namespace vcl;
61 namespace {
63 class CoreTextGlyphFallbackSubstititution
64 : public ImplGlyphFallbackFontSubstitution
66 public:
67 bool FindFontSubstitute(FontSelectPattern&, LogicalFontInstance* pLogicalFont, OUString&) const override;
72 bool CoreTextGlyphFallbackSubstititution::FindFontSubstitute(FontSelectPattern& rPattern, LogicalFontInstance* pLogicalFont,
73 OUString& rMissingChars) const
75 bool bFound = false;
76 CoreTextStyle* pStyle = static_cast<CoreTextStyle*>(pLogicalFont);
77 CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(pStyle->GetStyleDict(), kCTFontAttributeName));
78 CFStringRef pStr = CreateCFString(rMissingChars);
79 if (pStr)
81 CTFontRef pFallback = CTFontCreateForString(pFont, pStr, CFRangeMake(0, CFStringGetLength(pStr)));
82 if (pFallback)
84 bFound = true;
86 CTFontDescriptorRef pDesc = CTFontCopyFontDescriptor(pFallback);
87 FontAttributes rAttr = DevFontFromCTFontDescriptor(pDesc, nullptr);
89 rPattern.maSearchName = rAttr.GetFamilyName();
91 rPattern.SetWeight(rAttr.GetWeight());
92 rPattern.SetItalic(rAttr.GetItalic());
93 rPattern.SetPitch(rAttr.GetPitch());
94 rPattern.SetWidthType(rAttr.GetWidthType());
96 CFRelease(pFallback);
97 CFRelease(pDesc);
99 CFRelease(pStr);
102 return bFound;
105 CoreTextFontFace::CoreTextFontFace( const FontAttributes& rDFA, sal_IntPtr nFontId )
106 : PhysicalFontFace( rDFA )
107 , mnFontId( nFontId )
108 , mbFontCapabilitiesRead( false )
112 CoreTextFontFace::~CoreTextFontFace()
116 sal_IntPtr CoreTextFontFace::GetFontId() const
118 return mnFontId;
121 FontCharMapRef CoreTextFontFace::GetFontCharMap() const
123 // return the cached charmap
124 if( mxCharMap.is() )
125 return mxCharMap;
127 // set the default charmap
128 FontCharMapRef pCharMap( new FontCharMap() );
129 mxCharMap = pCharMap;
131 // get the CMAP byte size
132 // allocate a buffer for the CMAP raw data
133 const int nBufSize = GetFontTable( "cmap", nullptr );
134 SAL_WARN_IF( (nBufSize <= 0), "vcl", "CoreTextFontFace::GetFontCharMap : GetFontTable1 failed!");
135 if( nBufSize <= 0 )
136 return mxCharMap;
138 // get the CMAP raw data
139 std::vector<unsigned char> aBuffer( nBufSize );
140 const int nRawLength = GetFontTable( "cmap", aBuffer.data() );
141 SAL_WARN_IF( (nRawLength <= 0), "vcl", "CoreTextFontFace::GetFontCharMap : GetFontTable2 failed!");
142 if( nRawLength <= 0 )
143 return mxCharMap;
145 SAL_WARN_IF( (nBufSize!=nRawLength), "vcl", "CoreTextFontFace::GetFontCharMap : ByteCount mismatch!");
147 // parse the CMAP
148 CmapResult aCmapResult;
149 if( ParseCMAP( aBuffer.data(), nRawLength, aCmapResult ) )
151 FontCharMapRef xDefFontCharMap( new FontCharMap(aCmapResult) );
152 // create the matching charmap
153 mxCharMap = xDefFontCharMap;
156 return mxCharMap;
159 bool CoreTextFontFace::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
161 // read this only once per font
162 if( mbFontCapabilitiesRead )
164 rFontCapabilities = maFontCapabilities;
165 return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange;
167 mbFontCapabilitiesRead = true;
169 int nBufSize = GetFontTable( "OS/2", nullptr );
170 if( nBufSize > 0 )
172 // allocate a buffer for the OS/2 raw data
173 std::vector<unsigned char> aBuffer( nBufSize );
174 // get the OS/2 raw data
175 const int nRawLength = GetFontTable( "OS/2", aBuffer.data() );
176 if( nRawLength > 0 )
178 const unsigned char* pOS2Table = aBuffer.data();
179 vcl::getTTCoverage( maFontCapabilities.oUnicodeRange,
180 maFontCapabilities.oCodePageRange,
181 pOS2Table, nRawLength);
184 rFontCapabilities = maFontCapabilities;
185 return rFontCapabilities.oUnicodeRange || rFontCapabilities.oCodePageRange;
188 AquaSalGraphics::AquaSalGraphics()
189 : mpBackend(new AquaGraphicsBackend(maShared))
190 , mnRealDPIX( 0 )
191 , mnRealDPIY( 0 )
192 , maTextColor( COL_BLACK )
193 , mbNonAntialiasedText( false )
195 SAL_INFO( "vcl.quartz", "AquaSalGraphics::AquaSalGraphics() this=" << this );
197 for (int i = 0; i < MAX_FALLBACK; ++i)
198 mpTextStyle[i] = nullptr;
200 if (comphelper::LibreOfficeKit::isActive())
201 initWidgetDrawBackends(true);
204 AquaSalGraphics::~AquaSalGraphics()
206 SAL_INFO( "vcl.quartz", "AquaSalGraphics::~AquaSalGraphics() this=" << this );
208 maShared.unsetClipPath();
210 ReleaseFonts();
212 maShared.mpXorEmulation.reset();
214 #ifdef IOS
215 if (maShared.mbForeignContext)
216 return;
217 #endif
218 if (maShared.maLayer.isSet())
220 CGLayerRelease(maShared.maLayer.get());
222 else if (maShared.maContextHolder.isSet()
223 #ifdef MACOSX
224 && maShared.mbWindow
225 #endif
228 // destroy backbuffer bitmap context that we created ourself
229 CGContextRelease(maShared.maContextHolder.get());
230 maShared.maContextHolder.set(nullptr);
234 SalGraphicsImpl* AquaSalGraphics::GetImpl() const
236 return mpBackend.get();
239 void AquaSalGraphics::SetTextColor( Color nColor )
241 maTextColor = RGBAColor( nColor );
242 // SAL_ DEBUG(std::hex << nColor << std::dec << "={" << maTextColor.GetRed() << ", " << maTextColor.GetGreen() << ", " << maTextColor.GetBlue() << ", " << maTextColor.GetAlpha() << "}");
245 void AquaSalGraphics::GetFontMetric(ImplFontMetricDataRef& rxFontMetric, int nFallbackLevel)
247 if (nFallbackLevel < MAX_FALLBACK && mpTextStyle[nFallbackLevel])
249 mpTextStyle[nFallbackLevel]->GetFontMetric(rxFontMetric);
253 static bool AddTempDevFont(const OUString& rFontFileURL)
255 OUString aUSystemPath;
256 OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFontFileURL, aUSystemPath ) );
257 OString aCFileName = OUStringToOString( aUSystemPath, RTL_TEXTENCODING_UTF8 );
259 CFStringRef rFontPath = CFStringCreateWithCString(nullptr, aCFileName.getStr(), kCFStringEncodingUTF8);
260 CFURLRef rFontURL = CFURLCreateWithFileSystemPath(nullptr, rFontPath, kCFURLPOSIXPathStyle, true);
262 CFErrorRef error;
263 bool success = CTFontManagerRegisterFontsForURL(rFontURL, kCTFontManagerScopeProcess, &error);
264 if (!success)
266 CFRelease(error);
268 CFRelease(rFontPath);
269 CFRelease(rFontURL);
271 return success;
274 static void AddTempFontDir( const OUString &rFontDirUrl )
276 osl::Directory aFontDir( rFontDirUrl );
277 osl::FileBase::RC rcOSL = aFontDir.open();
278 if( rcOSL == osl::FileBase::E_None )
280 osl::DirectoryItem aDirItem;
282 while( aFontDir.getNextItem( aDirItem, 10 ) == osl::FileBase::E_None )
284 osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
285 rcOSL = aDirItem.getFileStatus( aFileStatus );
286 if ( rcOSL == osl::FileBase::E_None )
288 AddTempDevFont(aFileStatus.getFileURL());
294 static void AddLocalTempFontDirs()
296 static bool bFirst = true;
297 if( !bFirst )
298 return;
300 bFirst = false;
302 // add private font files
304 OUString aBrandStr( "$BRAND_BASE_DIR" );
305 rtl_bootstrap_expandMacros( &aBrandStr.pData );
307 // internal font resources, required for normal operation, like OpenSymbol
308 AddTempFontDir( aBrandStr + "/" LIBO_SHARE_RESOURCE_FOLDER "/common/fonts/" );
310 AddTempFontDir( aBrandStr + "/" LIBO_SHARE_FOLDER "/fonts/truetype/" );
313 void AquaSalGraphics::GetDevFontList( PhysicalFontCollection* pFontCollection )
315 SAL_WARN_IF( !pFontCollection, "vcl", "AquaSalGraphics::GetDevFontList(NULL) !");
317 AddLocalTempFontDirs();
319 // The idea is to cache the list of system fonts once it has been generated.
320 // SalData seems to be a good place for this caching. However we have to
321 // carefully make the access to the font list thread-safe. If we register
322 // a font-change event handler to update the font list in case fonts have
323 // changed on the system we have to lock access to the list. The right
324 // way to do that is the solar mutex since GetDevFontList is protected
325 // through it as should be all event handlers
327 SalData* pSalData = GetSalData();
328 if( !pSalData->mpFontList )
329 pSalData->mpFontList = GetCoretextFontList();
331 // Copy all PhysicalFontFace objects contained in the SystemFontList
332 pSalData->mpFontList->AnnounceFonts( *pFontCollection );
334 static CoreTextGlyphFallbackSubstititution aSubstFallback;
335 pFontCollection->SetFallbackHook(&aSubstFallback);
338 void AquaSalGraphics::ClearDevFontCache()
340 SalData* pSalData = GetSalData();
341 delete pSalData->mpFontList;
342 pSalData->mpFontList = nullptr;
345 bool AquaSalGraphics::AddTempDevFont( PhysicalFontCollection*,
346 const OUString& rFontFileURL, const OUString& /*rFontName*/ )
348 return ::AddTempDevFont(rFontFileURL);
351 void AquaSalGraphics::DrawTextLayout(const GenericSalLayout& rLayout)
353 #ifdef IOS
354 if (!maShared.checkContext())
356 SAL_WARN("vcl.quartz", "AquaSalGraphics::DrawTextLayout() without context");
357 return;
359 #endif
361 const CoreTextStyle& rStyle = *static_cast<const CoreTextStyle*>(&rLayout.GetFont());
362 const FontSelectPattern& rFontSelect = rStyle.GetFontSelectPattern();
363 if (rFontSelect.mnHeight == 0)
365 SAL_WARN("vcl.quartz", "AquaSalGraphics::DrawTextLayout(): rFontSelect.mnHeight is zero!?");
366 return;
369 CTFontRef pFont = static_cast<CTFontRef>(CFDictionaryGetValue(rStyle.GetStyleDict(), kCTFontAttributeName));
370 CGAffineTransform aRotMatrix = CGAffineTransformMakeRotation(-rStyle.mfFontRotation);
372 Point aPos;
373 const GlyphItem* pGlyph;
374 std::vector<CGGlyph> aGlyphIds;
375 std::vector<CGPoint> aGlyphPos;
376 std::vector<bool> aGlyphOrientation;
377 int nStart = 0;
378 while (rLayout.GetNextGlyph(&pGlyph, aPos, nStart))
380 CGPoint aGCPos = CGPointMake(aPos.X(), -aPos.Y());
382 // Whether the glyph should be upright in vertical mode or not
383 bool bUprightGlyph = false;
385 if (rStyle.mfFontRotation)
387 if (pGlyph->IsVertical())
389 bUprightGlyph = true;
390 // Adjust the position of upright (vertical) glyphs.
391 aGCPos.y -= CTFontGetAscent(pFont) - CTFontGetDescent(pFont);
393 else
395 // Transform the position of rotated glyphs.
396 aGCPos = CGPointApplyAffineTransform(aGCPos, aRotMatrix);
400 aGlyphIds.push_back(pGlyph->glyphId());
401 aGlyphPos.push_back(aGCPos);
402 aGlyphOrientation.push_back(bUprightGlyph);
405 if (aGlyphIds.empty())
406 return;
408 assert(aGlyphIds.size() == aGlyphPos.size());
409 #if 0
410 std::cerr << "aGlyphIds:[";
411 for (unsigned i = 0; i < aGlyphIds.size(); i++)
413 if (i > 0)
414 std::cerr << ",";
415 std::cerr << aGlyphIds[i];
417 std::cerr << "]\n";
418 std::cerr << "aGlyphPos:[";
419 for (unsigned i = 0; i < aGlyphPos.size(); i++)
421 if (i > 0)
422 std::cerr << ",";
423 std::cerr << aGlyphPos[i];
425 std::cerr << "]\n";
426 #endif
428 maShared.maContextHolder.saveState();
430 // The view is vertically flipped (no idea why), flip it back.
431 CGContextScaleCTM(maShared.maContextHolder.get(), 1.0, -1.0);
432 CGContextSetShouldAntialias(maShared.maContextHolder.get(), !mbNonAntialiasedText);
433 CGContextSetFillColor(maShared.maContextHolder.get(), maTextColor.AsArray());
435 if (rStyle.mbFauxBold)
438 float fSize = rFontSelect.mnHeight / 23.0f;
439 CGContextSetStrokeColor(maShared.maContextHolder.get(), maTextColor.AsArray());
440 CGContextSetLineWidth(maShared.maContextHolder.get(), fSize);
441 CGContextSetTextDrawingMode(maShared.maContextHolder.get(), kCGTextFillStroke);
444 auto aIt = aGlyphOrientation.cbegin();
445 while (aIt != aGlyphOrientation.cend())
447 bool bUprightGlyph = *aIt;
448 // Find the boundary of the run of glyphs with the same rotation, to be
449 // drawn together.
450 auto aNext = std::find(aIt, aGlyphOrientation.cend(), !bUprightGlyph);
451 size_t nStartIndex = std::distance(aGlyphOrientation.cbegin(), aIt);
452 size_t nLen = std::distance(aIt, aNext);
454 maShared.maContextHolder.saveState();
455 if (rStyle.mfFontRotation && !bUprightGlyph)
457 CGContextRotateCTM(maShared.maContextHolder.get(), rStyle.mfFontRotation);
459 CTFontDrawGlyphs(pFont, &aGlyphIds[nStartIndex], &aGlyphPos[nStartIndex], nLen, maShared.maContextHolder.get());
460 maShared.maContextHolder.restoreState();
462 aIt = aNext;
465 maShared.maContextHolder.restoreState();
468 void AquaSalGraphics::SetFont(LogicalFontInstance* pReqFont, int nFallbackLevel)
470 // release the text style
471 for (int i = nFallbackLevel; i < MAX_FALLBACK; ++i)
473 if (!mpTextStyle[i])
474 break;
475 mpTextStyle[i].clear();
478 if (!pReqFont)
479 return;
481 // update the text style
482 mpTextStyle[nFallbackLevel] = static_cast<CoreTextStyle*>(pReqFont);
485 std::unique_ptr<GenericSalLayout> AquaSalGraphics::GetTextLayout(int nFallbackLevel)
487 assert(mpTextStyle[nFallbackLevel]);
488 if (!mpTextStyle[nFallbackLevel])
489 return nullptr;
490 return std::make_unique<GenericSalLayout>(*mpTextStyle[nFallbackLevel]);
493 FontCharMapRef AquaSalGraphics::GetFontCharMap() const
495 if (!mpTextStyle[0])
497 return FontCharMapRef( new FontCharMap() );
500 return static_cast<const CoreTextFontFace*>(mpTextStyle[0]->GetFontFace())->GetFontCharMap();
503 bool AquaSalGraphics::GetFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
505 if (!mpTextStyle[0])
506 return false;
508 return static_cast<const CoreTextFontFace*>(mpTextStyle[0]->GetFontFace())->GetFontCapabilities(rFontCapabilities);
511 // fake a SFNT font directory entry for a font table
512 // see http://developer.apple.com/fonts/TTRefMan/RM06/Chap6.html#Directory
513 static void FakeDirEntry( const char aTag[5], ByteCount nOfs, ByteCount nLen,
514 const unsigned char* /*pData*/, unsigned char*& rpDest )
516 // write entry tag
517 rpDest[ 0] = aTag[0];
518 rpDest[ 1] = aTag[1];
519 rpDest[ 2] = aTag[2];
520 rpDest[ 3] = aTag[3];
521 // TODO: get entry checksum and write it
522 // not too important since the subsetter doesn't care currently
523 // for( pData+nOfs ... pData+nOfs+nLen )
524 // write entry offset
525 rpDest[ 8] = static_cast<char>(nOfs >> 24);
526 rpDest[ 9] = static_cast<char>(nOfs >> 16);
527 rpDest[10] = static_cast<char>(nOfs >> 8);
528 rpDest[11] = static_cast<char>(nOfs >> 0);
529 // write entry length
530 rpDest[12] = static_cast<char>(nLen >> 24);
531 rpDest[13] = static_cast<char>(nLen >> 16);
532 rpDest[14] = static_cast<char>(nLen >> 8);
533 rpDest[15] = static_cast<char>(nLen >> 0);
534 // advance to next entry
535 rpDest += 16;
538 // fake a TTF or CFF font as directly accessing font file is not possible
539 // when only the fontid is known. This approach also handles *.font fonts.
540 bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData,
541 std::vector<unsigned char>& rBuffer, bool* pJustCFF )
543 const CoreTextFontFace* pMacFont = static_cast<const CoreTextFontFace*>(pFontData);
545 // short circuit for CFF-only fonts
546 const int nCffSize = pMacFont->GetFontTable( "CFF ", nullptr);
547 if( pJustCFF != nullptr )
549 *pJustCFF = (nCffSize > 0);
550 if( *pJustCFF)
552 rBuffer.resize( nCffSize);
553 const int nCffRead = pMacFont->GetFontTable( "CFF ", rBuffer.data());
554 if( nCffRead != nCffSize)
556 return false;
558 return true;
562 // get font table availability and size in bytes
563 const int nHeadSize = pMacFont->GetFontTable( "head", nullptr);
564 if( nHeadSize <= 0)
565 return false;
567 const int nMaxpSize = pMacFont->GetFontTable( "maxp", nullptr);
568 if( nMaxpSize <= 0)
569 return false;
571 const int nCmapSize = pMacFont->GetFontTable( "cmap", nullptr);
572 if( nCmapSize <= 0)
573 return false;
575 const int nNameSize = pMacFont->GetFontTable( "name", nullptr);
576 if( nNameSize <= 0)
577 return false;
579 const int nHheaSize = pMacFont->GetFontTable( "hhea", nullptr);
580 if( nHheaSize <= 0)
581 return false;
583 const int nHmtxSize = pMacFont->GetFontTable( "hmtx", nullptr);
584 if( nHmtxSize <= 0)
585 return false;
587 // get the ttf-glyf outline tables
588 int nLocaSize = 0;
589 int nGlyfSize = 0;
590 if( nCffSize <= 0)
592 nLocaSize = pMacFont->GetFontTable( "loca", nullptr);
593 if( nLocaSize <= 0)
594 return false;
596 nGlyfSize = pMacFont->GetFontTable( "glyf", nullptr);
597 if( nGlyfSize <= 0)
598 return false;
601 int nPrepSize = 0, nCvtSize = 0, nFpgmSize = 0;
602 if( nGlyfSize) // TODO: reduce PDF size by making hint subsetting optional
604 nPrepSize = pMacFont->GetFontTable( "prep", nullptr);
605 nCvtSize = pMacFont->GetFontTable( "cvt ", nullptr);
606 nFpgmSize = pMacFont->GetFontTable( "fpgm", nullptr);
609 // prepare a byte buffer for a fake font
610 int nTableCount = 7;
611 nTableCount += (nPrepSize>0?1:0) + (nCvtSize>0?1:0) + (nFpgmSize>0?1:0) + (nGlyfSize>0?1:0);
612 const ByteCount nFdirSize = 12 + 16*nTableCount;
613 ByteCount nTotalSize = nFdirSize;
614 nTotalSize += nHeadSize + nMaxpSize + nNameSize + nCmapSize;
616 if( nGlyfSize )
618 nTotalSize += nLocaSize + nGlyfSize;
620 else
622 nTotalSize += nCffSize;
624 nTotalSize += nHheaSize + nHmtxSize;
625 nTotalSize += nPrepSize + nCvtSize + nFpgmSize;
626 rBuffer.resize( nTotalSize );
628 // fake a SFNT font directory header
629 if( nTableCount < 16 )
631 int nLog2 = 0;
632 while( (nTableCount >> nLog2) > 1 ) ++nLog2;
633 rBuffer[ 1] = 1; // Win-TTF style scaler
634 rBuffer[ 5] = nTableCount; // table count
635 rBuffer[ 7] = nLog2*16; // searchRange
636 rBuffer[ 9] = nLog2; // entrySelector
637 rBuffer[11] = (nTableCount-nLog2)*16; // rangeShift
640 // get font table raw data and update the fake directory entries
641 ByteCount nOfs = nFdirSize;
642 unsigned char* pFakeEntry = &rBuffer[12];
643 if( nCmapSize != pMacFont->GetFontTable( "cmap", &rBuffer[nOfs]))
644 return false;
646 FakeDirEntry( "cmap", nOfs, nCmapSize, rBuffer.data(), pFakeEntry );
647 nOfs += nCmapSize;
648 if( nCvtSize )
650 if( nCvtSize != pMacFont->GetFontTable( "cvt ", &rBuffer[nOfs]))
651 return false;
653 FakeDirEntry( "cvt ", nOfs, nCvtSize, rBuffer.data(), pFakeEntry );
654 nOfs += nCvtSize;
656 if( nFpgmSize )
658 if( nFpgmSize != pMacFont->GetFontTable( "fpgm", &rBuffer[nOfs]))
659 return false;
661 FakeDirEntry( "fpgm", nOfs, nFpgmSize, rBuffer.data(), pFakeEntry );
662 nOfs += nFpgmSize;
664 if( nCffSize )
666 if( nCffSize != pMacFont->GetFontTable( "CFF ", &rBuffer[nOfs]))
667 return false;
669 FakeDirEntry( "CFF ", nOfs, nCffSize, rBuffer.data(), pFakeEntry );
670 nOfs += nGlyfSize;
672 else
674 if( nGlyfSize != pMacFont->GetFontTable( "glyf", &rBuffer[nOfs]))
675 return false;
677 FakeDirEntry( "glyf", nOfs, nGlyfSize, rBuffer.data(), pFakeEntry );
678 nOfs += nGlyfSize;
680 if( nLocaSize != pMacFont->GetFontTable( "loca", &rBuffer[nOfs]))
681 return false;
683 FakeDirEntry( "loca", nOfs, nLocaSize, rBuffer.data(), pFakeEntry );
684 nOfs += nLocaSize;
686 if( nHeadSize != pMacFont->GetFontTable( "head", &rBuffer[nOfs]))
687 return false;
689 FakeDirEntry( "head", nOfs, nHeadSize, rBuffer.data(), pFakeEntry );
690 nOfs += nHeadSize;
692 if( nHheaSize != pMacFont->GetFontTable( "hhea", &rBuffer[nOfs]))
693 return false;
695 FakeDirEntry( "hhea", nOfs, nHheaSize, rBuffer.data(), pFakeEntry );
696 nOfs += nHheaSize;
697 if( nHmtxSize != pMacFont->GetFontTable( "hmtx", &rBuffer[nOfs]))
698 return false;
700 FakeDirEntry( "hmtx", nOfs, nHmtxSize, rBuffer.data(), pFakeEntry );
701 nOfs += nHmtxSize;
702 if( nMaxpSize != pMacFont->GetFontTable( "maxp", &rBuffer[nOfs]))
703 return false;
705 FakeDirEntry( "maxp", nOfs, nMaxpSize, rBuffer.data(), pFakeEntry );
706 nOfs += nMaxpSize;
707 if( nNameSize != pMacFont->GetFontTable( "name", &rBuffer[nOfs]))
708 return false;
710 FakeDirEntry( "name", nOfs, nNameSize, rBuffer.data(), pFakeEntry );
711 nOfs += nNameSize;
712 if( nPrepSize )
714 if( nPrepSize != pMacFont->GetFontTable( "prep", &rBuffer[nOfs]))
715 return false;
717 FakeDirEntry( "prep", nOfs, nPrepSize, rBuffer.data(), pFakeEntry );
718 nOfs += nPrepSize;
721 SAL_WARN_IF( (nOfs!=nTotalSize), "vcl", "AquaSalGraphics::GetRawFontData (nOfs!=nTotalSize)");
723 return true;
726 void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* pFontData, bool bVertical,
727 std::vector< sal_Int32 >& rGlyphWidths, Ucs2UIntMap& rUnicodeEnc )
729 rGlyphWidths.clear();
730 rUnicodeEnc.clear();
732 std::vector<unsigned char> aBuffer;
733 if( !GetRawFontData( pFontData, aBuffer, nullptr ) )
734 return;
736 // TODO: modernize psprint's horrible fontsubset C-API
737 // this probably only makes sense after the switch to another SCM
738 // that can preserve change history after file renames
740 // use the font subsetter to get the widths
741 TrueTypeFont* pSftFont = nullptr;
742 SFErrCodes nRC = ::OpenTTFontBuffer(static_cast<void*>(aBuffer.data()), aBuffer.size(), 0, &pSftFont,
743 pFontData->GetFontCharMap());
744 if( nRC != SFErrCodes::Ok )
745 return;
747 SalGraphics::GetGlyphWidths(*pSftFont, *pFontData, bVertical, rGlyphWidths, rUnicodeEnc);
749 ::CloseTTFont( pSftFont );
752 const void* AquaSalGraphics::GetEmbedFontData(const PhysicalFontFace*, tools::Long* /*pDataLen*/)
754 return nullptr;
757 void AquaSalGraphics::FreeEmbedFontData( const void* pData, tools::Long /*nDataLen*/ )
759 // TODO: implementing this only makes sense when the implementation of
760 // AquaSalGraphics::GetEmbedFontData() returns non-NULL
761 SAL_WARN_IF( (pData==nullptr), "vcl", "AquaSalGraphics::FreeEmbedFontData() is not implemented");
764 #ifdef IOS
766 bool AquaSharedAttributes::checkContext()
768 if (mbForeignContext)
770 SAL_INFO("vcl.ios", "CheckContext() this=" << this << ", mbForeignContext, return true");
771 return true;
774 SAL_INFO( "vcl.ios", "CheckContext() this=" << this << ", not foreign, return false");
775 return false;
778 #endif
780 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */