diff options
-rw-r--r-- | cocoa/DictionaryForCF.h | 36 | ||||
-rw-r--r-- | cocoa/PlatCocoa.h | 1 | ||||
-rw-r--r-- | cocoa/QuartzTextStyleAttribute.h | 88 | ||||
-rw-r--r-- | cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj | 4 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 3 |
5 files changed, 99 insertions, 33 deletions
diff --git a/cocoa/DictionaryForCF.h b/cocoa/DictionaryForCF.h new file mode 100644 index 000000000..09233bab5 --- /dev/null +++ b/cocoa/DictionaryForCF.h @@ -0,0 +1,36 @@ +/** + * Scintilla source code edit control + * @file DictionaryForCF.h - Wrapper for CFMutableDictionary + * + * Copyright 2024 Neil Hodgson. + * This file is dual licensed under LGPL v2.1 and the Scintilla license (http://www.scintilla.org/License.txt). + */ + +#ifndef DICTIONARYFORCF_H +#define DICTIONARYFORCF_H + +class DictionaryForCF { + CFMutableDictionaryRef dict; +public: + DictionaryForCF() noexcept : + dict(::CFDictionaryCreateMutable(kCFAllocatorDefault, 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)) { + } + ~DictionaryForCF() { + ::CFRelease(dict); + } + CFMutableDictionaryRef get() const noexcept { + return dict; + } + void SetValue(const void *key, const void *value) noexcept { + ::CFDictionarySetValue(dict, key, value); + } + void SetItem(const void *key, CFNumberType theType, const void *valuePtr) noexcept { + CFNumberRef number = ::CFNumberCreate(kCFAllocatorDefault, theType, valuePtr); + ::CFDictionarySetValue(dict, key, number); + ::CFRelease(number); + } +}; + +#endif diff --git a/cocoa/PlatCocoa.h b/cocoa/PlatCocoa.h index 536d3bcf9..0150287f1 100644 --- a/cocoa/PlatCocoa.h +++ b/cocoa/PlatCocoa.h @@ -22,6 +22,7 @@ #include "Geometry.h" #include "Platform.h" +#include "DictionaryForCF.h" #include "QuartzTextLayout.h" NSRect PRectangleToNSRect(const Scintilla::Internal::PRectangle &rc); diff --git a/cocoa/QuartzTextStyleAttribute.h b/cocoa/QuartzTextStyleAttribute.h index 22af29b4a..558daa58c 100644 --- a/cocoa/QuartzTextStyleAttribute.h +++ b/cocoa/QuartzTextStyleAttribute.h @@ -12,6 +12,42 @@ #ifndef QUARTZTEXTSTYLEATTRIBUTE_H #define QUARTZTEXTSTYLEATTRIBUTE_H +// Convert from a FontWeight value to a floating point value to pass to CoreText. +// This was defined based on Cocoa's NSFontWeight* values, discussion by other open +// source projects then tweaked until most values produced visibly different results. +inline double WeightFromEnumeration(Scintilla::FontWeight weight) { + switch (static_cast<int>(weight)/100) { + case 0: return -1.0; + case 1: return -0.7; + case 2: return -0.5; + case 3: return -0.23; + case 4: return 0.0; + case 5: return 0.2; + case 6: return 0.3; + case 7: return 0.4; + case 8: return 0.6; + case 9: return 0.8; + } + return 0.0; +} + +// Convert from a FontStretch value to a floating point value to pass to CoreText. +// This was defined based on values used by other open source projects then tweaked +// until most values produced reasonable results. +inline double StretchFromEnumeration(Scintilla::FontStretch stretch) { + switch (stretch) { + case Scintilla::FontStretch::UltraCondensed: return -0.8; + case Scintilla::FontStretch::ExtraCondensed: return -0.3; + case Scintilla::FontStretch::Condensed: return -0.23; + case Scintilla::FontStretch::SemiCondensed: return -0.1; + case Scintilla::FontStretch::Normal: return 0.0; + case Scintilla::FontStretch::SemiExpanded: return 0.1; + case Scintilla::FontStretch::Expanded: return 0.2; + case Scintilla::FontStretch::ExtraExpanded: return 0.3; + case Scintilla::FontStretch::UltraExpanded: return 0.7; + } +} + class QuartzFont { public: /** Create a font style from a name. */ @@ -20,42 +56,28 @@ public: CFStringRef fontName = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingMacRoman); assert(fontName != NULL); - bool bold = weight > Scintilla::FontWeight::Normal; - if (bold || italic || stretch != Scintilla::FontStretch::Normal) { - CTFontSymbolicTraits desiredTrait = 0; - CTFontSymbolicTraits traitMask = 0; - - // if bold was specified, add the trait - if (bold) { - desiredTrait |= kCTFontBoldTrait; - traitMask |= kCTFontBoldTrait; - } + // Specify the weight, stretch, and italics + DictionaryForCF traits; + const double weightValue = WeightFromEnumeration(weight); + traits.SetItem(kCTFontWeightTrait, kCFNumberCGFloatType, &weightValue); + const double stretchValue = StretchFromEnumeration(stretch); + traits.SetItem(kCTFontWidthTrait, kCFNumberCGFloatType, &stretchValue); + if (italic) { + const int italicValue = kCTFontTraitItalic; + traits.SetItem(kCTFontSymbolicTrait, kCFNumberIntType, &italicValue); + } - // if italic was specified, add the trait - if (italic) { - desiredTrait |= kCTFontItalicTrait; - traitMask |= kCTFontItalicTrait; - } - if (stretch < Scintilla::FontStretch::Normal) { - desiredTrait |= kCTFontCondensedTrait; - traitMask |= kCTFontCondensedTrait; - } else if (stretch > Scintilla::FontStretch::Normal) { - desiredTrait |= kCTFontExpandedTrait; - traitMask |= kCTFontExpandedTrait; - } + // create a font decriptor and then a font with that descriptor + DictionaryForCF attributes; + attributes.SetValue(kCTFontTraitsAttribute, traits.get()); + attributes.SetValue(kCTFontNameAttribute, fontName); - // create a font and then a copy of it with the sym traits - CTFontRef iFont = ::CTFontCreateWithName(fontName, size, NULL); - fontid = ::CTFontCreateCopyWithSymbolicTraits(iFont, size, NULL, desiredTrait, traitMask); - if (fontid) { - CFRelease(iFont); - } else { - // Traits failed so use base font - fontid = iFont; - } - } else { - // create the font, no traits + CTFontDescriptorRef desc = ::CTFontDescriptorCreateWithAttributes(attributes.get()); + fontid = ::CTFontCreateWithFontDescriptor(desc, size, NULL); + CFRelease(desc); + if (!fontid) { + // Traits failed so use base font fontid = ::CTFontCreateWithName(fontName, size, NULL); } diff --git a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj index 165ceaf9c..e8f729267 100644 --- a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj +++ b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj @@ -100,6 +100,7 @@ 287F3C6C246F90300040E76F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 287F3C6B246F90300040E76F /* QuartzCore.framework */; }; 28B962A52B6AF44F00ACCD96 /* UndoHistory.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 28B962A32B6AF44F00ACCD96 /* UndoHistory.cxx */; }; 28B962A62B6AF44F00ACCD96 /* UndoHistory.h in Headers */ = {isa = PBXBuildFile; fileRef = 28B962A42B6AF44F00ACCD96 /* UndoHistory.h */; }; + 28CC23042C6F10F300D75568 /* DictionaryForCF.h in Headers */ = {isa = PBXBuildFile; fileRef = 28CC23032C6F10F300D75568 /* DictionaryForCF.h */; }; 28EA9CAE255894B4007710C4 /* CharacterCategoryMap.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 28EA9CAA255894B4007710C4 /* CharacterCategoryMap.cxx */; }; 28EA9CAF255894B4007710C4 /* CharacterType.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 28EA9CAB255894B4007710C4 /* CharacterType.cxx */; }; 28EA9CB0255894B4007710C4 /* CharacterCategoryMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 28EA9CAC255894B4007710C4 /* CharacterCategoryMap.h */; }; @@ -203,6 +204,7 @@ 287F3E0F246F9AE50040E76F /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = SOURCE_ROOT; }; 28B962A32B6AF44F00ACCD96 /* UndoHistory.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UndoHistory.cxx; path = ../../src/UndoHistory.cxx; sourceTree = "<group>"; }; 28B962A42B6AF44F00ACCD96 /* UndoHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UndoHistory.h; path = ../../src/UndoHistory.h; sourceTree = "<group>"; }; + 28CC23032C6F10F300D75568 /* DictionaryForCF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DictionaryForCF.h; path = ../DictionaryForCF.h; sourceTree = "<group>"; }; 28EA9CAA255894B4007710C4 /* CharacterCategoryMap.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CharacterCategoryMap.cxx; path = ../../src/CharacterCategoryMap.cxx; sourceTree = "<group>"; }; 28EA9CAB255894B4007710C4 /* CharacterType.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CharacterType.cxx; path = ../../src/CharacterType.cxx; sourceTree = "<group>"; }; 28EA9CAC255894B4007710C4 /* CharacterCategoryMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CharacterCategoryMap.h; path = ../../src/CharacterCategoryMap.h; sourceTree = "<group>"; }; @@ -327,6 +329,7 @@ 287F3C4E246F8E560040E76F /* Classes */ = { isa = PBXGroup; children = ( + 28CC23032C6F10F300D75568 /* DictionaryForCF.h */, 282936DA24E2D55D00C84BA2 /* InfoBar.h */, 282936D424E2D55D00C84BA2 /* InfoBar.mm */, 282936D924E2D55D00C84BA2 /* InfoBarCommunicator.h */, @@ -416,6 +419,7 @@ 2829373B24E2D58800C84BA2 /* Position.h in Headers */, 282936E224E2D55D00C84BA2 /* ScintillaCocoa.h in Headers */, 2829373524E2D58800C84BA2 /* Style.h in Headers */, + 28CC23042C6F10F300D75568 /* DictionaryForCF.h in Headers */, 282936E424E2D55D00C84BA2 /* PlatCocoa.h in Headers */, 2807B4EB28964CA40063A31A /* ChangeHistory.h in Headers */, 2829376C24E2D58800C84BA2 /* Selection.h in Headers */, diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 67795148c..0f0d7911f 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -609,6 +609,9 @@ <li> Fix bug on Cocoa where double-click stopped working when system had been running for a long time. </li> + <li> + On Cocoa implement more values of font weight and stretch. + </li> </ul> <h3> <a href="https://www.scintilla.org/scintilla551.zip">Release 5.5.1</a> |