📄 render_image.cpp
字号:
/** * This file is part of the DOM implementation for KDE. * * Copyright (C) 1999 Lars Knoll (knoll@kde.org) * (C) 1999 Antti Koivisto (koivisto@kde.org) * (C) 2000 Dirk Mueller (mueller@kde.org) * Copyright (C) 2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * *///#define DEBUG_LAYOUT#include "render_image.h"#include "render_canvas.h"#include <qdrawutil.h>#include <qpainter.h>#include <kapplication.h>#include <kdebug.h>#include "css/csshelper.h"#include "misc/helper.h"#include "misc/htmlattrs.h"#include "misc/htmltags.h"#include "html/html_formimpl.h"#include "html/html_imageimpl.h"#include "html/dtd.h"#include "xml/dom2_eventsimpl.h"#include "html/html_documentimpl.h"#include <math.h>using namespace DOM;using namespace khtml;// -------------------------------------------------------------------------RenderImage::RenderImage(NodeImpl *_node) : RenderReplaced(_node){ image = 0; berrorPic = false; m_selectionState = SelectionNone; setIntrinsicWidth( 0 ); setIntrinsicHeight( 0 );}RenderImage::~RenderImage(){ if(image) image->deref(this); pix.decreaseUseCount();}void RenderImage::setStyle(RenderStyle* _style){ RenderReplaced::setStyle(_style); setShouldPaintBackgroundOrBorder(true);}void RenderImage::setContentObject(CachedObject* co){ if (co && image != co) { if (image) image->deref(this); image = static_cast<CachedImage*>(co); if (image) image->ref(this); }}void RenderImage::setImage(CachedImage* newImage){ if (image) image->deref(this); image = newImage; if (image) image->ref(this);}void RenderImage::setPixmap( const QPixmap &p, const QRect& r, CachedImage *o){ if(o != image) { RenderReplaced::setPixmap(p, r, o); return; } bool iwchanged = false; if(o->isErrorImage()) { int iw = p.width() + 8; int ih = p.height() + 8; // we have an alt and the user meant it (its not a text we invented) if ( element() && !alt.isEmpty() && !element()->getAttribute( ATTR_ALT ).isNull()) { const QFontMetrics &fm = style()->fontMetrics(); QRect br = fm.boundingRect ( 0, 0, 1024, 256, Qt::AlignAuto|Qt::WordBreak, alt.string() ); if ( br.width() > iw ) iw = br.width(); if ( br.height() > ih ) ih = br.height(); } if ( iw != intrinsicWidth() ) { setIntrinsicWidth( iw ); iwchanged = true; } if ( ih != intrinsicHeight() ) { setIntrinsicHeight( ih ); iwchanged = true; } } berrorPic = o->isErrorImage(); bool needlayout = false; // Image dimensions have been changed, see what needs to be done if ( ( o->pixmap_size().width() != intrinsicWidth() || o->pixmap_size().height() != intrinsicHeight() || iwchanged) ) {// qDebug("image dimensions have been changed, old: %d/%d new: %d/%d",// intrinsicWidth(), intrinsicHeight(),// o->pixmap_size().width(), o->pixmap_size().height()); if(!o->isErrorImage()) { setIntrinsicWidth( o->pixmap_size().width() ); setIntrinsicHeight( o->pixmap_size().height() ); } // In the case of generated image content using :before/:after, we might not be in the // render tree yet. In that case, we don't need to worry about check for layout, since we'll get a // layout when we get added in to the render tree hierarchy later. if (containingBlock()) { // lets see if we need to relayout at all.. int oldwidth = m_width; int oldheight = m_height; calcWidth(); calcHeight(); if(iwchanged || m_width != oldwidth || m_height != oldheight) needlayout = true; m_width = oldwidth; m_height = oldheight; } }#if APPLE_CHANGES && !KWIQ //FIXME: testing for animations // Stop the previous image, if it may be animating. pix.stopAnimations();#endif #if APPLE_CHANGES pix.decreaseUseCount();#endif pix = p;#if APPLE_CHANGES p.increaseUseCount();#endif if (needlayout) { if (!selfNeedsLayout()) setNeedsLayout(true); if (minMaxKnown()) setMinMaxKnown(false); } else {#if APPLE_CHANGES // FIXME: We always just do a complete repaint, since we always pass in the full pixmap // rect at the moment anyway. resizeCache = QPixmap(); repaintRectangle(QRect(borderLeft()+paddingLeft(), borderTop()+paddingTop(), contentWidth(), contentHeight()));#else // FIXME: This code doesn't handle scaling properly, since it doesn't scale |r|. bool completeRepaint = !resizeCache.isNull(); int cHeight = contentHeight(); int scaledHeight = intrinsicHeight() ? ((o->valid_rect().height()*cHeight)/intrinsicHeight()) : 0; // don't bog down X server doing xforms if(completeRepaint && cHeight >= 5 && o->valid_rect().height() < intrinsicHeight() && (scaledHeight / (cHeight/5) == resizeCache.height() / (cHeight/5))) return; resizeCache = QPixmap(); // for resized animations if(completeRepaint) repaintRectangle(QRect(borderLeft()+paddingLeft(), borderTop()+paddingTop(), contentWidth(), contentHeight())); else { repaintRectangle(QRect(r.x() + borderLeft() + paddingLeft(), r.y() + borderTop() + paddingTop(), r.width(), r.height())); }#endif }}#if APPLE_CHANGESQColor RenderImage::selectionTintColor(QPainter *p) const{ QColor color; RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION); if (pseudoStyle && pseudoStyle->backgroundColor().isValid()) { color = pseudoStyle->backgroundColor(); } else { color = p->selectedTextBackgroundColor(); } return QColor(qRgba(color.red(), color.green(), color.blue(), 160));}#endifvoid RenderImage::paint(PaintInfo& i, int _tx, int _ty){ if (!shouldPaint(i, _tx, _ty)) return; _tx += m_x; _ty += m_y; if (shouldPaintBackgroundOrBorder() && i.phase != PaintActionOutline) paintBoxDecorations(i, _tx, _ty); QPainter* p = i.p; if (i.phase == PaintActionOutline && style()->outlineWidth() && style()->visibility() == VISIBLE) paintOutline(p, _tx, _ty, width(), height(), style()); if (i.phase != PaintActionForeground && i.phase != PaintActionSelection) return; if (!shouldPaintWithinRoot(i)) return; #if APPLE_CHANGES bool drawSelectionTint = selectionState() != SelectionNone; if (i.phase == PaintActionSelection) { if (selectionState() == SelectionNone) { return; } drawSelectionTint = false; }#endif int cWidth = contentWidth(); int cHeight = contentHeight(); int leftBorder = borderLeft(); int topBorder = borderTop(); int leftPad = paddingLeft(); int topPad = paddingTop(); if (khtml::printpainter && !canvas()->printImages()) return; //kdDebug( 6040 ) << " contents (" << contentWidth << "/" << contentHeight << ") border=" << borderLeft() << " padding=" << paddingLeft() << endl; if ( pix.isNull() || berrorPic) { if (i.phase == PaintActionSelection) return; if(cWidth > 2 && cHeight > 2) {#if APPLE_CHANGES if ( !berrorPic ) { p->setPen (Qt::lightGray); p->setBrush (Qt::NoBrush); p->drawRect (_tx + leftBorder + leftPad, _ty + topBorder + topPad, cWidth, cHeight); } bool errorPictureDrawn = false; int imageX = 0, imageY = 0; int usableWidth = cWidth - leftBorder - borderRight() - leftPad - paddingRight(); int usableHeight = cHeight - topBorder - borderBottom() - topPad - paddingBottom(); if(berrorPic && !pix.isNull() && (usableWidth >= pix.width()) && (usableHeight >= pix.height()) ) { // Center the error image, accounting for border and padding. int centerX = (usableWidth - pix.width())/2; if (centerX < 0) centerX = 0; int centerY = (usableHeight - pix.height())/2; if (centerY < 0) centerY = 0; imageX = leftBorder + leftPad + centerX; imageY = topBorder + topPad + centerY; p->drawPixmap( QPoint(_tx + imageX, _ty + imageY), pix, pix.rect() ); errorPictureDrawn = true; } if(!alt.isEmpty()) { QString text = alt.string(); text.replace('\\', backslashAsCurrencySymbol()); p->setFont (style()->font()); p->setPen (style()->color()); int ax = _tx + leftBorder + leftPad; int ay = _ty + topBorder + topPad; const QFontMetrics &fm = style()->fontMetrics(); int ascent = fm.ascent(); // Only draw the alt text if it'll fit within the content box, // and only if it fits above the error image. int textWidth = fm.width (text, text.length()); if (errorPictureDrawn){ if (usableWidth > textWidth && fm.height() <= imageY) p->drawText(ax, ay+ascent, 0 /* ignored */, 0 /* ignored */, Qt::WordBreak /* not supported */, text ); } else if (usableWidth >= textWidth && cHeight>=fm.height()) p->drawText(ax, ay+ascent, 0 /* ignored */, 0 /* ignored */, Qt::WordBreak /* not supported */, text );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -