• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5#include "content/common/mac/attributed_string_coder.h"
6
7#include <AppKit/AppKit.h>
8
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/view_messages.h"
14#include "content/public/common/common_param_traits.h"
15#include "ipc/ipc_message_utils.h"
16
17namespace mac {
18
19// static
20const 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);
36    }
37    // Advance the iterator to the position outside of the effective range.
38    i = NSMaxRange(effective_range);
39  }
40  return encoded_string;
41}
42
43// static
44NSAttributedString* 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]) {
58      continue;
59    }
60    [decoded_string addAttributes:it->ToAttributesDictionary()
61                            range:range.ToNSRange()];
62  }
63  return [decoded_string.release() autorelease];
64}
65
66// Data Types //////////////////////////////////////////////////////////////////
67
68AttributedStringCoder::EncodedString::EncodedString(base::string16 string)
69    : string_(string) {
70}
71
72AttributedStringCoder::EncodedString::EncodedString()
73    : string_() {
74}
75
76AttributedStringCoder::EncodedString::~EncodedString() {
77}
78
79AttributedStringCoder::FontAttribute::FontAttribute(NSDictionary* dict,
80                                                    gfx::Range effective_range)
81    : font_descriptor_(),
82      effective_range_(effective_range) {
83  NSFont* font = [dict objectForKey:NSFontAttributeName];
84  if (font) {
85    font_descriptor_ = FontDescriptor(font);
86  }
87}
88
89AttributedStringCoder::FontAttribute::FontAttribute(FontDescriptor font,
90                                                    gfx::Range range)
91    : font_descriptor_(font),
92      effective_range_(range) {
93}
94
95AttributedStringCoder::FontAttribute::FontAttribute()
96    : font_descriptor_(),
97      effective_range_() {
98}
99
100AttributedStringCoder::FontAttribute::~FontAttribute() {
101}
102
103NSDictionary* AttributedStringCoder::FontAttribute::ToAttributesDictionary(
104    void) const {
105  DCHECK(ShouldEncode());
106  NSFont* font = font_descriptor_.ToNSFont();
107  return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
108}
109
110bool AttributedStringCoder::FontAttribute::ShouldEncode() const {
111  return !font_descriptor_.font_name.empty();
112}
113
114}  // namespace mac
115
116// IPC ParamTraits specialization //////////////////////////////////////////////
117
118namespace IPC {
119
120using mac::AttributedStringCoder;
121
122void ParamTraits<AttributedStringCoder::EncodedString>::Write(
123    Message* m, const param_type& p) {
124  WriteParam(m, p.string());
125  WriteParam(m, p.attributes());
126}
127
128bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
129    const Message* m, PickleIterator* iter, param_type* p) {
130  bool success = true;
131
132  base::string16 result;
133  success &= ReadParam(m, iter, &result);
134  *p = AttributedStringCoder::EncodedString(result);
135
136  success &= ReadParam(m, iter, p->attributes());
137  return success;
138}
139
140void ParamTraits<AttributedStringCoder::EncodedString>::Log(
141    const param_type& p, std::string* l) {
142  l->append(base::UTF16ToUTF8(p.string()));
143}
144
145void ParamTraits<AttributedStringCoder::FontAttribute>::Write(
146    Message* m, const param_type& p) {
147  WriteParam(m, p.font_descriptor());
148  WriteParam(m, p.effective_range());
149}
150
151bool ParamTraits<AttributedStringCoder::FontAttribute>::Read(
152    const Message* m, PickleIterator* iter, param_type* p) {
153  bool success = true;
154
155  FontDescriptor font;
156  success &= ReadParam(m, iter, &font);
157
158  gfx::Range range;
159  success &= ReadParam(m, iter, &range);
160
161  if (success) {
162    *p = AttributedStringCoder::FontAttribute(font, range);
163  }
164  return success;
165}
166
167void ParamTraits<AttributedStringCoder::FontAttribute>::Log(
168    const param_type& p, std::string* l) {
169}
170
171}  // namespace IPC
172