Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright 2011, 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 #define LOG_TAG "GLExtras"
     27 #define LOG_NDEBUG 1
     28 
     29 #include "config.h"
     30 
     31 #include "AndroidLog.h"
     32 #include "DrawExtra.h"
     33 #include "DrawQuadData.h"
     34 #include "GLExtras.h"
     35 #include "IntRect.h"
     36 #include "SkPath.h"
     37 #include "TilesManager.h"
     38 
     39 // Touch ring border width. This is doubled if the ring is not pressed
     40 #define RING_BORDER_WIDTH 1
     41 
     42 GLExtras::GLExtras()
     43     : m_drawExtra(0)
     44     , m_visibleContentRect()
     45 {
     46 }
     47 
     48 GLExtras::~GLExtras()
     49 {
     50 }
     51 
     52 void GLExtras::drawRing(SkRect& srcRect, Color color, const TransformationMatrix* drawMat)
     53 {
     54     if (srcRect.fRight <= srcRect.fLeft || srcRect.fBottom <= srcRect.fTop) {
     55         // Invalid rect, reject it
     56         return;
     57     }
     58     ALOGV("drawQuad [%fx%f, %f, %f]", srcRect.fLeft, srcRect.fTop,
     59           srcRect.width(), srcRect.height());
     60     // Pull the alpha out of the color so that the shader applies it correctly.
     61     // Otherwise we either don't have blending enabled, or the alpha will get
     62     // double applied
     63     Color colorWithoutAlpha(0xFF000000 | color.rgb());
     64     float alpha = color.alpha() / (float) 255;
     65 
     66     PureColorQuadData data(colorWithoutAlpha, drawMat ? LayerQuad : BaseQuad,
     67                            drawMat, &srcRect, alpha, false);
     68     TilesManager::instance()->shader()->drawQuad(&data);
     69 }
     70 
     71 void GLExtras::drawRegion(const SkRegion& region, bool fill, bool drawBorder,
     72                           const TransformationMatrix* drawMat, Color color)
     73 {
     74     if (region.isEmpty())
     75         return;
     76     if (fill) {
     77         SkRegion::Iterator rgnIter(region);
     78         while (!rgnIter.done()) {
     79             const SkIRect& ir = rgnIter.rect();
     80             SkRect r;
     81             r.set(ir.fLeft, ir.fTop, ir.fRight, ir.fBottom);
     82             drawRing(r, color, drawMat);
     83             rgnIter.next();
     84         }
     85     }
     86     if (fill && !drawBorder)
     87         return;
     88     SkPath path;
     89     if (!region.getBoundaryPath(&path))
     90         return;
     91     SkPath::Iter iter(path, true);
     92     SkPath::Verb verb;
     93     SkPoint pts[4];
     94     SkRegion clip;
     95     SkIRect startRect;
     96     while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
     97         if (verb == SkPath::kLine_Verb) {
     98             SkRect r;
     99             r.set(pts, 2);
    100             SkIRect line;
    101             int borderWidth = RING_BORDER_WIDTH;
    102             if (!fill)
    103                 borderWidth *= 2;
    104             line.fLeft = r.fLeft - borderWidth;
    105             line.fRight = r.fRight + borderWidth;
    106             line.fTop = r.fTop - borderWidth;
    107             line.fBottom = r.fBottom + borderWidth;
    108             if (clip.intersects(line)) {
    109                 clip.op(line, SkRegion::kReverseDifference_Op);
    110                 if (clip.isEmpty())
    111                     continue; // Nothing to draw, continue
    112                 line = clip.getBounds();
    113                 if (SkIRect::Intersects(startRect, line)) {
    114                     clip.op(startRect, SkRegion::kDifference_Op);
    115                     if (clip.isEmpty())
    116                         continue; // Nothing to draw, continue
    117                     line = clip.getBounds();
    118                 }
    119             } else {
    120                 clip.setRect(line);
    121             }
    122             r.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
    123             drawRing(r, color, drawMat);
    124             if (startRect.isEmpty()) {
    125                 startRect.set(line.fLeft, line.fTop, line.fRight, line.fBottom);
    126             }
    127         }
    128         if (verb == SkPath::kMove_Verb) {
    129             startRect.setEmpty();
    130         }
    131     }
    132 }
    133 
    134 void GLExtras::drawGL(const LayerAndroid* layer)
    135 {
    136     if (m_drawExtra)
    137         m_drawExtra->drawGL(this, layer);
    138 }
    139