1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/mac/attributed_string_coder.h"
7 #include <AppKit/AppKit.h>
9 #include "base/logging.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/common/render_process_messages.h"
14 #include "content/public/common/common_param_traits.h"
15 #include "ipc/ipc_message_utils.h"
20 const AttributedStringCoder::EncodedString* AttributedStringCoder::Encode(
21 NSAttributedString* str) {
22 // Create the return value.
23 EncodedString* encoded_string =
24 new EncodedString(base::SysNSStringToUTF16([str string]));
25 // Iterate over all the attributes in the string.
26 NSUInteger length = [str length];
27 for (NSUInteger i = 0; i < length; ) {
28 NSRange effective_range;
29 NSDictionary* ns_attributes = [str attributesAtIndex:i
30 effectiveRange:&effective_range];
31 // Convert the attributes to IPC-friendly types.
32 FontAttribute attrs(ns_attributes, gfx::Range(effective_range));
33 // Only encode the attributes if the filtered set contains font information.
34 if (attrs.ShouldEncode()) {
35 encoded_string->attributes()->push_back(attrs);
37 // Advance the iterator to the position outside of the effective range.
38 i = NSMaxRange(effective_range);
40 return encoded_string;
44 NSAttributedString* AttributedStringCoder::Decode(
45 const AttributedStringCoder::EncodedString* str) {
46 // Create the return value.
47 NSString* plain_text = base::SysUTF16ToNSString(str->string());
48 base::scoped_nsobject<NSMutableAttributedString> decoded_string(
49 [[NSMutableAttributedString alloc] initWithString:plain_text]);
50 // Iterate over all the encoded attributes, attaching each to the string.
51 const std::vector<FontAttribute> attributes = str->attributes();
52 for (std::vector<FontAttribute>::const_iterator it = attributes.begin();
53 it != attributes.end(); ++it) {
54 // Protect against ranges that are outside the range of the string.
55 const gfx::Range& range = it->effective_range();
56 if (range.GetMin() > [plain_text length] ||
57 range.GetMax() > [plain_text length]) {
60 [decoded_string addAttributes:it->ToAttributesDictionary()
61 range:range.ToNSRange()];
63 return [decoded_string.release() autorelease];
66 // Data Types //////////////////////////////////////////////////////////////////
68 AttributedStringCoder::EncodedString::EncodedString(base::string16 string)
72 AttributedStringCoder::EncodedString::EncodedString()
76 AttributedStringCoder::EncodedString::~EncodedString() {
79 AttributedStringCoder::FontAttribute::FontAttribute(NSDictionary* dict,
80 gfx::Range effective_range)
82 effective_range_(effective_range) {
83 NSFont* font = [dict objectForKey:NSFontAttributeName];
85 font_descriptor_ = FontDescriptor(font);
89 AttributedStringCoder::FontAttribute::FontAttribute(FontDescriptor font,
91 : font_descriptor_(font),
92 effective_range_(range) {
95 AttributedStringCoder::FontAttribute::FontAttribute()
100 AttributedStringCoder::FontAttribute::~FontAttribute() {
104 AttributedStringCoder::FontAttribute::ToAttributesDictionary() const {
105 DCHECK(ShouldEncode());
106 NSFont* font = font_descriptor_.ToNSFont();
108 return [NSDictionary dictionary];
109 return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
112 bool AttributedStringCoder::FontAttribute::ShouldEncode() const {
113 return !font_descriptor_.font_name.empty();
118 // IPC ParamTraits specialization //////////////////////////////////////////////
122 using mac::AttributedStringCoder;
124 void ParamTraits<AttributedStringCoder::EncodedString>::Write(
125 Message* m, const param_type& p) {
126 WriteParam(m, p.string());
127 WriteParam(m, p.attributes());
130 bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
132 base::PickleIterator* iter,
136 base::string16 result;
137 success &= ReadParam(m, iter, &result);
138 *p = AttributedStringCoder::EncodedString(result);
140 success &= ReadParam(m, iter, p->attributes());
144 void ParamTraits<AttributedStringCoder::EncodedString>::Log(
145 const param_type& p, std::string* l) {
146 l->append(base::UTF16ToUTF8(p.string()));
149 void ParamTraits<AttributedStringCoder::FontAttribute>::Write(
150 Message* m, const param_type& p) {
151 WriteParam(m, p.font_descriptor());
152 WriteParam(m, p.effective_range());
155 bool ParamTraits<AttributedStringCoder::FontAttribute>::Read(
157 base::PickleIterator* iter,
162 success &= ReadParam(m, iter, &font);
165 success &= ReadParam(m, iter, &range);
168 *p = AttributedStringCoder::FontAttribute(font, range);
173 void ParamTraits<AttributedStringCoder::FontAttribute>::Log(
174 const param_type& p, std::string* l) {