| /* libs/graphics/sgl/SkBlitter_ARGB32_Subpixel.cpp |
| ** |
| ** Copyright 2009, The Android Open Source Project |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| /* LCD blend functions: |
| |
| These functions take an alpha pixel of the following form: |
| red, green, blue -> an alpha value for the given colour component. |
| alpha -> the max of the red, green and blue alpha values. |
| |
| These alpha pixels result from subpixel renderering. The R/G/B values have |
| already been corrected for RGB/BGR element ordering. |
| |
| The alpha pixel is blended with an original pixel and a source colour, |
| resulting in a new pixel value. |
| */ |
| |
| #include "SkBitmap.h" |
| #include "SkColorPriv.h" |
| #include "SkMask.h" |
| #include "SkRect.h" |
| |
| namespace skia_blitter_support { |
| |
| /** Given a clip region which describes the desired location of a glyph and a |
| bitmap to which an LCD glyph is to be blitted, return a pointer to the |
| SkBitmap's pixels and output width and height adjusts for the glyph as well |
| as a pointer into the glyph. |
| |
| Recall that LCD glyphs have extra rows (vertical mode) or columns |
| (horizontal mode) at the edges as a result of low-pass filtering. If we |
| wanted to put a glyph on the hard-left edge of bitmap, we would have to know |
| to start one pixel into the glyph, as well as to only add 1 to the recorded |
| glyph width etc. This function encapsulates that behaviour. |
| |
| @param mask The glyph to be blitted. |
| @param clip The clip region describing the desired location of the glyph. |
| @param device The SkBitmap target for the blit. |
| @param widthAdjustment (output) a number to add to the glyph's nominal width. |
| @param heightAdjustment (output) a number to add to the glyph's nominal width. |
| @param alpha32 (output) a pointer into the 32-bit subpixel alpha data for the glyph |
| */ |
| uint32_t* adjustForSubpixelClip(const SkMask& mask, |
| const SkIRect& clip, const SkBitmap& device, |
| int* widthAdjustment, int* heightAdjustment, |
| const uint32_t** alpha32) { |
| const bool lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format; |
| const bool verticalLCDMode = mask.fFormat == SkMask::kVerticalLCD_Format; |
| const int leftOffset = clip.fLeft > 0 ? lcdMode : 0; |
| const int topOffset = clip.fTop > 0 ? verticalLCDMode : 0; |
| const int rightOffset = lcdMode && clip.fRight < device.width(); |
| const int bottomOffset = verticalLCDMode && clip.fBottom < device.height(); |
| |
| uint32_t* device32 = device.getAddr32(clip.fLeft - leftOffset, clip.fTop - topOffset); |
| *alpha32 = mask.getAddrLCD(clip.fLeft + (lcdMode && !leftOffset), |
| clip.fTop + (verticalLCDMode && !topOffset)); |
| |
| *widthAdjustment = leftOffset + rightOffset; |
| *heightAdjustment = topOffset + bottomOffset; |
| |
| return device32; |
| } |
| |
| uint32_t BlendLCDPixelWithColor(const uint32_t alphaPixel, const uint32_t originalPixel, |
| const uint32_t sourcePixel) { |
| unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel)); |
| unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel)); |
| unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel)); |
| |
| unsigned sourceRed = SkGetPackedR32(sourcePixel); |
| unsigned sourceGreen = SkGetPackedG32(sourcePixel); |
| unsigned sourceBlue = SkGetPackedB32(sourcePixel); |
| unsigned sourceAlpha = SkAlpha255To256(SkGetPackedA32(sourcePixel)); |
| |
| alphaRed = (alphaRed * sourceAlpha) >> 8; |
| alphaGreen = (alphaGreen * sourceAlpha) >> 8; |
| alphaBlue = (alphaBlue * sourceAlpha) >> 8; |
| unsigned alphaAlpha = SkMax32(SkMax32(alphaRed, alphaBlue), alphaGreen); |
| |
| unsigned originalRed = SkGetPackedR32(originalPixel); |
| unsigned originalGreen = SkGetPackedG32(originalPixel); |
| unsigned originalBlue = SkGetPackedB32(originalPixel); |
| unsigned originalAlpha = SkGetPackedA32(originalPixel); |
| |
| return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha), |
| ((sourceRed * alphaRed) >> 8) + ((originalRed * (256 - alphaRed)) >> 8), |
| ((sourceGreen * alphaGreen) >> 8) + ((originalGreen * (256 - alphaGreen)) >> 8), |
| ((sourceBlue * alphaBlue) >> 8) + ((originalBlue * (256 - alphaBlue)) >> 8)); |
| |
| } |
| |
| uint32_t BlendLCDPixelWithOpaqueColor(const uint32_t alphaPixel, const uint32_t originalPixel, |
| const uint32_t sourcePixel) { |
| unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel)); |
| unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel)); |
| unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel)); |
| unsigned alphaAlpha = SkGetPackedA32(alphaPixel); |
| |
| unsigned sourceRed = SkGetPackedR32(sourcePixel); |
| unsigned sourceGreen = SkGetPackedG32(sourcePixel); |
| unsigned sourceBlue = SkGetPackedB32(sourcePixel); |
| |
| unsigned originalRed = SkGetPackedR32(originalPixel); |
| unsigned originalGreen = SkGetPackedG32(originalPixel); |
| unsigned originalBlue = SkGetPackedB32(originalPixel); |
| unsigned originalAlpha = SkGetPackedA32(originalPixel); |
| |
| return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha), |
| ((sourceRed * alphaRed) >> 8) + ((originalRed * (256 - alphaRed)) >> 8), |
| ((sourceGreen * alphaGreen) >> 8) + ((originalGreen * (256 - alphaGreen)) >> 8), |
| ((sourceBlue * alphaBlue) >> 8) + ((originalBlue * (256 - alphaBlue)) >> 8)); |
| } |
| |
| uint32_t BlendLCDPixelWithBlack(const uint32_t alphaPixel, const uint32_t originalPixel) { |
| unsigned alphaRed = SkAlpha255To256(SkGetPackedR32(alphaPixel)); |
| unsigned alphaGreen = SkAlpha255To256(SkGetPackedG32(alphaPixel)); |
| unsigned alphaBlue = SkAlpha255To256(SkGetPackedB32(alphaPixel)); |
| unsigned alphaAlpha = SkGetPackedA32(alphaPixel); |
| |
| unsigned originalRed = SkGetPackedR32(originalPixel); |
| unsigned originalGreen = SkGetPackedG32(originalPixel); |
| unsigned originalBlue = SkGetPackedB32(originalPixel); |
| unsigned originalAlpha = SkGetPackedA32(originalPixel); |
| |
| return SkPackARGB32(SkMin32(255u, alphaAlpha + originalAlpha), |
| (originalRed * (256 - alphaRed)) >> 8, |
| (originalGreen * (256 - alphaGreen)) >> 8, |
| (originalBlue * (256 - alphaBlue)) >> 8); |
| } |
| |
| } // namespace skia_blitter_support |