Home | History | Annotate | Download | only in skia
      1 /*
      2  * Copyright (c) 2006,2007,2008, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #include "core/platform/graphics/skia/SkiaUtils.h"
     34 
     35 #include "SkColorPriv.h"
     36 #include "SkMatrix.h"
     37 #include "SkRegion.h"
     38 #include "core/platform/graphics/GraphicsContext.h"
     39 #include "core/platform/graphics/ImageBuffer.h"
     40 
     41 namespace WebCore {
     42 
     43 static const struct CompositOpToXfermodeMode {
     44     uint8_t mCompositOp;
     45     uint8_t m_xfermodeMode;
     46 } gMapCompositOpsToXfermodeModes[] = {
     47     { CompositeClear,           SkXfermode::kClear_Mode },
     48     { CompositeCopy,            SkXfermode::kSrc_Mode },
     49     { CompositeSourceOver,      SkXfermode::kSrcOver_Mode },
     50     { CompositeSourceIn,        SkXfermode::kSrcIn_Mode },
     51     { CompositeSourceOut,       SkXfermode::kSrcOut_Mode },
     52     { CompositeSourceAtop,      SkXfermode::kSrcATop_Mode },
     53     { CompositeDestinationOver, SkXfermode::kDstOver_Mode },
     54     { CompositeDestinationIn,   SkXfermode::kDstIn_Mode },
     55     { CompositeDestinationOut,  SkXfermode::kDstOut_Mode },
     56     { CompositeDestinationAtop, SkXfermode::kDstATop_Mode },
     57     { CompositeXOR,             SkXfermode::kXor_Mode },
     58     { CompositePlusDarker,      SkXfermode::kDarken_Mode },
     59     { CompositePlusLighter,     SkXfermode::kPlus_Mode }
     60 };
     61 
     62 // keep this array in sync with BlendMode enum in GraphicsTypes.h
     63 static const uint8_t gMapBlendOpsToXfermodeModes[] = {
     64     SkXfermode::kClear_Mode, // BlendModeNormal
     65     SkXfermode::kMultiply_Mode, // BlendModeMultiply
     66     SkXfermode::kScreen_Mode, // BlendModeScreen
     67     SkXfermode::kOverlay_Mode, // BlendModeOverlay
     68     SkXfermode::kDarken_Mode, // BlendModeDarken
     69     SkXfermode::kLighten_Mode, // BlendModeLighten
     70     SkXfermode::kColorDodge_Mode, // BlendModeColorDodge
     71     SkXfermode::kColorBurn_Mode, // BlendModeColorBurn
     72     SkXfermode::kHardLight_Mode, // BlendModeHardLight
     73     SkXfermode::kSoftLight_Mode, // BlendModeSoftLight
     74     SkXfermode::kDifference_Mode, // BlendModeDifference
     75     SkXfermode::kExclusion_Mode, // BlendModeExclusion
     76     SkXfermode::kHue_Mode, // BlendModeHue
     77     SkXfermode::kSaturation_Mode, // BlendModeSaturation
     78     SkXfermode::kColor_Mode, // BlendModeColor
     79     SkXfermode::kLuminosity_Mode // BlendModeLuminosity
     80 };
     81 
     82 SkXfermode::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op, BlendMode blendMode)
     83 {
     84     if (blendMode != BlendModeNormal) {
     85         if ((uint8_t)blendMode >= SK_ARRAY_COUNT(gMapBlendOpsToXfermodeModes)) {
     86             SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown BlendMode %d\n", blendMode));
     87             return SkXfermode::kSrcOver_Mode;
     88         }
     89         return (SkXfermode::Mode)gMapBlendOpsToXfermodeModes[(uint8_t)blendMode];
     90     }
     91 
     92     const CompositOpToXfermodeMode* table = gMapCompositOpsToXfermodeModes;
     93 
     94     for (unsigned i = 0; i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes); i++) {
     95         if (table[i].mCompositOp == op)
     96             return (SkXfermode::Mode)table[i].m_xfermodeMode;
     97     }
     98 
     99     SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown CompositeOperator %d\n", op));
    100     return SkXfermode::kSrcOver_Mode; // fall-back
    101 }
    102 
    103 static U8CPU InvScaleByte(U8CPU component, uint32_t scale)
    104 {
    105     SkASSERT(component == (uint8_t)component);
    106     return (component * scale + 0x8000) >> 16;
    107 }
    108 
    109 SkColor SkPMColorToColor(SkPMColor pm)
    110 {
    111     if (!pm)
    112         return 0;
    113     unsigned a = SkGetPackedA32(pm);
    114     if (!a) {
    115         // A zero alpha value when there are non-zero R, G, or B channels is an
    116         // invalid premultiplied color (since all channels should have been
    117         // multiplied by 0 if a=0).
    118         SkASSERT(false);
    119         // In production, return 0 to protect against division by zero.
    120         return 0;
    121     }
    122 
    123     uint32_t scale = (255 << 16) / a;
    124 
    125     return SkColorSetARGB(a,
    126                           InvScaleByte(SkGetPackedR32(pm), scale),
    127                           InvScaleByte(SkGetPackedG32(pm), scale),
    128                           InvScaleByte(SkGetPackedB32(pm), scale));
    129 }
    130 
    131 Color SkPMColorToWebCoreColor(SkPMColor pm)
    132 {
    133     return SkPMColorToColor(pm);
    134 }
    135 
    136 void ClipRectToCanvas(const GraphicsContext* context, const SkRect& srcRect, SkRect* destRect)
    137 {
    138     if (!context->getClipBounds(destRect) || !destRect->intersect(srcRect))
    139         destRect->setEmpty();
    140 }
    141 
    142 bool SkPathContainsPoint(const SkPath& originalPath, const FloatPoint& point, SkPath::FillType ft)
    143 {
    144     SkRect bounds = originalPath.getBounds();
    145 
    146     // We can immediately return false if the point is outside the bounding
    147     // rect.  We don't use bounds.contains() here, since it would exclude
    148     // points on the right and bottom edges of the bounding rect, and we want
    149     // to include them.
    150     SkScalar fX = SkFloatToScalar(point.x());
    151     SkScalar fY = SkFloatToScalar(point.y());
    152     if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
    153         return false;
    154 
    155     // Scale the path to a large size before hit testing for two reasons:
    156     // 1) Skia has trouble with coordinates close to the max signed 16-bit values, so we scale larger paths down.
    157     //    TODO: when Skia is patched to work properly with large values, this will not be necessary.
    158     // 2) Skia does not support analytic hit testing, so we scale paths up to do raster hit testing with subpixel accuracy.
    159     SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
    160     if (SkScalarNearlyZero(biggestCoord))
    161         return false;
    162     biggestCoord = std::max(std::max(biggestCoord, fX + 1), fY + 1);
    163 
    164     const SkScalar kMaxCoordinate = SkIntToScalar(1 << 15);
    165     SkScalar scale = SkScalarDiv(kMaxCoordinate, biggestCoord);
    166 
    167     SkRegion rgn;
    168     SkRegion clip;
    169     SkMatrix m;
    170     SkPath scaledPath(originalPath);
    171 
    172     scaledPath.setFillType(ft);
    173     m.setScale(scale, scale);
    174     scaledPath.transform(m, 0);
    175 
    176     int x = static_cast<int>(floorf(0.5f + point.x() * scale));
    177     int y = static_cast<int>(floorf(0.5f + point.y() * scale));
    178     clip.setRect(x - 1, y - 1, x + 1, y + 1);
    179 
    180     return rgn.setPath(scaledPath, clip);
    181 }
    182 
    183 }  // namespace WebCore
    184