2b4fd2c89a
Patches contributed by Pedro Giffuni: Avoid some uses of non portable #!/bin/bash in shell scripts. http://svn.apache.org/viewvc?view=revision&revision=1235297 Reduce the dependencies on non standard GNU copy. http://svn.apache.org/viewvc?view=revision&revision=1238684 Correct /usr/bin/env path. http://svn.apache.org/viewvc?view=revision&revision=1235619 Complex Toolbar Controls Extension from the SDK Patches contributed by Ariel Constenla-Haile http://svn.apache.org/viewvc?view=revision&revision=1190390 i118615 - make epm more verbose http://svn.apache.org/viewvc?view=revision&revision=1204288 Patches contributed by Mathias Bauer (and others) gnumake4 work variously http://svn.apache.org/viewvc?view=revision&revision=1394707 http://svn.apache.org/viewvc?view=revision&revision=1394326 Patches contributed by Juergen Schmidt: jsc341: i117327: take care if no dependency node in current description exists, create one http://svn.apache.org/viewvc?view=revision&revision=1172101 jsc341: i117327: add extra extension dependency check http://svn.apache.org/viewvc?view=revision&revision=1172098 make initial branding changes http://svn.apache.org/viewvc?view=revision&revision=1231878 Patches contributed by Ingo Schmidt native373: #i117733# no linux jre installation on 64 bit systems http://svn.apache.org/viewvc?view=revision&revision=1167536 native373: ##164464# improve debian support http://svn.apache.org/viewvc?view=revision&revision=1167537 Patch contribtued by Armin Le-Grand: Changed various aspects concerning usages of old vendor names http://svn.apache.org/viewvc?view=revision&revision=1293313 fix for neon webdav, remove coinmp bits, improve odk script, cleanup & remove OS/2 conditionals, system ucpp fixes, remove OS/2 conditionals, restore our license filenames.
611 lines
19 KiB
C++
611 lines
19 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 "ios/common.h"
|
|
|
|
#include "ios/salcoretextfontutils.hxx"
|
|
#include "ios/salgdi.h"
|
|
|
|
#include "sft.hxx"
|
|
#include "ios/salinst.h"
|
|
|
|
|
|
static bool GetDevFontAttributes( CTFontDescriptorRef font_descriptor, ImplDevFontAttributes& rDFA )
|
|
{
|
|
|
|
// reset the attributes
|
|
rDFA.meFamily = FAMILY_DONTKNOW;
|
|
rDFA.mePitch = PITCH_VARIABLE;
|
|
rDFA.meWidthType = WIDTH_NORMAL;
|
|
rDFA.meWeight = WEIGHT_NORMAL;
|
|
rDFA.meItalic = ITALIC_NONE;
|
|
rDFA.mbSymbolFlag = false;
|
|
rDFA.mbOrientation = true;
|
|
rDFA.mbDevice = true;
|
|
rDFA.mnQuality = 0;
|
|
|
|
CFNumberRef format = (CFNumberRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontFormatAttribute);
|
|
int value = 0;
|
|
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.maName = GetOUString(family_name);
|
|
CFRelease(family_name);
|
|
|
|
CFDictionaryRef traits = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontTraitsAttribute);
|
|
CFNumberRef symbolics = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontSymbolicTrait);
|
|
|
|
value = 0;
|
|
CFNumberGetValue(symbolics, kCFNumberIntType, &value);
|
|
CFRelease(symbolics);
|
|
|
|
if (value & kCTFontMonoSpaceTrait)
|
|
{
|
|
rDFA.mePitch = PITCH_FIXED;
|
|
}
|
|
|
|
if (value & kCTFontItalicTrait)
|
|
{
|
|
rDFA.meItalic = ITALIC_NORMAL;
|
|
}
|
|
|
|
if (value & kCTFontBoldTrait)
|
|
{
|
|
rDFA.meWeight = WEIGHT_BOLD;
|
|
}
|
|
|
|
if (value & kCTFontCondensedTrait)
|
|
{
|
|
rDFA.meWidthType = WIDTH_CONDENSED;
|
|
}
|
|
else if (value & kCTFontExpandedTrait)
|
|
{
|
|
rDFA.meWidthType = WIDTH_EXPANDED;
|
|
}
|
|
switch(value & kCTFontClassMaskTrait)
|
|
{
|
|
case kCTFontOldStyleSerifsClass:
|
|
rDFA.meFamily = FAMILY_ROMAN;
|
|
break;
|
|
case kCTFontTransitionalSerifsClass:
|
|
case kCTFontModernSerifsClass:
|
|
case kCTFontClarendonSerifsClass:
|
|
case kCTFontSlabSerifsClass:
|
|
case kCTFontFreeformSerifsClass:
|
|
break;
|
|
case kCTFontSansSerifClass:
|
|
rDFA.meFamily = FAMILY_SWISS;
|
|
case kCTFontOrnamentalsClass:
|
|
rDFA.meFamily = FAMILY_DECORATIVE;
|
|
break;
|
|
case kCTFontScriptsClass:
|
|
rDFA.meFamily = FAMILY_SCRIPT;
|
|
break;
|
|
case kCTFontSymbolicClass:
|
|
rDFA.mbSymbolFlag = true;
|
|
break;
|
|
}
|
|
|
|
CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(traits, kCTFontWeightTrait);
|
|
float fdval = 0.0;
|
|
CFNumberGetValue(weight, kCFNumberFloatType, &fdval);
|
|
if (fdval > 0.6)
|
|
{
|
|
rDFA.meWeight = WEIGHT_BLACK;
|
|
}
|
|
else if (fdval > 0.4)
|
|
{
|
|
rDFA.meWeight = WEIGHT_ULTRABOLD;
|
|
}
|
|
else if (fdval > 0.3)
|
|
{
|
|
rDFA.meWeight = WEIGHT_BOLD;
|
|
}
|
|
else if (fdval > 0.0)
|
|
{
|
|
rDFA.meWeight = WEIGHT_SEMIBOLD;
|
|
}
|
|
else if (fdval <= -0.8)
|
|
{
|
|
rDFA.meWeight = WEIGHT_ULTRALIGHT;
|
|
}
|
|
else if (fdval <= -0.4)
|
|
{
|
|
rDFA.meWeight = WEIGHT_LIGHT;
|
|
}
|
|
else if (fdval <= -0.3)
|
|
{
|
|
rDFA.meWeight = WEIGHT_SEMILIGHT;
|
|
}
|
|
else if (fdval <= -0.2)
|
|
{
|
|
rDFA.meWeight = WEIGHT_THIN;
|
|
}
|
|
else
|
|
{
|
|
rDFA.meWeight = WEIGHT_NORMAL;
|
|
}
|
|
|
|
CFStringRef string_ref = (CFStringRef)CTFontDescriptorCopyAttribute(font_descriptor, kCTFontStyleNameAttribute);
|
|
rtl::OUString font_name = GetOUString(string_ref);
|
|
rtl::OUString font_name_lc(font_name.toAsciiLowerCase());
|
|
CFRelease(string_ref);
|
|
|
|
// heuristics to adjust font slant
|
|
if ( (font_name_lc.indexOf("oblique") != -1) ||
|
|
(font_name_lc.indexOf("inclined") != -1) ||
|
|
(font_name_lc.indexOf("slanted") != -1) )
|
|
{
|
|
rDFA.meItalic = ITALIC_OBLIQUE;
|
|
}
|
|
|
|
// heuristics to adjust font width
|
|
if (font_name_lc.indexOf("narrow") != -1)
|
|
{
|
|
rDFA.meWidthType = WIDTH_SEMI_CONDENSED;
|
|
}
|
|
|
|
// heuristics for font family type
|
|
if ( (font_name_lc.indexOf("script") != -1) ||
|
|
(font_name_lc.indexOf("chancery") != -1) ||
|
|
(font_name_lc.indexOf("zapfino") != -1))
|
|
{
|
|
rDFA.meFamily = FAMILY_SCRIPT;
|
|
}
|
|
else if ( (font_name_lc.indexOf("comic") != -1) ||
|
|
(font_name_lc.indexOf("outline") != -1) ||
|
|
(font_name_lc.indexOf("pinpoint") != -1) )
|
|
{
|
|
rDFA.meFamily = FAMILY_DECORATIVE;
|
|
}
|
|
else if ( (font_name_lc.indexOf("sans") != -1) ||
|
|
(font_name_lc.indexOf("arial") != -1) )
|
|
{
|
|
rDFA.meFamily = FAMILY_SWISS;
|
|
}
|
|
else if ( (font_name_lc.indexOf("roman") != -1) ||
|
|
(font_name_lc.indexOf("times") != -1) )
|
|
{
|
|
rDFA.meFamily = FAMILY_ROMAN;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
SystemFontList::SystemFontList()
|
|
{
|
|
CTFontCollectionRef font_collection = CTFontCollectionCreateFromAvailableFonts(NULL);
|
|
if (font_collection)
|
|
{
|
|
CFArrayRef font_descriptors = CTFontCollectionCreateMatchingFontDescriptors(font_collection);
|
|
|
|
for(int i = 0; i < CFArrayGetCount(font_descriptors); i++)
|
|
{
|
|
CTFontDescriptorRef font_descriptor = (CTFontDescriptorRef)CFArrayGetValueAtIndex(font_descriptors, i);
|
|
CTFontRef font = CTFontCreateWithFontDescriptor(font_descriptor, 0, NULL);
|
|
ImplDevFontAttributes devfont_attr;
|
|
if (GetDevFontAttributes( font_descriptor, devfont_attr ) )
|
|
{
|
|
ImplCoreTextFontData* font_data = new ImplCoreTextFontData(devfont_attr, font);
|
|
if (font_data && font_data->GetCTFont())
|
|
{
|
|
m_aFontContainer [ font_data->GetCTFont() ] = font_data;
|
|
}
|
|
}
|
|
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();
|
|
}
|
|
|
|
ImplCoreTextFontData* 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() );
|
|
}
|
|
}
|
|
|
|
ImplCoreTextFontData::ImplCoreTextFontData( 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 )
|
|
{
|
|
}
|
|
|
|
ImplCoreTextFontData::~ImplCoreTextFontData()
|
|
{
|
|
if ( m_pCharMap )
|
|
{
|
|
m_pCharMap->DeReference();
|
|
}
|
|
if ( m_CTFontRef )
|
|
{
|
|
CFRelease(m_CTFontRef);
|
|
}
|
|
}
|
|
|
|
PhysicalFontFace* ImplCoreTextFontData::Clone() const
|
|
{
|
|
ImplCoreTextFontData* pClone = new ImplCoreTextFontData(*this);
|
|
if ( m_pCharMap )
|
|
{
|
|
m_pCharMap->AddReference();
|
|
}
|
|
if ( m_CTFontRef )
|
|
{
|
|
pClone->m_CTFontRef = (CTFontRef)CFRetain(m_CTFontRef);
|
|
}
|
|
return pClone;
|
|
}
|
|
|
|
ImplFontEntry* ImplCoreTextFontData::CreateFontInstance(FontSelectPattern& rFSD) const
|
|
{
|
|
return new ImplFontEntry(rFSD);
|
|
}
|
|
|
|
const ImplFontCharMap* ImplCoreTextFontData::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 ImplCoreTextFontData::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 ImplCoreTextFontData::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;
|
|
}
|
|
if (CFF_table)
|
|
{
|
|
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 ImplCoreTextFontData::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 ImplCoreTextFontData::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 ImplCoreTextFontData::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;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|