1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-24 01:54:22 +00:00

Better support for pixel strides in the software renderer.

This commit is contained in:
jules 2012-08-03 16:27:45 +01:00
parent 296f30f449
commit 19e304bc6f
3 changed files with 151 additions and 74 deletions

View file

@ -83,6 +83,9 @@ public:
void drawGlyph (int glyphNumber, float x, float y);
void drawGlyph (int glyphNumber, const AffineTransform&);
const Image& getImage() const noexcept { return savedState->image; }
const RenderingHelpers::TranslationOrTransform& getTransform() const noexcept { return savedState->transform; }
protected:
RenderingHelpers::SavedStateStack <RenderingHelpers::SoftwareRendererSavedState> savedState;

View file

@ -559,7 +559,7 @@ namespace EdgeTableFillers
: data (data_),
sourceColour (colour)
{
if (sizeof (PixelType) == 3)
if (sizeof (PixelType) == 3 && data.pixelStride == sizeof (PixelType))
{
areRGBComponentsEqual = sourceColour.getRed() == sourceColour.getGreen()
&& sourceColour.getGreen() == sourceColour.getBlue();
@ -578,17 +578,17 @@ namespace EdgeTableFillers
forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const noexcept
{
if (replaceExisting)
linePixels[x].set (sourceColour);
getPixel (x)->set (sourceColour);
else
linePixels[x].blend (sourceColour, (uint32) alphaLevel);
getPixel (x)->blend (sourceColour, (uint32) alphaLevel);
}
forcedinline void handleEdgeTablePixelFull (const int x) const noexcept
{
if (replaceExisting)
linePixels[x].set (sourceColour);
getPixel (x)->set (sourceColour);
else
linePixels[x].blend (sourceColour);
getPixel (x)->blend (sourceColour);
}
forcedinline void handleEdgeTableLine (const int x, const int width, const int alphaLevel) const noexcept
@ -596,7 +596,7 @@ namespace EdgeTableFillers
PixelARGB p (sourceColour);
p.multiplyAlpha (alphaLevel);
PixelType* dest = linePixels + x;
PixelType* dest = getPixel (x);
if (replaceExisting || p.getAlpha() >= 0xff)
replaceLine (dest, p, width);
@ -606,7 +606,7 @@ namespace EdgeTableFillers
forcedinline void handleEdgeTableLineFull (const int x, const int width) const noexcept
{
PixelType* dest = linePixels + x;
PixelType* dest = getPixel (x);
if (replaceExisting || sourceColour.getAlpha() >= 0xff)
replaceLine (dest, sourceColour, width);
@ -621,52 +621,91 @@ namespace EdgeTableFillers
PixelRGB filler [4];
bool areRGBComponentsEqual;
forcedinline PixelType* getPixel (const int x) const noexcept
{
return addBytesToPointer (linePixels, x * data.pixelStride);
}
forcedinline void incDestPixelPointer (PixelType*& p) const noexcept
{
p = addBytesToPointer (p, data.pixelStride);
}
inline void blendLine (PixelType* dest, const PixelARGB& colour, int width) const noexcept
{
do { dest++ ->blend (colour); } while (--width > 0);
do
{
dest->blend (colour);
incDestPixelPointer (dest);
}
while (--width > 0);
}
forcedinline void replaceLine (PixelRGB* dest, const PixelARGB& colour, int width) const noexcept
{
if (areRGBComponentsEqual) // if all the component values are the same, we can cheat..
if (data.pixelStride == sizeof (*dest))
{
memset (dest, colour.getRed(), (size_t) width * 3);
}
else
{
if (width >> 5)
if (areRGBComponentsEqual) // if all the component values are the same, we can cheat..
{
const int* const intFiller = reinterpret_cast<const int*> (filler);
memset (dest, colour.getRed(), (size_t) width * 3);
}
else
{
if (width >> 5)
{
const int* const intFiller = reinterpret_cast<const int*> (filler);
while (width > 8 && (((pointer_sized_int) dest) & 7) != 0)
while (width > 8 && (((pointer_sized_int) dest) & 7) != 0)
{
dest->set (colour);
++dest;
--width;
}
while (width > 4)
{
int* d = reinterpret_cast<int*> (dest);
*d++ = intFiller[0];
*d++ = intFiller[1];
*d++ = intFiller[2];
dest = reinterpret_cast<PixelRGB*> (d);
width -= 4;
}
}
while (--width >= 0)
{
dest->set (colour);
++dest;
--width;
}
while (width > 4)
{
int* d = reinterpret_cast<int*> (dest);
*d++ = intFiller[0];
*d++ = intFiller[1];
*d++ = intFiller[2];
dest = reinterpret_cast<PixelRGB*> (d);
width -= 4;
}
}
while (--width >= 0)
}
else
{
do
{
dest->set (colour);
++dest;
incDestPixelPointer (dest);
}
while (--width > 0);
}
}
forcedinline void replaceLine (PixelAlpha* const dest, const PixelARGB& colour, int const width) const noexcept
forcedinline void replaceLine (PixelAlpha* dest, const PixelARGB& colour, int width) const noexcept
{
memset (dest, colour.getAlpha(), (size_t) width);
if (data.pixelStride == sizeof (*dest))
{
memset (dest, colour.getAlpha(), (size_t) width);
}
else
{
do
{
dest->setAlpha (colour.getAlpha());
incDestPixelPointer (dest);
}
while (--width > 0);
}
}
forcedinline void replaceLine (PixelARGB* dest, const PixelARGB& colour, int width) const noexcept
@ -674,7 +713,7 @@ namespace EdgeTableFillers
do
{
dest->set (colour);
++dest;
incDestPixelPointer (dest);
} while (--width > 0);
}
@ -703,48 +742,63 @@ namespace EdgeTableFillers
forcedinline void handleEdgeTablePixel (const int x, const int alphaLevel) const noexcept
{
linePixels[x].blend (GradientType::getPixel (x), (uint32) alphaLevel);
getPixel (x)->blend (GradientType::getPixel (x), (uint32) alphaLevel);
}
forcedinline void handleEdgeTablePixelFull (const int x) const noexcept
{
linePixels[x].blend (GradientType::getPixel (x));
getPixel (x)->blend (GradientType::getPixel (x));
}
void handleEdgeTableLine (int x, int width, const int alphaLevel) const noexcept
{
PixelType* dest = linePixels + x;
PixelType* dest = getPixel (x);
if (alphaLevel < 0xff)
{
do
{
(dest++)->blend (GradientType::getPixel (x++), (uint32) alphaLevel);
dest->blend (GradientType::getPixel (x++), (uint32) alphaLevel);
incDestPixelPointer (dest);
} while (--width > 0);
}
else
{
do
{
(dest++)->blend (GradientType::getPixel (x++));
} while (--width > 0);
dest->blend (GradientType::getPixel (x++));
incDestPixelPointer (dest);
}
while (--width > 0);
}
}
void handleEdgeTableLineFull (int x, int width) const noexcept
{
PixelType* dest = linePixels + x;
PixelType* dest = getPixel (x);
do
{
(dest++)->blend (GradientType::getPixel (x++));
} while (--width > 0);
dest->blend (GradientType::getPixel (x++));
incDestPixelPointer (dest);
}
while (--width > 0);
}
private:
const Image::BitmapData& destData;
PixelType* linePixels;
forcedinline PixelType* getPixel (const int x) const noexcept
{
return addBytesToPointer (linePixels, x * destData.pixelStride);
}
forcedinline void incDestPixelPointer (PixelType*& p) const noexcept
{
p = addBytesToPointer (p, destData.pixelStride);
}
JUCE_DECLARE_NON_COPYABLE (Gradient);
};
@ -782,17 +836,17 @@ namespace EdgeTableFillers
{
alphaLevel = (alphaLevel * extraAlpha) >> 8;
linePixels[x].blend (sourceLineStart [repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)], (uint32) alphaLevel);
getDestPixel (x)->blend (*getSrcPixel (repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)), (uint32) alphaLevel);
}
forcedinline void handleEdgeTablePixelFull (const int x) const noexcept
{
linePixels[x].blend (sourceLineStart [repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)], (uint32) extraAlpha);
getDestPixel (x)->blend (*getSrcPixel (repeatPattern ? ((x - xOffset) % srcData.width) : (x - xOffset)), (uint32) extraAlpha);
}
void handleEdgeTableLine (int x, int width, int alphaLevel) const noexcept
{
DestPixelType* dest = linePixels + x;
DestPixelType* dest = getDestPixel (x);
alphaLevel = (alphaLevel * extraAlpha) >> 8;
x -= xOffset;
@ -802,7 +856,8 @@ namespace EdgeTableFillers
{
do
{
dest++ ->blend (sourceLineStart [repeatPattern ? (x++ % srcData.width) : x++], (uint32) alphaLevel);
dest->blend (*getSrcPixel (repeatPattern ? (x++ % srcData.width) : x++), (uint32) alphaLevel);
incDestPixelPointer (dest);
} while (--width > 0);
}
else
@ -811,19 +866,20 @@ namespace EdgeTableFillers
{
do
{
dest++ ->blend (sourceLineStart [x++ % srcData.width]);
dest->blend (*getSrcPixel (x++ % srcData.width));
incDestPixelPointer (dest);
} while (--width > 0);
}
else
{
copyRow (dest, sourceLineStart + x, width);
copyRow (dest, getSrcPixel (x), width);
}
}
}
void handleEdgeTableLineFull (int x, int width) const noexcept
{
DestPixelType* dest = linePixels + x;
DestPixelType* dest = getDestPixel (x);
x -= xOffset;
jassert (repeatPattern || (x >= 0 && x + width <= srcData.width));
@ -832,7 +888,8 @@ namespace EdgeTableFillers
{
do
{
dest++ ->blend (sourceLineStart [repeatPattern ? (x++ % srcData.width) : x++], (uint32) extraAlpha);
dest->blend (*getSrcPixel (repeatPattern ? (x++ % srcData.width) : x++), (uint32) extraAlpha);
incDestPixelPointer (dest);
} while (--width > 0);
}
else
@ -841,12 +898,13 @@ namespace EdgeTableFillers
{
do
{
dest++ ->blend (sourceLineStart [x++ % srcData.width]);
dest->blend (*getSrcPixel (x++ % srcData.width));
incDestPixelPointer (dest);
} while (--width > 0);
}
else
{
copyRow (dest, sourceLineStart + x, width);
copyRow (dest, getSrcPixel (x), width);
}
}
}
@ -870,18 +928,36 @@ namespace EdgeTableFillers
DestPixelType* linePixels;
SrcPixelType* sourceLineStart;
template <class PixelType1, class PixelType2>
static forcedinline void copyRow (PixelType1* dest, PixelType2* src, int width) noexcept
forcedinline DestPixelType* getDestPixel (int const x) const noexcept
{
do
{
dest++ ->blend (*src++);
} while (--width > 0);
return addBytesToPointer (linePixels, x * destData.pixelStride);
}
static forcedinline void copyRow (PixelRGB* dest, PixelRGB* src, int width) noexcept
forcedinline SrcPixelType const* getSrcPixel (int const x) const noexcept
{
memcpy (dest, src, sizeof (PixelRGB) * (size_t) width);
return addBytesToPointer (sourceLineStart, x * srcData.pixelStride);
}
forcedinline void incDestPixelPointer (DestPixelType*& p) const noexcept
{
p = addBytesToPointer (p, destData.pixelStride);
}
forcedinline void copyRow (DestPixelType* dest, SrcPixelType const* src, int width) const noexcept
{
if (srcData.pixelStride == 3 && destData.pixelStride == 3)
{
memcpy (dest, src, sizeof (PixelRGB) * (size_t) width);
}
else
{
do
{
dest->blend (*src);
incDestPixelPointer (dest);
src = addBytesToPointer (src, srcData.pixelStride);
} while (--width > 0);
}
}
JUCE_DECLARE_NON_COPYABLE (ImageFill);
@ -1466,7 +1542,6 @@ namespace EdgeTableFillers
template <class Iterator, class DestPixelType>
void renderSolidFill (Iterator& iter, const Image::BitmapData& destData, const PixelARGB& fillColour, const bool replaceContents, DestPixelType*)
{
jassert (destData.pixelStride == sizeof (DestPixelType));
if (replaceContents)
{
EdgeTableFillers::SolidColour <DestPixelType, true> r (destData, fillColour);
@ -1483,8 +1558,6 @@ namespace EdgeTableFillers
void renderGradient (Iterator& iter, const Image::BitmapData& destData, const ColourGradient& g, const AffineTransform& transform,
const PixelARGB* const lookupTable, const int numLookupEntries, const bool isIdentity, DestPixelType*)
{
jassert (destData.pixelStride == sizeof (DestPixelType));
if (g.isRadial)
{
if (isIdentity)

View file

@ -211,7 +211,9 @@ public:
{
jassert (format == Image::RGB || format == Image::ARGB);
pixelStride = (format == Image::RGB) ? 3 : 4;
static bool alwaysUse32Bits = isGraphicsCard32Bit(); // NB: for 32-bit cards, it's faster to use a 32-bit image.
pixelStride = (alwaysUse32Bits || format == Image::ARGB) ? 4 : 3;
lineStride = -((w * pixelStride + 3) & ~3);
zerostruct (bitmapInfo);
@ -353,6 +355,14 @@ public:
uint8* imageData;
private:
static bool isGraphicsCard32Bit()
{
HDC dc = GetDC (0);
const int bitsPerPixel = GetDeviceCaps (dc, BITSPIXEL);
ReleaseDC (0, dc);
return bitsPerPixel > 24;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WindowsBitmapImage);
};
@ -1076,8 +1086,7 @@ private:
Image& getImage (const bool transparent, const int w, const int h)
{
static bool alwaysUseARGB = isGraphicsCard32Bit(); // NB: for 32-bit cards, it's faster to use a 32-bit image.
const Image::PixelFormat format = (transparent || alwaysUseARGB) ? Image::ARGB : Image::RGB;
const Image::PixelFormat format = transparent ? Image::ARGB : Image::RGB;
if ((! image.isValid()) || image.getWidth() < w || image.getHeight() < h || image.getFormat() != format)
image = Image (new WindowsBitmapImage (format, (w + 31) & ~31, (h + 31) & ~31, false));
@ -1095,14 +1104,6 @@ private:
private:
Image image;
static bool isGraphicsCard32Bit()
{
HDC dc = GetDC (0);
const int bitsPerPixel = GetDeviceCaps (dc, BITSPIXEL);
ReleaseDC (0, dc);
return bitsPerPixel > 24;
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TemporaryImage);
};