1197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch 2197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch/* 3197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch * Copyright 2011 Google Inc. 453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be 653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * found in the LICENSE file. 793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) */ 893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "SkImageView.h" 953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "SkAnimator.h" 10aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkBitmap.h" 11aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkCanvas.h" 12aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkImageDecoder.h" 13aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkMatrix.h" 14aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkSystemEventTypes.h" 15aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#include "SkTime.h" 16aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch 17aafa69cb17c9d6606c07663ade5f81388a2c5986Ben MurdochSkImageView::SkImageView() 1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fMatrix = NULL; 2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fScaleType = kMatrix_ScaleType; 2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) fData.fAnim = NULL; // handles initializing the other union values 2393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fDataIsAnim = true; 2493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fUriIsValid = false; // an empty string is not valid 2693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 2793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)SkImageView::~SkImageView() 2993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 3093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (fMatrix) 3193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) sk_free(fMatrix); 3293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) this->freeData(); 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 3693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SkImageView::getUri(SkString* uri) const 3793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if (uri) 3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *uri = fUri; 4093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 4193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 4293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SkImageView::setUri(const char uri[]) 4393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 4493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (!fUri.equals(uri)) 4593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 4693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fUri.set(uri); 47aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch this->onUriChange(); 4893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 4993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 5093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 5193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SkImageView::setUri(const SkString& uri) 5293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 5393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (fUri != uri) 5493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 5593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fUri = uri; 5693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) this->onUriChange(); 5793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 5893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SkImageView::setScaleType(ScaleType st) 6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 6293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) SkASSERT((unsigned)st <= kFitEnd_ScaleType); 6393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) if ((ScaleType)fScaleType != st) 6593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fScaleType = SkToU8(st); 6793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (fUriIsValid) 6893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) this->inval(NULL); 6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 7193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 7293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)bool SkImageView::getImageMatrix(SkMatrix* matrix) const 73aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch{ 74aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch if (fMatrix) 75aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch { 7693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) SkASSERT(!fMatrix->isIdentity()); 7793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (matrix) 7893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *matrix = *fMatrix; 79aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch return true; 80aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch } 81aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch else 8293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 8393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (matrix) 8493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) matrix->reset(); 8593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) return false; 8693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 8793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 8893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 8993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SkImageView::setImageMatrix(const SkMatrix* matrix) 9093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){ 9193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) bool changed = false; 9293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 9393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (matrix && !matrix->isIdentity()) 9493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 9593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (fMatrix == NULL) 9693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); 9793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *fMatrix = *matrix; 9893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) changed = true; 9993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 10093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) else // set us to identity 10193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 10293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (fMatrix) 10393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) { 10493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) SkASSERT(!fMatrix->isIdentity()); 10593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) sk_free(fMatrix); 10693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) fMatrix = NULL; 10793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) changed = true; 10893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 10993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) } 11093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 11193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) // only redraw if we changed our matrix and we're not in scaleToFit mode 11293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) if (changed && this->getScaleType() == kMatrix_ScaleType && fUriIsValid) 11393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) this->inval(NULL); 11493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)} 11593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) 11693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)/////////////////////////////////////////////////////////////////////////////////////////////// 11753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 118aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdochbool SkImageView::onEvent(const SkEvent& evt) 119{ 120 if (evt.isType(SK_EventType_Inval)) 121 { 122 if (fUriIsValid) 123 this->inval(NULL); 124 return true; 125 } 126 return this->INHERITED::onEvent(evt); 127} 128 129static inline SkMatrix::ScaleToFit scaleTypeToScaleToFit(SkImageView::ScaleType st) 130{ 131 SkASSERT(st != SkImageView::kMatrix_ScaleType); 132 SkASSERT((unsigned)st <= SkImageView::kFitEnd_ScaleType); 133 134 SkASSERT(SkImageView::kFitXY_ScaleType - 1 == SkMatrix::kFill_ScaleToFit); 135 SkASSERT(SkImageView::kFitStart_ScaleType - 1 == SkMatrix::kStart_ScaleToFit); 136 SkASSERT(SkImageView::kFitCenter_ScaleType - 1 == SkMatrix::kCenter_ScaleToFit); 137 SkASSERT(SkImageView::kFitEnd_ScaleType - 1 == SkMatrix::kEnd_ScaleToFit); 138 139 return (SkMatrix::ScaleToFit)(st - 1); 140} 141 142void SkImageView::onDraw(SkCanvas* canvas) 143{ 144 SkRect src; 145 if (!this->getDataBounds(&src)) 146 { 147 SkDEBUGCODE(canvas->drawColor(SK_ColorRED);) 148 return; // nothing to draw 149 } 150 151 SkAutoCanvasRestore restore(canvas, true); 152 SkMatrix matrix; 153 154 if (this->getScaleType() == kMatrix_ScaleType) 155 (void)this->getImageMatrix(&matrix); 156 else 157 { 158 SkRect dst; 159 dst.set(0, 0, this->width(), this->height()); 160 matrix.setRectToRect(src, dst, scaleTypeToScaleToFit(this->getScaleType())); 161 } 162 canvas->concat(matrix); 163 164 SkPaint paint; 165 166 paint.setAntiAlias(true); 167 168 if (fDataIsAnim) 169 { 170 SkMSec now = SkTime::GetMSecs(); 171 172 SkAnimator::DifferenceType diff = fData.fAnim->draw(canvas, &paint, now); 173 174SkDEBUGF(("SkImageView : now = %X[%12.3f], diff = %d\n", now, now/1000., diff)); 175 176 if (diff == SkAnimator::kDifferent) 177 this->inval(NULL); 178 else if (diff == SkAnimator::kPartiallyDifferent) 179 { 180 SkRect bounds; 181 fData.fAnim->getInvalBounds(&bounds); 182 matrix.mapRect(&bounds); // get the bounds into view coordinates 183 this->inval(&bounds); 184 } 185 } 186 else 187 canvas->drawBitmap(*fData.fBitmap, 0, 0, &paint); 188} 189 190void SkImageView::onInflate(const SkDOM& dom, const SkDOMNode* node) 191{ 192 this->INHERITED::onInflate(dom, node); 193 194 const char* src = dom.findAttr(node, "src"); 195 if (src) 196 this->setUri(src); 197 198 int index = dom.findList(node, "scaleType", "matrix,fitXY,fitStart,fitCenter,fitEnd"); 199 if (index >= 0) 200 this->setScaleType((ScaleType)index); 201 202 // need inflate syntax/reader for matrix 203} 204 205///////////////////////////////////////////////////////////////////////////////////// 206 207void SkImageView::onUriChange() 208{ 209 if (this->freeData()) 210 this->inval(NULL); 211 fUriIsValid = true; // give ensureUriIsLoaded() a shot at the new uri 212} 213 214bool SkImageView::freeData() 215{ 216 if (fData.fAnim) // test is valid for all union values 217 { 218 if (fDataIsAnim) 219 delete fData.fAnim; 220 else 221 delete fData.fBitmap; 222 223 fData.fAnim = NULL; // valid for all union values 224 return true; 225 } 226 return false; 227} 228 229bool SkImageView::getDataBounds(SkRect* bounds) 230{ 231 SkASSERT(bounds); 232 233 if (this->ensureUriIsLoaded()) 234 { 235 SkScalar width, height; 236 237 if (fDataIsAnim) 238 { 239 if (SkScalarIsNaN(width = fData.fAnim->getScalar("dimensions", "x")) || 240 SkScalarIsNaN(height = fData.fAnim->getScalar("dimensions", "y"))) 241 { 242 // cons up fake bounds 243 width = this->width(); 244 height = this->height(); 245 } 246 } 247 else 248 { 249 width = SkIntToScalar(fData.fBitmap->width()); 250 height = SkIntToScalar(fData.fBitmap->height()); 251 } 252 bounds->set(0, 0, width, height); 253 return true; 254 } 255 return false; 256} 257 258bool SkImageView::ensureUriIsLoaded() 259{ 260 if (fData.fAnim) // test is valid for all union values 261 { 262 SkASSERT(fUriIsValid); 263 return true; 264 } 265 if (!fUriIsValid) 266 return false; 267 268 // try to load the url 269 if (fUri.endsWith(".xml")) // assume it is screenplay 270 { 271 SkAnimator* anim = new SkAnimator; 272 273 if (!anim->decodeURI(fUri.c_str())) 274 { 275 delete anim; 276 fUriIsValid = false; 277 return false; 278 } 279 anim->setHostEventSink(this); 280 281 fData.fAnim = anim; 282 fDataIsAnim = true; 283 } 284 else // assume it is an image format 285 { 286 #if 0 287 SkBitmap* bitmap = new SkBitmap; 288 289 if (!SkImageDecoder::DecodeURL(fUri.c_str(), bitmap)) 290 { 291 delete bitmap; 292 fUriIsValid = false; 293 return false; 294 } 295 fData.fBitmap = bitmap; 296 fDataIsAnim = false; 297 #else 298 return false; 299 #endif 300 } 301 return true; 302} 303