| OLD | NEW | 
 | (Empty) | 
|     1 /* |  | 
|     2  * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |  | 
|     3  * Copyright (C) 2013 Google Inc. All rights reserved. |  | 
|     4  * |  | 
|     5  * Redistribution and use in source and binary forms, with or without |  | 
|     6  * modification, are permitted provided that the following conditions |  | 
|     7  * are met: |  | 
|     8  * 1. Redistributions of source code must retain the above copyright |  | 
|     9  *    notice, this list of conditions and the following disclaimer. |  | 
|    10  * 2. Redistributions in binary form must reproduce the above copyright |  | 
|    11  *    notice, this list of conditions and the following disclaimer in the |  | 
|    12  *    documentation and/or other materials provided with the distribution. |  | 
|    13  * |  | 
|    14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |  | 
|    15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |  | 
|    16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |  | 
|    17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |  | 
|    18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |  | 
|    19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |  | 
|    20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |  | 
|    21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |  | 
|    22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |  | 
|    23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |  | 
|    24  * THE POSSIBILITY OF SUCH DAMAGE. |  | 
|    25  */ |  | 
|    26  |  | 
|    27 #include "config.h" |  | 
|    28 #include "core/platform/graphics/GraphicsContext.h" |  | 
|    29  |  | 
|    30 #include "core/platform/graphics/BitmapImage.h" |  | 
|    31 #include "core/platform/graphics/Gradient.h" |  | 
|    32 #include "platform/geometry/IntRect.h" |  | 
|    33 #include "platform/geometry/RoundedRect.h" |  | 
|    34 #include "platform/graphics/DisplayList.h" |  | 
|    35 #include "platform/graphics/TextRunIterator.h" |  | 
|    36 #include "platform/text/BidiResolver.h" |  | 
|    37 #include "platform/weborigin/KURL.h" |  | 
|    38 #include "third_party/skia/include/core/SkAnnotation.h" |  | 
|    39 #include "third_party/skia/include/core/SkColorFilter.h" |  | 
|    40 #include "third_party/skia/include/core/SkData.h" |  | 
|    41 #include "third_party/skia/include/core/SkPicture.h" |  | 
|    42 #include "third_party/skia/include/core/SkRRect.h" |  | 
|    43 #include "third_party/skia/include/core/SkRefCnt.h" |  | 
|    44 #include "third_party/skia/include/effects/SkBlurMaskFilter.h" |  | 
|    45 #include "third_party/skia/include/effects/SkCornerPathEffect.h" |  | 
|    46 #include "third_party/skia/include/effects/SkLumaColorFilter.h" |  | 
|    47 #include "wtf/Assertions.h" |  | 
|    48 #include "wtf/MathExtras.h" |  | 
|    49  |  | 
|    50 #if OS(MACOSX) |  | 
|    51 #include <ApplicationServices/ApplicationServices.h> |  | 
|    52 #endif |  | 
|    53  |  | 
|    54 using namespace std; |  | 
|    55 using blink::WebBlendMode; |  | 
|    56  |  | 
|    57 namespace WebCore { |  | 
|    58  |  | 
|    59 struct GraphicsContext::DeferredSaveState { |  | 
|    60     DeferredSaveState(unsigned mask, int count) : m_flags(mask), m_restoreCount(
      count) { } |  | 
|    61  |  | 
|    62     unsigned m_flags; |  | 
|    63     int m_restoreCount; |  | 
|    64 }; |  | 
|    65  |  | 
|    66 struct GraphicsContext::RecordingState { |  | 
|    67     RecordingState(SkCanvas* currentCanvas, const SkMatrix& currentMatrix, PassR
      efPtr<DisplayList> displayList) |  | 
|    68         : m_savedCanvas(currentCanvas) |  | 
|    69         , m_displayList(displayList) |  | 
|    70         , m_savedMatrix(currentMatrix) |  | 
|    71     { |  | 
|    72     } |  | 
|    73  |  | 
|    74     SkCanvas* m_savedCanvas; |  | 
|    75     RefPtr<DisplayList> m_displayList; |  | 
|    76     const SkMatrix m_savedMatrix; |  | 
|    77 }; |  | 
|    78  |  | 
|    79 GraphicsContext::GraphicsContext(SkCanvas* canvas) |  | 
|    80     : m_canvas(canvas) |  | 
|    81     , m_deferredSaveFlags(0) |  | 
|    82     , m_annotationMode(0) |  | 
|    83 #if !ASSERT_DISABLED |  | 
|    84     , m_annotationCount(0) |  | 
|    85     , m_layerCount(0) |  | 
|    86 #endif |  | 
|    87     , m_trackOpaqueRegion(false) |  | 
|    88     , m_trackTextRegion(false) |  | 
|    89     , m_useHighResMarker(false) |  | 
|    90     , m_updatingControlTints(false) |  | 
|    91     , m_accelerated(false) |  | 
|    92     , m_isCertainlyOpaque(true) |  | 
|    93     , m_printing(false) |  | 
|    94 { |  | 
|    95     m_stateStack.append(adoptPtr(new GraphicsContextState())); |  | 
|    96     m_state = m_stateStack.last().get(); |  | 
|    97 } |  | 
|    98  |  | 
|    99 GraphicsContext::~GraphicsContext() |  | 
|   100 { |  | 
|   101     ASSERT(m_stateStack.size() == 1); |  | 
|   102     ASSERT(!m_annotationCount); |  | 
|   103     ASSERT(!m_layerCount); |  | 
|   104     ASSERT(m_recordingStateStack.isEmpty()); |  | 
|   105 } |  | 
|   106  |  | 
|   107 const SkBitmap* GraphicsContext::bitmap() const |  | 
|   108 { |  | 
|   109     TRACE_EVENT0("skia", "GraphicsContext::bitmap"); |  | 
|   110     return &m_canvas->getDevice()->accessBitmap(false); |  | 
|   111 } |  | 
|   112  |  | 
|   113 const SkBitmap& GraphicsContext::layerBitmap(AccessMode access) const |  | 
|   114 { |  | 
|   115     return m_canvas->getTopDevice()->accessBitmap(access == ReadWrite); |  | 
|   116 } |  | 
|   117  |  | 
|   118 SkBaseDevice* GraphicsContext::createCompatibleDevice(const IntSize& size, bool 
      hasAlpha) const |  | 
|   119 { |  | 
|   120     if (paintingDisabled()) |  | 
|   121         return 0; |  | 
|   122  |  | 
|   123     return m_canvas->createCompatibleDevice(SkBitmap::kARGB_8888_Config, size.wi
      dth(), size.height(), !hasAlpha); |  | 
|   124 } |  | 
|   125  |  | 
|   126 void GraphicsContext::save() |  | 
|   127 { |  | 
|   128     if (paintingDisabled()) |  | 
|   129         return; |  | 
|   130  |  | 
|   131     m_stateStack.append(m_state->clone()); |  | 
|   132     m_state = m_stateStack.last().get(); |  | 
|   133  |  | 
|   134     m_saveStateStack.append(DeferredSaveState(m_deferredSaveFlags, m_canvas->get
      SaveCount())); |  | 
|   135     m_deferredSaveFlags |= SkCanvas::kMatrixClip_SaveFlag; |  | 
|   136 } |  | 
|   137  |  | 
|   138 void GraphicsContext::restore() |  | 
|   139 { |  | 
|   140     if (paintingDisabled()) |  | 
|   141         return; |  | 
|   142  |  | 
|   143     if (m_stateStack.size() == 1) { |  | 
|   144         WTF_LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty"); |  | 
|   145         return; |  | 
|   146     } |  | 
|   147  |  | 
|   148     m_stateStack.removeLast(); |  | 
|   149     m_state = m_stateStack.last().get(); |  | 
|   150  |  | 
|   151     DeferredSaveState savedState = m_saveStateStack.last(); |  | 
|   152     m_saveStateStack.removeLast(); |  | 
|   153     m_deferredSaveFlags = savedState.m_flags; |  | 
|   154     m_canvas->restoreToCount(savedState.m_restoreCount); |  | 
|   155 } |  | 
|   156  |  | 
|   157 void GraphicsContext::saveLayer(const SkRect* bounds, const SkPaint* paint, SkCa
      nvas::SaveFlags saveFlags) |  | 
|   158 { |  | 
|   159     if (paintingDisabled()) |  | 
|   160         return; |  | 
|   161  |  | 
|   162     realizeSave(SkCanvas::kMatrixClip_SaveFlag); |  | 
|   163  |  | 
|   164     m_canvas->saveLayer(bounds, paint, saveFlags); |  | 
|   165     if (bounds) |  | 
|   166         m_canvas->clipRect(*bounds); |  | 
|   167     if (m_trackOpaqueRegion) |  | 
|   168         m_opaqueRegion.pushCanvasLayer(paint); |  | 
|   169 } |  | 
|   170  |  | 
|   171 void GraphicsContext::restoreLayer() |  | 
|   172 { |  | 
|   173     if (paintingDisabled()) |  | 
|   174         return; |  | 
|   175  |  | 
|   176     m_canvas->restore(); |  | 
|   177     if (m_trackOpaqueRegion) |  | 
|   178         m_opaqueRegion.popCanvasLayer(this); |  | 
|   179 } |  | 
|   180  |  | 
|   181 void GraphicsContext::beginAnnotation(const GraphicsContextAnnotation& annotatio
      n) |  | 
|   182 { |  | 
|   183     if (paintingDisabled()) |  | 
|   184         return; |  | 
|   185  |  | 
|   186     canvas()->beginCommentGroup("GraphicsContextAnnotation"); |  | 
|   187  |  | 
|   188     AnnotationList annotations; |  | 
|   189     annotation.asAnnotationList(annotations); |  | 
|   190  |  | 
|   191     AnnotationList::const_iterator end = annotations.end(); |  | 
|   192     for (AnnotationList::const_iterator it = annotations.begin(); it != end; ++i
      t) |  | 
|   193         canvas()->addComment(it->first, it->second.ascii().data()); |  | 
|   194  |  | 
|   195 #if !ASSERT_DISABLED |  | 
|   196     ++m_annotationCount; |  | 
|   197 #endif |  | 
|   198 } |  | 
|   199  |  | 
|   200 void GraphicsContext::endAnnotation() |  | 
|   201 { |  | 
|   202     if (paintingDisabled()) |  | 
|   203         return; |  | 
|   204  |  | 
|   205     canvas()->endCommentGroup(); |  | 
|   206  |  | 
|   207     ASSERT(m_annotationCount > 0); |  | 
|   208 #if !ASSERT_DISABLED |  | 
|   209     --m_annotationCount; |  | 
|   210 #endif |  | 
|   211 } |  | 
|   212  |  | 
|   213 void GraphicsContext::setStrokeColor(const Color& color) |  | 
|   214 { |  | 
|   215     m_state->m_strokeData.setColor(color); |  | 
|   216     m_state->m_strokeData.clearGradient(); |  | 
|   217     m_state->m_strokeData.clearPattern(); |  | 
|   218 } |  | 
|   219  |  | 
|   220 void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern) |  | 
|   221 { |  | 
|   222     if (paintingDisabled()) |  | 
|   223         return; |  | 
|   224  |  | 
|   225     ASSERT(pattern); |  | 
|   226     if (!pattern) { |  | 
|   227         setStrokeColor(Color::black); |  | 
|   228         return; |  | 
|   229     } |  | 
|   230     m_state->m_strokeData.clearGradient(); |  | 
|   231     m_state->m_strokeData.setPattern(pattern); |  | 
|   232 } |  | 
|   233  |  | 
|   234 void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient) |  | 
|   235 { |  | 
|   236     if (paintingDisabled()) |  | 
|   237         return; |  | 
|   238  |  | 
|   239     ASSERT(gradient); |  | 
|   240     if (!gradient) { |  | 
|   241         setStrokeColor(Color::black); |  | 
|   242         return; |  | 
|   243     } |  | 
|   244     m_state->m_strokeData.setGradient(gradient); |  | 
|   245     m_state->m_strokeData.clearPattern(); |  | 
|   246 } |  | 
|   247  |  | 
|   248 void GraphicsContext::setFillColor(const Color& color) |  | 
|   249 { |  | 
|   250     m_state->m_fillColor = color; |  | 
|   251     m_state->m_fillGradient.clear(); |  | 
|   252     m_state->m_fillPattern.clear(); |  | 
|   253 } |  | 
|   254  |  | 
|   255 void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern) |  | 
|   256 { |  | 
|   257     if (paintingDisabled()) |  | 
|   258         return; |  | 
|   259  |  | 
|   260     ASSERT(pattern); |  | 
|   261     if (!pattern) { |  | 
|   262         setFillColor(Color::black); |  | 
|   263         return; |  | 
|   264     } |  | 
|   265     m_state->m_fillGradient.clear(); |  | 
|   266     m_state->m_fillPattern = pattern; |  | 
|   267 } |  | 
|   268  |  | 
|   269 void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient) |  | 
|   270 { |  | 
|   271     if (paintingDisabled()) |  | 
|   272         return; |  | 
|   273  |  | 
|   274     ASSERT(gradient); |  | 
|   275     if (!gradient) { |  | 
|   276         setFillColor(Color::black); |  | 
|   277         return; |  | 
|   278     } |  | 
|   279     m_state->m_fillGradient = gradient; |  | 
|   280     m_state->m_fillPattern.clear(); |  | 
|   281 } |  | 
|   282  |  | 
|   283 void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color
      & color, |  | 
|   284     DrawLooper::ShadowTransformMode shadowTransformMode, |  | 
|   285     DrawLooper::ShadowAlphaMode shadowAlphaMode) |  | 
|   286 { |  | 
|   287     if (paintingDisabled()) |  | 
|   288         return; |  | 
|   289  |  | 
|   290     if (!color.isValid() || !color.alpha() || (!offset.width() && !offset.height
      () && !blur)) { |  | 
|   291         clearShadow(); |  | 
|   292         return; |  | 
|   293     } |  | 
|   294  |  | 
|   295     DrawLooper drawLooper; |  | 
|   296     drawLooper.addShadow(offset, blur, color, shadowTransformMode, shadowAlphaMo
      de); |  | 
|   297     drawLooper.addUnmodifiedContent(); |  | 
|   298     setDrawLooper(drawLooper); |  | 
|   299 } |  | 
|   300  |  | 
|   301 void GraphicsContext::setDrawLooper(const DrawLooper& drawLooper) |  | 
|   302 { |  | 
|   303     if (paintingDisabled()) |  | 
|   304         return; |  | 
|   305  |  | 
|   306     m_state->m_looper = drawLooper.skDrawLooper(); |  | 
|   307 } |  | 
|   308  |  | 
|   309 void GraphicsContext::clearDrawLooper() |  | 
|   310 { |  | 
|   311     if (paintingDisabled()) |  | 
|   312         return; |  | 
|   313  |  | 
|   314     m_state->m_looper.clear(); |  | 
|   315 } |  | 
|   316  |  | 
|   317 bool GraphicsContext::hasShadow() const |  | 
|   318 { |  | 
|   319     return !!m_state->m_looper; |  | 
|   320 } |  | 
|   321  |  | 
|   322 int GraphicsContext::getNormalizedAlpha() const |  | 
|   323 { |  | 
|   324     int alpha = roundf(m_state->m_alpha * 256); |  | 
|   325     if (alpha > 255) |  | 
|   326         alpha = 255; |  | 
|   327     else if (alpha < 0) |  | 
|   328         alpha = 0; |  | 
|   329     return alpha; |  | 
|   330 } |  | 
|   331  |  | 
|   332 bool GraphicsContext::getClipBounds(SkRect* bounds) const |  | 
|   333 { |  | 
|   334     if (paintingDisabled()) |  | 
|   335         return false; |  | 
|   336     return m_canvas->getClipBounds(bounds); |  | 
|   337 } |  | 
|   338  |  | 
|   339 bool GraphicsContext::getTransformedClipBounds(FloatRect* bounds) const |  | 
|   340 { |  | 
|   341     if (paintingDisabled()) |  | 
|   342         return false; |  | 
|   343     SkIRect skIBounds; |  | 
|   344     if (!m_canvas->getClipDeviceBounds(&skIBounds)) |  | 
|   345         return false; |  | 
|   346     SkRect skBounds = SkRect::MakeFromIRect(skIBounds); |  | 
|   347     *bounds = FloatRect(skBounds); |  | 
|   348     return true; |  | 
|   349 } |  | 
|   350  |  | 
|   351 SkMatrix GraphicsContext::getTotalMatrix() const |  | 
|   352 { |  | 
|   353     if (paintingDisabled()) |  | 
|   354         return SkMatrix::I(); |  | 
|   355  |  | 
|   356     if (!isRecording()) |  | 
|   357         return m_canvas->getTotalMatrix(); |  | 
|   358  |  | 
|   359     const RecordingState& recordingState = m_recordingStateStack.last(); |  | 
|   360     SkMatrix totalMatrix = recordingState.m_savedMatrix; |  | 
|   361     totalMatrix.preConcat(m_canvas->getTotalMatrix()); |  | 
|   362  |  | 
|   363     return totalMatrix; |  | 
|   364 } |  | 
|   365  |  | 
|   366 bool GraphicsContext::isPrintingDevice() const |  | 
|   367 { |  | 
|   368     if (paintingDisabled()) |  | 
|   369         return false; |  | 
|   370     return m_canvas->getTopDevice()->getDeviceCapabilities() & SkBaseDevice::kVe
      ctor_Capability; |  | 
|   371 } |  | 
|   372  |  | 
|   373 void GraphicsContext::adjustTextRenderMode(SkPaint* paint) |  | 
|   374 { |  | 
|   375     if (paintingDisabled()) |  | 
|   376         return; |  | 
|   377  |  | 
|   378     if (!paint->isLCDRenderText()) |  | 
|   379         return; |  | 
|   380  |  | 
|   381     paint->setLCDRenderText(couldUseLCDRenderedText()); |  | 
|   382 } |  | 
|   383  |  | 
|   384 bool GraphicsContext::couldUseLCDRenderedText() |  | 
|   385 { |  | 
|   386     // Our layers only have a single alpha channel. This means that subpixel |  | 
|   387     // rendered text cannot be composited correctly when the layer is |  | 
|   388     // collapsed. Therefore, subpixel text is disabled when we are drawing |  | 
|   389     // onto a layer. |  | 
|   390     if (paintingDisabled() || isDrawingToLayer() || !isCertainlyOpaque()) |  | 
|   391         return false; |  | 
|   392  |  | 
|   393     return shouldSmoothFonts(); |  | 
|   394 } |  | 
|   395  |  | 
|   396 void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation
      , WebBlendMode blendMode) |  | 
|   397 { |  | 
|   398     m_state->m_compositeOperator = compositeOperation; |  | 
|   399     m_state->m_blendMode = blendMode; |  | 
|   400     m_state->m_xferMode = WebCoreCompositeToSkiaComposite(compositeOperation, bl
      endMode); |  | 
|   401 } |  | 
|   402  |  | 
|   403 SkColorFilter* GraphicsContext::colorFilter() |  | 
|   404 { |  | 
|   405     return m_state->m_colorFilter.get(); |  | 
|   406 } |  | 
|   407  |  | 
|   408 void GraphicsContext::setColorFilter(ColorFilter colorFilter) |  | 
|   409 { |  | 
|   410     // We only support one active color filter at the moment. If (when) this bec
      omes a problem, |  | 
|   411     // we should switch to using color filter chains (Skia work in progress). |  | 
|   412     ASSERT(!m_state->m_colorFilter); |  | 
|   413     m_state->m_colorFilter = WebCoreColorFilterToSkiaColorFilter(colorFilter); |  | 
|   414 } |  | 
|   415  |  | 
|   416 bool GraphicsContext::readPixels(SkBitmap* bitmap, int x, int y, SkCanvas::Confi
      g8888 config8888) |  | 
|   417 { |  | 
|   418     if (paintingDisabled()) |  | 
|   419         return false; |  | 
|   420  |  | 
|   421     return m_canvas->readPixels(bitmap, x, y, config8888); |  | 
|   422 } |  | 
|   423  |  | 
|   424 void GraphicsContext::setMatrix(const SkMatrix& matrix) |  | 
|   425 { |  | 
|   426     if (paintingDisabled()) |  | 
|   427         return; |  | 
|   428  |  | 
|   429     realizeSave(SkCanvas::kMatrix_SaveFlag); |  | 
|   430  |  | 
|   431     m_canvas->setMatrix(matrix); |  | 
|   432 } |  | 
|   433  |  | 
|   434 bool GraphicsContext::concat(const SkMatrix& matrix) |  | 
|   435 { |  | 
|   436     if (paintingDisabled()) |  | 
|   437         return false; |  | 
|   438  |  | 
|   439     realizeSave(SkCanvas::kMatrix_SaveFlag); |  | 
|   440  |  | 
|   441     return m_canvas->concat(matrix); |  | 
|   442 } |  | 
|   443  |  | 
|   444 void GraphicsContext::beginTransparencyLayer(float opacity, const FloatRect* bou
      nds) |  | 
|   445 { |  | 
|   446     beginLayer(opacity, m_state->m_compositeOperator, bounds); |  | 
|   447 } |  | 
|   448  |  | 
|   449 void GraphicsContext::beginLayer(float opacity, CompositeOperator op, const Floa
      tRect* bounds, ColorFilter colorFilter) |  | 
|   450 { |  | 
|   451     if (paintingDisabled()) |  | 
|   452         return; |  | 
|   453  |  | 
|   454     // We need the "alpha" layer flag here because the base layer is opaque |  | 
|   455     // (the surface of the page) but layers on top may have transparent parts. |  | 
|   456     // Without explicitly setting the alpha flag, the layer will inherit the |  | 
|   457     // opaque setting of the base and some things won't work properly. |  | 
|   458     SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::k
      HasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag); |  | 
|   459  |  | 
|   460     SkPaint layerPaint; |  | 
|   461     layerPaint.setAlpha(static_cast<unsigned char>(opacity * 255)); |  | 
|   462     layerPaint.setXfermode(WebCoreCompositeToSkiaComposite(op, m_state->m_blendM
      ode).get()); |  | 
|   463     layerPaint.setColorFilter(WebCoreColorFilterToSkiaColorFilter(colorFilter).g
      et()); |  | 
|   464  |  | 
|   465     if (bounds) { |  | 
|   466         SkRect skBounds = WebCoreFloatRectToSKRect(*bounds); |  | 
|   467         saveLayer(&skBounds, &layerPaint, saveFlags); |  | 
|   468     } else { |  | 
|   469         saveLayer(0, &layerPaint, saveFlags); |  | 
|   470     } |  | 
|   471  |  | 
|   472 #if !ASSERT_DISABLED |  | 
|   473     ++m_layerCount; |  | 
|   474 #endif |  | 
|   475 } |  | 
|   476  |  | 
|   477 void GraphicsContext::endLayer() |  | 
|   478 { |  | 
|   479     if (paintingDisabled()) |  | 
|   480         return; |  | 
|   481  |  | 
|   482     restoreLayer(); |  | 
|   483  |  | 
|   484     ASSERT(m_layerCount > 0); |  | 
|   485 #if !ASSERT_DISABLED |  | 
|   486     --m_layerCount; |  | 
|   487 #endif |  | 
|   488 } |  | 
|   489  |  | 
|   490 void GraphicsContext::beginRecording(const FloatRect& bounds) |  | 
|   491 { |  | 
|   492     RefPtr<DisplayList> displayList = adoptRef(new DisplayList(bounds)); |  | 
|   493  |  | 
|   494     SkCanvas* savedCanvas = m_canvas; |  | 
|   495     SkMatrix savedMatrix = getTotalMatrix(); |  | 
|   496  |  | 
|   497     IntRect recordingRect = enclosingIntRect(bounds); |  | 
|   498     m_canvas = displayList->picture()->beginRecording(recordingRect.width(), rec
      ordingRect.height(), |  | 
|   499         SkPicture::kUsePathBoundsForClip_RecordingFlag); |  | 
|   500  |  | 
|   501     // We want the bounds offset mapped to (0, 0), such that the display list co
      ntent |  | 
|   502     // is fully contained within the SkPictureRecord's bounds. |  | 
|   503     if (!toFloatSize(bounds.location()).isZero()) { |  | 
|   504         m_canvas->translate(-bounds.x(), -bounds.y()); |  | 
|   505         // To avoid applying the offset repeatedly in getTotalMatrix(), we pre-a
      pply it here. |  | 
|   506         savedMatrix.preTranslate(bounds.x(), bounds.y()); |  | 
|   507     } |  | 
|   508  |  | 
|   509     m_recordingStateStack.append(RecordingState(savedCanvas, savedMatrix, displa
      yList)); |  | 
|   510 } |  | 
|   511  |  | 
|   512 PassRefPtr<DisplayList> GraphicsContext::endRecording() |  | 
|   513 { |  | 
|   514     ASSERT(!m_recordingStateStack.isEmpty()); |  | 
|   515  |  | 
|   516     RecordingState recording = m_recordingStateStack.last(); |  | 
|   517     ASSERT(recording.m_displayList->picture()->getRecordingCanvas()); |  | 
|   518     recording.m_displayList->picture()->endRecording(); |  | 
|   519  |  | 
|   520     m_recordingStateStack.removeLast(); |  | 
|   521     m_canvas = recording.m_savedCanvas; |  | 
|   522  |  | 
|   523     return recording.m_displayList.release(); |  | 
|   524 } |  | 
|   525  |  | 
|   526 bool GraphicsContext::isRecording() const |  | 
|   527 { |  | 
|   528     return !m_recordingStateStack.isEmpty(); |  | 
|   529 } |  | 
|   530  |  | 
|   531 void GraphicsContext::drawDisplayList(DisplayList* displayList) |  | 
|   532 { |  | 
|   533     ASSERT(!displayList->picture()->getRecordingCanvas()); |  | 
|   534  |  | 
|   535     if (paintingDisabled() || !displayList) |  | 
|   536         return; |  | 
|   537  |  | 
|   538     realizeSave(SkCanvas::kMatrixClip_SaveFlag); |  | 
|   539  |  | 
|   540     const FloatRect& bounds = displayList->bounds(); |  | 
|   541     if (bounds.x() || bounds.y()) |  | 
|   542         m_canvas->translate(bounds.x(), bounds.y()); |  | 
|   543  |  | 
|   544     m_canvas->drawPicture(*displayList->picture()); |  | 
|   545  |  | 
|   546     if (bounds.x() || bounds.y()) |  | 
|   547         m_canvas->translate(-bounds.x(), -bounds.y()); |  | 
|   548 } |  | 
|   549  |  | 
|   550 void GraphicsContext::setupPaintForFilling(SkPaint* paint) const |  | 
|   551 { |  | 
|   552     if (paintingDisabled()) |  | 
|   553         return; |  | 
|   554  |  | 
|   555     setupPaintCommon(paint); |  | 
|   556  |  | 
|   557     setupShader(paint, m_state->m_fillGradient.get(), m_state->m_fillPattern.get
      (), m_state->m_fillColor.rgb()); |  | 
|   558 } |  | 
|   559  |  | 
|   560 float GraphicsContext::setupPaintForStroking(SkPaint* paint, int length) const |  | 
|   561 { |  | 
|   562     if (paintingDisabled()) |  | 
|   563         return 0.0f; |  | 
|   564  |  | 
|   565     setupPaintCommon(paint); |  | 
|   566  |  | 
|   567     setupShader(paint, m_state->m_strokeData.gradient(), m_state->m_strokeData.p
      attern(), |  | 
|   568         m_state->m_strokeData.color().rgb()); |  | 
|   569  |  | 
|   570     return m_state->m_strokeData.setupPaint(paint, length); |  | 
|   571 } |  | 
|   572  |  | 
|   573 void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin
      ts, bool shouldAntialias) |  | 
|   574 { |  | 
|   575     if (paintingDisabled()) |  | 
|   576         return; |  | 
|   577  |  | 
|   578     if (numPoints <= 1) |  | 
|   579         return; |  | 
|   580  |  | 
|   581     SkPath path; |  | 
|   582     setPathFromConvexPoints(&path, numPoints, points); |  | 
|   583  |  | 
|   584     SkPaint paint; |  | 
|   585     setupPaintForFilling(&paint); |  | 
|   586     paint.setAntiAlias(shouldAntialias); |  | 
|   587     drawPath(path, paint); |  | 
|   588  |  | 
|   589     if (strokeStyle() != NoStroke) { |  | 
|   590         paint.reset(); |  | 
|   591         setupPaintForStroking(&paint); |  | 
|   592         drawPath(path, paint); |  | 
|   593     } |  | 
|   594 } |  | 
|   595  |  | 
|   596 // This method is only used to draw the little circles used in lists. |  | 
|   597 void GraphicsContext::drawEllipse(const IntRect& elipseRect) |  | 
|   598 { |  | 
|   599     if (paintingDisabled()) |  | 
|   600         return; |  | 
|   601  |  | 
|   602     SkRect rect = elipseRect; |  | 
|   603     SkPaint paint; |  | 
|   604     setupPaintForFilling(&paint); |  | 
|   605     drawOval(rect, paint); |  | 
|   606  |  | 
|   607     if (strokeStyle() != NoStroke) { |  | 
|   608         paint.reset(); |  | 
|   609         setupPaintForStroking(&paint); |  | 
|   610         drawOval(rect, paint); |  | 
|   611     } |  | 
|   612 } |  | 
|   613  |  | 
|   614 void GraphicsContext::drawFocusRing(const Path& focusRingPath, int width, int of
      fset, const Color& color) |  | 
|   615 { |  | 
|   616     // FIXME: Implement support for offset. |  | 
|   617     UNUSED_PARAM(offset); |  | 
|   618  |  | 
|   619     if (paintingDisabled()) |  | 
|   620         return; |  | 
|   621  |  | 
|   622     SkPaint paint; |  | 
|   623     paint.setAntiAlias(true); |  | 
|   624     paint.setStyle(SkPaint::kStroke_Style); |  | 
|   625     paint.setColor(color.rgb()); |  | 
|   626  |  | 
|   627     drawOuterPath(focusRingPath.skPath(), paint, width); |  | 
|   628     drawInnerPath(focusRingPath.skPath(), paint, width); |  | 
|   629 } |  | 
|   630  |  | 
|   631 void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
       offset, const Color& color) |  | 
|   632 { |  | 
|   633     if (paintingDisabled()) |  | 
|   634         return; |  | 
|   635  |  | 
|   636     unsigned rectCount = rects.size(); |  | 
|   637     if (!rectCount) |  | 
|   638         return; |  | 
|   639  |  | 
|   640     SkRegion focusRingRegion; |  | 
|   641     const int focusRingOutset = getFocusRingOutset(offset); |  | 
|   642     for (unsigned i = 0; i < rectCount; i++) { |  | 
|   643         SkIRect r = rects[i]; |  | 
|   644         r.inset(-focusRingOutset, -focusRingOutset); |  | 
|   645         focusRingRegion.op(r, SkRegion::kUnion_Op); |  | 
|   646     } |  | 
|   647  |  | 
|   648     SkPath path; |  | 
|   649     SkPaint paint; |  | 
|   650     paint.setAntiAlias(true); |  | 
|   651     paint.setStyle(SkPaint::kStroke_Style); |  | 
|   652  |  | 
|   653     paint.setColor(color.rgb()); |  | 
|   654     focusRingRegion.getBoundaryPath(&path); |  | 
|   655     drawOuterPath(path, paint, width); |  | 
|   656     drawInnerPath(path, paint, width); |  | 
|   657 } |  | 
|   658  |  | 
|   659 static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shado
      wBlur, int shadowSpread, const IntSize& shadowOffset) |  | 
|   660 { |  | 
|   661     IntRect bounds(holeRect); |  | 
|   662  |  | 
|   663     bounds.inflate(shadowBlur); |  | 
|   664  |  | 
|   665     if (shadowSpread < 0) |  | 
|   666         bounds.inflate(-shadowSpread); |  | 
|   667  |  | 
|   668     IntRect offsetBounds = bounds; |  | 
|   669     offsetBounds.move(-shadowOffset); |  | 
|   670     return unionRect(bounds, offsetBounds); |  | 
|   671 } |  | 
|   672  |  | 
|   673 void GraphicsContext::drawInnerShadow(const RoundedRect& rect, const Color& shad
      owColor, const IntSize shadowOffset, int shadowBlur, int shadowSpread, Edges cli
      ppedEdges) |  | 
|   674 { |  | 
|   675     IntRect holeRect(rect.rect()); |  | 
|   676     holeRect.inflate(-shadowSpread); |  | 
|   677  |  | 
|   678     if (holeRect.isEmpty()) { |  | 
|   679         if (rect.isRounded()) |  | 
|   680             fillRoundedRect(rect, shadowColor); |  | 
|   681         else |  | 
|   682             fillRect(rect.rect(), shadowColor); |  | 
|   683         return; |  | 
|   684     } |  | 
|   685  |  | 
|   686     if (clippedEdges & LeftEdge) { |  | 
|   687         holeRect.move(-max(shadowOffset.width(), 0) - shadowBlur, 0); |  | 
|   688         holeRect.setWidth(holeRect.width() + max(shadowOffset.width(), 0) + shad
      owBlur); |  | 
|   689     } |  | 
|   690     if (clippedEdges & TopEdge) { |  | 
|   691         holeRect.move(0, -max(shadowOffset.height(), 0) - shadowBlur); |  | 
|   692         holeRect.setHeight(holeRect.height() + max(shadowOffset.height(), 0) + s
      hadowBlur); |  | 
|   693     } |  | 
|   694     if (clippedEdges & RightEdge) |  | 
|   695         holeRect.setWidth(holeRect.width() - min(shadowOffset.width(), 0) + shad
      owBlur); |  | 
|   696     if (clippedEdges & BottomEdge) |  | 
|   697         holeRect.setHeight(holeRect.height() - min(shadowOffset.height(), 0) + s
      hadowBlur); |  | 
|   698  |  | 
|   699     Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 
      255); |  | 
|   700  |  | 
|   701     IntRect outerRect = areaCastingShadowInHole(rect.rect(), shadowBlur, shadowS
      pread, shadowOffset); |  | 
|   702     RoundedRect roundedHole(holeRect, rect.radii()); |  | 
|   703  |  | 
|   704     save(); |  | 
|   705     if (rect.isRounded()) { |  | 
|   706         Path path; |  | 
|   707         path.addRoundedRect(rect); |  | 
|   708         clipPath(path); |  | 
|   709         roundedHole.shrinkRadii(shadowSpread); |  | 
|   710     } else { |  | 
|   711         clip(rect.rect()); |  | 
|   712     } |  | 
|   713  |  | 
|   714     DrawLooper drawLooper; |  | 
|   715     drawLooper.addShadow(shadowOffset, shadowBlur, shadowColor, |  | 
|   716         DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha); |  | 
|   717     setDrawLooper(drawLooper); |  | 
|   718     fillRectWithRoundedHole(outerRect, roundedHole, fillColor); |  | 
|   719     restore(); |  | 
|   720     clearDrawLooper(); |  | 
|   721 } |  | 
|   722  |  | 
|   723 // This is only used to draw borders. |  | 
|   724 void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) |  | 
|   725 { |  | 
|   726     if (paintingDisabled()) |  | 
|   727         return; |  | 
|   728  |  | 
|   729     StrokeStyle penStyle = strokeStyle(); |  | 
|   730     if (penStyle == NoStroke) |  | 
|   731         return; |  | 
|   732  |  | 
|   733     SkPaint paint; |  | 
|   734     FloatPoint p1 = point1; |  | 
|   735     FloatPoint p2 = point2; |  | 
|   736     bool isVerticalLine = (p1.x() == p2.x()); |  | 
|   737     int width = roundf(strokeThickness()); |  | 
|   738  |  | 
|   739     // We know these are vertical or horizontal lines, so the length will just |  | 
|   740     // be the sum of the displacement component vectors give or take 1 - |  | 
|   741     // probably worth the speed up of no square root, which also won't be exact. |  | 
|   742     FloatSize disp = p2 - p1; |  | 
|   743     int length = SkScalarRound(disp.width() + disp.height()); |  | 
|   744     setupPaintForStroking(&paint, length); |  | 
|   745  |  | 
|   746     if (strokeStyle() == DottedStroke || strokeStyle() == DashedStroke) { |  | 
|   747         // Do a rect fill of our endpoints.  This ensures we always have the |  | 
|   748         // appearance of being a border.  We then draw the actual dotted/dashed 
      line. |  | 
|   749  |  | 
|   750         SkRect r1, r2; |  | 
|   751         r1.set(p1.x(), p1.y(), p1.x() + width, p1.y() + width); |  | 
|   752         r2.set(p2.x(), p2.y(), p2.x() + width, p2.y() + width); |  | 
|   753  |  | 
|   754         if (isVerticalLine) { |  | 
|   755             r1.offset(-width / 2, 0); |  | 
|   756             r2.offset(-width / 2, -width); |  | 
|   757         } else { |  | 
|   758             r1.offset(0, -width / 2); |  | 
|   759             r2.offset(-width, -width / 2); |  | 
|   760         } |  | 
|   761         SkPaint fillPaint; |  | 
|   762         fillPaint.setColor(paint.getColor()); |  | 
|   763         drawRect(r1, fillPaint); |  | 
|   764         drawRect(r2, fillPaint); |  | 
|   765     } |  | 
|   766  |  | 
|   767     adjustLineToPixelBoundaries(p1, p2, width, penStyle); |  | 
|   768     SkPoint pts[2] = { (SkPoint)p1, (SkPoint)p2 }; |  | 
|   769  |  | 
|   770     m_canvas->drawPoints(SkCanvas::kLines_PointMode, 2, pts, paint); |  | 
|   771  |  | 
|   772     if (m_trackOpaqueRegion) |  | 
|   773         m_opaqueRegion.didDrawPoints(this, SkCanvas::kLines_PointMode, 2, pts, p
      aint); |  | 
|   774 } |  | 
|   775  |  | 
|   776 void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, float widt
      h, DocumentMarkerLineStyle style) |  | 
|   777 { |  | 
|   778     if (paintingDisabled()) |  | 
|   779         return; |  | 
|   780  |  | 
|   781     int deviceScaleFactor = m_useHighResMarker ? 2 : 1; |  | 
|   782  |  | 
|   783     // Create the pattern we'll use to draw the underline. |  | 
|   784     int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0; |  | 
|   785     static SkBitmap* misspellBitmap1x[2] = { 0, 0 }; |  | 
|   786     static SkBitmap* misspellBitmap2x[2] = { 0, 0 }; |  | 
|   787     SkBitmap** misspellBitmap = deviceScaleFactor == 2 ? misspellBitmap2x : miss
      pellBitmap1x; |  | 
|   788     if (!misspellBitmap[index]) { |  | 
|   789 #if OS(MACOSX) |  | 
|   790         // Match the artwork used by the Mac. |  | 
|   791         const int rowPixels = 4 * deviceScaleFactor; |  | 
|   792         const int colPixels = 3 * deviceScaleFactor; |  | 
|   793         misspellBitmap[index] = new SkBitmap; |  | 
|   794         misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, |  | 
|   795                                          rowPixels, colPixels); |  | 
|   796         misspellBitmap[index]->allocPixels(); |  | 
|   797  |  | 
|   798         misspellBitmap[index]->eraseARGB(0, 0, 0, 0); |  | 
|   799         const uint32_t transparentColor = 0x00000000; |  | 
|   800  |  | 
|   801         if (deviceScaleFactor == 1) { |  | 
|   802             const uint32_t colors[2][6] = { |  | 
|   803                 { 0x2a2a0600, 0x57571000,  0xa8a81b00, 0xbfbf1f00,  0x70701200, 
      0xe0e02400 }, |  | 
|   804                 { 0x2a0f0f0f, 0x571e1e1e,  0xa83d3d3d, 0xbf454545,  0x70282828, 
      0xe0515151 } |  | 
|   805             }; |  | 
|   806  |  | 
|   807             // Pattern: a b a   a b a |  | 
|   808             //          c d c   c d c |  | 
|   809             //          e f e   e f e |  | 
|   810             for (int x = 0; x < colPixels; ++x) { |  | 
|   811                 uint32_t* row = misspellBitmap[index]->getAddr32(0, x); |  | 
|   812                 row[0] = colors[index][x * 2]; |  | 
|   813                 row[1] = colors[index][x * 2 + 1]; |  | 
|   814                 row[2] = colors[index][x * 2]; |  | 
|   815                 row[3] = transparentColor; |  | 
|   816             } |  | 
|   817         } else if (deviceScaleFactor == 2) { |  | 
|   818             const uint32_t colors[2][18] = { |  | 
|   819                 { 0x0a090101, 0x33320806, 0x55540f0a,  0x37360906, 0x6e6c120c, 0
      x6e6c120c,  0x7674140d, 0x8d8b1810, 0x8d8b1810, |  | 
|   820                   0x96941a11, 0xb3b01f15, 0xb3b01f15,  0x6d6b130c, 0xd9d62619, 0
      xd9d62619,  0x19180402, 0x7c7a150e, 0xcecb2418 }, |  | 
|   821                 { 0x0a020202, 0x33141414, 0x55232323,  0x37161616, 0x6e2e2e2e, 0
      x6e2e2e2e,  0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, |  | 
|   822                   0x963e3e3e, 0xb34b4b4b, 0xb34b4b4b,  0x6d2d2d2d, 0xd95b5b5b, 0
      xd95b5b5b,  0x19090909, 0x7c343434, 0xce575757 } |  | 
|   823             }; |  | 
|   824  |  | 
|   825             // Pattern: a b c c b a |  | 
|   826             //          d e f f e d |  | 
|   827             //          g h j j h g |  | 
|   828             //          k l m m l k |  | 
|   829             //          n o p p o n |  | 
|   830             //          q r s s r q |  | 
|   831             for (int x = 0; x < colPixels; ++x) { |  | 
|   832                 uint32_t* row = misspellBitmap[index]->getAddr32(0, x); |  | 
|   833                 row[0] = colors[index][x * 3]; |  | 
|   834                 row[1] = colors[index][x * 3 + 1]; |  | 
|   835                 row[2] = colors[index][x * 3 + 2]; |  | 
|   836                 row[3] = colors[index][x * 3 + 2]; |  | 
|   837                 row[4] = colors[index][x * 3 + 1]; |  | 
|   838                 row[5] = colors[index][x * 3]; |  | 
|   839                 row[6] = transparentColor; |  | 
|   840                 row[7] = transparentColor; |  | 
|   841             } |  | 
|   842         } else |  | 
|   843             ASSERT_NOT_REACHED(); |  | 
|   844 #else |  | 
|   845         // We use a 2-pixel-high misspelling indicator because that seems to be |  | 
|   846         // what WebKit is designed for, and how much room there is in a typical |  | 
|   847         // page for it. |  | 
|   848         const int rowPixels = 32 * deviceScaleFactor; // Must be multiple of 4 f
      or pattern below. |  | 
|   849         const int colPixels = 2 * deviceScaleFactor; |  | 
|   850         misspellBitmap[index] = new SkBitmap; |  | 
|   851         misspellBitmap[index]->setConfig(SkBitmap::kARGB_8888_Config, rowPixels,
       colPixels); |  | 
|   852         misspellBitmap[index]->allocPixels(); |  | 
|   853  |  | 
|   854         misspellBitmap[index]->eraseARGB(0, 0, 0, 0); |  | 
|   855         if (deviceScaleFactor == 1) |  | 
|   856             draw1xMarker(misspellBitmap[index], index); |  | 
|   857         else if (deviceScaleFactor == 2) |  | 
|   858             draw2xMarker(misspellBitmap[index], index); |  | 
|   859         else |  | 
|   860             ASSERT_NOT_REACHED(); |  | 
|   861 #endif |  | 
|   862     } |  | 
|   863  |  | 
|   864 #if OS(MACOSX) |  | 
|   865     SkScalar originX = WebCoreFloatToSkScalar(pt.x()) * deviceScaleFactor; |  | 
|   866     SkScalar originY = WebCoreFloatToSkScalar(pt.y()) * deviceScaleFactor; |  | 
|   867  |  | 
|   868     // Make sure to draw only complete dots. |  | 
|   869     int rowPixels = misspellBitmap[index]->width(); |  | 
|   870     float widthMod = fmodf(width * deviceScaleFactor, rowPixels); |  | 
|   871     if (rowPixels - widthMod > deviceScaleFactor) |  | 
|   872         width -= widthMod / deviceScaleFactor; |  | 
|   873 #else |  | 
|   874     SkScalar originX = WebCoreFloatToSkScalar(pt.x()); |  | 
|   875  |  | 
|   876     // Offset it vertically by 1 so that there's some space under the text. |  | 
|   877     SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; |  | 
|   878     originX *= deviceScaleFactor; |  | 
|   879     originY *= deviceScaleFactor; |  | 
|   880 #endif |  | 
|   881  |  | 
|   882     RefPtr<SkShader> shader = adoptRef(SkShader::CreateBitmapShader( |  | 
|   883         *misspellBitmap[index], SkShader::kRepeat_TileMode, SkShader::kRepeat_Ti
      leMode)); |  | 
|   884     SkMatrix matrix; |  | 
|   885     matrix.setTranslate(originX, originY); |  | 
|   886     shader->setLocalMatrix(matrix); |  | 
|   887  |  | 
|   888     SkPaint paint; |  | 
|   889     paint.setShader(shader.get()); |  | 
|   890  |  | 
|   891     SkRect rect; |  | 
|   892     rect.set(originX, originY, originX + WebCoreFloatToSkScalar(width) * deviceS
      caleFactor, originY + SkIntToScalar(misspellBitmap[index]->height())); |  | 
|   893  |  | 
|   894     if (deviceScaleFactor == 2) { |  | 
|   895         save(); |  | 
|   896         scale(FloatSize(0.5, 0.5)); |  | 
|   897     } |  | 
|   898     drawRect(rect, paint); |  | 
|   899     if (deviceScaleFactor == 2) |  | 
|   900         restore(); |  | 
|   901 } |  | 
|   902  |  | 
|   903 void GraphicsContext::drawLineForText(const FloatPoint& pt, float width, bool pr
      inting) |  | 
|   904 { |  | 
|   905     if (paintingDisabled()) |  | 
|   906         return; |  | 
|   907  |  | 
|   908     if (width <= 0) |  | 
|   909         return; |  | 
|   910  |  | 
|   911     int thickness = SkMax32(static_cast<int>(strokeThickness()), 1); |  | 
|   912     SkRect r; |  | 
|   913     r.fLeft = WebCoreFloatToSkScalar(pt.x()); |  | 
|   914     // Avoid anti-aliasing lines. Currently, these are always horizontal. |  | 
|   915     // Round to nearest pixel to match text and other content. |  | 
|   916     r.fTop = WebCoreFloatToSkScalar(floorf(pt.y() + 0.5f)); |  | 
|   917     r.fRight = r.fLeft + WebCoreFloatToSkScalar(width); |  | 
|   918     r.fBottom = r.fTop + SkIntToScalar(thickness); |  | 
|   919  |  | 
|   920     SkPaint paint; |  | 
|   921     switch (strokeStyle()) { |  | 
|   922     case NoStroke: |  | 
|   923     case SolidStroke: |  | 
|   924     case DoubleStroke: |  | 
|   925     case WavyStroke: |  | 
|   926         setupPaintForFilling(&paint); |  | 
|   927         break; |  | 
|   928     case DottedStroke: |  | 
|   929     case DashedStroke: |  | 
|   930         setupPaintForStroking(&paint); |  | 
|   931         break; |  | 
|   932     } |  | 
|   933  |  | 
|   934     // Text lines are drawn using the stroke color. |  | 
|   935     paint.setColor(effectiveStrokeColor()); |  | 
|   936     drawRect(r, paint); |  | 
|   937 } |  | 
|   938  |  | 
|   939 // Draws a filled rectangle with a stroked border. |  | 
|   940 void GraphicsContext::drawRect(const IntRect& rect) |  | 
|   941 { |  | 
|   942     if (paintingDisabled()) |  | 
|   943         return; |  | 
|   944  |  | 
|   945     ASSERT(!rect.isEmpty()); |  | 
|   946     if (rect.isEmpty()) |  | 
|   947         return; |  | 
|   948  |  | 
|   949     SkRect skRect = rect; |  | 
|   950     SkPaint paint; |  | 
|   951     int fillcolorNotTransparent = m_state->m_fillColor.rgb() & 0xFF000000; |  | 
|   952     if (fillcolorNotTransparent) { |  | 
|   953         setupPaintForFilling(&paint); |  | 
|   954         drawRect(skRect, paint); |  | 
|   955     } |  | 
|   956  |  | 
|   957     if (m_state->m_strokeData.style() != NoStroke && (m_state->m_strokeData.colo
      r().rgb() & 0xFF000000)) { |  | 
|   958         // We do a fill of four rects to simulate the stroke of a border. |  | 
|   959         paint.reset(); |  | 
|   960         setupPaintForFilling(&paint); |  | 
|   961         // need to jam in the strokeColor |  | 
|   962         paint.setColor(this->effectiveStrokeColor()); |  | 
|   963  |  | 
|   964         SkRect topBorder = { skRect.fLeft, skRect.fTop, skRect.fRight, skRect.fT
      op + 1 }; |  | 
|   965         drawRect(topBorder, paint); |  | 
|   966         SkRect bottomBorder = { skRect.fLeft, skRect.fBottom - 1, skRect.fRight,
       skRect.fBottom }; |  | 
|   967         drawRect(bottomBorder, paint); |  | 
|   968         SkRect leftBorder = { skRect.fLeft, skRect.fTop + 1, skRect.fLeft + 1, s
      kRect.fBottom - 1 }; |  | 
|   969         drawRect(leftBorder, paint); |  | 
|   970         SkRect rightBorder = { skRect.fRight - 1, skRect.fTop + 1, skRect.fRight
      , skRect.fBottom - 1 }; |  | 
|   971         drawRect(rightBorder, paint); |  | 
|   972     } |  | 
|   973 } |  | 
|   974  |  | 
|   975 void GraphicsContext::drawText(const Font& font, const TextRunPaintInfo& runInfo
      , const FloatPoint& point) |  | 
|   976 { |  | 
|   977     if (paintingDisabled()) |  | 
|   978         return; |  | 
|   979  |  | 
|   980     font.drawText(this, runInfo, point); |  | 
|   981 } |  | 
|   982  |  | 
|   983 void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRunPaintInfo
      & runInfo, const AtomicString& mark, const FloatPoint& point) |  | 
|   984 { |  | 
|   985     if (paintingDisabled()) |  | 
|   986         return; |  | 
|   987  |  | 
|   988     font.drawEmphasisMarks(this, runInfo, mark, point); |  | 
|   989 } |  | 
|   990  |  | 
|   991 void GraphicsContext::drawBidiText(const Font& font, const TextRunPaintInfo& run
      Info, const FloatPoint& point, Font::CustomFontNotReadyAction customFontNotReady
      Action) |  | 
|   992 { |  | 
|   993     if (paintingDisabled()) |  | 
|   994         return; |  | 
|   995  |  | 
|   996     // sub-run painting is not supported for Bidi text. |  | 
|   997     const TextRun& run = runInfo.run; |  | 
|   998     ASSERT((runInfo.from == 0) && (runInfo.to == run.length())); |  | 
|   999     BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver; |  | 
|  1000     bidiResolver.setStatus(BidiStatus(run.direction(), run.directionalOverride()
      )); |  | 
|  1001     bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&run, 0)); |  | 
|  1002  |  | 
|  1003     // FIXME: This ownership should be reversed. We should pass BidiRunList |  | 
|  1004     // to BidiResolver in createBidiRunsForLine. |  | 
|  1005     BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs(); |  | 
|  1006     bidiResolver.createBidiRunsForLine(TextRunIterator(&run, run.length())); |  | 
|  1007     if (!bidiRuns.runCount()) |  | 
|  1008         return; |  | 
|  1009  |  | 
|  1010     FloatPoint currPoint = point; |  | 
|  1011     BidiCharacterRun* bidiRun = bidiRuns.firstRun(); |  | 
|  1012     while (bidiRun) { |  | 
|  1013         TextRun subrun = run.subRun(bidiRun->start(), bidiRun->stop() - bidiRun-
      >start()); |  | 
|  1014         bool isRTL = bidiRun->level() % 2; |  | 
|  1015         subrun.setDirection(isRTL ? RTL : LTR); |  | 
|  1016         subrun.setDirectionalOverride(bidiRun->dirOverride(false)); |  | 
|  1017  |  | 
|  1018         TextRunPaintInfo subrunInfo(subrun); |  | 
|  1019         subrunInfo.bounds = runInfo.bounds; |  | 
|  1020         font.drawText(this, subrunInfo, currPoint, customFontNotReadyAction); |  | 
|  1021  |  | 
|  1022         bidiRun = bidiRun->next(); |  | 
|  1023         // FIXME: Have Font::drawText return the width of what it drew so that w
      e don't have to re-measure here. |  | 
|  1024         if (bidiRun) |  | 
|  1025             currPoint.move(font.width(subrun), 0); |  | 
|  1026     } |  | 
|  1027  |  | 
|  1028     bidiRuns.deleteRuns(); |  | 
|  1029 } |  | 
|  1030  |  | 
|  1031 void GraphicsContext::drawHighlightForText(const Font& font, const TextRun& run,
       const FloatPoint& point, int h, const Color& backgroundColor, int from, int to) |  | 
|  1032 { |  | 
|  1033     if (paintingDisabled()) |  | 
|  1034         return; |  | 
|  1035  |  | 
|  1036     fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor
      ); |  | 
|  1037 } |  | 
|  1038  |  | 
|  1039 void GraphicsContext::drawImage(Image* image, const IntPoint& p, CompositeOperat
      or op, RespectImageOrientationEnum shouldRespectImageOrientation) |  | 
|  1040 { |  | 
|  1041     if (!image) |  | 
|  1042         return; |  | 
|  1043     drawImage(image, FloatRect(IntRect(p, image->size())), FloatRect(FloatPoint(
      ), FloatSize(image->size())), op, shouldRespectImageOrientation); |  | 
|  1044 } |  | 
|  1045  |  | 
|  1046 void GraphicsContext::drawImage(Image* image, const IntRect& r, CompositeOperato
      r op, RespectImageOrientationEnum shouldRespectImageOrientation, bool useLowQual
      ityScale) |  | 
|  1047 { |  | 
|  1048     if (!image) |  | 
|  1049         return; |  | 
|  1050     drawImage(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image->size
      ())), op, shouldRespectImageOrientation, useLowQualityScale); |  | 
|  1051 } |  | 
|  1052  |  | 
|  1053 void GraphicsContext::drawImage(Image* image, const IntPoint& dest, const IntRec
      t& srcRect, CompositeOperator op, RespectImageOrientationEnum shouldRespectImage
      Orientation) |  | 
|  1054 { |  | 
|  1055     drawImage(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(srcRect
      ), op, shouldRespectImageOrientation); |  | 
|  1056 } |  | 
|  1057  |  | 
|  1058 void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
      Rect& src, CompositeOperator op, RespectImageOrientationEnum shouldRespectImageO
      rientation, bool useLowQualityScale) |  | 
|  1059 { |  | 
|  1060     drawImage(image, dest, src, op, blink::WebBlendModeNormal, shouldRespectImag
      eOrientation, useLowQualityScale); |  | 
|  1061 } |  | 
|  1062  |  | 
|  1063 void GraphicsContext::drawImage(Image* image, const FloatRect& dest) |  | 
|  1064 { |  | 
|  1065     if (!image) |  | 
|  1066         return; |  | 
|  1067     drawImage(image, dest, FloatRect(IntRect(IntPoint(), image->size()))); |  | 
|  1068 } |  | 
|  1069  |  | 
|  1070 void GraphicsContext::drawImage(Image* image, const FloatRect& dest, const Float
      Rect& src, CompositeOperator op, WebBlendMode blendMode, RespectImageOrientation
      Enum shouldRespectImageOrientation, bool useLowQualityScale) |  | 
|  1071 {    if (paintingDisabled() || !image) |  | 
|  1072         return; |  | 
|  1073  |  | 
|  1074     InterpolationQuality previousInterpolationQuality = InterpolationDefault; |  | 
|  1075  |  | 
|  1076     if (useLowQualityScale) { |  | 
|  1077         previousInterpolationQuality = imageInterpolationQuality(); |  | 
|  1078         setImageInterpolationQuality(InterpolationLow); |  | 
|  1079     } |  | 
|  1080  |  | 
|  1081     image->draw(this, dest, src, op, blendMode, shouldRespectImageOrientation); |  | 
|  1082  |  | 
|  1083     if (useLowQualityScale) |  | 
|  1084         setImageInterpolationQuality(previousInterpolationQuality); |  | 
|  1085 } |  | 
|  1086  |  | 
|  1087 void GraphicsContext::drawTiledImage(Image* image, const IntRect& destRect, cons
      t IntPoint& srcPoint, const IntSize& tileSize, CompositeOperator op, bool useLow
      QualityScale, WebBlendMode blendMode, const IntSize& repeatSpacing) |  | 
|  1088 { |  | 
|  1089     if (paintingDisabled() || !image) |  | 
|  1090         return; |  | 
|  1091  |  | 
|  1092     if (useLowQualityScale) { |  | 
|  1093         InterpolationQuality previousInterpolationQuality = imageInterpolationQu
      ality(); |  | 
|  1094         setImageInterpolationQuality(InterpolationLow); |  | 
|  1095         image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repe
      atSpacing); |  | 
|  1096         setImageInterpolationQuality(previousInterpolationQuality); |  | 
|  1097     } else { |  | 
|  1098         image->drawTiled(this, destRect, srcPoint, tileSize, op, blendMode, repe
      atSpacing); |  | 
|  1099     } |  | 
|  1100 } |  | 
|  1101  |  | 
|  1102 void GraphicsContext::drawTiledImage(Image* image, const IntRect& dest, const In
      tRect& srcRect, |  | 
|  1103     const FloatSize& tileScaleFactor, Image::TileRule hRule, Image::TileRule vRu
      le, CompositeOperator op, bool useLowQualityScale) |  | 
|  1104 { |  | 
|  1105     if (paintingDisabled() || !image) |  | 
|  1106         return; |  | 
|  1107  |  | 
|  1108     if (hRule == Image::StretchTile && vRule == Image::StretchTile) { |  | 
|  1109         // Just do a scale. |  | 
|  1110         drawImage(image, dest, srcRect, op); |  | 
|  1111         return; |  | 
|  1112     } |  | 
|  1113  |  | 
|  1114     if (useLowQualityScale) { |  | 
|  1115         InterpolationQuality previousInterpolationQuality = imageInterpolationQu
      ality(); |  | 
|  1116         setImageInterpolationQuality(InterpolationLow); |  | 
|  1117         image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op)
      ; |  | 
|  1118         setImageInterpolationQuality(previousInterpolationQuality); |  | 
|  1119     } else { |  | 
|  1120         image->drawTiled(this, dest, srcRect, tileScaleFactor, hRule, vRule, op)
      ; |  | 
|  1121     } |  | 
|  1122 } |  | 
|  1123  |  | 
|  1124 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& p, Com
      positeOperator op, WebBlendMode blendMode) |  | 
|  1125 { |  | 
|  1126     if (!image) |  | 
|  1127         return; |  | 
|  1128     drawImageBuffer(image, FloatRect(IntRect(p, image->logicalSize())), FloatRec
      t(FloatPoint(), FloatSize(image->logicalSize())), op, blendMode); |  | 
|  1129 } |  | 
|  1130  |  | 
|  1131 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& r, Comp
      ositeOperator op, WebBlendMode blendMode, bool useLowQualityScale) |  | 
|  1132 { |  | 
|  1133     if (!image) |  | 
|  1134         return; |  | 
|  1135     drawImageBuffer(image, FloatRect(r), FloatRect(FloatPoint(), FloatSize(image
      ->logicalSize())), op, blendMode, useLowQualityScale); |  | 
|  1136 } |  | 
|  1137  |  | 
|  1138 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntPoint& dest, 
      const IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode) |  | 
|  1139 { |  | 
|  1140     drawImageBuffer(image, FloatRect(IntRect(dest, srcRect.size())), FloatRect(s
      rcRect), op, blendMode); |  | 
|  1141 } |  | 
|  1142  |  | 
|  1143 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const IntRect& dest, c
      onst IntRect& srcRect, CompositeOperator op, WebBlendMode blendMode, bool useLow
      QualityScale) |  | 
|  1144 { |  | 
|  1145     drawImageBuffer(image, FloatRect(dest), FloatRect(srcRect), op, blendMode, u
      seLowQualityScale); |  | 
|  1146 } |  | 
|  1147  |  | 
|  1148 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest) |  | 
|  1149 { |  | 
|  1150     if (!image) |  | 
|  1151         return; |  | 
|  1152     drawImageBuffer(image, dest, FloatRect(IntRect(IntPoint(), image->logicalSiz
      e()))); |  | 
|  1153 } |  | 
|  1154  |  | 
|  1155 void GraphicsContext::drawImageBuffer(ImageBuffer* image, const FloatRect& dest,
       const FloatRect& src, CompositeOperator op, WebBlendMode blendMode, bool useLow
      QualityScale) |  | 
|  1156 { |  | 
|  1157     if (paintingDisabled() || !image) |  | 
|  1158         return; |  | 
|  1159  |  | 
|  1160     if (useLowQualityScale) { |  | 
|  1161         InterpolationQuality previousInterpolationQuality = imageInterpolationQu
      ality(); |  | 
|  1162         setImageInterpolationQuality(InterpolationLow); |  | 
|  1163         image->draw(this, dest, src, op, blendMode, useLowQualityScale); |  | 
|  1164         setImageInterpolationQuality(previousInterpolationQuality); |  | 
|  1165     } else { |  | 
|  1166         image->draw(this, dest, src, op, blendMode, useLowQualityScale); |  | 
|  1167     } |  | 
|  1168 } |  | 
|  1169  |  | 
|  1170 void GraphicsContext::writePixels(const SkBitmap& bitmap, int x, int y, SkCanvas
      ::Config8888 config8888) |  | 
|  1171 { |  | 
|  1172     if (paintingDisabled()) |  | 
|  1173         return; |  | 
|  1174  |  | 
|  1175     m_canvas->writePixels(bitmap, x, y, config8888); |  | 
|  1176  |  | 
|  1177     if (m_trackOpaqueRegion) { |  | 
|  1178         SkRect rect = SkRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); |  | 
|  1179         SkPaint paint; |  | 
|  1180  |  | 
|  1181         paint.setXfermodeMode(SkXfermode::kSrc_Mode); |  | 
|  1182         m_opaqueRegion.didDrawRect(this, rect, paint, &bitmap); |  | 
|  1183     } |  | 
|  1184 } |  | 
|  1185  |  | 
|  1186 void GraphicsContext::drawBitmap(const SkBitmap& bitmap, SkScalar left, SkScalar
       top, const SkPaint* paint) |  | 
|  1187 { |  | 
|  1188     if (paintingDisabled()) |  | 
|  1189         return; |  | 
|  1190  |  | 
|  1191     m_canvas->drawBitmap(bitmap, left, top, paint); |  | 
|  1192  |  | 
|  1193     if (m_trackOpaqueRegion) { |  | 
|  1194         SkRect rect = SkRect::MakeXYWH(left, top, bitmap.width(), bitmap.height(
      )); |  | 
|  1195         m_opaqueRegion.didDrawRect(this, rect, *paint, &bitmap); |  | 
|  1196     } |  | 
|  1197 } |  | 
|  1198  |  | 
|  1199 void GraphicsContext::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, |  | 
|  1200     const SkRect& dst, const SkPaint* paint) |  | 
|  1201 { |  | 
|  1202     if (paintingDisabled()) |  | 
|  1203         return; |  | 
|  1204  |  | 
|  1205     SkCanvas::DrawBitmapRectFlags flags = m_state->m_shouldClampToSourceRect ? S
      kCanvas::kNone_DrawBitmapRectFlag : SkCanvas::kBleed_DrawBitmapRectFlag; |  | 
|  1206  |  | 
|  1207     m_canvas->drawBitmapRectToRect(bitmap, src, dst, paint, flags); |  | 
|  1208  |  | 
|  1209     if (m_trackOpaqueRegion) |  | 
|  1210         m_opaqueRegion.didDrawRect(this, dst, *paint, &bitmap); |  | 
|  1211 } |  | 
|  1212  |  | 
|  1213 void GraphicsContext::drawOval(const SkRect& oval, const SkPaint& paint) |  | 
|  1214 { |  | 
|  1215     if (paintingDisabled()) |  | 
|  1216         return; |  | 
|  1217  |  | 
|  1218     m_canvas->drawOval(oval, paint); |  | 
|  1219  |  | 
|  1220     if (m_trackOpaqueRegion) |  | 
|  1221         m_opaqueRegion.didDrawBounded(this, oval, paint); |  | 
|  1222 } |  | 
|  1223  |  | 
|  1224 void GraphicsContext::drawPath(const SkPath& path, const SkPaint& paint) |  | 
|  1225 { |  | 
|  1226     if (paintingDisabled()) |  | 
|  1227         return; |  | 
|  1228  |  | 
|  1229     m_canvas->drawPath(path, paint); |  | 
|  1230  |  | 
|  1231     if (m_trackOpaqueRegion) |  | 
|  1232         m_opaqueRegion.didDrawPath(this, path, paint); |  | 
|  1233 } |  | 
|  1234  |  | 
|  1235 void GraphicsContext::drawRect(const SkRect& rect, const SkPaint& paint) |  | 
|  1236 { |  | 
|  1237     if (paintingDisabled()) |  | 
|  1238         return; |  | 
|  1239  |  | 
|  1240     m_canvas->drawRect(rect, paint); |  | 
|  1241  |  | 
|  1242     if (m_trackOpaqueRegion) |  | 
|  1243         m_opaqueRegion.didDrawRect(this, rect, paint, 0); |  | 
|  1244 } |  | 
|  1245  |  | 
|  1246 void GraphicsContext::didDrawRect(const SkRect& rect, const SkPaint& paint, cons
      t SkBitmap* bitmap) |  | 
|  1247 { |  | 
|  1248     if (m_trackOpaqueRegion) |  | 
|  1249         m_opaqueRegion.didDrawRect(this, rect, paint, bitmap); |  | 
|  1250 } |  | 
|  1251  |  | 
|  1252 void GraphicsContext::drawPosText(const void* text, size_t byteLength, |  | 
|  1253     const SkPoint pos[],  const SkRect& textRect, const SkPaint& paint) |  | 
|  1254 { |  | 
|  1255     if (paintingDisabled()) |  | 
|  1256         return; |  | 
|  1257  |  | 
|  1258     m_canvas->drawPosText(text, byteLength, pos, paint); |  | 
|  1259     didDrawTextInRect(textRect); |  | 
|  1260  |  | 
|  1261     // FIXME: compute bounds for positioned text. |  | 
|  1262     if (m_trackOpaqueRegion) |  | 
|  1263         m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStr
      oke); |  | 
|  1264 } |  | 
|  1265  |  | 
|  1266 void GraphicsContext::drawPosTextH(const void* text, size_t byteLength, |  | 
|  1267     const SkScalar xpos[], SkScalar constY,  const SkRect& textRect, const SkPai
      nt& paint) |  | 
|  1268 { |  | 
|  1269     if (paintingDisabled()) |  | 
|  1270         return; |  | 
|  1271  |  | 
|  1272     m_canvas->drawPosTextH(text, byteLength, xpos, constY, paint); |  | 
|  1273     didDrawTextInRect(textRect); |  | 
|  1274  |  | 
|  1275     // FIXME: compute bounds for positioned text. |  | 
|  1276     if (m_trackOpaqueRegion) |  | 
|  1277         m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStr
      oke); |  | 
|  1278 } |  | 
|  1279  |  | 
|  1280 void GraphicsContext::drawTextOnPath(const void* text, size_t byteLength, |  | 
|  1281     const SkPath& path,  const SkRect& textRect, const SkMatrix* matrix, const S
      kPaint& paint) |  | 
|  1282 { |  | 
|  1283     if (paintingDisabled()) |  | 
|  1284         return; |  | 
|  1285  |  | 
|  1286     m_canvas->drawTextOnPath(text, byteLength, path, matrix, paint); |  | 
|  1287     didDrawTextInRect(textRect); |  | 
|  1288  |  | 
|  1289     // FIXME: compute bounds for positioned text. |  | 
|  1290     if (m_trackOpaqueRegion) |  | 
|  1291         m_opaqueRegion.didDrawUnbounded(this, paint, OpaqueRegionSkia::FillOrStr
      oke); |  | 
|  1292 } |  | 
|  1293  |  | 
|  1294 void GraphicsContext::fillPath(const Path& pathToFill) |  | 
|  1295 { |  | 
|  1296     if (paintingDisabled() || pathToFill.isEmpty()) |  | 
|  1297         return; |  | 
|  1298  |  | 
|  1299     // Use const_cast and temporarily modify the fill type instead of copying th
      e path. |  | 
|  1300     SkPath& path = const_cast<SkPath&>(pathToFill.skPath()); |  | 
|  1301     SkPath::FillType previousFillType = path.getFillType(); |  | 
|  1302  |  | 
|  1303     SkPath::FillType temporaryFillType = m_state->m_fillRule == RULE_EVENODD ? S
      kPath::kEvenOdd_FillType : SkPath::kWinding_FillType; |  | 
|  1304     path.setFillType(temporaryFillType); |  | 
|  1305  |  | 
|  1306     SkPaint paint; |  | 
|  1307     setupPaintForFilling(&paint); |  | 
|  1308     drawPath(path, paint); |  | 
|  1309  |  | 
|  1310     path.setFillType(previousFillType); |  | 
|  1311 } |  | 
|  1312  |  | 
|  1313 void GraphicsContext::fillRect(const FloatRect& rect) |  | 
|  1314 { |  | 
|  1315     if (paintingDisabled()) |  | 
|  1316         return; |  | 
|  1317  |  | 
|  1318     SkRect r = rect; |  | 
|  1319  |  | 
|  1320     SkPaint paint; |  | 
|  1321     setupPaintForFilling(&paint); |  | 
|  1322     drawRect(r, paint); |  | 
|  1323 } |  | 
|  1324  |  | 
|  1325 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color) |  | 
|  1326 { |  | 
|  1327     if (paintingDisabled()) |  | 
|  1328         return; |  | 
|  1329  |  | 
|  1330     SkRect r = rect; |  | 
|  1331     SkPaint paint; |  | 
|  1332     setupPaintCommon(&paint); |  | 
|  1333     paint.setColor(color.rgb()); |  | 
|  1334     drawRect(r, paint); |  | 
|  1335 } |  | 
|  1336  |  | 
|  1337 void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
      t, const IntSize& topRight, |  | 
|  1338     const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color) |  | 
|  1339 { |  | 
|  1340     if (paintingDisabled()) |  | 
|  1341         return; |  | 
|  1342  |  | 
|  1343     if (topLeft.width() + topRight.width() > rect.width() |  | 
|  1344             || bottomLeft.width() + bottomRight.width() > rect.width() |  | 
|  1345             || topLeft.height() + bottomLeft.height() > rect.height() |  | 
|  1346             || topRight.height() + bottomRight.height() > rect.height()) { |  | 
|  1347         // Not all the radii fit, return a rect. This matches the behavior of |  | 
|  1348         // Path::createRoundedRectangle. Without this we attempt to draw a round |  | 
|  1349         // shadow for a square box. |  | 
|  1350         fillRect(rect, color); |  | 
|  1351         return; |  | 
|  1352     } |  | 
|  1353  |  | 
|  1354     SkVector radii[4]; |  | 
|  1355     setRadii(radii, topLeft, topRight, bottomRight, bottomLeft); |  | 
|  1356  |  | 
|  1357     SkRRect rr; |  | 
|  1358     rr.setRectRadii(rect, radii); |  | 
|  1359  |  | 
|  1360     SkPaint paint; |  | 
|  1361     setupPaintForFilling(&paint); |  | 
|  1362     paint.setColor(color.rgb()); |  | 
|  1363  |  | 
|  1364     m_canvas->drawRRect(rr, paint); |  | 
|  1365  |  | 
|  1366     if (m_trackOpaqueRegion) |  | 
|  1367         m_opaqueRegion.didDrawBounded(this, rr.getBounds(), paint); |  | 
|  1368 } |  | 
|  1369  |  | 
|  1370 void GraphicsContext::fillEllipse(const FloatRect& ellipse) |  | 
|  1371 { |  | 
|  1372     if (paintingDisabled()) |  | 
|  1373         return; |  | 
|  1374  |  | 
|  1375     SkRect rect = ellipse; |  | 
|  1376     SkPaint paint; |  | 
|  1377     setupPaintForFilling(&paint); |  | 
|  1378     drawOval(rect, paint); |  | 
|  1379 } |  | 
|  1380  |  | 
|  1381 void GraphicsContext::strokePath(const Path& pathToStroke) |  | 
|  1382 { |  | 
|  1383     if (paintingDisabled() || pathToStroke.isEmpty()) |  | 
|  1384         return; |  | 
|  1385  |  | 
|  1386     const SkPath& path = pathToStroke.skPath(); |  | 
|  1387     SkPaint paint; |  | 
|  1388     setupPaintForStroking(&paint); |  | 
|  1389     drawPath(path, paint); |  | 
|  1390 } |  | 
|  1391  |  | 
|  1392 void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth) |  | 
|  1393 { |  | 
|  1394     if (paintingDisabled()) |  | 
|  1395         return; |  | 
|  1396  |  | 
|  1397     SkPaint paint; |  | 
|  1398     setupPaintForStroking(&paint); |  | 
|  1399     paint.setStrokeWidth(WebCoreFloatToSkScalar(lineWidth)); |  | 
|  1400     // strokerect has special rules for CSS when the rect is degenerate: |  | 
|  1401     // if width==0 && height==0, do nothing |  | 
|  1402     // if width==0 || height==0, then just draw line for the other dimension |  | 
|  1403     SkRect r(rect); |  | 
|  1404     bool validW = r.width() > 0; |  | 
|  1405     bool validH = r.height() > 0; |  | 
|  1406     if (validW && validH) { |  | 
|  1407         drawRect(r, paint); |  | 
|  1408     } else if (validW || validH) { |  | 
|  1409         // we are expected to respect the lineJoin, so we can't just call |  | 
|  1410         // drawLine -- we have to create a path that doubles back on itself. |  | 
|  1411         SkPath path; |  | 
|  1412         path.moveTo(r.fLeft, r.fTop); |  | 
|  1413         path.lineTo(r.fRight, r.fBottom); |  | 
|  1414         path.close(); |  | 
|  1415         drawPath(path, paint); |  | 
|  1416     } |  | 
|  1417 } |  | 
|  1418  |  | 
|  1419 void GraphicsContext::strokeEllipse(const FloatRect& ellipse) |  | 
|  1420 { |  | 
|  1421     if (paintingDisabled()) |  | 
|  1422         return; |  | 
|  1423  |  | 
|  1424     SkRect rect(ellipse); |  | 
|  1425     SkPaint paint; |  | 
|  1426     setupPaintForStroking(&paint); |  | 
|  1427     drawOval(rect, paint); |  | 
|  1428 } |  | 
|  1429  |  | 
|  1430 void GraphicsContext::clipRoundedRect(const RoundedRect& rect) |  | 
|  1431 { |  | 
|  1432     if (paintingDisabled()) |  | 
|  1433         return; |  | 
|  1434  |  | 
|  1435     SkVector radii[4]; |  | 
|  1436     RoundedRect::Radii wkRadii = rect.radii(); |  | 
|  1437     setRadii(radii, wkRadii.topLeft(), wkRadii.topRight(), wkRadii.bottomRight()
      , wkRadii.bottomLeft()); |  | 
|  1438  |  | 
|  1439     SkRRect r; |  | 
|  1440     r.setRectRadii(rect.rect(), radii); |  | 
|  1441  |  | 
|  1442     clipRRect(r, AntiAliased); |  | 
|  1443 } |  | 
|  1444  |  | 
|  1445 void GraphicsContext::clipOut(const Path& pathToClip) |  | 
|  1446 { |  | 
|  1447     if (paintingDisabled()) |  | 
|  1448         return; |  | 
|  1449  |  | 
|  1450     // Use const_cast and temporarily toggle the inverse fill type instead of co
      pying the path. |  | 
|  1451     SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |  | 
|  1452     path.toggleInverseFillType(); |  | 
|  1453     clipPath(path, AntiAliased); |  | 
|  1454     path.toggleInverseFillType(); |  | 
|  1455 } |  | 
|  1456  |  | 
|  1457 void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule) |  | 
|  1458 { |  | 
|  1459     if (paintingDisabled() || pathToClip.isEmpty()) |  | 
|  1460         return; |  | 
|  1461  |  | 
|  1462     // Use const_cast and temporarily modify the fill type instead of copying th
      e path. |  | 
|  1463     SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |  | 
|  1464     SkPath::FillType previousFillType = path.getFillType(); |  | 
|  1465  |  | 
|  1466     SkPath::FillType temporaryFillType = clipRule == RULE_EVENODD ? SkPath::kEve
      nOdd_FillType : SkPath::kWinding_FillType; |  | 
|  1467     path.setFillType(temporaryFillType); |  | 
|  1468     clipPath(path, AntiAliased); |  | 
|  1469  |  | 
|  1470     path.setFillType(previousFillType); |  | 
|  1471 } |  | 
|  1472  |  | 
|  1473 void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
      ts, bool antialiased) |  | 
|  1474 { |  | 
|  1475     if (paintingDisabled()) |  | 
|  1476         return; |  | 
|  1477  |  | 
|  1478     if (numPoints <= 1) |  | 
|  1479         return; |  | 
|  1480  |  | 
|  1481     SkPath path; |  | 
|  1482     setPathFromConvexPoints(&path, numPoints, points); |  | 
|  1483     clipPath(path, antialiased ? AntiAliased : NotAntiAliased); |  | 
|  1484 } |  | 
|  1485  |  | 
|  1486 void GraphicsContext::clipOutRoundedRect(const RoundedRect& rect) |  | 
|  1487 { |  | 
|  1488     if (paintingDisabled()) |  | 
|  1489         return; |  | 
|  1490  |  | 
|  1491     if (!rect.isRounded()) { |  | 
|  1492         clipOut(rect.rect()); |  | 
|  1493         return; |  | 
|  1494     } |  | 
|  1495  |  | 
|  1496     Path path; |  | 
|  1497     path.addRoundedRect(rect); |  | 
|  1498     clipOut(path); |  | 
|  1499 } |  | 
|  1500  |  | 
|  1501 void GraphicsContext::canvasClip(const Path& pathToClip, WindRule clipRule) |  | 
|  1502 { |  | 
|  1503     if (paintingDisabled()) |  | 
|  1504         return; |  | 
|  1505  |  | 
|  1506     // Use const_cast and temporarily modify the fill type instead of copying th
      e path. |  | 
|  1507     SkPath& path = const_cast<SkPath&>(pathToClip.skPath()); |  | 
|  1508     SkPath::FillType previousFillType = path.getFillType(); |  | 
|  1509  |  | 
|  1510     SkPath::FillType temporaryFillType = clipRule == RULE_EVENODD ? SkPath::kEve
      nOdd_FillType : SkPath::kWinding_FillType; |  | 
|  1511     path.setFillType(temporaryFillType); |  | 
|  1512     clipPath(path); |  | 
|  1513  |  | 
|  1514     path.setFillType(previousFillType); |  | 
|  1515 } |  | 
|  1516  |  | 
|  1517 bool GraphicsContext::clipRect(const SkRect& rect, AntiAliasingMode aa, SkRegion
      ::Op op) |  | 
|  1518 { |  | 
|  1519     if (paintingDisabled()) |  | 
|  1520         return false; |  | 
|  1521  |  | 
|  1522     realizeSave(SkCanvas::kClip_SaveFlag); |  | 
|  1523  |  | 
|  1524     return m_canvas->clipRect(rect, op, aa == AntiAliased); |  | 
|  1525 } |  | 
|  1526  |  | 
|  1527 bool GraphicsContext::clipPath(const SkPath& path, AntiAliasingMode aa, SkRegion
      ::Op op) |  | 
|  1528 { |  | 
|  1529     if (paintingDisabled()) |  | 
|  1530         return false; |  | 
|  1531  |  | 
|  1532     realizeSave(SkCanvas::kClip_SaveFlag); |  | 
|  1533  |  | 
|  1534     return m_canvas->clipPath(path, op, aa == AntiAliased); |  | 
|  1535 } |  | 
|  1536  |  | 
|  1537 bool GraphicsContext::clipRRect(const SkRRect& rect, AntiAliasingMode aa, SkRegi
      on::Op op) |  | 
|  1538 { |  | 
|  1539     if (paintingDisabled()) |  | 
|  1540         return false; |  | 
|  1541  |  | 
|  1542     realizeSave(SkCanvas::kClip_SaveFlag); |  | 
|  1543  |  | 
|  1544     return m_canvas->clipRRect(rect, op, aa == AntiAliased); |  | 
|  1545 } |  | 
|  1546  |  | 
|  1547 void GraphicsContext::rotate(float angleInRadians) |  | 
|  1548 { |  | 
|  1549     if (paintingDisabled()) |  | 
|  1550         return; |  | 
|  1551  |  | 
|  1552     realizeSave(SkCanvas::kMatrix_SaveFlag); |  | 
|  1553  |  | 
|  1554     m_canvas->rotate(WebCoreFloatToSkScalar(angleInRadians * (180.0f / 3.1415926
      5f))); |  | 
|  1555 } |  | 
|  1556  |  | 
|  1557 void GraphicsContext::translate(float w, float h) |  | 
|  1558 { |  | 
|  1559     if (paintingDisabled()) |  | 
|  1560         return; |  | 
|  1561  |  | 
|  1562     realizeSave(SkCanvas::kMatrix_SaveFlag); |  | 
|  1563  |  | 
|  1564     m_canvas->translate(WebCoreFloatToSkScalar(w), WebCoreFloatToSkScalar(h)); |  | 
|  1565 } |  | 
|  1566  |  | 
|  1567 void GraphicsContext::scale(const FloatSize& size) |  | 
|  1568 { |  | 
|  1569     if (paintingDisabled()) |  | 
|  1570         return; |  | 
|  1571  |  | 
|  1572     realizeSave(SkCanvas::kMatrix_SaveFlag); |  | 
|  1573  |  | 
|  1574     m_canvas->scale(WebCoreFloatToSkScalar(size.width()), WebCoreFloatToSkScalar
      (size.height())); |  | 
|  1575 } |  | 
|  1576  |  | 
|  1577 void GraphicsContext::setURLForRect(const KURL& link, const IntRect& destRect) |  | 
|  1578 { |  | 
|  1579     if (paintingDisabled()) |  | 
|  1580         return; |  | 
|  1581  |  | 
|  1582     SkAutoDataUnref url(SkData::NewWithCString(link.string().utf8().data())); |  | 
|  1583     SkAnnotateRectWithURL(m_canvas, destRect, url.get()); |  | 
|  1584 } |  | 
|  1585  |  | 
|  1586 void GraphicsContext::setURLFragmentForRect(const String& destName, const IntRec
      t& rect) |  | 
|  1587 { |  | 
|  1588     if (paintingDisabled()) |  | 
|  1589         return; |  | 
|  1590  |  | 
|  1591     SkAutoDataUnref skDestName(SkData::NewWithCString(destName.utf8().data())); |  | 
|  1592     SkAnnotateLinkToDestination(m_canvas, rect, skDestName.get()); |  | 
|  1593 } |  | 
|  1594  |  | 
|  1595 void GraphicsContext::addURLTargetAtPoint(const String& name, const IntPoint& po
      s) |  | 
|  1596 { |  | 
|  1597     if (paintingDisabled()) |  | 
|  1598         return; |  | 
|  1599  |  | 
|  1600     SkAutoDataUnref nameData(SkData::NewWithCString(name.utf8().data())); |  | 
|  1601     SkAnnotateNamedDestination(m_canvas, SkPoint::Make(pos.x(), pos.y()), nameDa
      ta); |  | 
|  1602 } |  | 
|  1603  |  | 
|  1604 AffineTransform GraphicsContext::getCTM(IncludeDeviceScale) const |  | 
|  1605 { |  | 
|  1606     if (paintingDisabled()) |  | 
|  1607         return AffineTransform(); |  | 
|  1608  |  | 
|  1609     SkMatrix m = getTotalMatrix(); |  | 
|  1610     return AffineTransform(SkScalarToDouble(m.getScaleX()), |  | 
|  1611                            SkScalarToDouble(m.getSkewY()), |  | 
|  1612                            SkScalarToDouble(m.getSkewX()), |  | 
|  1613                            SkScalarToDouble(m.getScaleY()), |  | 
|  1614                            SkScalarToDouble(m.getTranslateX()), |  | 
|  1615                            SkScalarToDouble(m.getTranslateY())); |  | 
|  1616 } |  | 
|  1617  |  | 
|  1618 void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, Compos
      iteOperator op) |  | 
|  1619 { |  | 
|  1620     if (paintingDisabled()) |  | 
|  1621         return; |  | 
|  1622  |  | 
|  1623     CompositeOperator previousOperator = compositeOperation(); |  | 
|  1624     setCompositeOperation(op); |  | 
|  1625     fillRect(rect, color); |  | 
|  1626     setCompositeOperation(previousOperator); |  | 
|  1627 } |  | 
|  1628  |  | 
|  1629 void GraphicsContext::fillRoundedRect(const RoundedRect& rect, const Color& colo
      r) |  | 
|  1630 { |  | 
|  1631     if (rect.isRounded()) |  | 
|  1632         fillRoundedRect(rect.rect(), rect.radii().topLeft(), rect.radii().topRig
      ht(), rect.radii().bottomLeft(), rect.radii().bottomRight(), color); |  | 
|  1633     else |  | 
|  1634         fillRect(rect.rect(), color); |  | 
|  1635 } |  | 
|  1636  |  | 
|  1637 void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
      Rect& roundedHoleRect, const Color& color) |  | 
|  1638 { |  | 
|  1639     if (paintingDisabled()) |  | 
|  1640         return; |  | 
|  1641  |  | 
|  1642     Path path; |  | 
|  1643     path.addRect(rect); |  | 
|  1644  |  | 
|  1645     if (!roundedHoleRect.radii().isZero()) |  | 
|  1646         path.addRoundedRect(roundedHoleRect); |  | 
|  1647     else |  | 
|  1648         path.addRect(roundedHoleRect.rect()); |  | 
|  1649  |  | 
|  1650     WindRule oldFillRule = fillRule(); |  | 
|  1651     Color oldFillColor = fillColor(); |  | 
|  1652  |  | 
|  1653     setFillRule(RULE_EVENODD); |  | 
|  1654     setFillColor(color); |  | 
|  1655  |  | 
|  1656     fillPath(path); |  | 
|  1657  |  | 
|  1658     setFillRule(oldFillRule); |  | 
|  1659     setFillColor(oldFillColor); |  | 
|  1660 } |  | 
|  1661  |  | 
|  1662 void GraphicsContext::clearRect(const FloatRect& rect) |  | 
|  1663 { |  | 
|  1664     if (paintingDisabled()) |  | 
|  1665         return; |  | 
|  1666  |  | 
|  1667     SkRect r = rect; |  | 
|  1668     SkPaint paint; |  | 
|  1669     setupPaintForFilling(&paint); |  | 
|  1670     paint.setXfermodeMode(SkXfermode::kClear_Mode); |  | 
|  1671     drawRect(r, paint); |  | 
|  1672 } |  | 
|  1673  |  | 
|  1674 void GraphicsContext::adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2
      , float strokeWidth, StrokeStyle penStyle) |  | 
|  1675 { |  | 
|  1676     // For odd widths, we add in 0.5 to the appropriate x/y so that the float ar
      ithmetic |  | 
|  1677     // works out.  For example, with a border width of 3, WebKit will pass us (y
      1+y2)/2, e.g., |  | 
|  1678     // (50+53)/2 = 103/2 = 51 when we want 51.5.  It is always true that an even
       width gave |  | 
|  1679     // us a perfect position, but an odd width gave us a position that is off by
       exactly 0.5. |  | 
|  1680     if (penStyle == DottedStroke || penStyle == DashedStroke) { |  | 
|  1681         if (p1.x() == p2.x()) { |  | 
|  1682             p1.setY(p1.y() + strokeWidth); |  | 
|  1683             p2.setY(p2.y() - strokeWidth); |  | 
|  1684         } else { |  | 
|  1685             p1.setX(p1.x() + strokeWidth); |  | 
|  1686             p2.setX(p2.x() - strokeWidth); |  | 
|  1687         } |  | 
|  1688     } |  | 
|  1689  |  | 
|  1690     if (static_cast<int>(strokeWidth) % 2) { //odd |  | 
|  1691         if (p1.x() == p2.x()) { |  | 
|  1692             // We're a vertical line.  Adjust our x. |  | 
|  1693             p1.setX(p1.x() + 0.5f); |  | 
|  1694             p2.setX(p2.x() + 0.5f); |  | 
|  1695         } else { |  | 
|  1696             // We're a horizontal line. Adjust our y. |  | 
|  1697             p1.setY(p1.y() + 0.5f); |  | 
|  1698             p2.setY(p2.y() + 0.5f); |  | 
|  1699         } |  | 
|  1700     } |  | 
|  1701 } |  | 
|  1702  |  | 
|  1703 PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& s
      ize, bool hasAlpha) const |  | 
|  1704 { |  | 
|  1705     // Make the buffer larger if the context's transform is scaling it so we nee
      d a higher |  | 
|  1706     // resolution than one pixel per unit. Also set up a corresponding scale fac
      tor on the |  | 
|  1707     // graphics context. |  | 
|  1708  |  | 
|  1709     AffineTransform transform = getCTM(DefinitelyIncludeDeviceScale); |  | 
|  1710     IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale()))
      , static_cast<int>(ceil(size.height() * transform.yScale()))); |  | 
|  1711  |  | 
|  1712     OwnPtr<ImageBuffer> buffer = ImageBuffer::createCompatibleBuffer(scaledSize,
       1, this, hasAlpha); |  | 
|  1713     if (!buffer) |  | 
|  1714         return nullptr; |  | 
|  1715  |  | 
|  1716     buffer->context()->scale(FloatSize(static_cast<float>(scaledSize.width()) / 
      size.width(), |  | 
|  1717         static_cast<float>(scaledSize.height()) / size.height())); |  | 
|  1718  |  | 
|  1719     return buffer.release(); |  | 
|  1720 } |  | 
|  1721  |  | 
|  1722 void GraphicsContext::addCornerArc(SkPath* path, const SkRect& rect, const IntSi
      ze& size, int startAngle) |  | 
|  1723 { |  | 
|  1724     SkIRect ir; |  | 
|  1725     int rx = SkMin32(SkScalarRound(rect.width()), size.width()); |  | 
|  1726     int ry = SkMin32(SkScalarRound(rect.height()), size.height()); |  | 
|  1727  |  | 
|  1728     ir.set(-rx, -ry, rx, ry); |  | 
|  1729     switch (startAngle) { |  | 
|  1730     case 0: |  | 
|  1731         ir.offset(rect.fRight - ir.fRight, rect.fBottom - ir.fBottom); |  | 
|  1732         break; |  | 
|  1733     case 90: |  | 
|  1734         ir.offset(rect.fLeft - ir.fLeft, rect.fBottom - ir.fBottom); |  | 
|  1735         break; |  | 
|  1736     case 180: |  | 
|  1737         ir.offset(rect.fLeft - ir.fLeft, rect.fTop - ir.fTop); |  | 
|  1738         break; |  | 
|  1739     case 270: |  | 
|  1740         ir.offset(rect.fRight - ir.fRight, rect.fTop - ir.fTop); |  | 
|  1741         break; |  | 
|  1742     default: |  | 
|  1743         ASSERT(0); |  | 
|  1744     } |  | 
|  1745  |  | 
|  1746     SkRect r; |  | 
|  1747     r.set(ir); |  | 
|  1748     path->arcTo(r, SkIntToScalar(startAngle), SkIntToScalar(90), false); |  | 
|  1749 } |  | 
|  1750  |  | 
|  1751 void GraphicsContext::setPathFromConvexPoints(SkPath* path, size_t numPoints, co
      nst FloatPoint* points) |  | 
|  1752 { |  | 
|  1753     path->incReserve(numPoints); |  | 
|  1754     path->moveTo(WebCoreFloatToSkScalar(points[0].x()), |  | 
|  1755                  WebCoreFloatToSkScalar(points[0].y())); |  | 
|  1756     for (size_t i = 1; i < numPoints; ++i) { |  | 
|  1757         path->lineTo(WebCoreFloatToSkScalar(points[i].x()), |  | 
|  1758                      WebCoreFloatToSkScalar(points[i].y())); |  | 
|  1759     } |  | 
|  1760  |  | 
|  1761     /*  The code used to just blindly call this |  | 
|  1762             path->setIsConvex(true); |  | 
|  1763         But webkit can sometimes send us non-convex 4-point values, so we mark t
      he path's |  | 
|  1764         convexity as unknown, so it will get computed by skia at draw time. |  | 
|  1765         See crbug.com 108605 |  | 
|  1766     */ |  | 
|  1767     SkPath::Convexity convexity = SkPath::kConvex_Convexity; |  | 
|  1768     if (numPoints == 4) |  | 
|  1769         convexity = SkPath::kUnknown_Convexity; |  | 
|  1770     path->setConvexity(convexity); |  | 
|  1771 } |  | 
|  1772  |  | 
|  1773 void GraphicsContext::setupPaintCommon(SkPaint* paint) const |  | 
|  1774 { |  | 
|  1775 #if defined(SK_DEBUG) |  | 
|  1776     { |  | 
|  1777         SkPaint defaultPaint; |  | 
|  1778         SkASSERT(*paint == defaultPaint); |  | 
|  1779     } |  | 
|  1780 #endif |  | 
|  1781  |  | 
|  1782     paint->setAntiAlias(m_state->m_shouldAntialias); |  | 
|  1783  |  | 
|  1784     if (!SkXfermode::IsMode(m_state->m_xferMode.get(), SkXfermode::kSrcOver_Mode
      )) |  | 
|  1785         paint->setXfermode(m_state->m_xferMode.get()); |  | 
|  1786  |  | 
|  1787     if (m_state->m_looper) |  | 
|  1788         paint->setLooper(m_state->m_looper.get()); |  | 
|  1789  |  | 
|  1790     paint->setColorFilter(m_state->m_colorFilter.get()); |  | 
|  1791 } |  | 
|  1792  |  | 
|  1793 void GraphicsContext::drawOuterPath(const SkPath& path, SkPaint& paint, int widt
      h) |  | 
|  1794 { |  | 
|  1795 #if OS(MACOSX) |  | 
|  1796     paint.setAlpha(64); |  | 
|  1797     paint.setStrokeWidth(width); |  | 
|  1798     paint.setPathEffect(new SkCornerPathEffect((width - 1) * 0.5f))->unref(); |  | 
|  1799 #else |  | 
|  1800     paint.setStrokeWidth(1); |  | 
|  1801     paint.setPathEffect(new SkCornerPathEffect(1))->unref(); |  | 
|  1802 #endif |  | 
|  1803     drawPath(path, paint); |  | 
|  1804 } |  | 
|  1805  |  | 
|  1806 void GraphicsContext::drawInnerPath(const SkPath& path, SkPaint& paint, int widt
      h) |  | 
|  1807 { |  | 
|  1808 #if OS(MACOSX) |  | 
|  1809     paint.setAlpha(128); |  | 
|  1810     paint.setStrokeWidth(width * 0.5f); |  | 
|  1811     drawPath(path, paint); |  | 
|  1812 #endif |  | 
|  1813 } |  | 
|  1814  |  | 
|  1815 void GraphicsContext::setRadii(SkVector* radii, IntSize topLeft, IntSize topRigh
      t, IntSize bottomRight, IntSize bottomLeft) |  | 
|  1816 { |  | 
|  1817     radii[SkRRect::kUpperLeft_Corner].set(SkIntToScalar(topLeft.width()), |  | 
|  1818         SkIntToScalar(topLeft.height())); |  | 
|  1819     radii[SkRRect::kUpperRight_Corner].set(SkIntToScalar(topRight.width()), |  | 
|  1820         SkIntToScalar(topRight.height())); |  | 
|  1821     radii[SkRRect::kLowerRight_Corner].set(SkIntToScalar(bottomRight.width()), |  | 
|  1822         SkIntToScalar(bottomRight.height())); |  | 
|  1823     radii[SkRRect::kLowerLeft_Corner].set(SkIntToScalar(bottomLeft.width()), |  | 
|  1824         SkIntToScalar(bottomLeft.height())); |  | 
|  1825 } |  | 
|  1826  |  | 
|  1827 PassRefPtr<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(C
      olorFilter colorFilter) |  | 
|  1828 { |  | 
|  1829     switch (colorFilter) { |  | 
|  1830     case ColorFilterLuminanceToAlpha: |  | 
|  1831         return adoptRef(SkLumaColorFilter::Create()); |  | 
|  1832     case ColorFilterLinearRGBToSRGB: |  | 
|  1833         return ImageBuffer::createColorSpaceFilter(ColorSpaceLinearRGB, ColorSpa
      ceDeviceRGB); |  | 
|  1834     case ColorFilterSRGBToLinearRGB: |  | 
|  1835         return ImageBuffer::createColorSpaceFilter(ColorSpaceDeviceRGB, ColorSpa
      ceLinearRGB); |  | 
|  1836     case ColorFilterNone: |  | 
|  1837         break; |  | 
|  1838     default: |  | 
|  1839         ASSERT_NOT_REACHED(); |  | 
|  1840         break; |  | 
|  1841     } |  | 
|  1842  |  | 
|  1843     return 0; |  | 
|  1844 } |  | 
|  1845  |  | 
|  1846  |  | 
|  1847 #if OS(MACOSX) |  | 
|  1848 CGColorSpaceRef deviceRGBColorSpaceRef() |  | 
|  1849 { |  | 
|  1850     static CGColorSpaceRef deviceSpace = CGColorSpaceCreateDeviceRGB(); |  | 
|  1851     return deviceSpace; |  | 
|  1852 } |  | 
|  1853 #else |  | 
|  1854 void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) |  | 
|  1855 { |  | 
|  1856     const SkPMColor lineColor = lineColors(index); |  | 
|  1857     const SkPMColor antiColor1 = antiColors1(index); |  | 
|  1858     const SkPMColor antiColor2 = antiColors2(index); |  | 
|  1859  |  | 
|  1860     uint32_t* row1 = bitmap->getAddr32(0, 0); |  | 
|  1861     uint32_t* row2 = bitmap->getAddr32(0, 1); |  | 
|  1862     uint32_t* row3 = bitmap->getAddr32(0, 2); |  | 
|  1863     uint32_t* row4 = bitmap->getAddr32(0, 3); |  | 
|  1864  |  | 
|  1865     // Pattern: X0o   o0X0o   o0 |  | 
|  1866     //          XX0o o0XXX0o o0X |  | 
|  1867     //           o0XXX0o o0XXX0o |  | 
|  1868     //            o0X0o   o0X0o |  | 
|  1869     const SkPMColor row1Color[] = { lineColor, antiColor1, antiColor2, 0,       
         0,         0,          antiColor2, antiColor1 }; |  | 
|  1870     const SkPMColor row2Color[] = { lineColor, lineColor,  antiColor1, antiColor
      2, 0,         antiColor2, antiColor1, lineColor }; |  | 
|  1871     const SkPMColor row3Color[] = { 0,         antiColor2, antiColor1, lineColor
      ,  lineColor, lineColor,  antiColor1, antiColor2 }; |  | 
|  1872     const SkPMColor row4Color[] = { 0,         0,          antiColor2, antiColor
      1, lineColor, antiColor1, antiColor2, 0 }; |  | 
|  1873  |  | 
|  1874     for (int x = 0; x < bitmap->width() + 8; x += 8) { |  | 
|  1875         int count = std::min(bitmap->width() - x, 8); |  | 
|  1876         if (count > 0) { |  | 
|  1877             memcpy(row1 + x, row1Color, count * sizeof(SkPMColor)); |  | 
|  1878             memcpy(row2 + x, row2Color, count * sizeof(SkPMColor)); |  | 
|  1879             memcpy(row3 + x, row3Color, count * sizeof(SkPMColor)); |  | 
|  1880             memcpy(row4 + x, row4Color, count * sizeof(SkPMColor)); |  | 
|  1881         } |  | 
|  1882     } |  | 
|  1883 } |  | 
|  1884  |  | 
|  1885 void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) |  | 
|  1886 { |  | 
|  1887     const uint32_t lineColor = lineColors(index); |  | 
|  1888     const uint32_t antiColor = antiColors2(index); |  | 
|  1889  |  | 
|  1890     // Pattern: X o   o X o   o X |  | 
|  1891     //            o X o   o X o |  | 
|  1892     uint32_t* row1 = bitmap->getAddr32(0, 0); |  | 
|  1893     uint32_t* row2 = bitmap->getAddr32(0, 1); |  | 
|  1894     for (int x = 0; x < bitmap->width(); x++) { |  | 
|  1895         switch (x % 4) { |  | 
|  1896         case 0: |  | 
|  1897             row1[x] = lineColor; |  | 
|  1898             break; |  | 
|  1899         case 1: |  | 
|  1900             row1[x] = antiColor; |  | 
|  1901             row2[x] = antiColor; |  | 
|  1902             break; |  | 
|  1903         case 2: |  | 
|  1904             row2[x] = lineColor; |  | 
|  1905             break; |  | 
|  1906         case 3: |  | 
|  1907             row1[x] = antiColor; |  | 
|  1908             row2[x] = antiColor; |  | 
|  1909             break; |  | 
|  1910         } |  | 
|  1911     } |  | 
|  1912 } |  | 
|  1913  |  | 
|  1914 const SkPMColor GraphicsContext::lineColors(int index) |  | 
|  1915 { |  | 
|  1916     static const SkPMColor colors[] = { |  | 
|  1917         SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red. |  | 
|  1918         SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0) // Opaque gray. |  | 
|  1919     }; |  | 
|  1920  |  | 
|  1921     return colors[index]; |  | 
|  1922 } |  | 
|  1923  |  | 
|  1924 const SkPMColor GraphicsContext::antiColors1(int index) |  | 
|  1925 { |  | 
|  1926     static const SkPMColor colors[] = { |  | 
|  1927         SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red. |  | 
|  1928         SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0)  // Semitransparent gray. |  | 
|  1929     }; |  | 
|  1930  |  | 
|  1931     return colors[index]; |  | 
|  1932 } |  | 
|  1933  |  | 
|  1934 const SkPMColor GraphicsContext::antiColors2(int index) |  | 
|  1935 { |  | 
|  1936     static const SkPMColor colors[] = { |  | 
|  1937         SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red |  | 
|  1938         SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0)  // More transparent gray |  | 
|  1939     }; |  | 
|  1940  |  | 
|  1941     return colors[index]; |  | 
|  1942 } |  | 
|  1943 #endif |  | 
|  1944  |  | 
|  1945 void GraphicsContext::setupShader(SkPaint* paint, Gradient* grad, Pattern* pat, 
      SkColor color) const |  | 
|  1946 { |  | 
|  1947     RefPtr<SkShader> shader; |  | 
|  1948  |  | 
|  1949     if (grad) { |  | 
|  1950         shader = grad->shader(); |  | 
|  1951         color = SK_ColorBLACK; |  | 
|  1952     } else if (pat) { |  | 
|  1953         shader = pat->shader(); |  | 
|  1954         color = SK_ColorBLACK; |  | 
|  1955         paint->setFilterBitmap(imageInterpolationQuality() != InterpolationNone)
      ; |  | 
|  1956     } |  | 
|  1957  |  | 
|  1958     paint->setColor(m_state->applyAlpha(color)); |  | 
|  1959  |  | 
|  1960     if (!shader) |  | 
|  1961         return; |  | 
|  1962  |  | 
|  1963     paint->setShader(shader.get()); |  | 
|  1964 } |  | 
|  1965  |  | 
|  1966 void GraphicsContext::didDrawTextInRect(const SkRect& textRect) |  | 
|  1967 { |  | 
|  1968     if (m_trackTextRegion) { |  | 
|  1969         TRACE_EVENT0("skia", "PlatformContextSkia::trackTextRegion"); |  | 
|  1970         m_textRegion.join(textRect); |  | 
|  1971     } |  | 
|  1972 } |  | 
|  1973  |  | 
|  1974 } |  | 
| OLD | NEW |