BufferEdgePad.cpp (3508B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "BufferEdgePad.h" 8 9 #include "2D.h" // for DrawTarget 10 #include "Point.h" // for IntSize 11 #include "Types.h" // for SurfaceFormat 12 13 #include "nsRegion.h" 14 15 namespace mozilla { 16 namespace gfx { 17 18 void PadDrawTargetOutFromRegion(DrawTarget* aDrawTarget, 19 const nsIntRegion& aRegion) { 20 struct LockedBits { 21 uint8_t* data; 22 IntSize size; 23 int32_t stride; 24 SurfaceFormat format; 25 static int clamp(int x, int min, int max) { 26 if (x < min) x = min; 27 if (x > max) x = max; 28 return x; 29 } 30 31 static void ensure_memcpy(uint8_t* dst, uint8_t* src, size_t n, 32 uint8_t* bitmap, int stride, int height) { 33 if (src + n > bitmap + stride * height) { 34 MOZ_CRASH("GFX: long src memcpy"); 35 } 36 if (src < bitmap) { 37 MOZ_CRASH("GFX: short src memcpy"); 38 } 39 if (dst + n > bitmap + stride * height) { 40 MOZ_CRASH("GFX: long dst mempcy"); 41 } 42 if (dst < bitmap) { 43 MOZ_CRASH("GFX: short dst mempcy"); 44 } 45 } 46 47 static void visitor(void* closure, VisitSide side, int x1, int y1, int x2, 48 int y2) { 49 LockedBits* lb = static_cast<LockedBits*>(closure); 50 uint8_t* bitmap = lb->data; 51 const int bpp = gfx::BytesPerPixel(lb->format); 52 const int stride = lb->stride; 53 const int width = lb->size.width; 54 const int height = lb->size.height; 55 56 if (side == VisitSide::TOP) { 57 if (y1 > 0) { 58 x1 = clamp(x1, 0, width - 1); 59 x2 = clamp(x2, 0, width - 1); 60 ensure_memcpy(&bitmap[x1 * bpp + (y1 - 1) * stride], 61 &bitmap[x1 * bpp + y1 * stride], (x2 - x1) * bpp, 62 bitmap, stride, height); 63 memcpy(&bitmap[x1 * bpp + (y1 - 1) * stride], 64 &bitmap[x1 * bpp + y1 * stride], (x2 - x1) * bpp); 65 } 66 } else if (side == VisitSide::BOTTOM) { 67 if (y1 < height) { 68 x1 = clamp(x1, 0, width - 1); 69 x2 = clamp(x2, 0, width - 1); 70 ensure_memcpy(&bitmap[x1 * bpp + y1 * stride], 71 &bitmap[x1 * bpp + (y1 - 1) * stride], (x2 - x1) * bpp, 72 bitmap, stride, height); 73 memcpy(&bitmap[x1 * bpp + y1 * stride], 74 &bitmap[x1 * bpp + (y1 - 1) * stride], (x2 - x1) * bpp); 75 } 76 } else if (side == VisitSide::LEFT) { 77 if (x1 > 0) { 78 while (y1 != y2) { 79 memcpy(&bitmap[(x1 - 1) * bpp + y1 * stride], 80 &bitmap[x1 * bpp + y1 * stride], bpp); 81 y1++; 82 } 83 } 84 } else if (side == VisitSide::RIGHT) { 85 if (x1 < width) { 86 while (y1 != y2) { 87 memcpy(&bitmap[x1 * bpp + y1 * stride], 88 &bitmap[(x1 - 1) * bpp + y1 * stride], bpp); 89 y1++; 90 } 91 } 92 } 93 } 94 } lb; 95 96 if (aDrawTarget->LockBits(&lb.data, &lb.size, &lb.stride, &lb.format)) { 97 // we can only pad software targets so if we can't lock the bits don't pad 98 aRegion.VisitEdges(lb.visitor, &lb); 99 aDrawTarget->ReleaseBits(lb.data); 100 } 101 } 102 103 } // namespace gfx 104 } // namespace mozilla