| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include "core/frame/VisualViewport.h" | 39 #include "core/frame/VisualViewport.h" |
| 40 #include "core/html/HTMLBodyElement.h" | 40 #include "core/html/HTMLBodyElement.h" |
| 41 #include "core/html/HTMLHeadElement.h" | 41 #include "core/html/HTMLHeadElement.h" |
| 42 #include "core/html/HTMLHtmlElement.h" | 42 #include "core/html/HTMLHtmlElement.h" |
| 43 #include "core/html/HTMLImageElement.h" | 43 #include "core/html/HTMLImageElement.h" |
| 44 #include "core/html/HTMLMetaElement.h" | 44 #include "core/html/HTMLMetaElement.h" |
| 45 #include "core/layout/LayoutObject.h" | 45 #include "core/layout/LayoutObject.h" |
| 46 #include "core/loader/DocumentLoader.h" | 46 #include "core/loader/DocumentLoader.h" |
| 47 #include "core/loader/FrameLoader.h" | 47 #include "core/loader/FrameLoader.h" |
| 48 #include "core/loader/FrameLoaderClient.h" | 48 #include "core/loader/FrameLoaderClient.h" |
| 49 #include "platform/HostWindow.h" |
| 49 #include "wtf/text/StringBuilder.h" | 50 #include "wtf/text/StringBuilder.h" |
| 50 #include <limits> | 51 #include <limits> |
| 51 | 52 |
| 52 using namespace std; | 53 using namespace std; |
| 53 | 54 |
| 54 namespace blink { | 55 namespace blink { |
| 55 | 56 |
| 56 using namespace HTMLNames; | 57 using namespace HTMLNames; |
| 57 | 58 |
| 58 class ImageEventListener : public EventListener { | 59 class ImageEventListener : public EventListener { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 if (m_shrinkToFitMode == Desktop) | 241 if (m_shrinkToFitMode == Desktop) |
| 241 m_imageElement->addEventListener("click", listener, false); | 242 m_imageElement->addEventListener("click", listener, false); |
| 242 } | 243 } |
| 243 | 244 |
| 244 rootElement->appendChild(head); | 245 rootElement->appendChild(head); |
| 245 rootElement->appendChild(body); | 246 rootElement->appendChild(body); |
| 246 } | 247 } |
| 247 | 248 |
| 248 float ImageDocument::scale() const | 249 float ImageDocument::scale() const |
| 249 { | 250 { |
| 251 DCHECK_EQ(m_shrinkToFitMode, Desktop); |
| 250 if (!m_imageElement || m_imageElement->document() != this) | 252 if (!m_imageElement || m_imageElement->document() != this) |
| 251 return 1.0f; | 253 return 1.0f; |
| 252 | 254 |
| 253 FrameView* view = frame()->view(); | 255 FrameView* view = frame()->view(); |
| 254 if (!view) | 256 if (!view) |
| 255 return 1; | 257 return 1.0f; |
| 256 | 258 |
| 257 DCHECK(m_imageElement->cachedImage()); | 259 DCHECK(m_imageElement->cachedImage()); |
| 258 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), pageZoomFactor(
this)); | 260 const float zoom = pageZoomFactor(this); |
| 259 LayoutSize windowSize = LayoutSize(view->width(), view->height()); | 261 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), zoom); |
| 260 | 262 |
| 261 float widthScale = windowSize.width().toFloat() / imageSize.width().toFloat(
); | 263 // We want to pretend the viewport is larger when the user has zoomed the |
| 262 float heightScale = windowSize.height().toFloat() / imageSize.height().toFlo
at(); | 264 // page in (but not when the zoom is coming from device scale). |
| 265 const float manualZoom = zoom / view->getHostWindow()->windowToViewportScala
r(1.f); |
| 266 float widthScale = view->width() * manualZoom / imageSize.width().toFloat(); |
| 267 float heightScale = view->height() * manualZoom / imageSize.height().toFloat
(); |
| 263 | 268 |
| 264 return min(widthScale, heightScale); | 269 return min(widthScale, heightScale); |
| 265 } | 270 } |
| 266 | 271 |
| 267 void ImageDocument::resizeImageToFit(ScaleType type) | 272 void ImageDocument::resizeImageToFit() |
| 268 { | 273 { |
| 269 if (!m_imageElement || m_imageElement->document() != this || (pageZoomFactor
(this) > 1 && type == ScaleOnlyUnzoomedDocument)) | 274 DCHECK_EQ(m_shrinkToFitMode, Desktop); |
| 275 if (!m_imageElement || m_imageElement->document() != this) |
| 270 return; | 276 return; |
| 271 | 277 |
| 272 DCHECK(m_imageElement->cachedImage()); | 278 DCHECK(m_imageElement->cachedImage()); |
| 273 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), pageZoomFactor(
this)); | 279 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), 1.f); |
| 274 | 280 |
| 275 float scale = this->scale(); | 281 const float scale = this->scale(); |
| 276 m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale)); | 282 m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale)); |
| 277 m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale)); | 283 m_imageElement->setHeight(static_cast<int>(imageSize.height() * scale)); |
| 278 | 284 |
| 279 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomIn); | 285 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomIn); |
| 280 } | 286 } |
| 281 | 287 |
| 282 void ImageDocument::imageClicked(int x, int y) | 288 void ImageDocument::imageClicked(int x, int y) |
| 283 { | 289 { |
| 284 DCHECK_EQ(m_shrinkToFitMode, Desktop); | 290 DCHECK_EQ(m_shrinkToFitMode, Desktop); |
| 285 | 291 |
| 286 if (!m_imageSizeIsKnown || imageFitsInWindow()) | 292 if (!m_imageSizeIsKnown || imageFitsInWindow()) |
| 287 return; | 293 return; |
| 288 | 294 |
| 289 m_shouldShrinkImage = !m_shouldShrinkImage; | 295 m_shouldShrinkImage = !m_shouldShrinkImage; |
| 290 | 296 |
| 291 if (m_shouldShrinkImage) { | 297 if (m_shouldShrinkImage) { |
| 292 windowSizeChanged(ScaleZoomedDocument); | 298 windowSizeChanged(); |
| 293 } else { | 299 } else { |
| 294 restoreImageSize(ScaleZoomedDocument); | 300 restoreImageSize(); |
| 295 | 301 |
| 296 updateStyleAndLayout(); | 302 updateStyleAndLayout(); |
| 297 | 303 |
| 298 double scale = this->scale(); | 304 double scale = this->scale(); |
| 299 | 305 |
| 300 double scrollX = x / scale - static_cast<double>(frame()->view()->width(
)) / 2; | 306 double scrollX = x / scale - static_cast<double>(frame()->view()->width(
)) / 2; |
| 301 double scrollY = y / scale - static_cast<double>(frame()->view()->height
()) / 2; | 307 double scrollY = y / scale - static_cast<double>(frame()->view()->height
()) / 2; |
| 302 | 308 |
| 303 frame()->view()->setScrollPosition(DoublePoint(scrollX, scrollY), Progra
mmaticScroll); | 309 frame()->view()->setScrollPosition(DoublePoint(scrollX, scrollY), Progra
mmaticScroll); |
| 304 } | 310 } |
| 305 } | 311 } |
| 306 | 312 |
| 307 void ImageDocument::imageUpdated() | 313 void ImageDocument::imageUpdated() |
| 308 { | 314 { |
| 309 DCHECK(m_imageElement); | 315 DCHECK(m_imageElement); |
| 310 | 316 |
| 311 if (m_imageSizeIsKnown) | 317 if (m_imageSizeIsKnown) |
| 312 return; | 318 return; |
| 313 | 319 |
| 314 updateStyleAndLayoutTree(); | 320 updateStyleAndLayoutTree(); |
| 315 if (!m_imageElement->cachedImage() || m_imageElement->cachedImage()->imageSi
ze(LayoutObject::shouldRespectImageOrientation(m_imageElement->layoutObject()),
pageZoomFactor(this)).isEmpty()) | 321 if (!m_imageElement->cachedImage() || m_imageElement->cachedImage()->imageSi
ze(LayoutObject::shouldRespectImageOrientation(m_imageElement->layoutObject()),
pageZoomFactor(this)).isEmpty()) |
| 316 return; | 322 return; |
| 317 | 323 |
| 318 m_imageSizeIsKnown = true; | 324 m_imageSizeIsKnown = true; |
| 319 | 325 |
| 320 if (shouldShrinkToFit()) { | 326 if (shouldShrinkToFit()) { |
| 321 // Force resizing of the image | 327 // Force resizing of the image |
| 322 windowSizeChanged(ScaleOnlyUnzoomedDocument); | 328 windowSizeChanged(); |
| 323 } | 329 } |
| 324 } | 330 } |
| 325 | 331 |
| 326 void ImageDocument::restoreImageSize(ScaleType type) | 332 void ImageDocument::restoreImageSize() |
| 327 { | 333 { |
| 328 DCHECK_EQ(m_shrinkToFitMode, Desktop); | 334 DCHECK_EQ(m_shrinkToFitMode, Desktop); |
| 329 | 335 |
| 330 if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() !=
this || (pageZoomFactor(this) < 1 && type == ScaleOnlyUnzoomedDocument)) | 336 if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() !=
this) |
| 331 return; | 337 return; |
| 332 | 338 |
| 333 DCHECK(m_imageElement->cachedImage()); | 339 DCHECK(m_imageElement->cachedImage()); |
| 334 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), 1.0f); | 340 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), 1.0f); |
| 335 m_imageElement->setWidth(imageSize.width().toInt()); | 341 m_imageElement->setWidth(imageSize.width().toInt()); |
| 336 m_imageElement->setHeight(imageSize.height().toInt()); | 342 m_imageElement->setHeight(imageSize.height().toInt()); |
| 337 | 343 |
| 338 if (imageFitsInWindow()) | 344 if (imageFitsInWindow()) |
| 339 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); | 345 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); |
| 340 else | 346 else |
| 341 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOu
t); | 347 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZoomOu
t); |
| 342 | 348 |
| 343 m_didShrinkImage = false; | 349 m_didShrinkImage = false; |
| 344 } | 350 } |
| 345 | 351 |
| 346 bool ImageDocument::imageFitsInWindow() const | 352 bool ImageDocument::imageFitsInWindow() const |
| 347 { | 353 { |
| 348 DCHECK_EQ(m_shrinkToFitMode, Desktop); | 354 DCHECK_EQ(m_shrinkToFitMode, Desktop); |
| 349 | 355 return this->scale() >= 1; |
| 350 if (!m_imageElement || m_imageElement->document() != this) | |
| 351 return true; | |
| 352 | |
| 353 FrameView* view = frame()->view(); | |
| 354 if (!view) | |
| 355 return true; | |
| 356 | |
| 357 DCHECK(m_imageElement->cachedImage()); | |
| 358 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(LayoutObject
::shouldRespectImageOrientation(m_imageElement->layoutObject()), pageZoomFactor(
this)); | |
| 359 LayoutSize windowSize = LayoutSize(view->width(), view->height()); | |
| 360 | |
| 361 return imageSize.width() <= windowSize.width() && imageSize.height() <= wind
owSize.height(); | |
| 362 } | 356 } |
| 363 | 357 |
| 364 void ImageDocument::windowSizeChanged(ScaleType type) | 358 void ImageDocument::windowSizeChanged() |
| 365 { | 359 { |
| 366 if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() !=
this) | 360 if (!m_imageElement || !m_imageSizeIsKnown || m_imageElement->document() !=
this) |
| 367 return; | 361 return; |
| 368 | 362 |
| 369 if (m_shrinkToFitMode == Viewport) { | 363 if (m_shrinkToFitMode == Viewport) { |
| 370 // For huge images, minimum-scale=0.1 is still too big on small screens. | 364 // For huge images, minimum-scale=0.1 is still too big on small screens. |
| 371 // Set max-width so that the image will shrink to fit the width of the s
creen when | 365 // Set max-width so that the image will shrink to fit the width of the s
creen when |
| 372 // the scale is minimum. | 366 // the scale is minimum. |
| 373 // Don't shrink height to fit because we use width=device-width in viewp
ort meta tag, | 367 // Don't shrink height to fit because we use width=device-width in viewp
ort meta tag, |
| 374 // and expect a full-width reading mode for normal-width-huge-height ima
ges. | 368 // and expect a full-width reading mode for normal-width-huge-height ima
ges. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 386 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); | 380 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); |
| 387 else | 381 else |
| 388 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZo
omOut); | 382 m_imageElement->setInlineStyleProperty(CSSPropertyCursor, CSSValueZo
omOut); |
| 389 return; | 383 return; |
| 390 } | 384 } |
| 391 | 385 |
| 392 if (m_didShrinkImage) { | 386 if (m_didShrinkImage) { |
| 393 // If the window has been resized so that the image fits, restore the im
age size | 387 // If the window has been resized so that the image fits, restore the im
age size |
| 394 // otherwise update the restored image size. | 388 // otherwise update the restored image size. |
| 395 if (fitsInWindow) | 389 if (fitsInWindow) |
| 396 restoreImageSize(type); | 390 restoreImageSize(); |
| 397 else | 391 else |
| 398 resizeImageToFit(type); | 392 resizeImageToFit(); |
| 399 } else { | 393 } else { |
| 400 // If the image isn't resized but needs to be, then resize it. | 394 // If the image isn't resized but needs to be, then resize it. |
| 401 if (!fitsInWindow) { | 395 if (!fitsInWindow) { |
| 402 resizeImageToFit(type); | 396 resizeImageToFit(); |
| 403 m_didShrinkImage = true; | 397 m_didShrinkImage = true; |
| 404 } | 398 } |
| 405 } | 399 } |
| 406 } | 400 } |
| 407 | 401 |
| 408 ImageResource* ImageDocument::cachedImage() | 402 ImageResource* ImageDocument::cachedImage() |
| 409 { | 403 { |
| 410 if (!m_imageElement) { | 404 if (!m_imageElement) { |
| 411 createDocumentStructure(); | 405 createDocumentStructure(); |
| 412 if (isStopped()) { | 406 if (isStopped()) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 427 { | 421 { |
| 428 visitor->trace(m_imageElement); | 422 visitor->trace(m_imageElement); |
| 429 HTMLDocument::trace(visitor); | 423 HTMLDocument::trace(visitor); |
| 430 } | 424 } |
| 431 | 425 |
| 432 // -------- | 426 // -------- |
| 433 | 427 |
| 434 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) | 428 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) |
| 435 { | 429 { |
| 436 if (event->type() == EventTypeNames::resize) { | 430 if (event->type() == EventTypeNames::resize) { |
| 437 m_doc->windowSizeChanged(ImageDocument::ScaleOnlyUnzoomedDocument); | 431 m_doc->windowSizeChanged(); |
| 438 } else if (event->type() == EventTypeNames::click && event->isMouseEvent())
{ | 432 } else if (event->type() == EventTypeNames::click && event->isMouseEvent())
{ |
| 439 MouseEvent* mouseEvent = toMouseEvent(event); | 433 MouseEvent* mouseEvent = toMouseEvent(event); |
| 440 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); | 434 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); |
| 441 } | 435 } |
| 442 } | 436 } |
| 443 | 437 |
| 444 bool ImageEventListener::operator==(const EventListener& listener) const | 438 bool ImageEventListener::operator==(const EventListener& listener) const |
| 445 { | 439 { |
| 446 if (const ImageEventListener* imageEventListener = ImageEventListener::cast(
&listener)) | 440 if (const ImageEventListener* imageEventListener = ImageEventListener::cast(
&listener)) |
| 447 return m_doc == imageEventListener->m_doc; | 441 return m_doc == imageEventListener->m_doc; |
| 448 return false; | 442 return false; |
| 449 } | 443 } |
| 450 | 444 |
| 451 } // namespace blink | 445 } // namespace blink |
| OLD | NEW |