1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/views/animated/SkImageView.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,302 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkImageView.h" 1.12 +#include "SkAnimator.h" 1.13 +#include "SkBitmap.h" 1.14 +#include "SkCanvas.h" 1.15 +#include "SkImageDecoder.h" 1.16 +#include "SkMatrix.h" 1.17 +#include "SkSystemEventTypes.h" 1.18 +#include "SkTime.h" 1.19 + 1.20 +SkImageView::SkImageView() 1.21 +{ 1.22 + fMatrix = NULL; 1.23 + fScaleType = kMatrix_ScaleType; 1.24 + 1.25 + fData.fAnim = NULL; // handles initializing the other union values 1.26 + fDataIsAnim = true; 1.27 + 1.28 + fUriIsValid = false; // an empty string is not valid 1.29 +} 1.30 + 1.31 +SkImageView::~SkImageView() 1.32 +{ 1.33 + if (fMatrix) 1.34 + sk_free(fMatrix); 1.35 + 1.36 + this->freeData(); 1.37 +} 1.38 + 1.39 +void SkImageView::getUri(SkString* uri) const 1.40 +{ 1.41 + if (uri) 1.42 + *uri = fUri; 1.43 +} 1.44 + 1.45 +void SkImageView::setUri(const char uri[]) 1.46 +{ 1.47 + if (!fUri.equals(uri)) 1.48 + { 1.49 + fUri.set(uri); 1.50 + this->onUriChange(); 1.51 + } 1.52 +} 1.53 + 1.54 +void SkImageView::setUri(const SkString& uri) 1.55 +{ 1.56 + if (fUri != uri) 1.57 + { 1.58 + fUri = uri; 1.59 + this->onUriChange(); 1.60 + } 1.61 +} 1.62 + 1.63 +void SkImageView::setScaleType(ScaleType st) 1.64 +{ 1.65 + SkASSERT((unsigned)st <= kFitEnd_ScaleType); 1.66 + 1.67 + if ((ScaleType)fScaleType != st) 1.68 + { 1.69 + fScaleType = SkToU8(st); 1.70 + if (fUriIsValid) 1.71 + this->inval(NULL); 1.72 + } 1.73 +} 1.74 + 1.75 +bool SkImageView::getImageMatrix(SkMatrix* matrix) const 1.76 +{ 1.77 + if (fMatrix) 1.78 + { 1.79 + SkASSERT(!fMatrix->isIdentity()); 1.80 + if (matrix) 1.81 + *matrix = *fMatrix; 1.82 + return true; 1.83 + } 1.84 + else 1.85 + { 1.86 + if (matrix) 1.87 + matrix->reset(); 1.88 + return false; 1.89 + } 1.90 +} 1.91 + 1.92 +void SkImageView::setImageMatrix(const SkMatrix* matrix) 1.93 +{ 1.94 + bool changed = false; 1.95 + 1.96 + if (matrix && !matrix->isIdentity()) 1.97 + { 1.98 + if (fMatrix == NULL) 1.99 + fMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); 1.100 + *fMatrix = *matrix; 1.101 + changed = true; 1.102 + } 1.103 + else // set us to identity 1.104 + { 1.105 + if (fMatrix) 1.106 + { 1.107 + SkASSERT(!fMatrix->isIdentity()); 1.108 + sk_free(fMatrix); 1.109 + fMatrix = NULL; 1.110 + changed = true; 1.111 + } 1.112 + } 1.113 + 1.114 + // only redraw if we changed our matrix and we're not in scaleToFit mode 1.115 + if (changed && this->getScaleType() == kMatrix_ScaleType && fUriIsValid) 1.116 + this->inval(NULL); 1.117 +} 1.118 + 1.119 +/////////////////////////////////////////////////////////////////////////////////////////////// 1.120 + 1.121 +bool SkImageView::onEvent(const SkEvent& evt) 1.122 +{ 1.123 + if (evt.isType(SK_EventType_Inval)) 1.124 + { 1.125 + if (fUriIsValid) 1.126 + this->inval(NULL); 1.127 + return true; 1.128 + } 1.129 + return this->INHERITED::onEvent(evt); 1.130 +} 1.131 + 1.132 +static inline SkMatrix::ScaleToFit scaleTypeToScaleToFit(SkImageView::ScaleType st) 1.133 +{ 1.134 + SkASSERT(st != SkImageView::kMatrix_ScaleType); 1.135 + SkASSERT((unsigned)st <= SkImageView::kFitEnd_ScaleType); 1.136 + 1.137 + SkASSERT(SkImageView::kFitXY_ScaleType - 1 == SkMatrix::kFill_ScaleToFit); 1.138 + SkASSERT(SkImageView::kFitStart_ScaleType - 1 == SkMatrix::kStart_ScaleToFit); 1.139 + SkASSERT(SkImageView::kFitCenter_ScaleType - 1 == SkMatrix::kCenter_ScaleToFit); 1.140 + SkASSERT(SkImageView::kFitEnd_ScaleType - 1 == SkMatrix::kEnd_ScaleToFit); 1.141 + 1.142 + return (SkMatrix::ScaleToFit)(st - 1); 1.143 +} 1.144 + 1.145 +void SkImageView::onDraw(SkCanvas* canvas) 1.146 +{ 1.147 + SkRect src; 1.148 + if (!this->getDataBounds(&src)) 1.149 + { 1.150 + SkDEBUGCODE(canvas->drawColor(SK_ColorRED);) 1.151 + return; // nothing to draw 1.152 + } 1.153 + 1.154 + SkAutoCanvasRestore restore(canvas, true); 1.155 + SkMatrix matrix; 1.156 + 1.157 + if (this->getScaleType() == kMatrix_ScaleType) 1.158 + (void)this->getImageMatrix(&matrix); 1.159 + else 1.160 + { 1.161 + SkRect dst; 1.162 + dst.set(0, 0, this->width(), this->height()); 1.163 + matrix.setRectToRect(src, dst, scaleTypeToScaleToFit(this->getScaleType())); 1.164 + } 1.165 + canvas->concat(matrix); 1.166 + 1.167 + SkPaint paint; 1.168 + 1.169 + paint.setAntiAlias(true); 1.170 + 1.171 + if (fDataIsAnim) 1.172 + { 1.173 + SkMSec now = SkTime::GetMSecs(); 1.174 + 1.175 + SkAnimator::DifferenceType diff = fData.fAnim->draw(canvas, &paint, now); 1.176 + 1.177 +SkDEBUGF(("SkImageView : now = %X[%12.3f], diff = %d\n", now, now/1000., diff)); 1.178 + 1.179 + if (diff == SkAnimator::kDifferent) 1.180 + this->inval(NULL); 1.181 + else if (diff == SkAnimator::kPartiallyDifferent) 1.182 + { 1.183 + SkRect bounds; 1.184 + fData.fAnim->getInvalBounds(&bounds); 1.185 + matrix.mapRect(&bounds); // get the bounds into view coordinates 1.186 + this->inval(&bounds); 1.187 + } 1.188 + } 1.189 + else 1.190 + canvas->drawBitmap(*fData.fBitmap, 0, 0, &paint); 1.191 +} 1.192 + 1.193 +void SkImageView::onInflate(const SkDOM& dom, const SkDOMNode* node) 1.194 +{ 1.195 + this->INHERITED::onInflate(dom, node); 1.196 + 1.197 + const char* src = dom.findAttr(node, "src"); 1.198 + if (src) 1.199 + this->setUri(src); 1.200 + 1.201 + int index = dom.findList(node, "scaleType", "matrix,fitXY,fitStart,fitCenter,fitEnd"); 1.202 + if (index >= 0) 1.203 + this->setScaleType((ScaleType)index); 1.204 + 1.205 + // need inflate syntax/reader for matrix 1.206 +} 1.207 + 1.208 +///////////////////////////////////////////////////////////////////////////////////// 1.209 + 1.210 +void SkImageView::onUriChange() 1.211 +{ 1.212 + if (this->freeData()) 1.213 + this->inval(NULL); 1.214 + fUriIsValid = true; // give ensureUriIsLoaded() a shot at the new uri 1.215 +} 1.216 + 1.217 +bool SkImageView::freeData() 1.218 +{ 1.219 + if (fData.fAnim) // test is valid for all union values 1.220 + { 1.221 + if (fDataIsAnim) 1.222 + delete fData.fAnim; 1.223 + else 1.224 + delete fData.fBitmap; 1.225 + 1.226 + fData.fAnim = NULL; // valid for all union values 1.227 + return true; 1.228 + } 1.229 + return false; 1.230 +} 1.231 + 1.232 +bool SkImageView::getDataBounds(SkRect* bounds) 1.233 +{ 1.234 + SkASSERT(bounds); 1.235 + 1.236 + if (this->ensureUriIsLoaded()) 1.237 + { 1.238 + SkScalar width, height; 1.239 + 1.240 + if (fDataIsAnim) 1.241 + { 1.242 + if (SkScalarIsNaN(width = fData.fAnim->getScalar("dimensions", "x")) || 1.243 + SkScalarIsNaN(height = fData.fAnim->getScalar("dimensions", "y"))) 1.244 + { 1.245 + // cons up fake bounds 1.246 + width = this->width(); 1.247 + height = this->height(); 1.248 + } 1.249 + } 1.250 + else 1.251 + { 1.252 + width = SkIntToScalar(fData.fBitmap->width()); 1.253 + height = SkIntToScalar(fData.fBitmap->height()); 1.254 + } 1.255 + bounds->set(0, 0, width, height); 1.256 + return true; 1.257 + } 1.258 + return false; 1.259 +} 1.260 + 1.261 +bool SkImageView::ensureUriIsLoaded() 1.262 +{ 1.263 + if (fData.fAnim) // test is valid for all union values 1.264 + { 1.265 + SkASSERT(fUriIsValid); 1.266 + return true; 1.267 + } 1.268 + if (!fUriIsValid) 1.269 + return false; 1.270 + 1.271 + // try to load the url 1.272 + if (fUri.endsWith(".xml")) // assume it is screenplay 1.273 + { 1.274 + SkAnimator* anim = new SkAnimator; 1.275 + 1.276 + if (!anim->decodeURI(fUri.c_str())) 1.277 + { 1.278 + delete anim; 1.279 + fUriIsValid = false; 1.280 + return false; 1.281 + } 1.282 + anim->setHostEventSink(this); 1.283 + 1.284 + fData.fAnim = anim; 1.285 + fDataIsAnim = true; 1.286 + } 1.287 + else // assume it is an image format 1.288 + { 1.289 + #if 0 1.290 + SkBitmap* bitmap = new SkBitmap; 1.291 + 1.292 + if (!SkImageDecoder::DecodeURL(fUri.c_str(), bitmap)) 1.293 + { 1.294 + delete bitmap; 1.295 + fUriIsValid = false; 1.296 + return false; 1.297 + } 1.298 + fData.fBitmap = bitmap; 1.299 + fDataIsAnim = false; 1.300 + #else 1.301 + return false; 1.302 + #endif 1.303 + } 1.304 + return true; 1.305 +}