[Libreoffice-commits] .: 6 commits - config_host.mk.in configure.in slideshow/source solenv/gbuild vcl/aqua vcl/inc vcl/Library_vcl.mk
Norbert Thiebaud
nthiebaud at kemper.freedesktop.org
Sat Jun 23 21:25:13 PDT 2012
config_host.mk.in | 3
configure.in | 20
slideshow/source/engine/OGLTrans/mac/aquaOpenGLView.m | 7
solenv/gbuild/Module.mk | 2
vcl/Library_vcl.mk | 36
vcl/aqua/source/gdi/atsui/salatslayout.cxx | 1167 +++++++
vcl/aqua/source/gdi/atsui/salatsuifontutils.cxx | 493 +++
vcl/aqua/source/gdi/atsui/salgdi.cxx | 1152 +++++++
vcl/aqua/source/gdi/coretext/salcoretextfontutils.cxx | 603 +++
vcl/aqua/source/gdi/coretext/salcoretextlayout.cxx | 458 +++
vcl/aqua/source/gdi/coretext/salcoretextstyle.cxx | 93
vcl/aqua/source/gdi/coretext/salgdi.cxx | 234 +
vcl/aqua/source/gdi/salatslayout.cxx | 1167 -------
vcl/aqua/source/gdi/salatsuifontutils.cxx | 493 ---
vcl/aqua/source/gdi/salgdi.cxx | 2718 ------------------
vcl/aqua/source/gdi/salgdicommon.cxx | 1649 ++++++++++
vcl/aqua/source/gdi/salgdiutils.cxx | 8
vcl/aqua/source/window/salframeview.mm | 7
vcl/inc/aqua/atsui/salatsuifontutils.hxx | 65
vcl/inc/aqua/atsui/salgdi.h | 370 ++
vcl/inc/aqua/common.h | 31
vcl/inc/aqua/coretext/salcoretextfontutils.hxx | 67
vcl/inc/aqua/coretext/salcoretextlayout.hxx | 64
vcl/inc/aqua/coretext/salcoretextstyle.hxx | 42
vcl/inc/aqua/coretext/salgdi.h | 297 +
vcl/inc/aqua/salatsuifontutils.hxx | 65
vcl/inc/aqua/salgdi.h | 419 --
vcl/inc/aqua/salgdicommon.hxx | 58
vcl/inc/vcl/sysdata.hxx | 8
29 files changed, 6927 insertions(+), 4869 deletions(-)
New commits:
commit 398552182ca6933a3f1693c8ca793cc35cd5e20c
Author: Norbert Thiebaud <nthiebaud at gmail.com>
Date: Mon Apr 2 00:18:09 2012 -0500
Export NOCPPUNIT to disable all cppunit test in gbuild.
This is convinient when coding/debuging stuff that break
unittest downstream, but oen still want to have a fully built
product to test
Change-Id: I4970db6ede1ed29bb3c421b56b5092c19fd9fa90
diff --git a/solenv/gbuild/Module.mk b/solenv/gbuild/Module.mk
index 20fbba5..435d1c9 100644
--- a/solenv/gbuild/Module.mk
+++ b/solenv/gbuild/Module.mk
@@ -235,6 +235,7 @@ $(call gb_Module_get_clean_target,$(1)) : $$(gb_Module_CURRENTCLEANTARGET)
endef
+ifeq ($(strip $(NOCPPUNIT)),)
define gb_Module_add_check_target
$(call gb_Module__read_targetfile,$(1),$(2),check target)
@@ -242,6 +243,7 @@ $(call gb_Module_get_check_target,$(1)) : $$(gb_Module_CURRENTTARGET)
$(call gb_Module_get_clean_target,$(1)) : $$(gb_Module_CURRENTCLEANTARGET)
endef
+endif # NOCPPUNIT
define gb_Module_add_slowcheck_target
$(call gb_Module__read_targetfile,$(1),$(2),slowcheck target)
commit 8c91ec1ab0b6f437b8b60ed9aee067f088fa4718
Author: Norbert Thiebaud <nthiebaud at gmail.com>
Date: Mon Apr 2 00:15:07 2012 -0500
Initial basic support for CoreText. very partial and highly unstable.
Change-Id: I5dc9fb342e45fa3d428e340a597a2d9d4e246cb5
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index f98ca98..451c15b 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 0000000..08db4fd
--- /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 0000000..408f2b2
--- /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 0000000..5a092af
--- /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 0000000..62e0903
--- /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 0a84429..72f97ed 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 7032fcd..a2cc9a0 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 0ee4420..5827706 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 d7a6541..c3789a5 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 0000000..3c75899
--- /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 0000000..e427522
--- /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 0000000..91bde52
--- /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 0000000..7f59de2
--- /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 d52cd94..1033239 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
commit 2c506447fcf020b17797c30d001fda9c177a4235
Author: Norbert Thiebaud <nthiebaud at gmail.com>
Date: Mon Apr 2 00:11:29 2012 -0500
WaE on Mac SDK > 10.4
Change-Id: Ie0e413a6beef87d399807f98f345103c82442a9c
diff --git a/slideshow/source/engine/OGLTrans/mac/aquaOpenGLView.m b/slideshow/source/engine/OGLTrans/mac/aquaOpenGLView.m
index 64af815..7d23b17 100644
--- a/slideshow/source/engine/OGLTrans/mac/aquaOpenGLView.m
+++ b/slideshow/source/engine/OGLTrans/mac/aquaOpenGLView.m
@@ -81,12 +81,13 @@ typedef int NSColorRenderingIntent;
- (void)prepareOpenGL
{
// for overriding to initialize OpenGL state, occurs after context creation
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
- GLint swapInt = 1;
-#else
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
long swapInt = 1;
+#else
+ NSInteger swapInt = 1;
#endif
+
[[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; // set to vbl sync
// init GL stuff here
diff --git a/vcl/aqua/source/window/salframeview.mm b/vcl/aqua/source/window/salframeview.mm
index 86e3dc4..02afa6c 100644
--- a/vcl/aqua/source/window/salframeview.mm
+++ b/vcl/aqua/source/window/salframeview.mm
@@ -1595,11 +1595,10 @@ private:
return 0;
}
-#if defined (NSFoundationVersionNumber10_5)
-/* SDK 10.5 or greater, even if MAC_OS_X_VERSION_MAX_ALLOWED might be less than 10.5 */
-- (NSInteger)conversationIdentifier
-#else
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
- (long)conversationIdentifier
+#else
+- (NSInteger)conversationIdentifier
#endif
{
return (long)self;
commit a95dbe7ad0bc8cf780bb9142bd9ffca3b0417d18
Author: Norbert Thiebaud <nthiebaud at gmail.com>
Date: Mon Apr 2 00:10:17 2012 -0500
Add a configure flag to enable CoreText Support
Change-Id: I0f3865beff53f199fae49e806f308c6dab3e3c11
diff --git a/config_host.mk.in b/config_host.mk.in
index 7a7e161..8aac2ea 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -110,6 +110,7 @@ export ENABLE_EVOAB2=@ENABLE_EVOAB2@
export ENABLE_GCONF=@ENABLE_GCONF@
export ENABLE_GIO=@ENABLE_GIO@
export ENABLE_GNOMEVFS=@ENABLE_GNOMEVFS@
+export ENABLE_CORETEXT?=@ENABLE_CORETEXT@
export ENABLE_GRAPHITE=@ENABLE_GRAPHITE@
export ENABLE_GSTREAMER=@ENABLE_GSTREAMER@
export ENABLE_GTK3=@ENABLE_GTK3@
@@ -167,7 +168,7 @@ export GIT_REPO_NAMES=@GIT_REPO_NAMES@
export GLIB_CFLAGS=@GLIB_CFLAGS@
export GLIB_LIBS=@GLIB_LIBS@
export GMAKE_MODULE_PARALLELISM=@GMAKE_MODULE_PARALLELISM@
-export GMAKE_PARALLELISM=@GMAKE_PARALLELISM@
+export GMAKE_PARALLELISM?=@GMAKE_PARALLELISM@
export GNOMEVFS_CFLAGS=@GNOMEVFS_CFLAGS@
export GNOMEVFS_LIBS=@GNOMEVFS_LIBS@
@x_GNUCP@ export GNUCOPY=@GNUCP@
diff --git a/configure.in b/configure.in
index d8ab8ab..b1f049d 100644
--- a/configure.in
+++ b/configure.in
@@ -975,6 +975,11 @@ AC_ARG_ENABLE(postgresql-sdbc,
[Disable the build of the PostgreSQL-SDBC driver.])
)
+AC_ARG_ENABLE(coretext,
+ AS_HELP_STRING([--enable-coretext],
+ [Use CoreText framework on Mac (instead of ATSU).]),
+)
+
dnl ===================================================================
dnl Optional Packages (--with/without-)
dnl ===================================================================
@@ -10093,6 +10098,21 @@ else
fi
AC_SUBST(WITH_HELPPACK_INTEGRATION)
+dnl ===================================================================
+dnl Test whether to use CoreText framework
+dnl ===================================================================
+ENABLE_CORETEXT=NO
+if test "$_os" = "Darwin"; then
+ AC_MSG_CHECKING([whether to use CoreText framework])
+ if test "$enable_coretext" = "yes"; then
+ AC_MSG_RESULT([yes])
+ ENABLE_CORETEXT=YES
+ else
+ AC_MSG_RESULT([no])
+ fi
+fi
+AC_SUBST(ENABLE_CORETEXT)
+
###############################################################################
# Extensions checking
###############################################################################
commit 9db88e11882c38cd22564c4a76bb0b878de5fe86
Author: Norbert Thiebaud <nthiebaud at gmail.com>
Date: Fri Mar 16 23:58:39 2012 -0500
factorize what we can share for salgdi between CoreText and ATSUI
diff --git a/vcl/aqua/source/gdi/atsui/salgdi.cxx b/vcl/aqua/source/gdi/atsui/salgdi.cxx
index 7fdd19f..18fe982 100644
--- a/vcl/aqua/source/gdi/atsui/salgdi.cxx
+++ b/vcl/aqua/source/gdi/atsui/salgdi.cxx
@@ -53,7 +53,6 @@
#include "fontsubset.hxx"
#include "impfont.hxx"
-#include "region.h"
#include "sallayout.hxx"
#include "sft.hxx"
@@ -372,1200 +371,8 @@ AquaSalGraphics::~AquaSalGraphics()
}
}
-bool AquaSalGraphics::supportsOperation( OutDevSupportType eType ) const
-{
- bool bRet = false;
- switch( eType )
- {
- case OutDevSupport_TransparentRect:
- case OutDevSupport_B2DClip:
- case OutDevSupport_B2DDraw:
- bRet = true;
- break;
- default: break;
- }
- return bRet;
-}
-
// =======================================================================
-void AquaSalGraphics::updateResolution()
-{
- DBG_ASSERT( mbWindow, "updateResolution on inappropriate graphics" );
-
- initResolution( (mbWindow && mpFrame) ? mpFrame->mpWindow : nil );
-}
-
-void AquaSalGraphics::initResolution( NSWindow* )
-{
- // #i100617# read DPI only once; there is some kind of weird caching going on
- // if the main screen changes
- // FIXME: this is really unfortunate and needs to be investigated
-
- SalData* pSalData = GetSalData();
- if( pSalData->mnDPIX == 0 || pSalData->mnDPIY == 0 )
- {
- NSScreen* pScreen = nil;
-
- /* #i91301#
- many woes went into the try to have different resolutions
- on different screens. The result of these trials is that OOo is not ready
- for that yet, vcl and applications would need to be adapted.
-
- Unfortunately this is not possible in the 3.0 timeframe.
- So let's stay with one resolution for all Windows and VirtualDevices
- which is the resolution of the main screen
-
- This of course also means that measurements are exact only on the main screen.
- For activating different resolutions again just comment out the two lines below.
-
- if( pWin )
- pScreen = [pWin screen];
- */
- if( pScreen == nil )
- {
- NSArray* pScreens = [NSScreen screens];
- if( pScreens )
- pScreen = [pScreens objectAtIndex: 0];
- }
-
- mnRealDPIX = mnRealDPIY = 96;
- if( pScreen )
- {
- NSDictionary* pDev = [pScreen deviceDescription];
- if( pDev )
- {
- NSNumber* pVal = [pDev objectForKey: @"NSScreenNumber"];
- if( pVal )
- {
- // FIXME: casting a long to CGDirectDisplayID is evil, but
- // Apple suggest to do it this way
- const CGDirectDisplayID nDisplayID = (CGDirectDisplayID)[pVal longValue];
- const CGSize aSize = CGDisplayScreenSize( nDisplayID ); // => result is in millimeters
- mnRealDPIX = static_cast<long>((CGDisplayPixelsWide( nDisplayID ) * 25.4) / aSize.width);
- mnRealDPIY = static_cast<long>((CGDisplayPixelsHigh( nDisplayID ) * 25.4) / aSize.height);
- }
- else
- {
- OSL_FAIL( "no resolution found in device description" );
- }
- }
- else
- {
- OSL_FAIL( "no device description" );
- }
- }
- else
- {
- OSL_FAIL( "no screen found" );
- }
-
- // #i107076# maintaining size-WYSIWYG-ness causes many problems for
- // low-DPI, high-DPI or for mis-reporting devices
- // => it is better to limit the calculation result then
- static const int nMinDPI = 72;
- if( (mnRealDPIX < nMinDPI) || (mnRealDPIY < nMinDPI) )
- mnRealDPIX = mnRealDPIY = nMinDPI;
- static const int nMaxDPI = 200;
- if( (mnRealDPIX > nMaxDPI) || (mnRealDPIY > nMaxDPI) )
- mnRealDPIX = mnRealDPIY = nMaxDPI;
-
- // for OSX any anisotropy reported for the display resolution is best ignored (e.g. TripleHead2Go)
- mnRealDPIX = mnRealDPIY = (mnRealDPIX + mnRealDPIY + 1) / 2;
-
- pSalData->mnDPIX = mnRealDPIX;
- pSalData->mnDPIY = mnRealDPIY;
- }
- else
- {
- mnRealDPIX = pSalData->mnDPIX;
- mnRealDPIY = pSalData->mnDPIY;
- }
-
- mfFakeDPIScale = 1.0;
-}
-
-void AquaSalGraphics::GetResolution( long& rDPIX, long& rDPIY )
-{
- if( !mnRealDPIY )
- initResolution( (mbWindow && mpFrame) ? mpFrame->mpWindow : nil );
-
- rDPIX = static_cast<long>(mfFakeDPIScale * mnRealDPIX);
- rDPIY = static_cast<long>(mfFakeDPIScale * mnRealDPIY);
-}
-
-void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics )
-{
- if( !rGraphics.mnRealDPIY && rGraphics.mbWindow && rGraphics.mpFrame )
- rGraphics.initResolution( rGraphics.mpFrame->mpWindow );
-
- mnRealDPIX = rGraphics.mnRealDPIX;
- mnRealDPIY = rGraphics.mnRealDPIY;
- mfFakeDPIScale = rGraphics.mfFakeDPIScale;
-}
-
-// -----------------------------------------------------------------------
-
-sal_uInt16 AquaSalGraphics::GetBitCount() const
-{
- sal_uInt16 nBits = mnBitmapDepth ? mnBitmapDepth : 32;//24;
- return nBits;
-}
-
-// -----------------------------------------------------------------------
-
-static const basegfx::B2DPoint aHalfPointOfs ( 0.5, 0.5 );
-
-static void AddPolygonToPath( CGMutablePathRef xPath,
- const ::basegfx::B2DPolygon& rPolygon, bool bClosePath, bool bPixelSnap, bool bLineDraw )
-{
- // short circuit if there is nothing to do
- const int nPointCount = rPolygon.count();
- if( nPointCount <= 0 )
- return;
-
- (void)bPixelSnap; // TODO
- const CGAffineTransform* pTransform = NULL;
-
- const bool bHasCurves = rPolygon.areControlPointsUsed();
- for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ )
- {
- int nClosedIdx = nPointIdx;
- if( nPointIdx >= nPointCount )
- {
- // prepare to close last curve segment if needed
- if( bClosePath && (nPointIdx == nPointCount) )
- nClosedIdx = 0;
- else
- break;
- }
-
- ::basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx );
-
- if( bPixelSnap)
- {
- // snap device coordinates to full pixels
- aPoint.setX( basegfx::fround( aPoint.getX() ) );
- aPoint.setY( basegfx::fround( aPoint.getY() ) );
- }
-
- if( bLineDraw )
- aPoint += aHalfPointOfs;
-
- if( !nPointIdx ) { // first point => just move there
- CGPathMoveToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() );
- continue;
- }
-
- bool bPendingCurve = false;
- if( bHasCurves )
- {
- bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx );
- bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx );
- }
-
- if( !bPendingCurve ) // line segment
- CGPathAddLineToPoint( xPath, pTransform, aPoint.getX(), aPoint.getY() );
- else // cubic bezier segment
- {
- basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx );
- basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx );
- if( bLineDraw )
- {
- aCP1 += aHalfPointOfs;
- aCP2 += aHalfPointOfs;
- }
- CGPathAddCurveToPoint( xPath, pTransform, aCP1.getX(), aCP1.getY(),
- aCP2.getX(), aCP2.getY(), aPoint.getX(), aPoint.getY() );
- }
- }
-
- if( bClosePath )
- CGPathCloseSubpath( xPath );
-}
-
-static void AddPolyPolygonToPath( CGMutablePathRef xPath,
- const ::basegfx::B2DPolyPolygon& rPolyPoly, bool bPixelSnap, bool bLineDraw )
-{
- // short circuit if there is nothing to do
- const int nPolyCount = rPolyPoly.count();
- if( nPolyCount <= 0 )
- return;
-
- for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
- {
- const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx );
- AddPolygonToPath( xPath, rPolygon, true, bPixelSnap, bLineDraw );
- }
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::ResetClipRegion()
-{
- // release old path and indicate no clipping
- if( mxClipPath )
- {
- CGPathRelease( mxClipPath );
- mxClipPath = NULL;
- }
- if( CheckContext() )
- SetState();
-}
-
-// -----------------------------------------------------------------------
-
-bool AquaSalGraphics::setClipRegion( const Region& i_rClip )
-{
- // release old clip path
- if( mxClipPath )
- {
- CGPathRelease( mxClipPath );
- mxClipPath = NULL;
- }
- mxClipPath = CGPathCreateMutable();
-
- // set current path, either as polypolgon or sequence of rectangles
- if( i_rClip.HasPolyPolygon() )
- {
- basegfx::B2DPolyPolygon aClip( const_cast<Region&>(i_rClip).ConvertToB2DPolyPolygon() );
- AddPolyPolygonToPath( mxClipPath, aClip, !getAntiAliasB2DDraw(), false );
- }
- else
- {
- long nX, nY, nW, nH;
- ImplRegionInfo aInfo;
- bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
- while( bRegionRect )
- {
- if( nW && nH )
- {
- CGRect aRect = {{nX,nY}, {nW,nH}};
- CGPathAddRect( mxClipPath, NULL, aRect );
- }
- bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
- }
- }
- // set the current path as clip region
- if( CheckContext() )
- SetState();
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::SetLineColor()
-{
- maLineColor.SetAlpha( 0.0 ); // transparent
- if( CheckContext() )
- CGContextSetStrokeColor( mrContext, maLineColor.AsArray() );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::SetLineColor( SalColor nSalColor )
-{
- maLineColor = RGBAColor( nSalColor );
- if( CheckContext() )
- CGContextSetStrokeColor( mrContext, maLineColor.AsArray() );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::SetFillColor()
-{
- maFillColor.SetAlpha( 0.0 ); // transparent
- if( CheckContext() )
- CGContextSetFillColor( mrContext, maFillColor.AsArray() );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::SetFillColor( SalColor nSalColor )
-{
- maFillColor = RGBAColor( nSalColor );
- if( CheckContext() )
- CGContextSetFillColor( mrContext, maFillColor.AsArray() );
-}
-
-// -----------------------------------------------------------------------
-
-static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
-{
- SalColor nSalColor;
- if ( nROPColor == SAL_ROP_0 )
- nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
- else
- nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
- return nSalColor;
-}
-
-void AquaSalGraphics::SetROPLineColor( SalROPColor nROPColor )
-{
- if( ! mbPrinter )
- SetLineColor( ImplGetROPSalColor( nROPColor ) );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::SetROPFillColor( SalROPColor nROPColor )
-{
- if( ! mbPrinter )
- SetFillColor( ImplGetROPSalColor( nROPColor ) );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::ImplDrawPixel( long nX, long nY, const RGBAColor& rColor )
-{
- if( !CheckContext() )
- return;
-
- // overwrite the fill color
- CGContextSetFillColor( mrContext, rColor.AsArray() );
- // draw 1x1 rect, there is no pixel drawing in Quartz
- CGRect aDstRect = {{nX,nY,},{1,1}};
- CGContextFillRect( mrContext, aDstRect );
- RefreshRect( aDstRect );
- // reset the fill color
- CGContextSetFillColor( mrContext, maFillColor.AsArray() );
-}
-
-void AquaSalGraphics::drawPixel( long nX, long nY )
-{
- // draw pixel with current line color
- ImplDrawPixel( nX, nY, maLineColor );
-}
-
-void AquaSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
-{
- const RGBAColor aPixelColor( nSalColor );
- ImplDrawPixel( nX, nY, aPixelColor );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
-{
- if( nX1 == nX2 && nY1 == nY2 )
- {
- // #i109453# platform independent code expects at least one pixel to be drawn
- drawPixel( nX1, nY1 );
- return;
- }
-
- if( !CheckContext() )
- return;
-
- CGContextBeginPath( mrContext );
- CGContextMoveToPoint( mrContext, static_cast<float>(nX1)+0.5, static_cast<float>(nY1)+0.5 );
- CGContextAddLineToPoint( mrContext, static_cast<float>(nX2)+0.5, static_cast<float>(nY2)+0.5 );
- CGContextDrawPath( mrContext, kCGPathStroke );
-
- Rectangle aRefreshRect( nX1, nY1, nX2, nY2 );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
-{
- if( !CheckContext() )
- return;
-
- CGRect aRect( CGRectMake(nX, nY, nWidth, nHeight) );
- if( IsPenVisible() )
- {
- aRect.origin.x += 0.5;
- aRect.origin.y += 0.5;
- aRect.size.width -= 1;
- aRect.size.height -= 1;
- }
-
- if( IsBrushVisible() )
- CGContextFillRect( mrContext, aRect );
-
- if( IsPenVisible() )
- CGContextStrokeRect( mrContext, aRect );
-
- RefreshRect( nX, nY, nWidth, nHeight );
-}
-
-// -----------------------------------------------------------------------
-
-static void getBoundRect( sal_uLong nPoints, const SalPoint *pPtAry, long &rX, long& rY, long& rWidth, long& rHeight )
-{
- long nX1 = pPtAry->mnX;
- long nX2 = nX1;
- long nY1 = pPtAry->mnY;
- long nY2 = nY1;
- for( sal_uLong n = 1; n < nPoints; n++ )
- {
- if( pPtAry[n].mnX < nX1 )
- nX1 = pPtAry[n].mnX;
- else if( pPtAry[n].mnX > nX2 )
- nX2 = pPtAry[n].mnX;
-
- if( pPtAry[n].mnY < nY1 )
- nY1 = pPtAry[n].mnY;
- else if( pPtAry[n].mnY > nY2 )
- nY2 = pPtAry[n].mnY;
- }
- rX = nX1;
- rY = nY1;
- rWidth = nX2 - nX1 + 1;
- rHeight = nY2 - nY1 + 1;
-}
-
-static inline void alignLinePoint( const SalPoint* i_pIn, float& o_fX, float& o_fY )
-{
- o_fX = static_cast<float>(i_pIn->mnX ) + 0.5;
- o_fY = static_cast<float>(i_pIn->mnY ) + 0.5;
-}
-
-void AquaSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry )
-{
- if( nPoints < 1 )
- return;
- if( !CheckContext() )
- return;
-
- long nX = 0, nY = 0, nWidth = 0, nHeight = 0;
- getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight );
-
- float fX, fY;
-
- CGContextBeginPath( mrContext );
- alignLinePoint( pPtAry, fX, fY );
- CGContextMoveToPoint( mrContext, fX, fY );
- pPtAry++;
- for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
- {
- alignLinePoint( pPtAry, fX, fY );
- CGContextAddLineToPoint( mrContext, fX, fY );
- }
- CGContextDrawPath( mrContext, kCGPathStroke );
-
- RefreshRect( nX, nY, nWidth, nHeight );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint *pPtAry )
-{
- if( nPoints <= 1 )
- return;
- if( !CheckContext() )
- return;
-
- long nX = 0, nY = 0, nWidth = 0, nHeight = 0;
- getBoundRect( nPoints, pPtAry, nX, nY, nWidth, nHeight );
-
- CGPathDrawingMode eMode;
- if( IsBrushVisible() && IsPenVisible() )
- eMode = kCGPathEOFillStroke;
- else if( IsPenVisible() )
- eMode = kCGPathStroke;
- else if( IsBrushVisible() )
- eMode = kCGPathEOFill;
- else
- return;
-
- CGContextBeginPath( mrContext );
-
- if( IsPenVisible() )
- {
- float fX, fY;
- alignLinePoint( pPtAry, fX, fY );
- CGContextMoveToPoint( mrContext, fX, fY );
- pPtAry++;
- for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
- {
- alignLinePoint( pPtAry, fX, fY );
- CGContextAddLineToPoint( mrContext, fX, fY );
- }
- }
- else
- {
- CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY );
- pPtAry++;
- for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
- CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY );
- }
-
- CGContextDrawPath( mrContext, eMode );
- RefreshRect( nX, nY, nWidth, nHeight );
-}
-
-// -----------------------------------------------------------------------
-
-void AquaSalGraphics::drawPolyPolygon( sal_uLong nPolyCount, const sal_uLong *pPoints, PCONSTSALPOINT *ppPtAry )
-{
- if( nPolyCount <= 0 )
- return;
- if( !CheckContext() )
- return;
-
- // find bound rect
- long leftX = 0, topY = 0, maxWidth = 0, maxHeight = 0;
- getBoundRect( pPoints[0], ppPtAry[0], leftX, topY, maxWidth, maxHeight );
- for( sal_uLong n = 1; n < nPolyCount; n++ )
- {
- long nX = leftX, nY = topY, nW = maxWidth, nH = maxHeight;
- getBoundRect( pPoints[n], ppPtAry[n], nX, nY, nW, nH );
- if( nX < leftX )
- {
- maxWidth += leftX - nX;
- leftX = nX;
- }
- if( nY < topY )
- {
- maxHeight += topY - nY;
- topY = nY;
- }
- if( nX + nW > leftX + maxWidth )
- maxWidth = nX + nW - leftX;
- if( nY + nH > topY + maxHeight )
- maxHeight = nY + nH - topY;
- }
-
- // prepare drawing mode
- CGPathDrawingMode eMode;
- if( IsBrushVisible() && IsPenVisible() )
- eMode = kCGPathEOFillStroke;
- else if( IsPenVisible() )
- eMode = kCGPathStroke;
- else if( IsBrushVisible() )
- eMode = kCGPathEOFill;
- else
- return;
-
- // convert to CGPath
- CGContextBeginPath( mrContext );
- if( IsPenVisible() )
- {
- for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ )
- {
- const sal_uLong nPoints = pPoints[nPoly];
- if( nPoints > 1 )
- {
- const SalPoint *pPtAry = ppPtAry[nPoly];
- float fX, fY;
- alignLinePoint( pPtAry, fX, fY );
- CGContextMoveToPoint( mrContext, fX, fY );
- pPtAry++;
- for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
- {
- alignLinePoint( pPtAry, fX, fY );
- CGContextAddLineToPoint( mrContext, fX, fY );
- }
- CGContextClosePath(mrContext);
- }
- }
- }
- else
- {
- for( sal_uLong nPoly = 0; nPoly < nPolyCount; nPoly++ )
- {
- const sal_uLong nPoints = pPoints[nPoly];
- if( nPoints > 1 )
- {
- const SalPoint *pPtAry = ppPtAry[nPoly];
- CGContextMoveToPoint( mrContext, pPtAry->mnX, pPtAry->mnY );
- pPtAry++;
- for( sal_uLong nPoint = 1; nPoint < nPoints; nPoint++, pPtAry++ )
- CGContextAddLineToPoint( mrContext, pPtAry->mnX, pPtAry->mnY );
- CGContextClosePath(mrContext);
- }
- }
- }
-
- CGContextDrawPath( mrContext, eMode );
-
- RefreshRect( leftX, topY, maxWidth, maxHeight );
-}
-
-// -----------------------------------------------------------------------
-
-bool AquaSalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rPolyPoly,
- double fTransparency )
-{
- // short circuit if there is nothing to do
- const int nPolyCount = rPolyPoly.count();
- if( nPolyCount <= 0 )
- return true;
-
- // ignore invisible polygons
- if( (fTransparency >= 1.0) || (fTransparency < 0) )
- return true;
-
- // setup poly-polygon path
- CGMutablePathRef xPath = CGPathCreateMutable();
- for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx )
- {
- const ::basegfx::B2DPolygon rPolygon = rPolyPoly.getB2DPolygon( nPolyIdx );
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list