00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "config.h"
00028 #include "Image.h"
00029
00030 #include "AffineTransform.h"
00031 #include "GraphicsContext.h"
00032 #include "IntRect.h"
00033 #include "MIMETypeRegistry.h"
00034
00035 #include <math.h>
00036
00037 #if PLATFORM(CG)
00038 #include <CoreFoundation/CoreFoundation.h>
00039 #endif
00040
00041 namespace WebCore {
00042
00043 Image::Image(ImageObserver* observer)
00044 : m_imageObserver(observer)
00045 {
00046 }
00047
00048 Image::~Image()
00049 {
00050 }
00051
00052 bool Image::supportsType(const String& type)
00053 {
00054 return MIMETypeRegistry::isSupportedImageResourceMIMEType(type);
00055 }
00056
00057 bool Image::isNull() const
00058 {
00059 return size().isEmpty();
00060 }
00061
00062 bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
00063 {
00064 m_data = data;
00065 if (!m_data.get())
00066 return true;
00067
00068 int length = m_data->size();
00069 if (!length)
00070 return true;
00071
00072 return dataChanged(allDataReceived);
00073 }
00074
00075 IntRect Image::rect() const
00076 {
00077 return IntRect(IntPoint(), size());
00078 }
00079
00080 int Image::width() const
00081 {
00082 return size().width();
00083 }
00084
00085 int Image::height() const
00086 {
00087 return size().height();
00088 }
00089
00090 void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op)
00091 {
00092 if (color.alpha() <= 0)
00093 return;
00094
00095 ctxt->save();
00096 ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
00097 ctxt->fillRect(dstRect, color);
00098 ctxt->restore();
00099 }
00100
00101 static inline FloatSize calculatePatternScale(const FloatRect& dstRect, const FloatRect& srcRect, Image::TileRule hRule, Image::TileRule vRule)
00102 {
00103 float scaleX = 1.0f, scaleY = 1.0f;
00104
00105 if (hRule == Image::StretchTile)
00106 scaleX = dstRect.width() / srcRect.width();
00107 if (vRule == Image::StretchTile)
00108 scaleY = dstRect.height() / srcRect.height();
00109
00110 if (hRule == Image::RepeatTile)
00111 scaleX = scaleY;
00112 if (vRule == Image::RepeatTile)
00113 scaleY = scaleX;
00114
00115 return FloatSize(scaleX, scaleY);
00116 }
00117
00118
00119 void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, CompositeOperator op)
00120 {
00121 if (mayFillWithSolidColor()) {
00122 fillWithSolidColor(ctxt, destRect, solidColor(), op);
00123 return;
00124 }
00125
00126 FloatSize intrinsicTileSize = size();
00127 if (hasRelativeWidth())
00128 intrinsicTileSize.setWidth(scaledTileSize.width());
00129 if (hasRelativeHeight())
00130 intrinsicTileSize.setHeight(scaledTileSize.height());
00131
00132 FloatSize scale(scaledTileSize.width() / intrinsicTileSize.width(),
00133 scaledTileSize.height() / intrinsicTileSize.height());
00134 AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
00135
00136 FloatRect oneTileRect;
00137 oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
00138 oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
00139 oneTileRect.setSize(scaledTileSize);
00140
00141
00142 if (oneTileRect.contains(destRect)) {
00143 FloatRect visibleSrcRect;
00144 visibleSrcRect.setX((destRect.x() - oneTileRect.x()) / scale.width());
00145 visibleSrcRect.setY((destRect.y() - oneTileRect.y()) / scale.height());
00146 visibleSrcRect.setWidth(destRect.width() / scale.width());
00147 visibleSrcRect.setHeight(destRect.height() / scale.height());
00148 draw(ctxt, destRect, visibleSrcRect, op);
00149 return;
00150 }
00151
00152 FloatRect tileRect(FloatPoint(), intrinsicTileSize);
00153 drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), op, destRect);
00154
00155 startAnimation();
00156 }
00157
00158
00159 void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule, TileRule vRule, CompositeOperator op)
00160 {
00161 if (mayFillWithSolidColor()) {
00162 fillWithSolidColor(ctxt, dstRect, solidColor(), op);
00163 return;
00164 }
00165
00166
00167 if (hRule == RoundTile)
00168 hRule = RepeatTile;
00169 if (vRule == RoundTile)
00170 vRule = RepeatTile;
00171
00172 FloatSize scale = calculatePatternScale(dstRect, srcRect, hRule, vRule);
00173 AffineTransform patternTransform = AffineTransform().scale(scale.width(), scale.height());
00174
00175
00176
00177 float hPhase = scale.width() * srcRect.x();
00178 float vPhase = scale.height() * srcRect.y();
00179 if (hRule == Image::RepeatTile)
00180 hPhase -= fmodf(dstRect.width(), scale.width() * srcRect.width()) / 2.0f;
00181 if (vRule == Image::RepeatTile)
00182 vPhase -= fmodf(dstRect.height(), scale.height() * srcRect.height()) / 2.0f;
00183 FloatPoint patternPhase(dstRect.x() - hPhase, dstRect.y() - vPhase);
00184
00185 drawPattern(ctxt, srcRect, patternTransform, patternPhase, op, dstRect);
00186
00187 startAnimation();
00188 }
00189
00190
00191 }