// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/common/mac/attributed_string_coder.h" #include <AppKit/AppKit.h> #include "base/logging.h" #include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "content/common/view_messages.h" #include "content/public/common/common_param_traits.h" #include "ipc/ipc_message_utils.h" namespace mac { // static const AttributedStringCoder::EncodedString* AttributedStringCoder::Encode( NSAttributedString* str) { // Create the return value. EncodedString* encoded_string = new EncodedString(base::SysNSStringToUTF16([str string])); // Iterate over all the attributes in the string. NSUInteger length = [str length]; for (NSUInteger i = 0; i < length; ) { NSRange effective_range; NSDictionary* ns_attributes = [str attributesAtIndex:i effectiveRange:&effective_range]; // Convert the attributes to IPC-friendly types. FontAttribute attrs(ns_attributes, gfx::Range(effective_range)); // Only encode the attributes if the filtered set contains font information. if (attrs.ShouldEncode()) { encoded_string->attributes()->push_back(attrs); } // Advance the iterator to the position outside of the effective range. i = NSMaxRange(effective_range); } return encoded_string; } // static NSAttributedString* AttributedStringCoder::Decode( const AttributedStringCoder::EncodedString* str) { // Create the return value. NSString* plain_text = base::SysUTF16ToNSString(str->string()); base::scoped_nsobject<NSMutableAttributedString> decoded_string( [[NSMutableAttributedString alloc] initWithString:plain_text]); // Iterate over all the encoded attributes, attaching each to the string. const std::vector<FontAttribute> attributes = str->attributes(); for (std::vector<FontAttribute>::const_iterator it = attributes.begin(); it != attributes.end(); ++it) { // Protect against ranges that are outside the range of the string. const gfx::Range& range = it->effective_range(); if (range.GetMin() > [plain_text length] || range.GetMax() > [plain_text length]) { continue; } [decoded_string addAttributes:it->ToAttributesDictionary() range:range.ToNSRange()]; } return [decoded_string.release() autorelease]; } // Data Types ////////////////////////////////////////////////////////////////// AttributedStringCoder::EncodedString::EncodedString(base::string16 string) : string_(string) { } AttributedStringCoder::EncodedString::EncodedString() : string_() { } AttributedStringCoder::EncodedString::~EncodedString() { } AttributedStringCoder::FontAttribute::FontAttribute(NSDictionary* dict, gfx::Range effective_range) : font_descriptor_(), effective_range_(effective_range) { NSFont* font = [dict objectForKey:NSFontAttributeName]; if (font) { font_descriptor_ = FontDescriptor(font); } } AttributedStringCoder::FontAttribute::FontAttribute(FontDescriptor font, gfx::Range range) : font_descriptor_(font), effective_range_(range) { } AttributedStringCoder::FontAttribute::FontAttribute() : font_descriptor_(), effective_range_() { } AttributedStringCoder::FontAttribute::~FontAttribute() { } NSDictionary* AttributedStringCoder::FontAttribute::ToAttributesDictionary( void) const { DCHECK(ShouldEncode()); NSFont* font = font_descriptor_.ToNSFont(); return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]; } bool AttributedStringCoder::FontAttribute::ShouldEncode() const { return !font_descriptor_.font_name.empty(); } } // namespace mac // IPC ParamTraits specialization ////////////////////////////////////////////// namespace IPC { using mac::AttributedStringCoder; void ParamTraits<AttributedStringCoder::EncodedString>::Write( Message* m, const param_type& p) { WriteParam(m, p.string()); WriteParam(m, p.attributes()); } bool ParamTraits<AttributedStringCoder::EncodedString>::Read( const Message* m, PickleIterator* iter, param_type* p) { bool success = true; base::string16 result; success &= ReadParam(m, iter, &result); *p = AttributedStringCoder::EncodedString(result); success &= ReadParam(m, iter, p->attributes()); return success; } void ParamTraits<AttributedStringCoder::EncodedString>::Log( const param_type& p, std::string* l) { l->append(base::UTF16ToUTF8(p.string())); } void ParamTraits<AttributedStringCoder::FontAttribute>::Write( Message* m, const param_type& p) { WriteParam(m, p.font_descriptor()); WriteParam(m, p.effective_range()); } bool ParamTraits<AttributedStringCoder::FontAttribute>::Read( const Message* m, PickleIterator* iter, param_type* p) { bool success = true; FontDescriptor font; success &= ReadParam(m, iter, &font); gfx::Range range; success &= ReadParam(m, iter, &range); if (success) { *p = AttributedStringCoder::FontAttribute(font, range); } return success; } void ParamTraits<AttributedStringCoder::FontAttribute>::Log( const param_type& p, std::string* l) { } } // namespace IPC