blob: cde2b427389fad6c738289c1716ca2a471804764 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkWidget.h"
9#include "SkCanvas.h"
10#include "SkKey.h"
11#include "SkParsePaint.h"
12#include "SkSystemEventTypes.h"
13#include "SkTextBox.h"
14
15#if 0
16
17#ifdef SK_DEBUG
rmistry@google.comd6176b02012-08-23 18:14:13 +000018 static void assert_no_attr(const SkDOM& dom, const SkDOM::Node* node, const char attr[])
19 {
20 const char* value = dom.findAttr(node, attr);
21 if (value)
22 SkDebugf("unknown attribute %s=\"%s\"\n", attr, value);
23 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000024#else
rmistry@google.comd6176b02012-08-23 18:14:13 +000025 #define assert_no_attr(dom, node, attr)
reed@android.com8a1c16f2008-12-17 15:59:43 +000026#endif
27
28#include "SkAnimator.h"
29#include "SkTime.h"
30
31///////////////////////////////////////////////////////////////////////////////
32
33enum SkinType {
rmistry@google.comd6176b02012-08-23 18:14:13 +000034 kPushButton_SkinType,
35 kStaticText_SkinType,
reed@android.com8a1c16f2008-12-17 15:59:43 +000036
rmistry@google.comd6176b02012-08-23 18:14:13 +000037 kSkinTypeCount
reed@android.com8a1c16f2008-12-17 15:59:43 +000038};
39
40struct SkinSuite {
rmistry@google.comd6176b02012-08-23 18:14:13 +000041 SkinSuite();
42 ~SkinSuite()
43 {
44 for (int i = 0; i < kSkinTypeCount; i++)
45 delete fAnimators[i];
46 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000047
rmistry@google.comd6176b02012-08-23 18:14:13 +000048 SkAnimator* get(SkinType);
reed@android.com8a1c16f2008-12-17 15:59:43 +000049
50private:
rmistry@google.comd6176b02012-08-23 18:14:13 +000051 SkAnimator* fAnimators[kSkinTypeCount];
reed@android.com8a1c16f2008-12-17 15:59:43 +000052};
53
54SkinSuite::SkinSuite()
55{
rmistry@google.comd6176b02012-08-23 18:14:13 +000056 static const char kSkinPath[] = "skins/";
reed@android.com8a1c16f2008-12-17 15:59:43 +000057
rmistry@google.comd6176b02012-08-23 18:14:13 +000058 static const char* gSkinNames[] = {
59 "pushbutton_skin.xml",
60 "statictext_skin.xml"
61 };
reed@android.com8a1c16f2008-12-17 15:59:43 +000062
rmistry@google.comd6176b02012-08-23 18:14:13 +000063 for (unsigned i = 0; i < SK_ARRAY_COUNT(gSkinNames); i++)
64 {
65 size_t len = strlen(gSkinNames[i]);
66 SkString path(sizeof(kSkinPath) - 1 + len);
reed@android.com8a1c16f2008-12-17 15:59:43 +000067
rmistry@google.comd6176b02012-08-23 18:14:13 +000068 memcpy(path.writable_str(), kSkinPath, sizeof(kSkinPath) - 1);
69 memcpy(path.writable_str() + sizeof(kSkinPath) - 1, gSkinNames[i], len);
reed@android.com8a1c16f2008-12-17 15:59:43 +000070
rmistry@google.comd6176b02012-08-23 18:14:13 +000071 fAnimators[i] = new SkAnimator;
72 if (!fAnimators[i]->decodeURI(path.c_str()))
73 {
74 delete fAnimators[i];
75 fAnimators[i] = NULL;
76 }
77 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000078}
79
80SkAnimator* SkinSuite::get(SkinType st)
81{
rmistry@google.comd6176b02012-08-23 18:14:13 +000082 SkASSERT((unsigned)st < kSkinTypeCount);
83 return fAnimators[st];
reed@android.com8a1c16f2008-12-17 15:59:43 +000084}
85
86static SkinSuite* gSkinSuite;
87
88static SkAnimator* get_skin_animator(SkinType st)
89{
90#if 0
rmistry@google.comd6176b02012-08-23 18:14:13 +000091 if (gSkinSuite == NULL)
92 gSkinSuite = new SkinSuite;
93 return gSkinSuite->get(st);
reed@android.com8a1c16f2008-12-17 15:59:43 +000094#else
rmistry@google.comd6176b02012-08-23 18:14:13 +000095 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +000096#endif
97}
98
99///////////////////////////////////////////////////////////////////////////////
100
101void SkWidget::Init()
102{
103}
104
105void SkWidget::Term()
106{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000107 delete gSkinSuite;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108}
109
110void SkWidget::onEnabledChange()
111{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000112 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000113}
114
115void SkWidget::postWidgetEvent()
116{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000117 if (!fEvent.isType("") && this->hasListeners())
118 {
119 this->prepareWidgetEvent(&fEvent);
120 this->postToListeners(fEvent);
121 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122}
123
124void SkWidget::prepareWidgetEvent(SkEvent*)
125{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000126 // override in subclass to add any additional fields before posting
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127}
128
129void SkWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
130{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000131 this->INHERITED::onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132
rmistry@google.comd6176b02012-08-23 18:14:13 +0000133 if ((node = dom.getFirstChild(node, "event")) != NULL)
134 fEvent.inflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135}
136
137///////////////////////////////////////////////////////////////////////////////
138
139size_t SkHasLabelWidget::getLabel(SkString* str) const
140{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000141 if (str)
142 *str = fLabel;
143 return fLabel.size();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144}
145
146size_t SkHasLabelWidget::getLabel(char buffer[]) const
147{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 if (buffer)
149 memcpy(buffer, fLabel.c_str(), fLabel.size());
150 return fLabel.size();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151}
152
153void SkHasLabelWidget::setLabel(const SkString& str)
154{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000155 this->setLabel(str.c_str(), str.size());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156}
157
158void SkHasLabelWidget::setLabel(const char label[])
159{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000160 this->setLabel(label, strlen(label));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161}
162
163void SkHasLabelWidget::setLabel(const char label[], size_t len)
164{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165 if (!fLabel.equals(label, len))
166 {
167 fLabel.set(label, len);
168 this->onLabelChange();
169 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170}
171
172void SkHasLabelWidget::onLabelChange()
173{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000174 // override in subclass
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175}
176
177void SkHasLabelWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
178{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000179 this->INHERITED::onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181 const char* text = dom.findAttr(node, "label");
182 if (text)
183 this->setLabel(text);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184}
185
186/////////////////////////////////////////////////////////////////////////////////////
187
188void SkButtonWidget::setButtonState(State state)
189{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000190 if (fState != state)
191 {
192 fState = state;
193 this->onButtonStateChange();
194 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195}
196
197void SkButtonWidget::onButtonStateChange()
198{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000199 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200}
201
202void SkButtonWidget::onInflate(const SkDOM& dom, const SkDOM::Node* node)
203{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000204 this->INHERITED::onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205
rmistry@google.comd6176b02012-08-23 18:14:13 +0000206 int index;
207 if ((index = dom.findList(node, "buttonState", "off,on,unknown")) >= 0)
208 this->setButtonState((State)index);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209}
210
211/////////////////////////////////////////////////////////////////////////////////////
212
213bool SkPushButtonWidget::onEvent(const SkEvent& evt)
214{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000215 if (evt.isType(SK_EventType_Key) && evt.getFast32() == kOK_SkKey)
216 {
217 this->postWidgetEvent();
218 return true;
219 }
220 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000221}
222
223static const char* computeAnimatorState(int enabled, int focused, SkButtonWidget::State state)
224{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000225 if (!enabled)
226 return "disabled";
227 if (state == SkButtonWidget::kOn_State)
228 {
229 SkASSERT(focused);
230 return "enabled-pressed";
231 }
232 if (focused)
233 return "enabled-focused";
234 return "enabled";
reed@android.com8a1c16f2008-12-17 15:59:43 +0000235}
236
commit-bot@chromium.org7c9d0f32014-02-21 10:13:32 +0000237#include "SkBlurMask.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238#include "SkBlurMaskFilter.h"
239#include "SkEmbossMaskFilter.h"
240
241static void create_emboss(SkPaint* paint, SkScalar radius, bool focus, bool pressed)
242{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000243 SkEmbossMaskFilter::Light light;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244
rmistry@google.comd6176b02012-08-23 18:14:13 +0000245 light.fDirection[0] = SK_Scalar1/2;
246 light.fDirection[1] = SK_Scalar1/2;
247 light.fDirection[2] = SK_Scalar1/3;
248 light.fAmbient = 0x48;
249 light.fSpecular = 0x80;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250
rmistry@google.comd6176b02012-08-23 18:14:13 +0000251 if (pressed)
252 {
253 light.fDirection[0] = -light.fDirection[0];
254 light.fDirection[1] = -light.fDirection[1];
255 }
256 if (focus)
257 light.fDirection[2] += SK_Scalar1/4;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258
commit-bot@chromium.org7c9d0f32014-02-21 10:13:32 +0000259 SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
260 paint->setMaskFilter(new SkEmbossMaskFilter(sigma, light))->unref();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261}
262
263void SkPushButtonWidget::onDraw(SkCanvas* canvas)
264{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000265 this->INHERITED::onDraw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266
rmistry@google.comd6176b02012-08-23 18:14:13 +0000267 SkString label;
268 this->getLabel(&label);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269
rmistry@google.comd6176b02012-08-23 18:14:13 +0000270 SkAnimator* anim = get_skin_animator(kPushButton_SkinType);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000271
rmistry@google.comd6176b02012-08-23 18:14:13 +0000272 if (anim)
273 {
274 SkEvent evt("user");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275
rmistry@google.comd6176b02012-08-23 18:14:13 +0000276 evt.setString("id", "prime");
277 evt.setScalar("prime-width", this->width());
278 evt.setScalar("prime-height", this->height());
279 evt.setString("prime-text", label);
280 evt.setString("prime-state", computeAnimatorState(this->isEnabled(), this->hasFocus(), this->getButtonState()));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281
rmistry@google.comd6176b02012-08-23 18:14:13 +0000282 (void)anim->doUserEvent(evt);
283 SkPaint paint;
284 anim->draw(canvas, &paint, SkTime::GetMSecs());
285 }
286 else
287 {
288 SkRect r;
289 SkPaint p;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000290
rmistry@google.comd6176b02012-08-23 18:14:13 +0000291 r.set(0, 0, this->width(), this->height());
292 p.setAntiAliasOn(true);
293 p.setColor(SK_ColorBLUE);
294 create_emboss(&p, SkIntToScalar(12)/5, this->hasFocus(), this->getButtonState() == kOn_State);
295 canvas->drawRoundRect(r, SkScalarHalf(this->height()), SkScalarHalf(this->height()), p);
296 p.setMaskFilter(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000297
rmistry@google.comd6176b02012-08-23 18:14:13 +0000298 p.setTextAlign(SkPaint::kCenter_Align);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299
rmistry@google.comd6176b02012-08-23 18:14:13 +0000300 SkTextBox box;
301 box.setMode(SkTextBox::kOneLine_Mode);
302 box.setSpacingAlign(SkTextBox::kCenter_SpacingAlign);
303 box.setBox(0, 0, this->width(), this->height());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000304
rmistry@google.comd6176b02012-08-23 18:14:13 +0000305// if (this->getButtonState() == kOn_State)
306// p.setColor(SK_ColorRED);
307// else
308 p.setColor(SK_ColorWHITE);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000309
rmistry@google.comd6176b02012-08-23 18:14:13 +0000310 box.draw(canvas, label.c_str(), label.size(), p);
311 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000312}
313
sugoi@google.com9c55f802013-03-07 20:52:59 +0000314SkView::Click* SkPushButtonWidget::onFindClickHandler(SkScalar x, SkScalar y, unsigned modi)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000316 this->acceptFocus();
317 return new Click(this);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000318}
319
320bool SkPushButtonWidget::onClick(Click* click)
321{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000322 SkRect r;
323 State state = kOff_State;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000324
rmistry@google.comd6176b02012-08-23 18:14:13 +0000325 this->getLocalBounds(&r);
326 if (r.contains(click->fCurr))
327 {
328 if (click->fState == Click::kUp_State)
329 this->postWidgetEvent();
330 else
331 state = kOn_State;
332 }
333 this->setButtonState(state);
334 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000335}
336
337//////////////////////////////////////////////////////////////////////////////////////////
338
339SkStaticTextView::SkStaticTextView(U32 flags) : SkView(flags)
340{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000341 fMargin.set(0, 0);
342 fMode = kFixedSize_Mode;
343 fSpacingAlign = SkTextBox::kStart_SpacingAlign;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344}
345
346SkStaticTextView::~SkStaticTextView()
347{
348}
349
350void SkStaticTextView::computeSize()
351{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000352 if (fMode == kAutoWidth_Mode)
353 {
354 SkScalar width = fPaint.measureText(fText.c_str(), fText.size(), NULL, NULL);
355 this->setWidth(width + fMargin.fX * 2);
356 }
357 else if (fMode == kAutoHeight_Mode)
358 {
359 SkScalar width = this->width() - fMargin.fX * 2;
360 int lines = width > 0 ? SkTextLineBreaker::CountLines(fText.c_str(), fText.size(), fPaint, width) : 0;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000361
rmistry@google.comd6176b02012-08-23 18:14:13 +0000362 SkScalar before, after;
363 (void)fPaint.measureText(0, NULL, &before, &after);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000364
rmistry@google.comd6176b02012-08-23 18:14:13 +0000365 this->setHeight(lines * (after - before) + fMargin.fY * 2);
366 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000367}
368
369void SkStaticTextView::setMode(Mode mode)
370{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000371 SkASSERT((unsigned)mode < kModeCount);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000372
rmistry@google.comd6176b02012-08-23 18:14:13 +0000373 if (fMode != mode)
374 {
375 fMode = SkToU8(mode);
376 this->computeSize();
377 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378}
379
380void SkStaticTextView::setSpacingAlign(SkTextBox::SpacingAlign align)
381{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000382 fSpacingAlign = SkToU8(align);
383 this->inval(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000384}
385
386void SkStaticTextView::getMargin(SkPoint* margin) const
387{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000388 if (margin)
389 *margin = fMargin;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000390}
391
392void SkStaticTextView::setMargin(SkScalar dx, SkScalar dy)
393{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000394 if (fMargin.fX != dx || fMargin.fY != dy)
395 {
396 fMargin.set(dx, dy);
397 this->computeSize();
398 this->inval(NULL);
399 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000400}
401
402size_t SkStaticTextView::getText(SkString* text) const
403{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000404 if (text)
405 *text = fText;
406 return fText.size();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000407}
408
409size_t SkStaticTextView::getText(char text[]) const
410{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000411 if (text)
412 memcpy(text, fText.c_str(), fText.size());
413 return fText.size();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000414}
415
416void SkStaticTextView::setText(const SkString& text)
417{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000418 this->setText(text.c_str(), text.size());
reed@android.com8a1c16f2008-12-17 15:59:43 +0000419}
420
421void SkStaticTextView::setText(const char text[])
422{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000423 this->setText(text, strlen(text));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000424}
425
426void SkStaticTextView::setText(const char text[], size_t len)
427{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000428 if (!fText.equals(text, len))
429 {
430 fText.set(text, len);
431 this->computeSize();
432 this->inval(NULL);
433 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000434}
435
436void SkStaticTextView::getPaint(SkPaint* paint) const
437{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000438 if (paint)
439 *paint = fPaint;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000440}
441
442void SkStaticTextView::setPaint(const SkPaint& paint)
443{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000444 if (fPaint != paint)
445 {
446 fPaint = paint;
447 this->computeSize();
448 this->inval(NULL);
449 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000450}
451
452void SkStaticTextView::onDraw(SkCanvas* canvas)
453{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000454 this->INHERITED::onDraw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000455
rmistry@google.comd6176b02012-08-23 18:14:13 +0000456 if (fText.isEmpty())
457 return;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000458
rmistry@google.comd6176b02012-08-23 18:14:13 +0000459 SkTextBox box;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000460
rmistry@google.comd6176b02012-08-23 18:14:13 +0000461 box.setMode(fMode == kAutoWidth_Mode ? SkTextBox::kOneLine_Mode : SkTextBox::kLineBreak_Mode);
462 box.setSpacingAlign(this->getSpacingAlign());
463 box.setBox(fMargin.fX, fMargin.fY, this->width() - fMargin.fX, this->height() - fMargin.fY);
464 box.draw(canvas, fText.c_str(), fText.size(), fPaint);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000465}
466
467void SkStaticTextView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
468{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000469 this->INHERITED::onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000470
rmistry@google.comd6176b02012-08-23 18:14:13 +0000471 int index;
472 if ((index = dom.findList(node, "mode", "fixed,auto-width,auto-height")) >= 0)
473 this->setMode((Mode)index);
474 else
475 assert_no_attr(dom, node, "mode");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000476
rmistry@google.comd6176b02012-08-23 18:14:13 +0000477 if ((index = dom.findList(node, "spacing-align", "start,center,end")) >= 0)
478 this->setSpacingAlign((SkTextBox::SpacingAlign)index);
479 else
480 assert_no_attr(dom, node, "mode");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000481
rmistry@google.comd6176b02012-08-23 18:14:13 +0000482 SkScalar s[2];
483 if (dom.findScalars(node, "margin", s, 2))
484 this->setMargin(s[0], s[1]);
485 else
486 assert_no_attr(dom, node, "margin");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000487
rmistry@google.comd6176b02012-08-23 18:14:13 +0000488 const char* text = dom.findAttr(node, "text");
489 if (text)
490 this->setText(text);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000491
rmistry@google.comd6176b02012-08-23 18:14:13 +0000492 if ((node = dom.getFirstChild(node, "paint")) != NULL)
493 SkPaint_Inflate(&fPaint, dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000494}
495
496/////////////////////////////////////////////////////////////////////////////////////////////////////
497
498#include "SkImageDecoder.h"
499
500SkBitmapView::SkBitmapView(U32 flags) : SkView(flags)
501{
502}
503
504SkBitmapView::~SkBitmapView()
505{
506}
507
508bool SkBitmapView::getBitmap(SkBitmap* bitmap) const
509{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000510 if (bitmap)
511 *bitmap = fBitmap;
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +0000512 return fBitmap.colorType() != kUnknown_SkColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000513}
514
515void SkBitmapView::setBitmap(const SkBitmap* bitmap, bool viewOwnsPixels)
516{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000517 if (bitmap)
518 {
519 fBitmap = *bitmap;
520 fBitmap.setOwnsPixels(viewOwnsPixels);
521 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000522}
523
524bool SkBitmapView::loadBitmapFromFile(const char path[])
525{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000526 SkBitmap bitmap;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000527
rmistry@google.comd6176b02012-08-23 18:14:13 +0000528 if (SkImageDecoder::DecodeFile(path, &bitmap))
529 {
530 this->setBitmap(&bitmap, true);
531 bitmap.setOwnsPixels(false);
532 return true;
533 }
534 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000535}
536
537void SkBitmapView::onDraw(SkCanvas* canvas)
538{
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +0000539 if (fBitmap.colorType() != kUnknown_SkColorType &&
rmistry@google.comd6176b02012-08-23 18:14:13 +0000540 fBitmap.width() && fBitmap.height())
541 {
542 SkAutoCanvasRestore restore(canvas, true);
543 SkPaint p;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000544
rmistry@google.comd6176b02012-08-23 18:14:13 +0000545 p.setFilterType(SkPaint::kBilinear_FilterType);
546 canvas->scale( this->width() / fBitmap.width(),
547 this->height() / fBitmap.height(),
548 0, 0);
549 canvas->drawBitmap(fBitmap, 0, 0, p);
550 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000551}
552
553void SkBitmapView::onInflate(const SkDOM& dom, const SkDOM::Node* node)
554{
rmistry@google.comd6176b02012-08-23 18:14:13 +0000555 this->INHERITED::onInflate(dom, node);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000556
rmistry@google.comd6176b02012-08-23 18:14:13 +0000557 const char* src = dom.findAttr(node, "src");
558 if (src)
559 (void)this->loadBitmapFromFile(src);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000560}
561
562#endif