Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2007, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "CachedPrefix.h"
     27 #include "android_graphics.h"
     28 #include "CachedColor.h"
     29 #include "CachedRoot.h"
     30 #include "IntRect.h"
     31 #include "LayerAndroid.h"
     32 #include "SkCanvas.h"
     33 #include "SkCornerPathEffect.h"
     34 #include "SkPath.h"
     35 #include "SkRegion.h"
     36 #include "WebViewCore.h"
     37 
     38 namespace android {
     39 
     40 // The CSS values for the inner and outer widths may be specified as fractions
     41 #define WIDTH_SCALE 0.0625f // 1/16, to offset the scale in CSSStyleSelector
     42 
     43 void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer, IntRect* inval)
     44 {
     45     if (!m_lastBounds.isEmpty()) {
     46         *inval = m_lastBounds;
     47         m_lastBounds = IntRect(0, 0, 0, 0);
     48     }
     49 #if USE(ACCELERATED_COMPOSITING)
     50     int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1;
     51     if (layer->uniqueId() != layerId)
     52         return;
     53 #endif
     54     if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) {
     55         DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)"
     56             " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(),
     57             m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height());
     58         return;
     59     }
     60     const CachedColor& colors = m_frame->color(m_node);
     61     unsigned rectCount = m_rings.size();
     62     SkRegion rgn;
     63     SkPath path;
     64     for (unsigned i = 0; i < rectCount; i++)
     65     {
     66         SkRect  r(m_rings[i]);
     67         SkIRect ir;
     68 
     69         r.round(&ir);
     70         ir.inset(-colors.outset(), -colors.outset());
     71         rgn.op(ir, SkRegion::kUnion_Op);
     72     }
     73     rgn.getBoundaryPath(&path);
     74 
     75     SkPaint paint;
     76     paint.setAntiAlias(true);
     77     paint.setPathEffect(new SkCornerPathEffect(
     78         SkIntToScalar(colors.radius())))->unref();
     79     SkColor outer;
     80     SkColor inner;
     81     if (m_isPressed) {
     82         SkColor pressed;
     83         pressed = colors.fillColor();
     84         paint.setColor(pressed);
     85         canvas->drawPath(path, paint);
     86         outer = colors.pressedOuterColor();
     87         inner = colors.pressedInnerColor();
     88     } else {
     89         outer = colors.selectedOuterColor();
     90         inner = colors.selectedInnerColor();
     91     }
     92     paint.setStyle(SkPaint::kStroke_Style);
     93     paint.setStrokeWidth(colors.outerWidth() * WIDTH_SCALE);
     94     paint.setColor(outer);
     95     canvas->drawPath(path, paint);
     96     paint.setStrokeWidth(colors.innerWidth() * WIDTH_SCALE);
     97     paint.setColor(inner);
     98     canvas->drawPath(path, paint);
     99     SkRect localBounds, globalBounds;
    100     localBounds = path.getBounds();
    101     float width = std::max(colors.innerWidth(), colors.outerWidth());
    102     width *= WIDTH_SCALE;
    103     localBounds.inset(-width, -width);
    104     const SkMatrix& matrix = canvas->getTotalMatrix();
    105     matrix.mapRect(&globalBounds, localBounds);
    106     SkIRect globalIBounds;
    107     globalBounds.round(&globalIBounds);
    108     m_lastBounds = globalIBounds;
    109     inval->unite(m_lastBounds);
    110 }
    111 
    112 void CursorRing::setIsButton(const CachedNode* node)
    113 {
    114     m_isButton = false;
    115 }
    116 
    117 bool CursorRing::setup()
    118 {
    119     m_node->cursorRings(m_frame, &m_rings);
    120     if (!m_rings.size()) {
    121         DBG_NAV_LOG("!rings.size()");
    122         m_viewImpl->m_hasCursorBounds = false;
    123         return false;
    124     }
    125     setIsButton(m_node);
    126     m_bounds = m_node->bounds(m_frame);
    127     m_viewImpl->updateCursorBounds(m_root, m_frame, m_node);
    128 
    129     bool useHitBounds = m_node->useHitBounds();
    130     if (useHitBounds)
    131         m_bounds = m_node->hitBounds(m_frame);
    132     if (useHitBounds || m_node->useBounds()) {
    133         m_rings.clear();
    134         m_rings.append(m_bounds);
    135     }
    136     m_absBounds = m_node->bounds(m_frame);
    137     const CachedColor& colors = m_frame->color(m_node);
    138     m_bounds.inflate(SkScalarCeil(colors.outerWidth()));
    139     m_absBounds.inflate(SkScalarCeil(colors.outerWidth()));
    140     if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus()))
    141         return false;
    142 #if DEBUG_NAV_UI
    143     const WebCore::IntRect& ring = m_rings[0];
    144     DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) pressed=%s rings=%d"
    145         " (%d, %d, %d, %d) isPlugin=%s",
    146         m_node->index(), m_node->nodePointer(),
    147         m_isPressed ? "true" : "false",
    148         m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(),
    149         m_node->isPlugin() ? "true" : "false");
    150     DBG_NAV_LOGD("[%d] inner=%d outer=%d outset=%d radius=%d"
    151         " fill=0x%08x pin=0x%08x pout=0x%08x sin=0x%08x sout=0x%08x",
    152         m_node->colorIndex(), colors.innerWidth(), colors.outerWidth(),
    153         colors.outset(), colors.radius(), colors.fillColor(),
    154         colors.pressedInnerColor(), colors.pressedOuterColor(),
    155         colors.selectedInnerColor(), colors.selectedInnerColor());
    156 #endif
    157     return true;
    158 }
    159 
    160 }
    161