diff options
author | Norbert Thiebaud <nthiebaud@gmail.com> | 2012-04-02 00:15:07 -0500 |
---|---|---|
committer | Norbert Thiebaud <nthiebaud@gmail.com> | 2012-06-23 23:23:25 -0500 |
commit | 8c91ec1ab0b6f437b8b60ed9aee067f088fa4718 (patch) | |
tree | 251d1945755046b411c1370c737e84821db7ff0a /vcl | |
parent | 2c506447fcf020b17797c30d001fda9c177a4235 (diff) |
Initial basic support for CoreText. very partial and highly unstable.
Change-Id: I5dc9fb342e45fa3d428e340a597a2d9d4e246cb5
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Library_vcl.mk | 12 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/coretext/salcoretextfontutils.cxx | 603 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/coretext/salcoretextlayout.cxx | 458 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/coretext/salcoretextstyle.cxx | 93 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/coretext/salgdi.cxx | 234 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salgdicommon.cxx | 2 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salgdiutils.cxx | 8 | ||||
-rw-r--r-- | vcl/inc/aqua/atsui/salgdi.h | 3 | ||||
-rw-r--r-- | vcl/inc/aqua/common.h | 19 | ||||
-rw-r--r-- | vcl/inc/aqua/coretext/salcoretextfontutils.hxx | 67 | ||||
-rw-r--r-- | vcl/inc/aqua/coretext/salcoretextlayout.hxx | 64 | ||||
-rw-r--r-- | vcl/inc/aqua/coretext/salcoretextstyle.hxx | 42 | ||||
-rw-r--r-- | vcl/inc/aqua/coretext/salgdi.h | 297 | ||||
-rw-r--r-- | vcl/inc/vcl/sysdata.hxx | 3 |
14 files changed, 1899 insertions, 6 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index f98ca9835c51..451c15b4f709 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -335,6 +335,17 @@ $(eval $(call gb_Library_add_defs,vcl,\ -DENABLE_CORETEXT \ )) +$(eval $(call gb_Library_add_exception_objects,vcl,\ + vcl/aqua/source/gdi/coretext/salcoretextfontutils \ + vcl/aqua/source/gdi/coretext/salcoretextlayout \ + vcl/aqua/source/gdi/coretext/salcoretextstyle \ + vcl/aqua/source/gdi/coretext/salgdi \ +)) + +$(eval $(call gb_Library_use_externals,vcl,\ + coretext \ +)) + else # ATSUI $(eval $(call gb_Library_add_exception_objects,vcl,\ @@ -399,6 +410,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/aqua/source/dtrans/service_entry \ vcl/aqua/source/gdi/salbmp \ vcl/aqua/source/gdi/salcolorutils \ + vcl/aqua/source/gdi/salgdicommon \ vcl/aqua/source/gdi/salgdiutils \ vcl/aqua/source/gdi/salmathutils \ vcl/aqua/source/gdi/salnativewidgets \ diff --git a/vcl/aqua/source/gdi/coretext/salcoretextfontutils.cxx b/vcl/aqua/source/gdi/coretext/salcoretextfontutils.cxx new file mode 100644 index 000000000000..08db4fdc19ec --- /dev/null +++ b/vcl/aqua/source/gdi/coretext/salcoretextfontutils.cxx @@ -0,0 +1,603 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include "aqua/common.h" + +#include "aqua/coretext/salcoretextfontutils.hxx" +#include "aqua/coretext/salgdi.h" + +#include "sft.hxx" +#include "aqua/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; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 + CTFontRef font = CTFontCreateWithFontDescriptor(font_descriptor, 0.0, NULL); + CFDataRef rHeadTable = CTFontCopyTable(font, kCTFontTableHead, kCTFontTableOptionNoOptions); + CFRelease(font); + if(!rHeadTable || CFDataGetLength(rHeadTable) == 0) + { + SafeCFRelease(rHeadTable); + return false; + } + CFRelease(rHeadTable); +#else + 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; + } +#endif + 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); + int 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; +} diff --git a/vcl/aqua/source/gdi/coretext/salcoretextlayout.cxx b/vcl/aqua/source/gdi/coretext/salcoretextlayout.cxx new file mode 100644 index 000000000000..408f2b2ec34e --- /dev/null +++ b/vcl/aqua/source/gdi/coretext/salcoretextlayout.cxx @@ -0,0 +1,458 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include "aqua/common.h" +#include "aqua/coretext/salcoretextstyle.hxx" +#include "aqua/coretext/salcoretextlayout.hxx" +#include "aqua/coretext/salgdi.h" + + +CoreTextLayout::CoreTextLayout(AquaSalGraphics* graphics, CoreTextStyleInfo* style) : + m_graphics(graphics), + m_style(style), + m_glyphs_count(-1), + m_chars_count(-1), + m_chars2glyphs(NULL), + m_glyphs2chars(NULL), + m_glyphs(NULL), + m_char_widths(NULL), + m_glyph_advances(NULL), + m_glyph_positions(NULL), + m_typesetter(NULL), + m_line(NULL), + m_has_bound_rec(false), + m_base_advance(0), + m_cached_width(0.0F), + m_current_run_index(0), + m_current_glyph_index(0), + m_current_glyphrun_index(0), + m_runs(NULL) +{ +} + +CoreTextLayout::~CoreTextLayout() +{ + Clean(); +} + +void CoreTextLayout::AdjustLayout( ImplLayoutArgs& /*rArgs*/ ) +{ + msgs_debug(layout,"-->"); + msgs_debug(layout,"<--"); + /* TODO */ +} + +void CoreTextLayout::Clean() +{ + msgs_debug(layout,"-->"); + if(m_glyphs) + { + delete[] m_glyphs; + m_glyphs = NULL; + } + if(m_chars2glyphs) + { + delete[] m_chars2glyphs; + m_chars2glyphs = NULL; + } + if(m_glyphs2chars) + { + delete[] m_glyphs2chars; + m_glyphs2chars = NULL; + } + if(m_char_widths) + { + delete[] m_char_widths; + m_char_widths = NULL; + } + if(m_glyph_advances) + { + delete[] m_glyph_advances; + m_glyph_advances = NULL; + } + if(m_glyph_positions) + { + delete[] m_glyph_positions; + m_glyph_positions = NULL; + } + SafeCFRelease(m_typesetter); + SafeCFRelease(m_line); + m_has_bound_rec = false; + msgs_debug(layout,"<--"); +} + +void CoreTextLayout::DrawText( SalGraphics& rGraphics ) const +{ + msgs_debug(layout,"-->"); + AquaSalGraphics& gr = static_cast<AquaSalGraphics&>(rGraphics); + if(m_chars_count <= 0 || !gr.CheckContext()) + { + return; + } + CGContextSaveGState( gr.mrContext ); + Point pos = GetDrawPosition(Point(0,0)); +#if 0 + msgs_debug(layout,"at pos (%ld, %ld)", pos.X(), pos.Y()); + CGContextSetTextMatrix(gr.mrContext, CGAffineTransformMakeScale(1.0, -1.0)); + CGContextSetShouldAntialias( gr.mrContext, !gr.mbNonAntialiasedText ); + CGContextSetTextPosition(gr.mrContext, pos.X(), pos.Y()); + CTLineDraw(m_line, gr.mrContext); +#else + InitGIA(); + msgs_debug(layout,"at- pos (%ld, %ld)", pos.X(), pos.Y()); + CGFontRef cg_font = CTFontCopyGraphicsFont(m_style->GetFont(), NULL); + CGContextSetFont(gr.mrContext, cg_font); + CGContextSetFontSize(gr.mrContext, CTFontGetSize(m_style->GetFont())); + CGContextSetTextDrawingMode(gr.mrContext, kCGTextFill); + CGContextSetShouldAntialias( gr.mrContext, true ); + if(m_style->GetColor()) + { + CGContextSetFillColorWithColor(gr.mrContext, m_style->GetColor()); + CGContextSetStrokeColorWithColor(gr.mrContext, m_style->GetColor()); + } + else + { + CGContextSetRGBFillColor(gr.mrContext, 0.0, 0.0, 0.0, 1.0); + } + CFRelease(cg_font); +// CGContextSetTextPosition(gr.mrContext, pos.X(), pos.Y()); + CGContextSetTextMatrix(gr.mrContext, CGAffineTransformMakeScale(1.0, -1.0)); + CGContextSetShouldAntialias( gr.mrContext, !gr.mbNonAntialiasedText ); + CGContextTranslateCTM(gr.mrContext, pos.X(), pos.Y()); +// for(int i = 0; i < m_glyphs_count ; ++i) +// { +// msgs_debug(layout,"m_glyph=%p m_glyph_positions=%p count=%d", m_glyphs, m_glyph_positions, m_glyphs_count); +// msgs_debug(layout,"glyph[%d]=0x%x position(%g,%g)", i, m_glyphs[i], m_glyph_positions[i].x, m_glyph_positions[i].y); + CGContextShowGlyphs(gr.mrContext, m_glyphs, m_glyphs_count); +// CGContextShowGlyphsAtPositions(gr.mrContext, m_glyphs, m_glyph_positions, m_glyphs_count); +// CGContextShowGlyphsWidthAdvances(gr.mrContext, m_glyphs, m_glyph_advances, m_glyphs_count); + +// CGContextShowGlyphsAtPoint(gr.mrContext, pos.X(), pos.Y(), m_glyphs, m_glyphs_count); +// } +#endif + // restore the original graphic context transformations + CGContextRestoreGState( gr.mrContext ); + msgs_debug(layout,"<--"); + +} + +// not needed. CoreText manage fallback directly +void CoreTextLayout::DropGlyph( int /*nStart*/ ) {} + +long CoreTextLayout::FillDXArray( long* pDXArray ) const +{ + msgs_debug(layout,"-->"); + // short circuit requests which don't need full details + if( !pDXArray ) + { + return GetTextWidth(); + } + // check assumptions + DBG_ASSERT( !mnTrailingSpaceWidth, "CoreText::FillDXArray() with nTSW!=0" ); + + // initialize details about the resulting layout + InitGIA(); + + // distribute the widths among the string elements + long width = 0; + float scale = m_style->GetFontStretchFactor(); + m_cached_width = 0; + + for( int i = 0; i < m_chars_count; ++i ) + { + // convert and adjust for accumulated rounding errors + m_cached_width += m_char_widths[i]; + const long old_width = width; + width = round_to_long(m_cached_width * scale); + pDXArray[i] = width - old_width; + } + msgs_debug(layout," w=%ld <--", width); + return width; +} + +bool CoreTextLayout::GetBoundRect( SalGraphics& rGraphics, Rectangle& rVCLRect ) const +{ + + msgs_debug(layout,"-->"); + if ( !m_has_bound_rec ) + { + AquaSalGraphics& gr = static_cast<AquaSalGraphics&>(rGraphics); + CGRect bound_rect = CTLineGetImageBounds( m_line, gr.mrContext ); + if ( !CGRectIsNull( bound_rect ) ) + { + m_bound_rect = Rectangle( + Point( round_to_long(bound_rect.origin.x * m_style->GetFontStretchFactor()), + round_to_long(bound_rect.origin.y - bound_rect.size.height )), + Size( round_to_long(bound_rect.size.width * m_style->GetFontStretchFactor()), round_to_long(bound_rect.size.height))); + m_bound_rect.Justify(); + } + m_has_bound_rec = true; + } + rVCLRect = m_bound_rect; + msgs_debug(layout,"<--"); + return true; +} + +void CoreTextLayout::GetCaretPositions( int max_index, long* caret_position) const +{ + msgs_debug(layout,"max_index %d -->", max_index); + int local_max = max_index < m_chars_count * 2 ? max_index : m_chars_count; + for(int i = 0 ; i < max_index - 1; i+=2) + { + CGFloat primary, secondary; + primary = CTLineGetOffsetForStringIndex(m_line, i >> 1, &secondary); + caret_position[i] = round_to_long(m_base_advance + primary); + caret_position[i+1] = round_to_long(m_base_advance + secondary); + i += 2; + } + for(int i = local_max ; i < max_index ; ++i) + { + caret_position[i] = -1; + } + msgs_debug(layout,"<--"); +} + +bool CoreTextLayout::GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const { return false; } + +int CoreTextLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIDs, Point& rPos, int& nStart, + sal_Int32* pGlyphAdvances, int* pCharIndexes ) const +{ + msgs_debug(layout,"nLen=%d nStart=%d-->", nLen, nStart); + // get glyph measurements + InitGIA(); + + if( nStart < 0 ) // first glyph requested? + { + nStart = 0; + m_current_run_index = 0; + m_current_glyph_index = 0; + m_current_glyphrun_index = 0; + } + else if(nStart >= m_glyphs_count) + { + m_current_run_index = 0; + m_current_glyph_index = 0; + m_current_glyphrun_index = 0; + return 0; + } + if(!m_runs) + { + m_runs = CTLineGetGlyphRuns(m_line); + } + CFIndex nb_runs = CFArrayGetCount( m_runs ); + CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex( m_runs, m_current_run_index ); + CFIndex nb_glyphs = CTRunGetGlyphCount( run ); + + int i = 0; + bool first = true; + while(i < nLen) + { + if(m_current_glyphrun_index >= nb_glyphs) + { + m_current_run_index += 1; + if(m_current_run_index >= nb_runs) + { + break; + } + run = (CTRunRef)CFArrayGetValueAtIndex( m_runs, m_current_run_index ); + nb_glyphs = CTRunGetGlyphCount( run ); + m_current_glyphrun_index = 0; + } + if(first) + { + CGPoint first_pos; + CTRunGetPositions(run, CFRangeMake(m_current_glyphrun_index,1), &first_pos); + Point pos(first_pos.x, first_pos.y); + rPos = GetDrawPosition(pos); + msgs_debug(layout,"rPos(%ld, %ld)", rPos.X(),rPos.Y()); + first = false; + } + pGlyphIDs[i] = m_glyphs[m_current_glyph_index]; + if(pGlyphAdvances) + { + pGlyphAdvances[i] = m_glyph_advances[m_current_glyph_index]; + } + if(pCharIndexes) + { + pCharIndexes[i] = m_glyphs2chars[m_current_glyph_index]; + } + m_current_glyph_index += 1; + m_current_glyphrun_index += 1; + i += 1; + nStart += 1; + } + msgs_debug(layout,"i=%d <--", i); + return i; +} + +int CoreTextLayout::GetTextBreak( long /*nMaxWidth*/, long /*nCharExtra*/, int /*nFactor*/ ) const +{ + /* TODO */ + return false; +} + +long CoreTextLayout::GetTextWidth() const +{ + msgs_debug(layout,"-->"); + + CGRect bound_rect = CTLineGetImageBounds(m_line, m_graphics->GetContext()); + long w = round_to_long(bound_rect.size.width * m_style->GetFontStretchFactor()); + msgs_debug(layout,"w=%ld <--", w); + return w; +} + +// not needed. CoreText manage fallback directly +void CoreTextLayout::InitFont() const +{ + msgs_debug(layout,"<-->"); +} + +bool CoreTextLayout::InitGIA() const +{ + msgs_debug(layout,"count=%d <--", m_chars_count); + + if( m_chars_count <= 0) + { + return false; + } + if(m_glyphs) + { + return true; + } + + m_glyphs = new CGGlyph[m_glyphs_count]; + m_char_widths = new int[ m_chars_count ]; + m_chars2glyphs = new int[ m_chars_count ]; + for( int i = 0; i < m_chars_count; ++i) + { + m_char_widths[i] = 0.0; + m_chars2glyphs[i] = -1; + } + m_glyphs2chars = new int[m_glyphs_count]; + m_glyph_advances = new int[m_glyphs_count]; + m_glyph_positions = new CGPoint[m_glyphs_count]; + + + CFArrayRef runs = CTLineGetGlyphRuns( m_line ); + CFIndex nb_runs = CFArrayGetCount( runs ); + int p = 0; + for( CFIndex i = 0; i < nb_runs; ++i ) + { + CTRunRef run = (CTRunRef)CFArrayGetValueAtIndex( runs, i ); + if( run ) + { + CFIndex nb_glyphs = CTRunGetGlyphCount( run ); + if(nb_glyphs) + { + CFRange text_range = CTRunGetStringRange( run ); + if( text_range.location != kCFNotFound && text_range.length > 0 ) + { + CFIndex indices[ nb_glyphs ]; + CGGlyph glyphs[ nb_glyphs ]; + CTRunGetStringIndices( run, CFRangeMake( 0, 0 ), indices ); + CTRunGetGlyphs( run, CFRangeMake( 0, 0 ), glyphs ); + CTRunGetPositions( run, CFRangeMake( 0, 0 ), &m_glyph_positions[p] ); + bool is_vertical_run = false; + CFDictionaryRef aDict = CTRunGetAttributes( run ); + if ( aDict ) + { + const CFBooleanRef aValue = (const CFBooleanRef)CFDictionaryGetValue( aDict, kCTVerticalFormsAttributeName ); + is_vertical_run = (aValue == kCFBooleanTrue) ? true : false; + } + + for (CFIndex j = 0 ; j < nb_glyphs; ++p, ++j ) + { + m_glyphs[ p ] = glyphs[ j ]; + CFIndex k = indices[ j ]; + m_glyphs2chars[p] = k; + m_chars2glyphs[k] = p; + + if ( j < nb_glyphs - 1 ) + { + m_char_widths[ k ] += m_glyph_positions[ p + 1 ].x - m_glyph_positions[ p ].x; + } + if( p > 0) + { + m_glyph_advances[p - 1] = m_glyph_positions[ p ].x - m_glyph_positions[p - 1].x; + } + } + } + } + } + } + msgs_debug(layout,"<--"); + return true; +} + +bool CoreTextLayout::LayoutText(ImplLayoutArgs& args) +{ + msgs_debug(layout,"-->"); + Clean(); + m_style->SetColor(); + /* retreive MinCharPos EndCharPos Flags and Orientation */ + SalLayout::AdjustLayout(args); + m_chars_count = mnEndCharPos - mnMinCharPos; + + /* don't layout emptty (or worse negative size) strings */ + if(m_chars_count <= 0) + { + return false; + } + /* c0 and c1 are construction objects */ + CFStringRef c0 = CFStringCreateWithCharactersNoCopy( NULL, &(args.mpStr[args.mnMinCharPos]), m_chars_count, kCFAllocatorNull ); + if ( !c0 ) + { + Clean(); + return false; + } + + CFStringRef keys[6]; + CFTypeRef values[6]; + int nb_attributes = 0; + + keys[nb_attributes]= kCTFontAttributeName; + values[nb_attributes] = m_style->GetFont(); + nb_attributes += 1; + + CFDictionaryRef attributes = CFDictionaryCreate(kCFAllocatorDefault, + (const void**)&keys, + (const void**)&values, + nb_attributes, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + + CFAttributedStringRef string = CFAttributedStringCreate( NULL, c0, attributes ); + CFRelease( c0 ); + CFRelease( attributes ); + if ( !string ) + { + Clean(); + return false; + } + m_typesetter = CTTypesetterCreateWithAttributedString(string); + CFRelease(string); + if(!m_typesetter) + { + Clean(); + return false; + } + m_line = CTTypesetterCreateLine(m_typesetter, CFRangeMake(0, 0)); + if(!m_line) + { + Clean(); + return false; + } + m_glyphs_count = CTLineGetGlyphCount(m_line); + + msgs_debug(layout,"glyph_count=%d <--", m_glyphs_count); + return true; +} + +// not needed. CoreText manage fallback directly +void CoreTextLayout::MoveGlyph( int /*nStart*/, long /*nNewXPos*/ ) {} + +// not needed. CoreText manage fallback directly +void CoreTextLayout::Simplify( bool /*bIsBase*/ ) {} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ + diff --git a/vcl/aqua/source/gdi/coretext/salcoretextstyle.cxx b/vcl/aqua/source/gdi/coretext/salcoretextstyle.cxx new file mode 100644 index 000000000000..5a092af3c96a --- /dev/null +++ b/vcl/aqua/source/gdi/coretext/salcoretextstyle.cxx @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include "aqua/common.h" +#include "outfont.hxx" +#include "aqua/coretext/salcoretextfontutils.hxx" +#include "aqua/coretext/salcoretextstyle.hxx" + +CoreTextStyleInfo::CoreTextStyleInfo() : + m_fake_bold(false), + m_fake_italic(false), + m_matrix(CGAffineTransformIdentity), + m_stretch_factor(1.0), + m_CTParagraphStyle(NULL), + m_CTFont(NULL), + m_color(NULL), + m_font_data(NULL) +{ + msgs_debug(style,"create <-->"); +} + +CoreTextStyleInfo::~CoreTextStyleInfo() +{ + msgs_debug(style,"destroy (font:%p) <-->", m_CTFont); + SafeCFRelease(m_CTFont); + SafeCFRelease(m_CTParagraphStyle); + SafeCFRelease(m_color); +} + +long CoreTextStyleInfo::GetFontStretchedSize() const +{ + CGFloat size = CTFontGetSize(m_CTFont); + return static_cast<long>(size * m_stretch_factor + 0.5); +} + +void CoreTextStyleInfo::SetFont(FontSelectPattern* requested_font) +{ + msgs_debug(style,"req(%p) release font %p -->", requested_font, m_CTFont); + SafeCFRelease(m_CTFont); + if(!requested_font) + { + m_font_data = NULL; + return; + } + const ImplCoreTextFontData* font_data = static_cast<const ImplCoreTextFontData*>(requested_font->mpFontData); + + m_font_data = (ImplCoreTextFontData*)font_data; + m_matrix = CGAffineTransformIdentity; + CGFloat font_size = (CGFloat)requested_font->mfExactHeight; + + // enable bold-emulation if needed + if( (requested_font->GetWeight() >= WEIGHT_BOLD) && + (font_data->GetWeight() < WEIGHT_SEMIBOLD) ) + { + /* FIXME: add support for fake bold */ + m_fake_bold = true; + } + if( ((requested_font->GetSlant() == ITALIC_NORMAL) || (requested_font->GetSlant() == ITALIC_OBLIQUE)) && + !((font_data->GetSlant() == ITALIC_NORMAL) || (font_data->GetSlant() == ITALIC_OBLIQUE)) ) + { +#define kRotationForItalicText 10 + m_fake_italic = true; + /* about 6 degree of slant */ + m_matrix = CGAffineTransformMake( 1, 0, -tanf( kRotationForItalicText * acosf(0) / 90 ), 1, 0, 0); + } + + // prepare font stretching + if( (requested_font->mnWidth != 0) && (requested_font->mnWidth != requested_font->mnHeight) ) + { + m_stretch_factor = (float)requested_font->mnWidth / requested_font->mnHeight; + m_matrix = CGAffineTransformScale(m_matrix, m_stretch_factor, 1.0F ); + } + + /* FIXME: pass attribute to take into accout 'VerticalStyle' */ + /* FIXME: how to deal with 'rendering options' i.e anti-aliasing, does it even matter in CoreText ? */ + m_CTFont = CTFontCreateCopyWithAttributes(font_data->GetCTFont(), font_size, &m_matrix, NULL); + msgs_debug(style,"font %p <--", m_CTFont); +} + +void CoreTextStyleInfo::SetColor(SalColor color) +{ + msgs_debug(style, "r:%d g:%d b:%d -->", SALCOLOR_RED(color), SALCOLOR_GREEN(color), SALCOLOR_BLUE(color)); + SafeCFRelease(m_color); + m_color = CGColorCreateGenericRGB(SALCOLOR_RED(color) / 255.0, SALCOLOR_GREEN(color) / 255.0, SALCOLOR_BLUE(color) / 255.0, 1.0); + msgs_debug(style,"color=%p <--", m_color); +} + +void CoreTextStyleInfo::SetColor(void) +{ + msgs_debug(style, "null -->"); + SafeCFRelease(m_color); + msgs_debug(style,"color=%p <--", m_color); +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/coretext/salgdi.cxx b/vcl/aqua/source/gdi/coretext/salgdi.cxx new file mode 100644 index 000000000000..62e0903b2171 --- /dev/null +++ b/vcl/aqua/source/gdi/coretext/salgdi.cxx @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#include "aqua/common.h" + +#include "aqua/salframe.h" + +#include "aqua/coretext/salgdi.h" +#include "aqua/coretext/salcoretextstyle.hxx" +#include "aqua/coretext/salcoretextlayout.hxx" + +AquaSalGraphics::AquaSalGraphics() + : mpFrame( NULL ) + , mxLayer( NULL ) + , mrContext( NULL ) + , mpXorEmulation( NULL ) + , mnXorMode( 0 ) + , mnWidth( 0 ) + , mnHeight( 0 ) + , mnBitmapDepth( 0 ) + , mnRealDPIX( 0 ) + , mnRealDPIY( 0 ) + , mfFakeDPIScale( 1.0 ) + , mxClipPath( NULL ) + , maLineColor( COL_WHITE ) + , maFillColor( COL_BLACK ) + , m_pCoreTextFontData( NULL ) + , mbNonAntialiasedText( false ) + , mbPrinter( false ) + , mbVirDev( false ) + , mbWindow( false ) +{ + msgs_debug(gr,"-->"); + m_style = new CoreTextStyleInfo(); + msgs_debug(gr,"m_style=%p <--", m_style); +} + +AquaSalGraphics::~AquaSalGraphics() +{ + msgs_debug(gr,"-->"); + if(m_style) + { + delete m_style; + m_style = NULL; + } + msgs_debug(gr,"<--"); +} + +inline bool AquaSalGraphics::AddTempDevFont( ImplDevFontList*, + const rtl::OUString& , + const rtl::OUString& ) +{ + OSL_ASSERT( FALSE ); + return false; +} + +void AquaSalGraphics::DrawServerFontLayout( const ServerFontLayout& ) +{ +} + +void AquaSalGraphics::FreeEmbedFontData( const void* pData, long /*nDataLen*/ ) +{ + // TODO: implementing this only makes sense when the implementation of + // AquaSalGraphics::GetEmbedFontData() returns non-NULL + (void)pData; + DBG_ASSERT( (pData!=NULL), "AquaSalGraphics::FreeEmbedFontData() is not implemented\n"); +} + +void AquaSalGraphics::GetDevFontList( ImplDevFontList* pFontList ) +{ + DBG_ASSERT( pFontList, "AquaSalGraphics::GetDevFontList(NULL) !"); + + SalData* pSalData = GetSalData(); + if (pSalData->mpFontList == NULL) + { + pSalData->mpFontList = new SystemFontList(); + } + // Copy all PhysicalFontFace objects contained in the SystemFontList + pSalData->mpFontList->AnnounceFonts( *pFontList ); +} + +void AquaSalGraphics::GetDevFontSubstList( OutputDevice* ) +{ + // nothing to do since there are no device-specific fonts on Aqua +} + +const void* AquaSalGraphics::GetEmbedFontData( const PhysicalFontFace*, + const sal_Ucs* /*pUnicodes*/, + sal_Int32* /*pWidths*/, + FontSubsetInfo&, + long* /*pDataLen*/ ) +{ + return NULL; +} + +const Ucs2SIntMap* AquaSalGraphics::GetFontEncodingVector(const PhysicalFontFace*, + const Ucs2OStrMap** /*ppNonEncoded*/ ) +{ + return NULL; +} + +void AquaSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLevel ) +{ + (void)nFallbackLevel; // glyph-fallback on CoreText is done differently -> no fallback level + + pMetric->mbScalableFont = true; + pMetric->mbKernableFont = true; + CTFontRef font = m_style->GetFont(); + DBG_ASSERT(font, "GetFontMetric without font set in style"); + + pMetric->mnAscent = static_cast<long>( CTFontGetAscent(font) * mfFakeDPIScale + 0.5); + pMetric->mnDescent = static_cast<long>(CTFontGetDescent(font) * mfFakeDPIScale + 0.5); + const long nExtDescent = static_cast<long>((CTFontGetLeading(font) + CTFontGetDescent(font)) * + mfFakeDPIScale + 0.5); + pMetric->mnExtLeading = nExtDescent + pMetric->mnDescent; + pMetric->mnIntLeading = 0; + pMetric->mnWidth = m_style->GetFontStretchedSize(); + msgs_debug(gr,"ascent=%ld, descent=%ld, extleading=%ld, intleading=%ld,w=%ld", + pMetric->mnAscent, pMetric->mnDescent, + pMetric->mnExtLeading, + pMetric->mnIntLeading, + pMetric->mnWidth); +} + +sal_Bool AquaSalGraphics::GetGlyphBoundRect( sal_GlyphId /*nGlyphId*/, Rectangle& /*rRect*/ ) +{ + /* TODO: create a Ghyph iterator to keep track ot 'state' between call */ + return false; +} + +sal_Bool AquaSalGraphics::GetGlyphOutline( sal_GlyphId /*nGlyphId*/, basegfx::B2DPolyPolygon& /*rPolyPoly*/ ) +{ + /* TODO */ + return false; +} + +void AquaSalGraphics::GetGlyphWidths( const PhysicalFontFace* /*pFontData*/, bool /*bVertical*/, + Int32Vector& /*rGlyphWidths*/, Ucs2UIntMap& /*rUnicodeEnc*/ ) +{ +} + +sal_uLong AquaSalGraphics::GetKernPairs( sal_uLong, ImplKernPairData* ) +{ + return 0; +} + +bool AquaSalGraphics::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const +{ + if( !m_pCoreTextFontData ) + { + return false; + } + return m_pCoreTextFontData->GetImplFontCapabilities(rFontCapabilities); +} + +const ImplFontCharMap* AquaSalGraphics::GetImplFontCharMap() const +{ + if( !m_pCoreTextFontData ) + { + return ImplFontCharMap::GetDefaultMap(); + } + return m_pCoreTextFontData->GetImplFontCharMap(); +} + +bool AquaSalGraphics::GetRawFontData( const PhysicalFontFace* pFontData, + std::vector<unsigned char>& rBuffer, bool* pJustCFF ) +{ + const ImplCoreTextFontData* font_data = static_cast<const ImplCoreTextFontData*>(pFontData); + + return font_data->GetRawFontData(rBuffer, pJustCFF); +} + +SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const +{ + msgs_debug(gr,"-->"); + SystemFontData aSysFontData; + aSysFontData.nSize = sizeof( SystemFontData ); + aSysFontData.bAntialias = true; + + CTFontRef font = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 0.0, NULL); + font = (CTFontRef)CFRetain(font); + aSysFontData.rCTFont = (void*)font; + + CTFontRef italic_font = CTFontCreateCopyWithSymbolicTraits( font, + 0.0, + NULL, + kCTFontItalicTrait, + kCTFontItalicTrait + kCTFontBoldTrait); + aSysFontData.bFakeItalic = italic_font ? false : true; + SafeCFRelease(italic_font); + + CTFontRef bold_font = CTFontCreateCopyWithSymbolicTraits( font, + 0.0, + NULL, + kCTFontBoldTrait, + kCTFontItalicTrait + kCTFontBoldTrait); + aSysFontData.bFakeBold = bold_font ? false : true; + SafeCFRelease(bold_font); + + CTFontRef vertical_font = CTFontCreateCopyWithSymbolicTraits( font, + 0.0, + NULL, + kCTFontVerticalTrait, + kCTFontVerticalTrait); + aSysFontData.bVerticalCharacterType = vertical_font ? true : false; + SafeCFRelease(vertical_font); + + msgs_debug(gr,"<--"); + return aSysFontData; +} + +SalLayout* AquaSalGraphics::GetTextLayout( ImplLayoutArgs&, int /*nFallbackLevel*/ ) +{ + msgs_debug(gr,"-->"); + CoreTextLayout* layout = new CoreTextLayout( this, m_style ); + msgs_debug(gr,"layout:%p <--", layout); + return layout; +} + +sal_uInt16 AquaSalGraphics::SetFont( FontSelectPattern* pReqFont, int /*nFallbackLevel*/ ) +{ + msgs_debug(gr,"m_style=%p -->", m_style); + m_style->SetFont(pReqFont); + msgs_debug(gr,"<--"); + return 0; +} + +void AquaSalGraphics::SetTextColor( SalColor nSalColor ) +{ + msgs_debug(gr,"m_style=%p -->", m_style); + m_style->SetColor(nSalColor); + msgs_debug(gr,"<--"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/aqua/source/gdi/salgdicommon.cxx b/vcl/aqua/source/gdi/salgdicommon.cxx index 0a844292e6e1..72f97ed0e4ca 100644 --- a/vcl/aqua/source/gdi/salgdicommon.cxx +++ b/vcl/aqua/source/gdi/salgdicommon.cxx @@ -117,7 +117,7 @@ static void AddPolyPolygonToPath( CGMutablePathRef xPath, } sal_Bool AquaSalGraphics::CreateFontSubset( const rtl::OUString& rToFile, - const ImplFontData* pFontData, + const PhysicalFontFace* pFontData, long* pGlyphIDs, sal_uInt8* pEncoding, sal_Int32* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rInfo ) diff --git a/vcl/aqua/source/gdi/salgdiutils.cxx b/vcl/aqua/source/gdi/salgdiutils.cxx index 7032fcda1c20..a2cc9a002bd8 100644 --- a/vcl/aqua/source/gdi/salgdiutils.cxx +++ b/vcl/aqua/source/gdi/salgdiutils.cxx @@ -234,6 +234,14 @@ bool AquaSalGraphics::CheckContext() return (mrContext != NULL); } +CGContextRef AquaSalGraphics::GetContext() +{ + if(!mrContext) + { + CheckContext(); + } + return mrContext; +} void AquaSalGraphics::RefreshRect(float lX, float lY, float lWidth, float lHeight) { diff --git a/vcl/inc/aqua/atsui/salgdi.h b/vcl/inc/aqua/atsui/salgdi.h index 0ee4420ef8e5..5827706f7f0e 100644 --- a/vcl/inc/aqua/atsui/salgdi.h +++ b/vcl/inc/aqua/atsui/salgdi.h @@ -161,6 +161,7 @@ public: void ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels bool CheckContext(); + CGContextRef GetContext(); void UpdateWindow( NSRect& ); // delivered in NSView coordinates void RefreshRect( const CGRect& ); void RefreshRect( const NSRect& ); @@ -347,7 +348,7 @@ private: void Pattern50Fill(); UInt32 getState( ControlState nState ); UInt32 getTrackState( ControlState nState ); - bool GetRawFontData( const ImplFontData* pFontData, + bool GetRawFontData( const PhysicalFontFace* pFontData, std::vector<unsigned char>& rBuffer, bool* pJustCFF ); }; diff --git a/vcl/inc/aqua/common.h b/vcl/inc/aqua/common.h index d7a654128d08..c3789a5f46f0 100644 --- a/vcl/inc/aqua/common.h +++ b/vcl/inc/aqua/common.h @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #ifndef _VCL_AQUA_COMMON_H #define _VCL_AQUA_COMMON_H @@ -6,11 +7,25 @@ #include <premac.h> #include <ApplicationServices/ApplicationServices.h> #include <postmac.h> +#include <tools/debug.hxx> // CoreFoundation designers, in their wisdom, decided that CFRelease of NULL // cause a Crash, yet few API can return NULL when asking for the creation // of an object, which force us to peper the code with egly if construct everywhere // and open the door to very nasty crash on rare occasion // this macro hide the mess -#define SafeCFRelease(a) do { if(a) { CFRelease(a); } } while(false) -#endif +#define SafeCFRelease(a) do { if(a) { CFRelease(a); (a)=NULL; } } while(false) + + +#define round_to_long(a) ((a) >= 0 ? ((long)((a) + 0.5)) : ((long)((a) - 0.5))) + +#include "vcl/salgtype.hxx" +#endif/* _VCL_AQUA_COMMON_H */ + +//#define msgs_debug(c,f,...) +// fprintf(stderr, "%s::%s(%p:%04.4x)\n", this, #c, __func__, 0, __VA_ARGS__ ) + +#define msgs_debug(c,f,...) \ + fprintf(stderr, "%s::%s(%p:%4.4u)" f "\n", #c, __func__, this, ((unsigned int)pthread_self() & 8191), ##__VA_ARGS__ ); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/coretext/salcoretextfontutils.hxx b/vcl/inc/aqua/coretext/salcoretextfontutils.hxx new file mode 100644 index 000000000000..3c75899b0a8d --- /dev/null +++ b/vcl/inc/aqua/coretext/salcoretextfontutils.hxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#ifndef _VCL_AQUA_CORETEXT_SALCORETEXTFONTUTILS_HXX +#define _VCL_AQUA_CORETEXT_SALCORETEXTFONTUTILS_HXX + +class ImplCoreTextFontData; +class ImplDevFontList; + +#include <boost/unordered_map.hpp> + +#include <vcl/fontcapabilities.hxx> + +#include "outfont.hxx" +#include "impfont.hxx" + +class ImplCoreTextFontData : public PhysicalFontFace +{ +public: + ImplCoreTextFontData(const ImplDevFontAttributes&, CTFontRef font); + virtual ~ImplCoreTextFontData(); + virtual PhysicalFontFace* Clone() const; + virtual ImplFontEntry* CreateFontInstance( FontSelectPattern& ) const; + virtual sal_IntPtr GetFontId() const { return (sal_IntPtr)m_CTFontRef;}; + CTFontRef GetCTFont() const { return m_CTFontRef; }; + const ImplFontCharMap* GetImplFontCharMap(); + bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities); + bool HasChar( sal_uInt32 cChar ) const; + void ReadOs2Table(); + void ReadIosCmapEncoding(); + bool HasCJKSupport(); + bool GetRawFontData( std::vector<unsigned char>& rBuffer, bool* pJustCFF ) const; + +private: + void DetermineCJKSupport_OS2(CFDataRef rOS2Table); + void DetermineCJKSupport_cmap(CFDataRef rCmapTable); + CTFontRef m_CTFontRef; + mutable const ImplFontCharMap* m_pCharMap; + mutable vcl::FontCapabilities m_aFontCapabilities; + mutable bool m_bHasOs2Table; + mutable bool m_bOs2TableRead; + mutable bool m_bCmapTableRead; // true if cmap encoding of Mac font is read + mutable bool m_bHasCJKSupport; // #i78970# CJK fonts need extra leading + mutable bool m_bFontCapabilitiesRead; +}; + +/* This class has the responsibility of assembling a list of CoreText + fonts available on the system and enabling access to that list. + */ +class SystemFontList +{ +public: + SystemFontList(); + ~SystemFontList(); + + void AnnounceFonts( ImplDevFontList& ) const; + ImplCoreTextFontData* GetFontDataFromRef( CTFontRef ) const; + +private: + typedef boost::unordered_map<CTFontRef,ImplCoreTextFontData*> CoreTextFontContainer; + CoreTextFontContainer m_aFontContainer; + + void InitGlyphFallbacks(); +}; + +#endif // _VCL_AQUA_CORETEXT_SALCORETEXTFONTUTILS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/coretext/salcoretextlayout.hxx b/vcl/inc/aqua/coretext/salcoretextlayout.hxx new file mode 100644 index 000000000000..e42752283b9d --- /dev/null +++ b/vcl/inc/aqua/coretext/salcoretextlayout.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#ifndef _VCL_AQUA_CORETEXT_SALCORETEXTLAYOUT_HXX +#define _VCL_AQUA_CORETEXT_SALCORETEXTLAYOUT_HXX + +#include <tools/poly.hxx> + +#include "sallayout.hxx" + +class AquaSalGraphics; +class CoreTextStyleInfo; + +class CoreTextLayout : public SalLayout +{ +public: + CoreTextLayout( AquaSalGraphics* graphics, CoreTextStyleInfo* style); + virtual ~CoreTextLayout(); + + virtual void AdjustLayout( ImplLayoutArgs& ); + virtual void DrawText( SalGraphics& ) const; + virtual void DropGlyph( int nStart ); + virtual long FillDXArray( long* pDXArray ) const; + virtual bool GetBoundRect( SalGraphics&, Rectangle& ) const; + virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const; + virtual bool GetGlyphOutlines( SalGraphics&, PolyPolyVector& ) const; + virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&, + sal_Int32* pGlyphAdvances, int* pCharIndexes ) const; + virtual int GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const; + virtual long GetTextWidth() const; + virtual void InitFont() const; + virtual bool LayoutText( ImplLayoutArgs& ); + virtual void MoveGlyph( int nStart, long nNewXPos ); + virtual void Simplify( bool bIsBase ); + +private: + void Clean(); + bool InitGIA() const; + + AquaSalGraphics* m_graphics; + CoreTextStyleInfo* m_style; + mutable int m_glyphs_count; + mutable int m_chars_count; + mutable int* m_chars2glyphs; + mutable int* m_glyphs2chars; + mutable CGGlyph* m_glyphs; + mutable int* m_char_widths; + mutable int* m_glyph_advances; + mutable CGPoint* m_glyph_positions; + CTTypesetterRef m_typesetter; + CTLineRef m_line; + mutable bool m_has_bound_rec; + mutable Rectangle m_bound_rect; + CGFloat m_base_advance; + mutable CGFloat m_cached_width; + mutable CFIndex m_current_run_index; + mutable CFIndex m_current_glyph_index; + mutable CFIndex m_current_glyphrun_index; + mutable CFArrayRef m_runs; + +}; + +#endif // _VCL_AQUA_CORETEXT_SALCORETEXTLAYOUT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/coretext/salcoretextstyle.hxx b/vcl/inc/aqua/coretext/salcoretextstyle.hxx new file mode 100644 index 000000000000..91bde5209fcc --- /dev/null +++ b/vcl/inc/aqua/coretext/salcoretextstyle.hxx @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#ifndef _VCL_AQUA_CORETEXT_SALCORETEXTSTYLE_HXX +#define _VCL_AQUA_CORETEXT_SALCORETEXTSTYLE_HXX + +#include "aqua/salgdicommon.hxx" + +class FontSelectPattern; +class ImplCoreTextFontData; + +class CoreTextStyleInfo +{ +public: + CoreTextStyleInfo(); + ~CoreTextStyleInfo(); + CTFontRef GetFont() const { return m_CTFont; }; + long GetFontStretchedSize() const; + float GetFontStretchFactor() const { return m_stretch_factor; }; + CTParagraphStyleRef GetParagraphStyle() const { return m_CTParagraphStyle; } ; + CGSize GetSize() const; + CGColorRef GetColor() const { return m_color; } ; + void SetColor(SalColor color); + void SetColor(void); + void SetFont(FontSelectPattern* requested_font); + +private: + bool m_fake_bold; + bool m_fake_italic; + CGAffineTransform m_matrix; + float m_stretch_factor; + float m_font_scale; + float m_fake_dpi_scale; + CTParagraphStyleRef m_CTParagraphStyle; + CTFontRef m_CTFont; + CGColorRef m_color; + const ImplCoreTextFontData* m_font_data; + +}; + +#endif // _VCL_AQUA_CORETEXT_SALCORETEXTSTYLE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/aqua/coretext/salgdi.h b/vcl/inc/aqua/coretext/salgdi.h new file mode 100644 index 000000000000..7f59de203aba --- /dev/null +++ b/vcl/inc/aqua/coretext/salgdi.h @@ -0,0 +1,297 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#ifndef _VCL_AQUA_CORETEXT_SALGDI_H +#define _VCL_AQUA_CORETEXT_SALGDI_H + + +#include "premac.h" +#include <ApplicationServices/ApplicationServices.h> +#include "postmac.h" + +#include "aqua/aquavcltypes.h" +#include "aqua/coretext/salcoretextfontutils.hxx" +#include "aqua/salframe.h" +#include "salgdi.hxx" + +#include "aqua/salgdicommon.hxx" + +class CoreTextStyleInfo; + +// ------------------- +// - AquaSalGraphics - +// ------------------- +class AquaSalGraphics : public SalGraphics +{ + friend class CoreTextLayout; +protected: + AquaSalFrame* mpFrame; + CGLayerRef mxLayer; //< Quartz graphics layer + CGContextRef mrContext; //< Quartz drawing context + class XorEmulation* mpXorEmulation; + int mnXorMode; //< 0: off 1: on 2: invert only + int mnWidth; + int mnHeight; + int mnBitmapDepth; //< zero unless bitmap + long mnRealDPIX; //< device X-resolution of this graphics + long mnRealDPIY; //< device Y-resolution of this graphics + + /// some graphics implementations (e.g. AquaSalInfoPrinter) scale + /// everything down by a factor (see SetupPrinterGraphics for details) + /// so we have to compensate for it with the inverse factor + double mfFakeDPIScale; + double mfFontScale; + + + CGMutablePathRef mxClipPath; //< path representing current clip region + + /// Drawing colors + RGBAColor maLineColor; //< pen color RGBA + RGBAColor maFillColor; //< brush color RGBA + + ImplCoreTextFontData* m_pCoreTextFontData; //< Device Font settings + + bool mbNonAntialiasedText; //< allows text to be rendered without antialiasing + + // Graphics types + + bool mbPrinter; //< is this a printer graphics + bool mbVirDev; //< is this a virtual device graphics + bool mbWindow; //< is this a window graphics + + RGBColor m_TextColor; + + CoreTextStyleInfo* m_style; + +public: + AquaSalGraphics(); + virtual ~AquaSalGraphics(); + + bool IsPenVisible() const { return maLineColor.IsVisible(); } + bool IsBrushVisible() const { return maFillColor.IsVisible(); } + + void SetWindowGraphics( AquaSalFrame* pFrame ); + void SetPrinterGraphics( CGContextRef, long nRealDPIX, long nRealDPIY, double fFakeScale ); + void SetVirDevGraphics( CGLayerRef, CGContextRef, int nBitDepth = 0 ); + + void initResolution( NSWindow* ); + void copyResolution( AquaSalGraphics& ); + void updateResolution(); + + bool IsWindowGraphics() const { return mbWindow; } + bool IsPrinterGraphics() const { return mbPrinter; } + bool IsVirDevGraphics() const { return mbVirDev; } + AquaSalFrame* getGraphicsFrame() const { return mpFrame; } + void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; } + + void ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels + + bool CheckContext(); + CGContextRef GetContext(); + void UpdateWindow( NSRect& ); // delivered in NSView coordinates + void RefreshRect( const CGRect& ); + void RefreshRect( const NSRect& ); + void RefreshRect(float lX, float lY, float lWidth, float lHeight); + + void SetState(); + void UnsetState(); + // InvalidateContext does an UnsetState and sets mrContext to 0 + void InvalidateContext(); + + virtual bool setClipRegion( const Region& ); + + // draw --> LineColor and FillColor and RasterOp and ClipRegion + virtual void drawPixel( long nX, long nY ); + virtual void drawPixel( long nX, long nY, SalColor nSalColor ); + virtual void drawLine( long nX1, long nY1, long nX2, long nY2 ); + virtual void drawRect( long nX, long nY, long nWidth, long nHeight ); + virtual void drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry ); + virtual void drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ); + virtual void drawPolyPolygon( sal_uLong nPoly, const sal_uLong* pPoints, PCONSTSALPOINT* pPtAry ); + virtual bool drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double fTransparency ); + virtual sal_Bool drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); + virtual sal_Bool drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const sal_uInt8* pFlgAry ); + virtual sal_Bool drawPolyPolygonBezier( sal_uLong nPoly, const sal_uLong* pPoints, + const SalPoint* const* pPtAry, const sal_uInt8* const* pFlgAry ); + virtual bool drawPolyLine( const ::basegfx::B2DPolygon&, double fTransparency, + const ::basegfx::B2DVector& rLineWidths, basegfx::B2DLineJoin ); + + // CopyArea --> No RasterOp, but ClipRegion + virtual void copyArea( long nDestX, long nDestY, long nSrcX, long nSrcY, long nSrcWidth, + long nSrcHeight, sal_uInt16 nFlags ); + + // CopyBits and DrawBitmap --> RasterOp and ClipRegion + // CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics + virtual void copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics ); + virtual void drawBitmap( const SalTwoRect* pPosAry, const SalBitmap& rSalBitmap ); + virtual void drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nTransparentColor ); + virtual void drawBitmap( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + const SalBitmap& rTransparentBitmap ); + virtual void drawMask( const SalTwoRect* pPosAry, + const SalBitmap& rSalBitmap, + SalColor nMaskColor ); + + virtual SalBitmap* getBitmap( long nX, long nY, long nWidth, long nHeight ); + virtual SalColor getPixel( long nX, long nY ); + + // invert --> ClipRegion (only Windows or VirDevs) + virtual void invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags); + virtual void invert( sal_uLong nPoints, const SalPoint* pPtAry, SalInvert nFlags ); + + virtual sal_Bool drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ); + + virtual bool drawAlphaBitmap( const SalTwoRect&, + const SalBitmap& rSourceBitmap, + const SalBitmap& rAlphaBitmap ); + + virtual bool drawAlphaRect( long nX, long nY, long nWidth, + long nHeight, sal_uInt8 nTransparency ); + + CGPoint* makeCGptArray(sal_uLong nPoints, const SalPoint* pPtAry); + // native widget rendering methods that require mirroring + virtual sal_Bool hitTestNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + const Point& aPos, sal_Bool& rIsInside ); + virtual sal_Bool drawNativeControl( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + ControlState nState, const ImplControlValue& aValue, + const rtl::OUString& aCaption ); + virtual sal_Bool getNativeControlRegion( ControlType nType, ControlPart nPart, const Rectangle& rControlRegion, + ControlState nState, const ImplControlValue& aValue, + const rtl::OUString& aCaption, + Rectangle &rNativeBoundingRegion, + Rectangle &rNativeContentRegion ); + + // get device resolution + virtual void GetResolution( long& rDPIX, long& rDPIY ); + // get the depth of the device + virtual sal_uInt16 GetBitCount() const; + // get the width of the device + virtual long GetGraphicsWidth() const; + + // set the clip region to empty + virtual void ResetClipRegion(); + + // set the line color to transparent (= don't draw lines) + virtual void SetLineColor(); + // set the line color to a specific color + virtual void SetLineColor( SalColor nSalColor ); + // set the fill color to transparent (= don't fill) + virtual void SetFillColor(); + // set the fill color to a specific color, shapes will be + // filled accordingly + virtual void SetFillColor( SalColor nSalColor ); + // enable/disable XOR drawing + virtual void SetXORMode( bool bSet, bool bInvertOnly ); + // set line color for raster operations + virtual void SetROPLineColor( SalROPColor nROPColor ); + // set fill color for raster operations + virtual void SetROPFillColor( SalROPColor nROPColor ); + // set the text color to a specific color + virtual void SetTextColor( SalColor nSalColor ); + // set the font + virtual sal_uInt16 SetFont( FontSelectPattern*, int nFallbackLevel ); + // get the current font's etrics + virtual void GetFontMetric( ImplFontMetricData*, int nFallbackLevel ); + // get kernign pairs of the current font + // return only PairCount if (pKernPairs == NULL) + virtual sal_uLong GetKernPairs( sal_uLong nPairs, ImplKernPairData* pKernPairs ); + // get the repertoire of the current font + virtual const ImplFontCharMap* GetImplFontCharMap() const; + virtual bool GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const; + // graphics must fill supplied font list + virtual void GetDevFontList( ImplDevFontList* ); + // graphics should call ImplAddDevFontSubstitute on supplied + // OutputDevice for all its device specific preferred font substitutions + virtual void GetDevFontSubstList( OutputDevice* ); + virtual bool AddTempDevFont( ImplDevFontList*, const rtl::OUString& rFileURL, + const rtl::OUString& rFontName ); + // CreateFontSubset: a method to get a subset of glyhps of a font + // inside a new valid font file + // returns TRUE if creation of subset was successfull + // parameters: rToFile: contains a osl file URL to write the subset to + // pFont: describes from which font to create a subset + // pGlyphIDs: the glyph ids to be extracted + // pEncoding: the character code corresponding to each glyph + // pWidths: the advance widths of the correspoding glyphs (in PS font units) + // nGlyphs: the number of glyphs + // rInfo: additional outgoing information + // implementation note: encoding 0 with glyph id 0 should be added implicitly + // as "undefined character" + virtual sal_Bool CreateFontSubset( const rtl::OUString& rToFile, + const PhysicalFontFace* pFont, + long* pGlyphIDs, + sal_uInt8* pEncoding, + sal_Int32* pWidths, + int nGlyphs, + FontSubsetInfo& rInfo); + + // GetFontEncodingVector: a method to get the encoding map Unicode + // to font encoded character; this is only used for type1 fonts and + // may return NULL in case of unknown encoding vector + // if ppNonEncoded is set and non encoded characters (that is type1 + // glyphs with only a name) exist it is set to the corresponding + // map for non encoded glyphs; the encoding vector contains -1 + // as encoding for these cases + virtual const Ucs2SIntMap* GetFontEncodingVector( const PhysicalFontFace*, const Ucs2OStrMap** ppNonEncoded ); + + // GetEmbedFontData: gets the font data for a font marked + // embeddable by GetDevFontList or NULL in case of error + // parameters: pFont: describes the font in question + // pWidths: the widths of all glyphs from char code 0 to 255 + // pWidths MUST support at least 256 members; + // rInfo: additional outgoing information + // pDataLen: out parameter, contains the byte length of the returned buffer + virtual const void* GetEmbedFontData( const PhysicalFontFace*, + const sal_Ucs* pUnicodes, + sal_Int32* pWidths, + FontSubsetInfo& rInfo, + long* pDataLen ); + // frees the font data again + virtual void FreeEmbedFontData( const void* pData, long nDataLen ); + + virtual void GetGlyphWidths( const PhysicalFontFace*, + bool bVertical, + Int32Vector& rWidths, + Ucs2UIntMap& rUnicodeEnc ); + + virtual sal_Bool GetGlyphBoundRect( sal_GlyphId nIndex, Rectangle& ); + virtual sal_Bool GetGlyphOutline( sal_GlyphId nIndex, basegfx::B2DPolyPolygon& ); + + virtual SalLayout* GetTextLayout( ImplLayoutArgs&, int nFallbackLevel ); + virtual void DrawServerFontLayout( const ServerFontLayout& ); + virtual bool supportsOperation( OutDevSupportType ) const; + + // Query the platform layer for control support + virtual sal_Bool IsNativeControlSupported( ControlType nType, ControlPart nPart ); + + virtual SystemGraphicsData GetGraphicsData() const; + virtual SystemFontData GetSysFontData( int /* nFallbacklevel */ ) const; + +private: + // differences between VCL, Quartz and kHiThemeOrientation coordinate systems + // make some graphics seem to be vertically-mirrored from a VCL perspective + bool IsFlipped() const { return mbWindow; }; + + void ApplyXorContext(); + void Pattern50Fill(); + UInt32 getState( ControlState nState ); + UInt32 getTrackState( ControlState nState ); + bool GetRawFontData( const PhysicalFontFace* pFontData, + std::vector<unsigned char>& rBuffer, + bool* pJustCFF ); +}; + +inline void AquaSalGraphics::RefreshRect( const CGRect& rRect ) +{ + RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); +} + +inline void AquaSalGraphics::RefreshRect( const NSRect& rRect ) +{ + RefreshRect( rRect.origin.x, rRect.origin.y, rRect.size.width, rRect.size.height ); +} + +#endif /* _VCL_AQUA_CORETEXT_SALGDI_H */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/vcl/sysdata.hxx b/vcl/inc/vcl/sysdata.hxx index d52cd9483795..1033239779bd 100644 --- a/vcl/inc/vcl/sysdata.hxx +++ b/vcl/inc/vcl/sysdata.hxx @@ -194,7 +194,6 @@ struct SystemGlyphData // -------------------- // - SystemFontData - // -------------------- - struct SystemFontData { unsigned long nSize; // size in bytes of this structure @@ -202,7 +201,7 @@ struct SystemFontData HFONT hFont; // native font object #elif defined( QUARTZ ) #ifdef ENABLE_CORETEXT - CTFontRef rCTFont; + void* rCTFont; #else void* aATSUFontID; // native font object #endif |