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