OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | |
7 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
8 #include "base/strings/string_tokenizer.h" | 9 #include "base/strings/string_tokenizer.h" |
9 #include "mojo/examples/media_viewer/media_viewer.mojom.h" | 10 #include "mojo/examples/media_viewer/media_viewer.mojom.h" |
10 #include "mojo/public/c/system/main.h" | 11 #include "mojo/public/c/system/main.h" |
11 #include "mojo/public/cpp/application/application_connection.h" | 12 #include "mojo/public/cpp/application/application_connection.h" |
12 #include "mojo/public/cpp/application/application_delegate.h" | 13 #include "mojo/public/cpp/application/application_delegate.h" |
14 #include "mojo/public/cpp/application/application_impl.h" | |
13 #include "mojo/public/cpp/application/application_runner_chromium.h" | 15 #include "mojo/public/cpp/application/application_runner_chromium.h" |
14 #include "mojo/public/cpp/application/interface_factory_impl.h" | 16 #include "mojo/public/cpp/application/interface_factory_impl.h" |
17 #include "mojo/public/cpp/application/service_provider_impl.h" | |
15 #include "mojo/services/public/cpp/view_manager/types.h" | 18 #include "mojo/services/public/cpp/view_manager/types.h" |
16 #include "mojo/services/public/cpp/view_manager/view.h" | 19 #include "mojo/services/public/cpp/view_manager/view.h" |
17 #include "mojo/services/public/cpp/view_manager/view_manager.h" | 20 #include "mojo/services/public/cpp/view_manager/view_manager.h" |
18 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" | 21 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" |
19 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" | 22 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" |
20 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 23 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
21 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h" | 24 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom. h" |
22 #include "skia/ext/platform_canvas.h" | 25 #include "skia/ext/platform_canvas.h" |
23 #include "skia/ext/refptr.h" | 26 #include "skia/ext/refptr.h" |
24 #include "third_party/skia/include/core/SkBitmap.h" | 27 #include "third_party/skia/include/core/SkBitmap.h" |
25 #include "third_party/skia/include/core/SkCanvas.h" | 28 #include "third_party/skia/include/core/SkCanvas.h" |
26 #include "third_party/skia/include/core/SkPaint.h" | 29 #include "third_party/skia/include/core/SkPaint.h" |
27 #include "third_party/skia/include/core/SkScalar.h" | 30 #include "third_party/skia/include/core/SkScalar.h" |
28 #include "ui/gfx/codec/png_codec.h" | 31 #include "ui/gfx/codec/png_codec.h" |
29 | 32 |
30 namespace mojo { | 33 namespace mojo { |
31 namespace examples { | 34 namespace examples { |
32 | 35 |
33 class PNGViewer; | 36 class PNGViewer; |
34 | 37 |
35 class ZoomableMediaImpl : public InterfaceImpl<ZoomableMedia> { | 38 // TODO(aa): Hook up ZoomableMedia interface again. |
39 class PNGView : public ViewManagerDelegate, | |
40 public ViewObserver { | |
36 public: | 41 public: |
37 explicit ZoomableMediaImpl(PNGViewer* viewer) : viewer_(viewer) {} | 42 PNGView(URLResponsePtr response, |
38 virtual ~ZoomableMediaImpl() {} | 43 ServiceProviderImpl* exported_services, |
44 scoped_ptr<ServiceProvider> imported_services, | |
45 Shell* shell) | |
46 : imported_services_(imported_services.Pass()), | |
47 root_(NULL), | |
48 view_manager_client_factory_(shell, this), | |
49 zoom_percentage_(kDefaultZoomPercentage) { | |
50 exported_services->AddService(&view_manager_client_factory_); | |
51 DecodePNG(response.Pass()); | |
52 } | |
39 | 53 |
40 private: | 54 private: |
41 // Overridden from ZoomableMedia: | 55 static const uint16_t kMaxZoomPercentage = 400; |
42 virtual void ZoomIn() OVERRIDE; | 56 static const uint16_t kMinZoomPercentage = 20; |
43 virtual void ZoomOut() OVERRIDE; | 57 static const uint16_t kDefaultZoomPercentage = 100; |
44 virtual void ZoomToActualSize() OVERRIDE; | 58 static const uint16_t kZoomStep = 20; |
45 | 59 |
46 PNGViewer* viewer_; | 60 virtual ~PNGView() { |
61 if (root_) | |
62 root_->RemoveObserver(this); | |
63 } | |
47 | 64 |
48 DISALLOW_COPY_AND_ASSIGN(ZoomableMediaImpl); | 65 // Overridden from ViewManagerDelegate: |
49 }; | 66 virtual void OnEmbed(ViewManager* view_manager, |
67 View* root, | |
68 ServiceProviderImpl* exported_services, | |
69 scoped_ptr<ServiceProvider> imported_services) OVERRIDE { | |
70 root_ = root; | |
71 root_->AddObserver(this); | |
72 root_->SetColor(SK_ColorGRAY); | |
73 if (!bitmap_.isNull()) | |
74 DrawBitmap(); | |
75 } | |
50 | 76 |
51 class NavigatorImpl : public InterfaceImpl<Navigator> { | 77 virtual void OnViewManagerDisconnected( |
52 public: | 78 ViewManager* view_manager) OVERRIDE { |
53 explicit NavigatorImpl(PNGViewer* viewer) : viewer_(viewer) {} | 79 // TODO(aa): Need to figure out how shutdown works. |
54 virtual ~NavigatorImpl() {} | 80 } |
55 | 81 |
56 private: | 82 // Overridden from ViewObserver: |
57 // Overridden from Navigator: | 83 virtual void OnViewBoundsChanged(View* view, |
58 virtual void Navigate( | 84 const gfx::Rect& old_bounds, |
59 uint32_t view_id, | 85 const gfx::Rect& new_bounds) OVERRIDE { |
60 NavigationDetailsPtr navigation_details, | 86 DCHECK_EQ(view, root_); |
61 ResponseDetailsPtr response_details) OVERRIDE { | 87 DrawBitmap(); |
62 int content_length = GetContentLength(response_details->response->headers); | 88 } |
63 unsigned char* data = new unsigned char[content_length]; | 89 |
64 unsigned char* buf = data; | 90 virtual void OnViewDestroyed(View* view) OVERRIDE { |
91 DCHECK_EQ(view, root_); | |
92 delete this; | |
93 } | |
94 | |
95 void DecodePNG(URLResponsePtr response) { | |
96 int content_length = GetContentLength(response->headers); | |
97 scoped_ptr<unsigned char[]> data(new unsigned char[content_length]); | |
98 unsigned char* buf = data.get(); | |
65 uint32_t bytes_remaining = content_length; | 99 uint32_t bytes_remaining = content_length; |
66 uint32_t num_bytes = bytes_remaining; | 100 uint32_t num_bytes = bytes_remaining; |
67 while (bytes_remaining > 0) { | 101 while (bytes_remaining > 0) { |
68 MojoResult result = ReadDataRaw( | 102 MojoResult result = ReadDataRaw(response->body.get(), |
69 response_details->response->body.get(), | 103 buf, |
70 buf, | 104 &num_bytes, |
71 &num_bytes, | 105 MOJO_READ_DATA_FLAG_NONE); |
72 MOJO_READ_DATA_FLAG_NONE); | |
73 if (result == MOJO_RESULT_SHOULD_WAIT) { | 106 if (result == MOJO_RESULT_SHOULD_WAIT) { |
74 Wait(response_details->response->body.get(), | 107 Wait(response->body.get(), |
75 MOJO_HANDLE_SIGNAL_READABLE, | 108 MOJO_HANDLE_SIGNAL_READABLE, |
76 MOJO_DEADLINE_INDEFINITE); | 109 MOJO_DEADLINE_INDEFINITE); |
77 } else if (result == MOJO_RESULT_OK) { | 110 } else if (result == MOJO_RESULT_OK) { |
78 buf += num_bytes; | 111 buf += num_bytes; |
79 num_bytes = bytes_remaining -= num_bytes; | 112 num_bytes = bytes_remaining -= num_bytes; |
80 } else { | 113 } else { |
81 break; | 114 break; |
82 } | 115 } |
83 } | 116 } |
84 | 117 |
85 SkBitmap bitmap; | 118 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()), |
86 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data), | 119 content_length, &bitmap_); |
87 content_length, &bitmap); | |
88 UpdateView(view_id, bitmap); | |
89 | |
90 delete[] data; | |
91 } | 120 } |
92 | 121 |
93 void UpdateView(Id view_id, const SkBitmap& bitmap); | 122 void DrawBitmap() { |
123 if (!root_) | |
124 return; | |
125 | |
126 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas( | |
127 root_->bounds().width(), | |
128 root_->bounds().height(), | |
129 true))); | |
130 canvas->drawColor(SK_ColorGRAY); | |
131 SkPaint paint; | |
132 SkScalar scale = | |
133 SkFloatToScalar(zoom_percentage_ * 1.0f / kDefaultZoomPercentage); | |
134 canvas->scale(scale, scale); | |
135 canvas->drawBitmap(bitmap_, 0, 0, &paint); | |
136 root_->SetContents(skia::GetTopDevice(*canvas)->accessBitmap(true)); | |
137 } | |
138 | |
139 void ZoomIn() { | |
140 if (zoom_percentage_ >= kMaxZoomPercentage) | |
141 return; | |
142 zoom_percentage_ += kZoomStep; | |
143 DrawBitmap(); | |
144 } | |
145 | |
146 void ZoomOut() { | |
147 if (zoom_percentage_ <= kMinZoomPercentage) | |
148 return; | |
149 zoom_percentage_ -= kZoomStep; | |
150 DrawBitmap(); | |
151 } | |
152 | |
153 void ZoomToActualSize() { | |
154 if (zoom_percentage_ == kDefaultZoomPercentage) | |
155 return; | |
156 zoom_percentage_ = kDefaultZoomPercentage; | |
157 DrawBitmap(); | |
158 } | |
94 | 159 |
95 int GetContentLength(const Array<String>& headers) { | 160 int GetContentLength(const Array<String>& headers) { |
96 for (size_t i = 0; i < headers.size(); ++i) { | 161 for (size_t i = 0; i < headers.size(); ++i) { |
97 base::StringTokenizer t(headers[i], ": ;="); | 162 base::StringTokenizer t(headers[i], ": ;="); |
98 while (t.GetNext()) { | 163 while (t.GetNext()) { |
99 if (!t.token_is_delim() && t.token() == "Content-Length") { | 164 if (!t.token_is_delim() && t.token() == "Content-Length") { |
100 while (t.GetNext()) { | 165 while (t.GetNext()) { |
101 if (!t.token_is_delim()) | 166 if (!t.token_is_delim()) |
102 return atoi(t.token().c_str()); | 167 return atoi(t.token().c_str()); |
103 } | 168 } |
104 } | 169 } |
105 } | 170 } |
106 } | 171 } |
107 return 0; | 172 return 0; |
108 } | 173 } |
109 | 174 |
110 PNGViewer* viewer_; | 175 SkBitmap bitmap_; |
176 scoped_ptr<ServiceProvider> imported_services_; | |
177 View* root_; | |
178 ViewManagerClientFactory view_manager_client_factory_; | |
179 uint16_t zoom_percentage_; | |
111 | 180 |
112 DISALLOW_COPY_AND_ASSIGN(NavigatorImpl); | 181 DISALLOW_COPY_AND_ASSIGN(PNGView); |
113 }; | 182 }; |
114 | 183 |
115 class PNGViewer | 184 class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { |
116 : public ApplicationDelegate, | |
117 public ViewManagerDelegate, | |
118 public ViewObserver { | |
119 public: | 185 public: |
120 PNGViewer() | 186 explicit ContentHandlerImpl(Shell* shell) |
121 : navigator_factory_(this), | 187 : shell_(shell) { |
122 zoomable_media_factory_(this), | 188 } |
123 view_manager_client_factory_(this), | 189 virtual ~ContentHandlerImpl() {} |
124 root_(NULL), | 190 |
125 zoom_percentage_(kDefaultZoomPercentage) {} | 191 private: |
126 virtual ~PNGViewer() { | 192 // Overridden from ContentHandler: |
127 if (root_) | 193 virtual void OnConnect( |
128 root_->RemoveObserver(this); | 194 const mojo::String& url, |
195 URLResponsePtr response, | |
196 InterfaceRequest<ServiceProvider> service_provider) OVERRIDE { | |
197 ServiceProviderImpl* exported_services = new ServiceProviderImpl(); | |
198 BindToRequest(exported_services, &service_provider); | |
199 scoped_ptr<ServiceProvider> remote( | |
200 exported_services->CreateRemoteServiceProvider()); | |
201 new PNGView(response.Pass(), exported_services, remote.Pass(), shell_); | |
darin (slow to review)
2014/09/04 21:33:51
nit: add a comment here about memory management?
Aaron Boodman
2014/09/05 02:41:31
Yeah good point -- instead, I made the ctor privat
| |
129 } | 202 } |
130 | 203 |
131 void UpdateView(Id view_id, const SkBitmap& bitmap) { | 204 Shell* shell_; |
132 bitmap_ = bitmap; | 205 |
133 zoom_percentage_ = kDefaultZoomPercentage; | 206 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); |
134 DrawBitmap(); | 207 }; |
208 | |
209 class PNGViewer : public ApplicationDelegate { | |
210 public: | |
211 PNGViewer() { | |
135 } | 212 } |
136 | 213 private: |
137 void ZoomIn() { | 214 // Overridden from ApplicationDelegate: |
138 if (zoom_percentage_ >= kMaxZoomPercentage) | 215 virtual void Initialize(ApplicationImpl* app) MOJO_OVERRIDE { |
139 return; | 216 content_handler_factory_.reset( |
darin (slow to review)
2014/09/04 21:33:51
food for thought...
it seems like it'd be possibl
Aaron Boodman
2014/09/04 22:31:43
I'm keeping it in mind. I wanted to flush things o
| |
140 zoom_percentage_ += kZoomStep; | 217 new InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell>( |
141 DrawBitmap(); | 218 app->shell())); |
142 } | 219 } |
143 | 220 |
144 void ZoomOut() { | |
145 if (zoom_percentage_ <= kMinZoomPercentage) | |
146 return; | |
147 zoom_percentage_ -= kZoomStep; | |
148 DrawBitmap(); | |
149 } | |
150 | |
151 void ZoomToActualSize() { | |
152 if (zoom_percentage_ == kDefaultZoomPercentage) | |
153 return; | |
154 zoom_percentage_ = kDefaultZoomPercentage; | |
155 DrawBitmap(); | |
156 } | |
157 | |
158 private: | |
159 static const uint16_t kMaxZoomPercentage = 400; | |
160 static const uint16_t kMinZoomPercentage = 20; | |
161 static const uint16_t kDefaultZoomPercentage = 100; | |
162 static const uint16_t kZoomStep = 20; | |
163 | |
164 // Overridden from ApplicationDelegate: | 221 // Overridden from ApplicationDelegate: |
165 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection) | 222 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection) |
166 MOJO_OVERRIDE { | 223 MOJO_OVERRIDE { |
167 connection->AddService(&navigator_factory_); | 224 connection->AddService(content_handler_factory_.get()); |
168 connection->AddService(&zoomable_media_factory_); | |
169 connection->AddService(&view_manager_client_factory_); | |
170 return true; | 225 return true; |
171 } | 226 } |
172 | 227 |
173 // Overridden from ViewManagerDelegate: | 228 scoped_ptr<InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell> > |
174 virtual void OnEmbed(ViewManager* view_manager, | 229 content_handler_factory_; |
175 View* root, | |
176 ServiceProviderImpl* exported_services, | |
177 scoped_ptr<ServiceProvider> imported_services) OVERRIDE { | |
178 root_ = root; | |
179 root_->AddObserver(this); | |
180 root_->SetColor(SK_ColorGRAY); | |
181 if (!bitmap_.isNull()) | |
182 DrawBitmap(); | |
183 } | |
184 virtual void OnViewManagerDisconnected( | |
185 ViewManager* view_manager) OVERRIDE { | |
186 base::MessageLoop::current()->Quit(); | |
187 } | |
188 | |
189 void DrawBitmap() { | |
190 if (!root_) | |
191 return; | |
192 | |
193 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas( | |
194 root_->bounds().width(), | |
195 root_->bounds().height(), | |
196 true))); | |
197 canvas->drawColor(SK_ColorGRAY); | |
198 SkPaint paint; | |
199 SkScalar scale = | |
200 SkFloatToScalar(zoom_percentage_ * 1.0f / kDefaultZoomPercentage); | |
201 canvas->scale(scale, scale); | |
202 canvas->drawBitmap(bitmap_, 0, 0, &paint); | |
203 root_->SetContents(skia::GetTopDevice(*canvas)->accessBitmap(true)); | |
204 } | |
205 | |
206 // ViewObserver: | |
207 virtual void OnViewBoundsChanged(View* view, | |
208 const gfx::Rect& old_bounds, | |
209 const gfx::Rect& new_bounds) OVERRIDE { | |
210 DCHECK_EQ(view, root_); | |
211 DrawBitmap(); | |
212 } | |
213 virtual void OnViewDestroyed(View* view) OVERRIDE { | |
214 DCHECK_EQ(view, root_); | |
215 view->RemoveObserver(this); | |
216 root_ = NULL; | |
217 } | |
218 | |
219 InterfaceFactoryImplWithContext<NavigatorImpl, PNGViewer> navigator_factory_; | |
220 InterfaceFactoryImplWithContext<ZoomableMediaImpl, PNGViewer> | |
221 zoomable_media_factory_; | |
222 ViewManagerClientFactory view_manager_client_factory_; | |
223 | |
224 View* root_; | |
225 SkBitmap bitmap_; | |
226 uint16_t zoom_percentage_; | |
227 | 230 |
228 DISALLOW_COPY_AND_ASSIGN(PNGViewer); | 231 DISALLOW_COPY_AND_ASSIGN(PNGViewer); |
229 }; | 232 }; |
230 | 233 |
231 void ZoomableMediaImpl::ZoomIn() { | |
232 viewer_->ZoomIn(); | |
233 } | |
234 | |
235 void ZoomableMediaImpl::ZoomOut() { | |
236 viewer_->ZoomOut(); | |
237 } | |
238 | |
239 void ZoomableMediaImpl::ZoomToActualSize() { | |
240 viewer_->ZoomToActualSize(); | |
241 } | |
242 | |
243 void NavigatorImpl::UpdateView(Id view_id, | |
244 const SkBitmap& bitmap) { | |
245 viewer_->UpdateView(view_id, bitmap); | |
246 } | |
247 | |
248 } // namespace examples | 234 } // namespace examples |
249 } // namespace mojo | 235 } // namespace mojo |
250 | 236 |
251 MojoResult MojoMain(MojoHandle shell_handle) { | 237 MojoResult MojoMain(MojoHandle shell_handle) { |
252 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer); | 238 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer); |
253 return runner.Run(shell_handle); | 239 return runner.Run(shell_handle); |
254 } | 240 } |
OLD | NEW |