mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Use bit mask for font attribute calculation
This commit is contained in:
parent
74042f17f0
commit
03e09b7489
@ -57,17 +57,40 @@ public func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttrib
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ChatTextFontAttributes: OptionSet {
|
public struct ChatTextFontAttributes: OptionSet, Hashable, Sequence {
|
||||||
public var rawValue: Int32 = 0
|
public var rawValue: UInt32 = 0
|
||||||
|
|
||||||
public init(rawValue: Int32) {
|
public init(rawValue: UInt32) {
|
||||||
self.rawValue = rawValue
|
self.rawValue = rawValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.rawValue = 0
|
||||||
|
}
|
||||||
|
|
||||||
public static let bold = ChatTextFontAttributes(rawValue: 1 << 0)
|
public static let bold = ChatTextFontAttributes(rawValue: 1 << 0)
|
||||||
public static let italic = ChatTextFontAttributes(rawValue: 1 << 1)
|
public static let italic = ChatTextFontAttributes(rawValue: 1 << 1)
|
||||||
public static let monospace = ChatTextFontAttributes(rawValue: 1 << 2)
|
public static let monospace = ChatTextFontAttributes(rawValue: 1 << 2)
|
||||||
public static let blockQuote = ChatTextFontAttributes(rawValue: 1 << 3)
|
public static let blockQuote = ChatTextFontAttributes(rawValue: 1 << 3)
|
||||||
|
|
||||||
|
public func makeIterator() -> AnyIterator<ChatTextFontAttributes> {
|
||||||
|
var index = 0
|
||||||
|
return AnyIterator { () -> ChatTextFontAttributes? in
|
||||||
|
while index < 31 {
|
||||||
|
let currentTags = self.rawValue >> UInt32(index)
|
||||||
|
let tag = ChatTextFontAttributes(rawValue: 1 << UInt32(index))
|
||||||
|
index += 1
|
||||||
|
if currentTags == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTags & 1) != 0 {
|
||||||
|
return tag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) -> NSAttributedString {
|
public func textAttributedStringForStateText(_ stateText: NSAttributedString, fontSize: CGFloat, textColor: UIColor, accentTextColor: UIColor, writingDirection: NSWritingDirection?, spoilersRevealed: Bool, availableEmojis: Set<String>, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?) -> NSAttributedString {
|
||||||
|
@ -65,7 +65,13 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
|||||||
if linkColor.argb == baseColor.argb {
|
if linkColor.argb == baseColor.argb {
|
||||||
underlineAllLinks = true
|
underlineAllLinks = true
|
||||||
}
|
}
|
||||||
var fontAttributes: [NSRange: ChatTextFontAttributes] = [:]
|
|
||||||
|
var fontAttributeMask: [ChatTextFontAttributes] = Array(repeating: [], count: string.length)
|
||||||
|
let addFontAttributes: (NSRange, ChatTextFontAttributes) -> Void = { range, attributes in
|
||||||
|
for i in range.lowerBound ..< range.upperBound {
|
||||||
|
fontAttributeMask[i].formUnion(attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i in 0 ..< entities.count {
|
for i in 0 ..< entities.count {
|
||||||
if skipEntity {
|
if skipEntity {
|
||||||
@ -125,17 +131,9 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
|||||||
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.URL), value: url, range: range)
|
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.URL), value: url, range: range)
|
||||||
}
|
}
|
||||||
case .Bold:
|
case .Bold:
|
||||||
if let fontAttribute = fontAttributes[range] {
|
addFontAttributes(range, .bold)
|
||||||
fontAttributes[range] = fontAttribute.union(.bold)
|
|
||||||
} else {
|
|
||||||
fontAttributes[range] = .bold
|
|
||||||
}
|
|
||||||
case .Italic:
|
case .Italic:
|
||||||
if let fontAttribute = fontAttributes[range] {
|
addFontAttributes(range, .italic)
|
||||||
fontAttributes[range] = fontAttribute.union(.italic)
|
|
||||||
} else {
|
|
||||||
fontAttributes[range] = .italic
|
|
||||||
}
|
|
||||||
case .Mention:
|
case .Mention:
|
||||||
string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range)
|
string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range)
|
||||||
if underlineLinks && underlineAllLinks {
|
if underlineLinks && underlineAllLinks {
|
||||||
@ -214,11 +212,7 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
|||||||
}
|
}
|
||||||
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Pre), value: nsString!.substring(with: range), range: range)
|
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Pre), value: nsString!.substring(with: range), range: range)
|
||||||
case .BlockQuote:
|
case .BlockQuote:
|
||||||
if let fontAttribute = fontAttributes[range] {
|
addFontAttributes(range, .blockQuote)
|
||||||
fontAttributes[range] = fontAttribute.union(.blockQuote)
|
|
||||||
} else {
|
|
||||||
fontAttributes[range] = .blockQuote
|
|
||||||
}
|
|
||||||
|
|
||||||
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(title: nil, color: baseQuoteTintColor), range: range)
|
string.addAttribute(NSAttributedString.Key(rawValue: "Attribute__Blockquote"), value: TextNodeBlockQuoteData(title: nil, color: baseQuoteTintColor), range: range)
|
||||||
case .BankCard:
|
case .BankCard:
|
||||||
@ -263,71 +257,45 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
var addedAttributes: [(NSRange, ChatTextFontAttributes)] = []
|
func setFont(range: NSRange, fontAttributes: ChatTextFontAttributes) {
|
||||||
func addFont(ranges: [NSRange], fontAttributes: ChatTextFontAttributes) {
|
var font: UIFont
|
||||||
for range in ranges {
|
|
||||||
var font: UIFont?
|
var isQuote = false
|
||||||
|
|
||||||
var fontAttributes = fontAttributes
|
|
||||||
let initialFontAttributes = fontAttributes
|
|
||||||
var isQuote = false
|
|
||||||
if fontAttributes.contains(.blockQuote) {
|
|
||||||
isQuote = true
|
|
||||||
fontAttributes.remove(.blockQuote)
|
|
||||||
}
|
|
||||||
if fontAttributes == [.bold, .italic] {
|
|
||||||
font = boldItalicFont
|
|
||||||
} else if fontAttributes == [.bold] {
|
|
||||||
font = boldFont
|
|
||||||
addedAttributes.append((range, initialFontAttributes))
|
|
||||||
} else if fontAttributes == [.italic] {
|
|
||||||
font = italicFont
|
|
||||||
addedAttributes.append((range, initialFontAttributes))
|
|
||||||
} else {
|
|
||||||
font = baseFont
|
|
||||||
}
|
|
||||||
|
|
||||||
if adjustQuoteFontSize, let fontValue = font, isQuote {
|
|
||||||
font = fontValue.withSize(round(fontValue.pointSize * 0.8235294117647058))
|
|
||||||
}
|
|
||||||
|
|
||||||
if let font = font {
|
|
||||||
string.addAttribute(NSAttributedString.Key.font, value: font, range: range)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (range, fontAttributes) in fontAttributes {
|
|
||||||
var ranges = [range]
|
|
||||||
var fontAttributes = fontAttributes
|
var fontAttributes = fontAttributes
|
||||||
if fontAttributes != [.bold, .italic] {
|
if fontAttributes.contains(.blockQuote) {
|
||||||
for (existingRange, existingAttributes) in addedAttributes {
|
fontAttributes.remove(.blockQuote)
|
||||||
if let intersection = existingRange.intersection(range) {
|
isQuote = true
|
||||||
if intersection.length == range.length {
|
}
|
||||||
if existingAttributes == .bold || existingAttributes == .italic {
|
if fontAttributes == [.bold, .italic] {
|
||||||
fontAttributes.insert(existingAttributes)
|
font = boldItalicFont
|
||||||
}
|
} else if fontAttributes == [.bold] {
|
||||||
} else {
|
font = boldFont
|
||||||
var fontAttributes = fontAttributes
|
} else if fontAttributes == [.italic] {
|
||||||
if existingAttributes == .bold || existingAttributes == .italic {
|
font = italicFont
|
||||||
fontAttributes.insert(existingAttributes)
|
} else if fontAttributes == [.monospace] {
|
||||||
}
|
font = fixedFont
|
||||||
addFont(ranges: [intersection], fontAttributes: fontAttributes)
|
} else {
|
||||||
|
font = baseFont
|
||||||
ranges = []
|
|
||||||
if range.upperBound > existingRange.lowerBound {
|
|
||||||
ranges.append(NSRange(location: range.lowerBound, length: existingRange.lowerBound - range.lowerBound))
|
|
||||||
}
|
|
||||||
if range.upperBound > existingRange.upperBound {
|
|
||||||
ranges.append(NSRange(location: existingRange.upperBound, length: range.upperBound - existingRange.upperBound))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addFont(ranges: ranges, fontAttributes: fontAttributes)
|
if adjustQuoteFontSize, isQuote {
|
||||||
|
font = font.withSize(round(font.pointSize * 0.8235294117647058))
|
||||||
|
}
|
||||||
|
|
||||||
|
string.addAttribute(.font, value: font, range: range)
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentAttributeSpan: (startIndex: Int, attributes: ChatTextFontAttributes)?
|
||||||
|
for i in 0 ..< fontAttributeMask.count {
|
||||||
|
if fontAttributeMask[i] != currentAttributeSpan?.attributes {
|
||||||
|
if let currentAttributeSpan {
|
||||||
|
setFont(range: NSRange(location: currentAttributeSpan.startIndex, length: i - currentAttributeSpan.startIndex), fontAttributes: currentAttributeSpan.attributes)
|
||||||
|
}
|
||||||
|
currentAttributeSpan = (i, fontAttributeMask[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let currentAttributeSpan {
|
||||||
|
setFont(range: NSRange(location: currentAttributeSpan.startIndex, length: fontAttributeMask.count - currentAttributeSpan.startIndex), fontAttributes: currentAttributeSpan.attributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return string
|
return string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user