| OLD | NEW |
| (Empty) |
| 1 | |
| 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 */ | |
| 8 #include "SkImageView.h" | |
| 9 #include "SkAnimator.h" | |
| 10 #include "SkBitmap.h" | |
| 11 #include "SkCanvas.h" | |
| 12 #include "SkImageDecoder.h" | |
| 13 #include "SkMatrix.h" | |
| 14 #include "SkSystemEventTypes.h" | |
| 15 #include "SkTime.h" | |
| 16 | |
| 17 SkImageView::SkImageView() | |
| 18 { | |
| 19 fMatrix = nullptr; | |
| 20 fScaleType = kMatrix_ScaleType; | |
| 21 | |
| 22 fData.fAnim = nullptr; // handles initializing the other union val
ues | |
| 23 fDataIsAnim = true; | |
| 24 | |
| 25 fUriIsValid = false; // an empty string is not valid | |
| 26 } | |
| 27 | |
| 28 SkImageView::~SkImageView() | |
| 29 { | |
| 30 if (fMatrix) | |
| 31 sk_free(fMatrix); | |
| 32 | |
| 33 this->freeData(); | |
| 34 } | |
| 35 | |
| 36 void SkImageView::getUri(SkString* uri) const | |
| 37 { | |
| 38 if (uri) | |
| 39 *uri = fUri; | |
| 40 } | |
| 41 | |
| 42 void SkImageView::setUri(const char uri[]) | |
| 43 { | |
| 44 if (!fUri.equals(uri)) | |
| 45 { | |
| 46 fUri.set(uri); | |
| 47 this->onUriChange(); | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 void SkImageView::setUri(const SkString& uri) | |
| 52 { | |
| 53 if (fUri != uri) | |
| 54 { | |
| 55 fUri = uri; | |
| 56 this->onUriChange(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 void SkImageView::setScaleType(ScaleType st) | |
| 61 { | |
| 62 SkASSERT((unsigned)st <= kFitEnd_ScaleType); | |
| 63 | |
| 64 if ((ScaleType)fScaleType != st) | |
| 65 { | |
| 66 fScaleType = SkToU8(st); | |
| 67 if (fUriIsValid) | |
| 68 this->inval(nullptr); | |
| 69 } | |
| 70 } | |
| 71 | |
| 72 bool SkImageView::getImageMatrix(SkMatrix* matrix) const | |
| 73 { | |
| 74 if (fMatrix) | |
| 75 { | |
| 76 SkASSERT(!fMatrix->isIdentity()); | |
| 77 if (matrix) | |
| 78 *matrix = *fMatrix; | |
| 79 return true; | |
| 80 } | |
| 81 else | |
| 82 { | |
| 83 if (matrix) | |
| 84 matrix->reset(); | |
| 85 return false; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 void SkImageView::setImageMatrix(const SkMatrix* matrix) | |
| 90 { | |
| 91 bool changed = false; | |
| 92 | |
| 93 if (matrix && !matrix->isIdentity()) | |
| 94 { | |
| 95 if (fMatrix == nullptr) | |
| 96 fMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); | |
| 97 *fMatrix = *matrix; | |
| 98 changed = true; | |
| 99 } | |
| 100 else // set us to identity | |
| 101 { | |
| 102 if (fMatrix) | |
| 103 { | |
| 104 SkASSERT(!fMatrix->isIdentity()); | |
| 105 sk_free(fMatrix); | |
| 106 fMatrix = nullptr; | |
| 107 changed = true; | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 // only redraw if we changed our matrix and we're not in scaleToFit mode | |
| 112 if (changed && this->getScaleType() == kMatrix_ScaleType && fUriIsValid) | |
| 113 this->inval(nullptr); | |
| 114 } | |
| 115 | |
| 116 ////////////////////////////////////////////////////////////////////////////////
/////////////// | |
| 117 | |
| 118 bool SkImageView::onEvent(const SkEvent& evt) | |
| 119 { | |
| 120 if (evt.isType(SK_EventType_Inval)) | |
| 121 { | |
| 122 if (fUriIsValid) | |
| 123 this->inval(nullptr); | |
| 124 return true; | |
| 125 } | |
| 126 return this->INHERITED::onEvent(evt); | |
| 127 } | |
| 128 | |
| 129 static 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_ScaleToF
it); | |
| 137 SkASSERT(SkImageView::kFitEnd_ScaleType - 1 == SkMatrix::kEnd_ScaleToFit); | |
| 138 | |
| 139 return (SkMatrix::ScaleToFit)(st - 1); | |
| 140 } | |
| 141 | |
| 142 void 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 | |
| 174 SkDEBUGF(("SkImageView : now = %X[%12.3f], diff = %d\n", now, now/1000., diff)); | |
| 175 | |
| 176 if (diff == SkAnimator::kDifferent) | |
| 177 this->inval(nullptr); | |
| 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 | |
| 190 void 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,fitCen
ter,fitEnd"); | |
| 199 if (index >= 0) | |
| 200 this->setScaleType((ScaleType)index); | |
| 201 | |
| 202 // need inflate syntax/reader for matrix | |
| 203 } | |
| 204 | |
| 205 ////////////////////////////////////////////////////////////////////////////////
///// | |
| 206 | |
| 207 void SkImageView::onUriChange() | |
| 208 { | |
| 209 if (this->freeData()) | |
| 210 this->inval(nullptr); | |
| 211 fUriIsValid = true; // give ensureUriIsLoaded() a shot at the new uri | |
| 212 } | |
| 213 | |
| 214 bool 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 = nullptr; // valid for all union values | |
| 224 return true; | |
| 225 } | |
| 226 return false; | |
| 227 } | |
| 228 | |
| 229 bool 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 | |
| 258 bool 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 } | |
| OLD | NEW |