KHTML
GraphicsContext.cpp
Go to the documentation of this file.00001 /* 00002 * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 1. Redistributions of source code must retain the above copyright 00008 * notice, this list of conditions and the following disclaimer. 00009 * 2. Redistributions in binary form must reproduce the above copyright 00010 * notice, this list of conditions and the following disclaimer in the 00011 * documentation and/or other materials provided with the distribution. 00012 * 00013 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 00014 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00015 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00016 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 00017 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00018 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00019 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00020 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00021 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00023 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 */ 00025 00026 #include "config.h" 00027 #include "GraphicsContext.h" 00028 00029 #include "BidiResolver.h" 00030 #include "Generator.h" 00031 #include "GraphicsContextPrivate.h" 00032 #include "Font.h" 00033 //#include "NotImplemented.h" 00034 00035 using namespace std; 00036 00037 namespace WebCore { 00038 00039 /*class TextRunIterator { 00040 public: 00041 TextRunIterator() 00042 : m_textRun(0) 00043 , m_offset(0) 00044 { 00045 } 00046 00047 TextRunIterator(const TextRun* textRun, unsigned offset) 00048 : m_textRun(textRun) 00049 , m_offset(offset) 00050 { 00051 } 00052 00053 TextRunIterator(const TextRunIterator& other) 00054 : m_textRun(other.m_textRun) 00055 , m_offset(other.m_offset) 00056 { 00057 } 00058 00059 unsigned offset() const { return m_offset; } 00060 void increment() { m_offset++; } 00061 bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); } 00062 UChar current() const { return (*m_textRun)[m_offset]; } 00063 WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); } 00064 00065 bool operator==(const TextRunIterator& other) 00066 { 00067 return m_offset == other.m_offset && m_textRun == other.m_textRun; 00068 } 00069 00070 bool operator!=(const TextRunIterator& other) { return !operator==(other); } 00071 00072 private: 00073 const TextRun* m_textRun; 00074 int m_offset; 00075 };*/ 00076 00077 GraphicsContextPrivate* GraphicsContext::createGraphicsContextPrivate() 00078 { 00079 return new GraphicsContextPrivate; 00080 } 00081 00082 void GraphicsContext::destroyGraphicsContextPrivate(GraphicsContextPrivate* deleteMe) 00083 { 00084 delete deleteMe; 00085 } 00086 00087 void GraphicsContext::save() 00088 { 00089 if (paintingDisabled()) 00090 return; 00091 00092 m_common->stack.append(m_common->state); 00093 00094 savePlatformState(); 00095 } 00096 00097 void GraphicsContext::restore() 00098 { 00099 if (paintingDisabled()) 00100 return; 00101 00102 if (m_common->stack.isEmpty()) { 00103 //LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty"); 00104 return; 00105 } 00106 m_common->state = m_common->stack.last(); 00107 m_common->stack.removeLast(); 00108 00109 restorePlatformState(); 00110 } 00111 00112 /*const Font& GraphicsContext::font() const 00113 { 00114 return m_common->state.font; 00115 } 00116 00117 void GraphicsContext::setFont(const Font& aFont) 00118 { 00119 m_common->state.font = aFont; 00120 setPlatformFont(aFont); 00121 } 00122 00123 void GraphicsContext::setStrokeThickness(float thickness) 00124 { 00125 m_common->state.strokeThickness = thickness; 00126 setPlatformStrokeThickness(thickness); 00127 }*/ 00128 00129 /*void GraphicsContext::setStrokeStyle(const StrokeStyle& style) 00130 { 00131 m_common->state.strokeStyle = style; 00132 setPlatformStrokeStyle(style); 00133 } 00134 00135 void GraphicsContext::setStrokeColor(const Color& color) 00136 { 00137 m_common->state.strokeColor = color; 00138 setPlatformStrokeColor(color); 00139 } 00140 00141 void GraphicsContext::setShadow(const IntSize& size, int blur, const Color& color) 00142 { 00143 m_common->state.shadowSize = size; 00144 m_common->state.shadowBlur = blur; 00145 m_common->state.shadowColor = color; 00146 setPlatformShadow(size, blur, color); 00147 } 00148 00149 void GraphicsContext::clearShadow() 00150 { 00151 m_common->state.shadowSize = IntSize(); 00152 m_common->state.shadowBlur = 0; 00153 m_common->state.shadowColor = Color(); 00154 clearPlatformShadow(); 00155 } 00156 00157 void GraphicsContext::getShadow(IntSize& size, int& blur, Color& color) 00158 { 00159 size = m_common->state.shadowSize; 00160 blur = m_common->state.shadowBlur; 00161 color = m_common->state.shadowColor; 00162 } 00163 00164 float GraphicsContext::strokeThickness() const 00165 { 00166 return m_common->state.strokeThickness; 00167 } 00168 00169 StrokeStyle GraphicsContext::strokeStyle() const 00170 { 00171 return m_common->state.strokeStyle; 00172 } 00173 00174 Color GraphicsContext::strokeColor() const 00175 { 00176 return m_common->state.strokeColor; 00177 } 00178 00179 void GraphicsContext::setFillColor(const Color& color) 00180 { 00181 m_common->state.fillColor = color; 00182 setPlatformFillColor(color); 00183 } 00184 00185 Color GraphicsContext::fillColor() const 00186 { 00187 return m_common->state.fillColor; 00188 }*/ 00189 00190 bool GraphicsContext::updatingControlTints() const 00191 { 00192 return m_common->m_updatingControlTints; 00193 } 00194 00195 void GraphicsContext::setUpdatingControlTints(bool b) 00196 { 00197 setPaintingDisabled(b); 00198 m_common->m_updatingControlTints = b; 00199 } 00200 00201 void GraphicsContext::setPaintingDisabled(bool f) 00202 { 00203 m_common->state.paintingDisabled = f; 00204 } 00205 00206 bool GraphicsContext::paintingDisabled() const 00207 { 00208 return m_common->state.paintingDisabled; 00209 } 00210 00211 /*void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperator op) 00212 { 00213 drawImage(image, p, IntRect(0, 0, -1, -1), op); 00214 } 00215 00216 void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperator op, bool useLowQualityScale) 00217 { 00218 drawImage(image, r, IntRect(0, 0, -1, -1), op, useLowQualityScale); 00219 } 00220 00221 void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op) 00222 { 00223 drawImage(image, IntRect(dest, srcRect.size()), srcRect, op); 00224 } 00225 00226 void GraphicsContext::drawImage(Image* image, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale) 00227 { 00228 drawImage(image, FloatRect(dest), srcRect, op, useLowQualityScale); 00229 } 00230 00231 void GraphicsContext::drawText(const TextRun& run, const IntPoint& point, int from, int to) 00232 { 00233 if (paintingDisabled()) 00234 return; 00235 00236 font().drawText(this, run, point, from, to); 00237 } 00238 00239 void GraphicsContext::drawBidiText(const TextRun& run, const IntPoint& point) 00240 { 00241 if (paintingDisabled()) 00242 return; 00243 00244 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; 00245 WTF::Unicode::Direction paragraphDirection = run.ltr() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft; 00246 00247 bidiResolver.setStatus(BidiStatus(paragraphDirection, paragraphDirection, paragraphDirection, new BidiContext(run.ltr() ? 0 : 1, paragraphDirection, run.directionalOverride()))); 00248 00249 bidiResolver.setPosition(TextRunIterator(&run, 0)); 00250 bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); 00251 00252 if (!bidiResolver.runCount()) 00253 return; 00254 00255 FloatPoint currPoint = point; 00256 BidiCharacterRun* bidiRun = bidiResolver.firstRun(); 00257 while (bidiRun) { 00258 00259 TextRun subrun = run; 00260 subrun.setText(run.data(bidiRun->start()), bidiRun->stop() - bidiRun->start()); 00261 subrun.setRTL(bidiRun->level() % 2); 00262 subrun.setDirectionalOverride(bidiRun->dirOverride(false)); 00263 00264 font().drawText(this, subrun, currPoint); 00265 00266 bidiRun = bidiRun->next(); 00267 // FIXME: Have Font::drawText return the width of what it drew so that we don't have to re-measure here. 00268 if (bidiRun) 00269 currPoint.move(font().floatWidth(subrun), 0.f); 00270 } 00271 00272 bidiResolver.deleteRuns(); 00273 } 00274 00275 void GraphicsContext::drawHighlightForText(const TextRun& run, const IntPoint& point, int h, const Color& backgroundColor, int from, int to) 00276 { 00277 if (paintingDisabled()) 00278 return; 00279 00280 fillRect(font().selectionRectForText(run, point, h, from, to), backgroundColor); 00281 }*/ 00282 00283 void GraphicsContext::initFocusRing(int width, int offset) 00284 { 00285 if (paintingDisabled()) 00286 return; 00287 clearFocusRing(); 00288 00289 m_common->m_focusRingWidth = width; 00290 m_common->m_focusRingOffset = offset; 00291 } 00292 00293 void GraphicsContext::clearFocusRing() 00294 { 00295 m_common->m_focusRingRects.clear(); 00296 } 00297 00298 IntRect GraphicsContext::focusRingBoundingRect() 00299 { 00300 IntRect result = IntRect(0, 0, 0, 0); 00301 00302 const Vector<IntRect>& rects = focusRingRects(); 00303 unsigned rectCount = rects.size(); 00304 for (unsigned i = 0; i < rectCount; i++) 00305 result.unite(rects[i]); 00306 00307 return result; 00308 } 00309 00310 void GraphicsContext::addFocusRingRect(const IntRect& rect) 00311 { 00312 if (paintingDisabled() || rect.isEmpty()) 00313 return; 00314 m_common->m_focusRingRects.append(rect); 00315 } 00316 00317 int GraphicsContext::focusRingWidth() const 00318 { 00319 return m_common->m_focusRingWidth; 00320 } 00321 00322 int GraphicsContext::focusRingOffset() const 00323 { 00324 return m_common->m_focusRingOffset; 00325 } 00326 00327 const Vector<IntRect>& GraphicsContext::focusRingRects() const 00328 { 00329 return m_common->m_focusRingRects; 00330 } 00331 00332 static const int cInterpolationCutoff = 800 * 800; 00333 00334 /*void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale) 00335 { 00336 if (paintingDisabled() || !image) 00337 return; 00338 00339 float tsw = src.width(); 00340 float tsh = src.height(); 00341 float tw = dest.width(); 00342 float th = dest.height(); 00343 00344 if (tsw == -1) 00345 tsw = image->width(); 00346 if (tsh == -1) 00347 tsh = image->height(); 00348 00349 if (tw == -1) 00350 tw = image->width(); 00351 if (th == -1) 00352 th = image->height(); 00353 00354 bool shouldUseLowQualityInterpolation = useLowQualityScale && (tsw != tw || tsh != th) && tsw * tsh > cInterpolationCutoff; 00355 if (shouldUseLowQualityInterpolation) { 00356 save(); 00357 setUseLowQualityImageInterpolation(true); 00358 } 00359 image->draw(this, FloatRect(dest.location(), FloatSize(tw, th)), FloatRect(src.location(), FloatSize(tsw, tsh)), op); 00360 if (shouldUseLowQualityInterpolation) 00361 restore(); 00362 } 00363 00364 void GraphicsContext::drawTiledImage(Image* image, const IntRect& rect, const IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op) 00365 { 00366 if (paintingDisabled() || !image) 00367 return; 00368 00369 image->drawTiled(this, rect, srcPoint, tileSize, op); 00370 } 00371 00372 void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const IntRect& srcRect, Image::TileRule hRule, Image::TileRule vRule, CompositeOperator op) 00373 { 00374 if (paintingDisabled() || !image) 00375 return; 00376 00377 if (hRule == Image::StretchTile && vRule == Image::StretchTile) 00378 // Just do a scale. 00379 return drawImage(image, dest, srcRect); 00380 00381 image->drawTiled(this, dest, srcRect, hRule, vRule, op); 00382 }*/ 00383 00384 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, 00385 const IntSize& bottomLeft, const IntSize& bottomRight) 00386 { 00387 if (paintingDisabled()) 00388 return; 00389 00390 clip(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight)); 00391 } 00392 00393 /*void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, 00394 const IntSize& bottomLeft, const IntSize& bottomRight) 00395 { 00396 if (paintingDisabled()) 00397 return; 00398 00399 clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight)); 00400 } 00401 00402 int GraphicsContext::textDrawingMode() 00403 { 00404 return m_common->state.textDrawingMode; 00405 } 00406 00407 void GraphicsContext::setTextDrawingMode(int mode) 00408 { 00409 m_common->state.textDrawingMode = mode; 00410 if (paintingDisabled()) 00411 return; 00412 setPlatformTextDrawingMode(mode); 00413 }*/ 00414 00415 /*void GraphicsContext::fillRect(const FloatRect& rect, Generator& generator) 00416 { 00417 if (paintingDisabled()) 00418 return; 00419 generator.fill(this, rect); 00420 }*/ 00421 00422 #if !PLATFORM(CG) 00423 // Implement this if you want to go ahead and push the drawing mode into your native context 00424 // immediately. 00425 /*void GraphicsContext::setPlatformTextDrawingMode(int mode) 00426 { 00427 } 00428 00429 // Other platforms need to implement this. 00430 void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*) 00431 { 00432 //notImplemented(); 00433 }*/ 00434 #endif 00435 00436 #if !PLATFORM(QT) && !PLATFORM(CAIRO) 00437 void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&) 00438 { 00439 } 00440 #endif 00441 00442 #if !PLATFORM(QT) 00443 void GraphicsContext::setPlatformFont(const Font&) 00444 { 00445 } 00446 #endif 00447 00448 }