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