0d6ed6ff7c
Change-Id: If878ae08131ab425ea958f54fc0bd5a07fc76881
627 lines
20 KiB
C++
627 lines
20 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include "coretext/common.h"
|
|
#include "coretext/salcoretextfontutils.hxx"
|
|
#include "quartz/utils.h"
|
|
|
|
#include "sft.hxx"
|
|
|
|
#ifdef MACOSX
|
|
#include "coretext/salgdi.h"
|
|
#include "aqua/salinst.h"
|
|
#else // IOS
|
|
#include "headless/svpinst.hxx"
|
|
#endif
|
|
|
|
static bool GetDevFontAttributes( CTFontDescriptorRef font_descriptor, ImplDevFontAttributes& rDFA )
|
|
{
|
|
int value = 0;
|
|
|
|
// reset the attributes
|
|
rDFA.SetFamilyType( FAMILY_DONTKNOW );
|
|
rDFA.SetPitch( PITCH_VARIABLE );
|
|
rDFA.SetWidthType( WIDTH_NORMAL );
|
|
rDFA.SetWeight( WEIGHT_NORMAL );
|
|
rDFA.SetItalic( ITALIC_NONE );
|
|
rDFA.SetSymbolFlag( false );
|
|
rDFA.mbOrientation = true;
|
|
rDFA.mbDevice = true;
|
|
rDFA.mnQuality = 0;
|
|
|
|
CFNumberRef format = (CFNumberRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontFormatAttribute);
|
|
CFNumberGetValue(format, kCFNumberIntType, &value);
|
|
CFRelease(format);
|
|
|
|
if(value == kCTFontFormatBitmap)
|
|
{
|
|
/* we don't want bitmap fonts */
|
|
return false;
|
|
}
|
|
|
|
rDFA.mbSubsettable = true;
|
|
rDFA.mbEmbeddable = false;
|
|
|
|
CFStringRef family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontFamilyNameAttribute);
|
|
rDFA.SetFamilyName( GetOUString(family_name) );
|
|
CFRelease(family_name);
|
|
|
|
CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontTraitsAttribute);
|
|
CFNumberRef symbolics = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
|
|
CFNumberGetValue(symbolics, kCFNumberIntType, &value);
|
|
|
|
if(value & kCTFontMonoSpaceTrait)
|
|
{
|
|
rDFA.SetPitch( PITCH_FIXED );
|
|
}
|
|
|
|
if(value & kCTFontItalicTrait)
|
|
{
|
|
rDFA.SetItalic( ITALIC_NORMAL );
|
|
}
|
|
|
|
if(value & kCTFontBoldTrait)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_BOLD );
|
|
}
|
|
|
|
if(value & kCTFontCondensedTrait)
|
|
{
|
|
rDFA.SetWidthType( WIDTH_CONDENSED );
|
|
}
|
|
else if(value & kCTFontExpandedTrait)
|
|
{
|
|
rDFA.SetWidthType( WIDTH_EXPANDED );
|
|
}
|
|
switch(value & kCTFontClassMaskTrait)
|
|
{
|
|
case kCTFontOldStyleSerifsClass:
|
|
rDFA.SetFamilyType( FAMILY_ROMAN );
|
|
break;
|
|
case kCTFontTransitionalSerifsClass:
|
|
case kCTFontModernSerifsClass:
|
|
case kCTFontClarendonSerifsClass:
|
|
case kCTFontSlabSerifsClass:
|
|
case kCTFontFreeformSerifsClass:
|
|
break;
|
|
case kCTFontSansSerifClass:
|
|
rDFA.SetFamilyType( FAMILY_SWISS );
|
|
break;
|
|
case kCTFontOrnamentalsClass:
|
|
rDFA.SetFamilyType( FAMILY_DECORATIVE );
|
|
break;
|
|
case kCTFontScriptsClass:
|
|
rDFA.SetFamilyType( FAMILY_SCRIPT );
|
|
break;
|
|
case kCTFontSymbolicClass:
|
|
rDFA.SetSymbolFlag( true );
|
|
break;
|
|
}
|
|
|
|
CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
|
|
float fdval = 0.0;
|
|
CFNumberGetValue(weight, kCFNumberFloatType, &fdval);
|
|
if(fdval > 0.6)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_BLACK );
|
|
}
|
|
else if(fdval > 0.4)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_ULTRABOLD );
|
|
}
|
|
else if (fdval > 0.3)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_BOLD );
|
|
}
|
|
else if (fdval > 0.0)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_SEMIBOLD );
|
|
}
|
|
else if (fdval <= -0.8)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_ULTRALIGHT );
|
|
}
|
|
else if (fdval <= -0.4)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_LIGHT );
|
|
}
|
|
else if (fdval <= -0.3)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_SEMILIGHT );
|
|
}
|
|
else if (fdval <= -0.2)
|
|
{
|
|
rDFA.SetWeight( WEIGHT_THIN );
|
|
}
|
|
else
|
|
{
|
|
rDFA.SetWeight( WEIGHT_NORMAL );
|
|
}
|
|
|
|
CFStringRef string_ref = (CFStringRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontStyleNameAttribute);
|
|
OUString style(GetOUString(string_ref).toAsciiLowerCase());
|
|
CFRelease(string_ref);
|
|
|
|
// heuristics to adjust font slant
|
|
if( (style.indexOf("oblique") != -1) ||
|
|
(style.indexOf("inclined") != -1) ||
|
|
(style.indexOf("slanted") != -1) )
|
|
{
|
|
rDFA.SetItalic( ITALIC_OBLIQUE );
|
|
}
|
|
|
|
// heuristics to adjust font width
|
|
if (style.indexOf("narrow") != -1)
|
|
{
|
|
rDFA.SetWidthType( WIDTH_SEMI_CONDENSED );
|
|
}
|
|
|
|
// heuristics for font family type
|
|
if( (style.indexOf("script") != -1) ||
|
|
(style.indexOf("chancery") != -1) )
|
|
{
|
|
rDFA.SetFamilyType( FAMILY_SCRIPT );
|
|
}
|
|
else if( (style.indexOf("comic") != -1) ||
|
|
(style.indexOf("outline") != -1) ||
|
|
(style.indexOf("pinpoint") != -1) )
|
|
{
|
|
rDFA.SetFamilyType( FAMILY_DECORATIVE );
|
|
}
|
|
else if( (style.indexOf("sans") != -1) )
|
|
{
|
|
rDFA.SetFamilyType( FAMILY_SWISS );
|
|
}
|
|
else if( (style.indexOf("roman") != -1) )
|
|
{
|
|
rDFA.SetFamilyType( FAMILY_ROMAN );
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SystemFontList::SystemFontList()
|
|
{
|
|
CTFontCollectionRef font_collection = CTFontCollectionCreateFromAvailableFonts(NULL);
|
|
if(font_collection)
|
|
{
|
|
CFArrayRef font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(font_collection);
|
|
|
|
if(font_descriptors)
|
|
{
|
|
for(int i = 0; i < CFArrayGetCount(font_descriptors); i++)
|
|
{
|
|
CTFontDescriptorRef font_descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(font_descriptors, i);
|
|
CTFontRef font = CTFontCreateWithFontDescriptor(font_descriptor, 0, NULL);
|
|
if(font)
|
|
{
|
|
ImplDevFontAttributes devfont_attr;
|
|
if(GetDevFontAttributes( font_descriptor, devfont_attr ) )
|
|
{
|
|
CoreTextPhysicalFontFace* font_face = new CoreTextPhysicalFontFace(devfont_attr, font);
|
|
if(font_face && font_face->GetCTFont())
|
|
{
|
|
m_aFontContainer [ font_face->GetCTFont() ] = font_face;
|
|
}
|
|
}
|
|
CFRelease(font);
|
|
}
|
|
}
|
|
CFRelease(font_descriptors);
|
|
}
|
|
CFRelease(font_collection);
|
|
}
|
|
|
|
}
|
|
|
|
SystemFontList::~SystemFontList()
|
|
{
|
|
CoreTextFontContainer::const_iterator it = m_aFontContainer.begin();
|
|
for(; it != m_aFontContainer.end(); ++it )
|
|
delete (*it).second;
|
|
m_aFontContainer.clear();
|
|
}
|
|
|
|
CoreTextPhysicalFontFace* SystemFontList::GetFontDataFromRef( CTFontRef font ) const
|
|
{
|
|
CoreTextFontContainer::const_iterator it = m_aFontContainer.find( font );
|
|
return it == m_aFontContainer.end() ? NULL : (*it).second;
|
|
}
|
|
|
|
|
|
void SystemFontList::AnnounceFonts( ImplDevFontList& rFontList ) const
|
|
{
|
|
CoreTextFontContainer::const_iterator it = m_aFontContainer.begin();
|
|
for(; it != m_aFontContainer.end(); ++it )
|
|
{
|
|
rFontList.Add( (*it).second->Clone() );
|
|
}
|
|
}
|
|
|
|
CoreTextPhysicalFontFace::CoreTextPhysicalFontFace( const ImplDevFontAttributes& rDFA, CTFontRef font )
|
|
: PhysicalFontFace( rDFA, 0 )
|
|
, m_CTFontRef((CTFontRef)CFRetain(font))
|
|
, m_pCharMap( NULL )
|
|
, m_bHasOs2Table( false )
|
|
, m_bOs2TableRead( false )
|
|
, m_bCmapTableRead( false )
|
|
, m_bHasCJKSupport( false )
|
|
, m_bFontCapabilitiesRead( false )
|
|
{
|
|
}
|
|
|
|
CoreTextPhysicalFontFace::~CoreTextPhysicalFontFace()
|
|
{
|
|
if( m_pCharMap )
|
|
{
|
|
m_pCharMap->DeReference();
|
|
}
|
|
SafeCFRelease(m_CTFontRef);
|
|
}
|
|
|
|
PhysicalFontFace* CoreTextPhysicalFontFace::Clone() const
|
|
{
|
|
CoreTextPhysicalFontFace* pClone = new CoreTextPhysicalFontFace(*this);
|
|
if( m_pCharMap )
|
|
{
|
|
m_pCharMap->AddReference();
|
|
}
|
|
if( m_CTFontRef )
|
|
{
|
|
pClone->m_CTFontRef = (CTFontRef)CFRetain(m_CTFontRef);
|
|
}
|
|
return pClone;
|
|
}
|
|
|
|
ImplFontEntry* CoreTextPhysicalFontFace::CreateFontInstance(FontSelectPattern& rFSD) const
|
|
{
|
|
return new ImplFontEntry(rFSD);
|
|
}
|
|
|
|
const ImplFontCharMap* CoreTextPhysicalFontFace::GetImplFontCharMap()
|
|
{
|
|
// return the cached charmap
|
|
if( m_pCharMap )
|
|
{
|
|
return m_pCharMap;
|
|
}
|
|
// set the default charmap
|
|
m_pCharMap = ImplFontCharMap::GetDefaultMap();
|
|
m_pCharMap->AddReference();
|
|
|
|
// get the CMAP byte size
|
|
CFDataRef rCmapTable = CTFontCopyTable( m_CTFontRef, kCTFontTableCmap, kCTFontTableOptionNoOptions);
|
|
if(!rCmapTable)
|
|
{
|
|
return m_pCharMap;
|
|
}
|
|
if(!m_bCmapTableRead)
|
|
{
|
|
m_bCmapTableRead = true;
|
|
DetermineCJKSupport_cmap(rCmapTable);
|
|
}
|
|
// parse the CMAP
|
|
CmapResult aCmapResult;
|
|
if(ParseCMAP( CFDataGetBytePtr(rCmapTable), CFDataGetLength(rCmapTable), aCmapResult ) )
|
|
{
|
|
m_pCharMap = new ImplFontCharMap( aCmapResult );
|
|
m_pCharMap->AddReference();
|
|
}
|
|
CFRelease(rCmapTable);
|
|
return m_pCharMap;
|
|
}
|
|
|
|
bool CoreTextPhysicalFontFace::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities)
|
|
{
|
|
// read this only once per font
|
|
if( m_bFontCapabilitiesRead )
|
|
{
|
|
rFontCapabilities = m_aFontCapabilities;
|
|
return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
|
|
}
|
|
m_bFontCapabilitiesRead = true;
|
|
|
|
// get the GSUB table raw data
|
|
CFDataRef rGSUBTable = CTFontCopyTable( m_CTFontRef, kCTFontTableGSUB, kCTFontTableOptionNoOptions);
|
|
if(rGSUBTable)
|
|
{
|
|
|
|
vcl::getTTScripts(m_aFontCapabilities.maGSUBScriptTags,
|
|
CFDataGetBytePtr(rGSUBTable), CFDataGetLength(rGSUBTable));
|
|
CFRelease(rGSUBTable);
|
|
}
|
|
CFDataRef OS2_Table = CTFontCopyTable( m_CTFontRef, kCTFontTableOS2, kCTFontTableOptionNoOptions);
|
|
if(OS2_Table)
|
|
{
|
|
vcl::getTTCoverage(
|
|
m_aFontCapabilities.maUnicodeRange,
|
|
m_aFontCapabilities.maCodePageRange,
|
|
CFDataGetBytePtr(OS2_Table), CFDataGetLength(OS2_Table));
|
|
/* while we are at it let's solve HasCJK for the same price */
|
|
if(!m_bOs2TableRead )
|
|
{
|
|
m_bOs2TableRead = true;
|
|
m_bHasOs2Table = true;
|
|
DetermineCJKSupport_OS2(OS2_Table);
|
|
}
|
|
CFRelease(OS2_Table);
|
|
}
|
|
rFontCapabilities = m_aFontCapabilities;
|
|
return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
|
|
}
|
|
|
|
struct font_table
|
|
{
|
|
unsigned char* table;
|
|
unsigned char* dir_entry;
|
|
unsigned char* cursor;
|
|
};
|
|
|
|
void addTable(struct font_table* table, CTFontTableTag tag, CFDataRef data)
|
|
{
|
|
if(data && CFDataGetLength(data) > 0)
|
|
{
|
|
*(uint32_t*)table->dir_entry = CFSwapInt32HostToBig(tag);
|
|
table->dir_entry += 4;
|
|
*(uint32_t*)table->dir_entry = 0; /* TODO: checksum */
|
|
table->dir_entry += 4;
|
|
*(uint32_t*)table->dir_entry = CFSwapInt32HostToBig((uint32_t)((uintptr_t)table->cursor - (uintptr_t)table));
|
|
table->dir_entry += 4;
|
|
*(uint32_t*)table->dir_entry = CFSwapInt32HostToBig(CFDataGetLength(data));
|
|
table->dir_entry += 4;
|
|
|
|
memcpy(table->cursor, CFDataGetBytePtr(data), CFDataGetLength(data));
|
|
table->cursor += CFDataGetLength(data);
|
|
}
|
|
}
|
|
|
|
bool CoreTextPhysicalFontFace::GetRawFontData( std::vector<unsigned char>& rBuffer, bool* pJustCFF ) const
|
|
{
|
|
bool rc;
|
|
int table_count = 0;
|
|
|
|
CFDataRef CFF_table = CTFontCopyTable( m_CTFontRef, kCTFontTableCFF, kCTFontTableOptionNoOptions);
|
|
if(pJustCFF)
|
|
{
|
|
if(CFF_table)
|
|
{
|
|
*pJustCFF = CFDataGetLength(CFF_table) ? true : false;
|
|
CFRelease(CFF_table);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
size_t total_len = 0;
|
|
CFDataRef head_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHead, kCTFontTableOptionNoOptions);
|
|
CFDataRef maxp_table = CTFontCopyTable( m_CTFontRef, kCTFontTableMaxp, kCTFontTableOptionNoOptions);
|
|
CFDataRef cmap_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHead, kCTFontTableOptionNoOptions);
|
|
CFDataRef name_table = CTFontCopyTable( m_CTFontRef, kCTFontTableName, kCTFontTableOptionNoOptions);
|
|
CFDataRef hhea_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHhea, kCTFontTableOptionNoOptions);
|
|
CFDataRef hmtx_table = CTFontCopyTable( m_CTFontRef, kCTFontTableHmtx, kCTFontTableOptionNoOptions);
|
|
rc = false;
|
|
if(head_table && maxp_table && cmap_table && name_table && hhea_table && hmtx_table)
|
|
{
|
|
if(CFDataGetLength(head_table) &&
|
|
CFDataGetLength(maxp_table) &&
|
|
CFDataGetLength(name_table) &&
|
|
CFDataGetLength(hhea_table) &&
|
|
CFDataGetLength(hmtx_table))
|
|
{
|
|
table_count += 6;
|
|
total_len = CFDataGetLength(head_table) +
|
|
CFDataGetLength(maxp_table) +
|
|
CFDataGetLength(name_table) +
|
|
CFDataGetLength(hhea_table) +
|
|
CFDataGetLength(hmtx_table);
|
|
rc = true;
|
|
}
|
|
}
|
|
|
|
CFDataRef loca_table = NULL;
|
|
CFDataRef glyf_table = NULL;
|
|
CFDataRef prep_table = NULL;
|
|
CFDataRef cvt_table = NULL;
|
|
CFDataRef fpgm_table = NULL;
|
|
if(rc)
|
|
{
|
|
if(!CFF_table || CFDataGetLength(CFF_table) == 0)
|
|
{
|
|
loca_table = CTFontCopyTable( m_CTFontRef, kCTFontTableLoca, kCTFontTableOptionNoOptions);
|
|
glyf_table = CTFontCopyTable( m_CTFontRef, kCTFontTableGlyf, kCTFontTableOptionNoOptions);
|
|
if(!loca_table || !glyf_table || !CFDataGetLength(loca_table) || !CFDataGetLength(glyf_table))
|
|
{
|
|
rc = false;
|
|
}
|
|
else
|
|
{
|
|
table_count += 2;
|
|
total_len += CFDataGetLength(loca_table) + CFDataGetLength(glyf_table);
|
|
prep_table = CTFontCopyTable( m_CTFontRef, kCTFontTablePrep, kCTFontTableOptionNoOptions);
|
|
cvt_table = CTFontCopyTable( m_CTFontRef, kCTFontTableCvt, kCTFontTableOptionNoOptions);
|
|
fpgm_table = CTFontCopyTable( m_CTFontRef, kCTFontTableFpgm, kCTFontTableOptionNoOptions);
|
|
if(prep_table || CFDataGetLength(prep_table) > 0)
|
|
{
|
|
table_count += 1;
|
|
total_len += CFDataGetLength(prep_table);
|
|
}
|
|
if(cvt_table || CFDataGetLength(cvt_table) > 0)
|
|
{
|
|
table_count += 1;
|
|
total_len += CFDataGetLength(cvt_table);
|
|
}
|
|
if(fpgm_table || CFDataGetLength(fpgm_table) > 0)
|
|
{
|
|
table_count += 1;
|
|
total_len += CFDataGetLength(fpgm_table);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
table_count += 1;
|
|
total_len += CFDataGetLength(CFF_table);
|
|
}
|
|
}
|
|
if(rc)
|
|
{
|
|
total_len += 12 + 16 * table_count;
|
|
rBuffer.resize(total_len);
|
|
struct font_table table;
|
|
unsigned char* cursor = &rBuffer[0];
|
|
int nLog2 = 0;
|
|
|
|
while( (table_count >> nLog2) > 1 ) ++nLog2;
|
|
|
|
table.table = cursor;
|
|
*(uint16_t*)cursor = CFSwapInt16HostToBig(1);
|
|
cursor += 2;
|
|
*(uint16_t*)cursor = 0;
|
|
cursor += 2;
|
|
*(uint16_t*)cursor = CFSwapInt16HostToBig(table_count);
|
|
cursor += 2;
|
|
*(uint16_t*)cursor = CFSwapInt16HostToBig(nLog2 * 16);
|
|
cursor += 2;
|
|
*(uint16_t*)cursor = CFSwapInt16HostToBig(nLog2);
|
|
cursor += 2;
|
|
*(uint16_t*)cursor = CFSwapInt16HostToBig((table_count - nLog2) * 16); // rangeShift
|
|
cursor += 2;
|
|
table.dir_entry = cursor;
|
|
cursor += (16 * table_count);
|
|
table.cursor = cursor;
|
|
addTable(&table, kCTFontTableCmap, cmap_table);
|
|
addTable(&table, kCTFontTableCvt, cvt_table);
|
|
addTable(&table, kCTFontTableFpgm, fpgm_table);
|
|
addTable(&table, kCTFontTableCFF, CFF_table);
|
|
addTable(&table, kCTFontTableGlyf, glyf_table);
|
|
addTable(&table, kCTFontTableLoca, loca_table);
|
|
addTable(&table, kCTFontTableHead, head_table);
|
|
addTable(&table, kCTFontTableHhea, hhea_table);
|
|
addTable(&table, kCTFontTableHmtx, hmtx_table);
|
|
addTable(&table, kCTFontTableMaxp, maxp_table);
|
|
addTable(&table, kCTFontTableName, name_table);
|
|
addTable(&table, kCTFontTablePrep, prep_table);
|
|
}
|
|
SafeCFRelease(cmap_table);
|
|
SafeCFRelease(cvt_table);
|
|
SafeCFRelease(fpgm_table);
|
|
SafeCFRelease(CFF_table);
|
|
SafeCFRelease(glyf_table);
|
|
SafeCFRelease(loca_table);
|
|
SafeCFRelease(head_table);
|
|
SafeCFRelease(hhea_table);
|
|
SafeCFRelease(hmtx_table);
|
|
SafeCFRelease(maxp_table);
|
|
SafeCFRelease(name_table);
|
|
SafeCFRelease(prep_table);
|
|
|
|
return rc;
|
|
}
|
|
|
|
void CoreTextPhysicalFontFace::DetermineCJKSupport_OS2(CFDataRef rOS2Table)
|
|
{
|
|
if(CFDataGetLength(rOS2Table) >= 48)
|
|
{
|
|
const unsigned short* pOS2buffer = (const unsigned short*)CFDataGetBytePtr(rOS2Table);
|
|
const unsigned short version = CFSwapInt16BigToHost(pOS2buffer[0]);
|
|
if( version >= 1)
|
|
{
|
|
const unsigned short unicode_range = CFSwapInt16BigToHost(pOS2buffer[23]);
|
|
if( unicode_range & 0x2DF0)
|
|
{
|
|
m_bHasCJKSupport = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CoreTextPhysicalFontFace::DetermineCJKSupport_cmap(CFDataRef rCmapTable)
|
|
{
|
|
int table_len = CFDataGetLength(rCmapTable) / 2;
|
|
if(table_len >= 12)
|
|
{
|
|
const unsigned short* pCmap = (const unsigned short*)CFDataGetBytePtr(rCmapTable);
|
|
if(pCmap[0] == 0)
|
|
{
|
|
short nb_sub_tables = CFSwapInt16BigToHost(pCmap[1]);
|
|
for(int i = 2; --nb_sub_tables >= 0 && i < table_len; i += 4)
|
|
{
|
|
short platform = CFSwapInt16BigToHost(pCmap[i]);
|
|
if( platform == kFontMacintoshPlatform )
|
|
{
|
|
short encoding = CFSwapInt16BigToHost(pCmap[i+1]);
|
|
if( encoding == kFontJapaneseScript ||
|
|
encoding == kFontTraditionalChineseScript ||
|
|
encoding == kFontKoreanScript ||
|
|
encoding == kFontSimpleChineseScript )
|
|
{
|
|
m_bHasCJKSupport = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CoreTextPhysicalFontFace::HasCJKSupport( void )
|
|
{
|
|
// read this only once per font
|
|
if(!m_bOs2TableRead )
|
|
{
|
|
m_bOs2TableRead = true;
|
|
CFDataRef rOS2Table = CTFontCopyTable( m_CTFontRef, kCTFontTableOS2, kCTFontTableOptionNoOptions);
|
|
if(rOS2Table)
|
|
{
|
|
m_bHasOs2Table = true;
|
|
DetermineCJKSupport_OS2(rOS2Table);
|
|
CFRelease(rOS2Table);
|
|
}
|
|
}
|
|
if( !m_bCmapTableRead && !m_bHasOs2Table && !m_bHasCJKSupport )
|
|
{
|
|
m_bCmapTableRead = true;
|
|
CFDataRef rCmapTable = CTFontCopyTable( m_CTFontRef, kCTFontTableCmap, kCTFontTableOptionNoOptions);
|
|
if(rCmapTable)
|
|
{
|
|
DetermineCJKSupport_cmap(rCmapTable);
|
|
CFRelease(rCmapTable);
|
|
}
|
|
}
|
|
return m_bHasCJKSupport;
|
|
}
|
|
|
|
std::ostream &operator <<(std::ostream& s, CTFontRef pFont)
|
|
{
|
|
#ifndef SAL_LOG_INFO
|
|
(void) pFont;
|
|
#else
|
|
if (pFont) {
|
|
CFStringRef fontString = CTFontCopyFullName(pFont);
|
|
s << "{" << GetOUString(fontString) << "@" << CTFontGetSize(pFont) << "}";
|
|
CFRelease(fontString);
|
|
} else {
|
|
s << "NULL";
|
|
}
|
|
#endif
|
|
return s;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|