mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-02 03:20:06 +00:00
Tweaks to font-rendering: fonts are now vertically hinted by finding the best overall scale that will make the most common horizontal features better aligned. Changed the font gamma to be greater when rendering with brighter colours.
This commit is contained in:
parent
d582a66917
commit
a1a43ea418
3 changed files with 205 additions and 57 deletions
|
|
@ -101,8 +101,8 @@ struct FontStyleHelpers
|
|||
};
|
||||
|
||||
//==============================================================================
|
||||
Typeface::Typeface (const String& name_, const String& style_) noexcept
|
||||
: name (name_), style (style_)
|
||||
Typeface::Typeface (const String& faceName, const String& styleName) noexcept
|
||||
: name (faceName), style (styleName)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -126,3 +126,134 @@ EdgeTable* Typeface::getEdgeTableForGlyph (int glyphNumber, const AffineTransfor
|
|||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct Typeface::HintingParams
|
||||
{
|
||||
HintingParams (Typeface& t)
|
||||
: top (0), middle (0), bottom (0)
|
||||
{
|
||||
Font font (&t);
|
||||
font = font.withHeight ((float) standardHeight);
|
||||
|
||||
top = getAverageY (font, "BDEFPRTZOQC", true);
|
||||
middle = getAverageY (font, "acegmnopqrsuvwxy", true);
|
||||
bottom = getAverageY (font, "BDELZOC", false);
|
||||
}
|
||||
|
||||
AffineTransform getVerticalHintingTransform (float fontSize) noexcept
|
||||
{
|
||||
if (cachedSize == fontSize)
|
||||
return cachedTransform;
|
||||
|
||||
const float t = fontSize * top;
|
||||
const float m = fontSize * middle;
|
||||
const float b = fontSize * bottom;
|
||||
|
||||
if (b < t + 2.0f)
|
||||
return AffineTransform();
|
||||
|
||||
Scaling s[] = { Scaling (t, m, b, 0.0f, 0.0f),
|
||||
Scaling (t, m, b, 1.0f, 0.0f),
|
||||
Scaling (t, m, b, 0.0f, 1.0f),
|
||||
Scaling (t, m, b, 1.0f, 1.0f) };
|
||||
|
||||
int best = 0;
|
||||
|
||||
for (int i = 1; i < numElementsInArray (s); ++i)
|
||||
if (s[i].drift < s[best].drift)
|
||||
best = i;
|
||||
|
||||
cachedSize = fontSize;
|
||||
|
||||
AffineTransform result (s[best].getTransform());
|
||||
cachedTransform = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
float cachedSize;
|
||||
AffineTransform cachedTransform;
|
||||
|
||||
struct Scaling
|
||||
{
|
||||
Scaling (float t, float m, float b, float direction1, float direction2) noexcept
|
||||
{
|
||||
float newT = std::floor (t) + direction1;
|
||||
float newB = std::floor (b) + direction2;
|
||||
float newM = newT + (newB - newT) * (m - t) / (b - t);
|
||||
|
||||
float middleOffset = newM - std::floor (newM);
|
||||
float nudge = middleOffset < 0.5f ? (middleOffset * -0.2f) : ((1.0f - middleOffset) * 0.2f);
|
||||
newT += nudge;
|
||||
newB += nudge;
|
||||
|
||||
scale = (newB - newT) / (b - t);
|
||||
offset = (newB / scale) - b;
|
||||
|
||||
drift = getDrift (t) + getDrift (m) + getDrift (b) + offset + 20.0f * std::abs (scale - 1.0f);
|
||||
}
|
||||
|
||||
AffineTransform getTransform() const noexcept
|
||||
{
|
||||
return AffineTransform::translation (0, offset).scaled (1.0f, scale);
|
||||
}
|
||||
|
||||
float getDrift (float n) const noexcept
|
||||
{
|
||||
n = (n + offset) * scale;
|
||||
const float diff = n - std::floor (n);
|
||||
return jmin (diff, 1.0f - diff);
|
||||
}
|
||||
|
||||
float offset, scale, drift;
|
||||
};
|
||||
|
||||
static float getAverageY (const Font& font, const char* chars, bool getTop)
|
||||
{
|
||||
GlyphArrangement ga;
|
||||
ga.addLineOfText (font, chars, 0, 0);
|
||||
|
||||
Array<float> y;
|
||||
DefaultElementComparator<float> sorter;
|
||||
|
||||
for (int i = 0; i < ga.getNumGlyphs(); ++i)
|
||||
{
|
||||
Path p;
|
||||
ga.getGlyph (i).createPath (p);
|
||||
Rectangle<float> bounds (p.getBounds());
|
||||
|
||||
if (! p.isEmpty())
|
||||
y.addSorted (sorter, getTop ? bounds.getY() : bounds.getBottom());
|
||||
}
|
||||
|
||||
float median = y[y.size() / 2];
|
||||
|
||||
int total = 0;
|
||||
int num = 0;
|
||||
|
||||
for (int i = 0; i < y.size(); ++i)
|
||||
{
|
||||
if (std::abs (median - y.getUnchecked(i)) < 0.05f * (float) standardHeight)
|
||||
{
|
||||
total += y.getUnchecked(i);
|
||||
++num;
|
||||
}
|
||||
}
|
||||
|
||||
return num < 4 ? 0.0f : total / (num * (float) standardHeight);
|
||||
}
|
||||
|
||||
enum { standardHeight = 100 };
|
||||
float top, middle, bottom;
|
||||
};
|
||||
|
||||
AffineTransform Typeface::getVerticalHintingTransform (float fontSize)
|
||||
{
|
||||
ScopedLock sl (hintingLock);
|
||||
|
||||
if (hintingParams == nullptr)
|
||||
hintingParams = new HintingParams (*this);
|
||||
|
||||
return hintingParams->getVerticalHintingTransform (fontSize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,11 @@ public:
|
|||
*/
|
||||
static void scanFolderForFonts (const File& folder);
|
||||
|
||||
/** Makes an attempt at estimating a good overall transform that will scale a font of
|
||||
the given size to align vertically with the pixel grid.
|
||||
*/
|
||||
AffineTransform getVerticalHintingTransform (float fontHeight);
|
||||
|
||||
protected:
|
||||
//==============================================================================
|
||||
String name, style;
|
||||
|
|
@ -143,6 +148,11 @@ protected:
|
|||
static Ptr getFallbackTypeface();
|
||||
|
||||
private:
|
||||
struct HintingParams;
|
||||
friend struct ContainerDeletePolicy<HintingParams>;
|
||||
ScopedPointer<HintingParams> hintingParams;
|
||||
CriticalSection hintingLock;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Typeface)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -283,11 +283,9 @@ public:
|
|||
glyph = glyphNumber;
|
||||
|
||||
const float fontHeight = font.getHeight();
|
||||
edgeTable = typeface->getEdgeTableForGlyph (glyphNumber, AffineTransform::scale (fontHeight * font.getHorizontalScale(),
|
||||
fontHeight));
|
||||
|
||||
if (edgeTable != nullptr)
|
||||
edgeTable->multiplyLevels (1.5f);
|
||||
edgeTable = typeface->getEdgeTableForGlyph (glyphNumber,
|
||||
AffineTransform::scale (fontHeight * font.getHorizontalScale(), fontHeight)
|
||||
.followedBy (font.getTypeface()->getVerticalHintingTransform (fontHeight)));
|
||||
}
|
||||
|
||||
Font font;
|
||||
|
|
@ -295,7 +293,7 @@ public:
|
|||
bool snapToIntegerCoordinate;
|
||||
|
||||
private:
|
||||
ScopedPointer <EdgeTable> edgeTable;
|
||||
ScopedPointer<EdgeTable> edgeTable;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable)
|
||||
};
|
||||
|
|
@ -1351,7 +1349,7 @@ namespace EdgeTableFillers
|
|||
const int maxX, maxY;
|
||||
int y;
|
||||
DestPixelType* linePixels;
|
||||
HeapBlock <SrcPixelType> scratchBuffer;
|
||||
HeapBlock<SrcPixelType> scratchBuffer;
|
||||
size_t scratchSize;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (TransformedImageFill)
|
||||
|
|
@ -1369,16 +1367,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelARGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelARGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelARGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelARGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelARGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelARGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelARGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelARGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { TransformedImageFill <PixelARGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelARGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelARGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelARGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1387,16 +1385,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelRGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelRGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelRGB, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelRGB, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelRGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelRGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelRGB, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelRGB, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { TransformedImageFill <PixelRGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelRGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelRGB, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelRGB, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1405,16 +1403,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelAlpha, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelAlpha, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelAlpha, PixelARGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelAlpha, PixelARGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { TransformedImageFill <PixelAlpha, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelAlpha, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelAlpha, PixelRGB, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelAlpha, PixelRGB, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { TransformedImageFill <PixelAlpha, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill <PixelAlpha, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
if (tiledFill) { TransformedImageFill<PixelAlpha, PixelAlpha, true> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
else { TransformedImageFill<PixelAlpha, PixelAlpha, false> r (destData, srcData, transform, alpha, quality); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1430,16 +1428,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { ImageFill <PixelARGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelARGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelARGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelARGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { ImageFill <PixelARGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelARGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelARGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelARGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { ImageFill <PixelARGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelARGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelARGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelARGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1448,16 +1446,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { ImageFill <PixelRGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelRGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelRGB, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelRGB, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { ImageFill <PixelRGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelRGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelRGB, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelRGB, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { ImageFill <PixelRGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelRGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelRGB, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelRGB, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1466,16 +1464,16 @@ namespace EdgeTableFillers
|
|||
switch (srcData.pixelFormat)
|
||||
{
|
||||
case Image::ARGB:
|
||||
if (tiledFill) { ImageFill <PixelAlpha, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelAlpha, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelAlpha, PixelARGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelAlpha, PixelARGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
case Image::RGB:
|
||||
if (tiledFill) { ImageFill <PixelAlpha, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelAlpha, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelAlpha, PixelRGB, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelAlpha, PixelRGB, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
default:
|
||||
if (tiledFill) { ImageFill <PixelAlpha, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill <PixelAlpha, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
if (tiledFill) { ImageFill<PixelAlpha, PixelAlpha, true> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
else { ImageFill<PixelAlpha, PixelAlpha, false> r (destData, srcData, alpha, x, y); iter.iterate (r); }
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1487,12 +1485,12 @@ namespace EdgeTableFillers
|
|||
{
|
||||
if (replaceContents)
|
||||
{
|
||||
EdgeTableFillers::SolidColour <DestPixelType, true> r (destData, fillColour);
|
||||
EdgeTableFillers::SolidColour<DestPixelType, true> r (destData, fillColour);
|
||||
iter.iterate (r);
|
||||
}
|
||||
else
|
||||
{
|
||||
EdgeTableFillers::SolidColour <DestPixelType, false> r (destData, fillColour);
|
||||
EdgeTableFillers::SolidColour<DestPixelType, false> r (destData, fillColour);
|
||||
iter.iterate (r);
|
||||
}
|
||||
}
|
||||
|
|
@ -1505,18 +1503,18 @@ namespace EdgeTableFillers
|
|||
{
|
||||
if (isIdentity)
|
||||
{
|
||||
EdgeTableFillers::Gradient <DestPixelType, GradientPixelIterators::Radial> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Radial> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
iter.iterate (renderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
EdgeTableFillers::Gradient <DestPixelType, GradientPixelIterators::TransformedRadial> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::TransformedRadial> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
iter.iterate (renderer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EdgeTableFillers::Gradient <DestPixelType, GradientPixelIterators::Linear> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
EdgeTableFillers::Gradient<DestPixelType, GradientPixelIterators::Linear> renderer (destData, g, transform, lookupTable, numLookupEntries);
|
||||
iter.iterate (renderer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1721,7 +1719,7 @@ struct ClipRegions
|
|||
template <class SrcPixelType>
|
||||
void transformedClipImage (const Image::BitmapData& srcData, const AffineTransform& transform, const Graphics::ResamplingQuality quality, const SrcPixelType*)
|
||||
{
|
||||
EdgeTableFillers::TransformedImageFill <SrcPixelType, SrcPixelType, false> renderer (srcData, srcData, transform, 255, quality);
|
||||
EdgeTableFillers::TransformedImageFill<SrcPixelType, SrcPixelType, false> renderer (srcData, srcData, transform, 255, quality);
|
||||
|
||||
for (int y = 0; y < edgeTable.getMaximumBounds().getHeight(); ++y)
|
||||
renderer.clipEdgeTableLine (edgeTable, edgeTable.getMaximumBounds().getX(), y + edgeTable.getMaximumBounds().getY(),
|
||||
|
|
@ -1734,7 +1732,7 @@ struct ClipRegions
|
|||
Rectangle<int> r (imageX, imageY, srcData.width, srcData.height);
|
||||
edgeTable.clipToRectangle (r);
|
||||
|
||||
EdgeTableFillers::ImageFill <SrcPixelType, SrcPixelType, false> renderer (srcData, srcData, 255, imageX, imageY);
|
||||
EdgeTableFillers::ImageFill<SrcPixelType, SrcPixelType, false> renderer (srcData, srcData, 255, imageX, imageY);
|
||||
|
||||
for (int y = 0; y < r.getHeight(); ++y)
|
||||
renderer.clipEdgeTableLine (edgeTable, r.getX(), y + r.getY(), r.getWidth());
|
||||
|
|
@ -2002,7 +2000,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
SavedStateType& getThis() noexcept { return *static_cast <SavedStateType*> (this); }
|
||||
SavedStateType& getThis() noexcept { return *static_cast<SavedStateType*> (this); }
|
||||
|
||||
bool clipToRectangle (const Rectangle<int>& r)
|
||||
{
|
||||
|
|
@ -2253,11 +2251,20 @@ public:
|
|||
{
|
||||
EdgeTableRegionType* edgeTableClip = new EdgeTableRegionType (edgeTable);
|
||||
edgeTableClip->edgeTable.translate (x, y);
|
||||
|
||||
if (fillType.isColour())
|
||||
{
|
||||
float brightness = fillType.colour.getBrightness() - 0.5f;
|
||||
|
||||
if (brightness > 0.0f)
|
||||
edgeTableClip->edgeTable.multiplyLevels (1.0f + 1.6f * brightness);
|
||||
}
|
||||
|
||||
fillShape (edgeTableClip, false);
|
||||
}
|
||||
}
|
||||
|
||||
void drawLine (const Line <float>& line)
|
||||
void drawLine (const Line<float>& line)
|
||||
{
|
||||
Path p;
|
||||
p.addLineSegment (line, 1.0f);
|
||||
|
|
@ -2437,7 +2444,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
typedef GlyphCache<CachedGlyphEdgeTable <SoftwareRendererSavedState>, SoftwareRendererSavedState> GlyphCacheType;
|
||||
typedef GlyphCache<CachedGlyphEdgeTable<SoftwareRendererSavedState>, SoftwareRendererSavedState> GlyphCacheType;
|
||||
|
||||
static void clearGlyphCache()
|
||||
{
|
||||
|
|
@ -2523,7 +2530,7 @@ public:
|
|||
template <typename IteratorType>
|
||||
void fillWithGradient (IteratorType& iter, ColourGradient& gradient, const AffineTransform& trans, bool isIdentity) const
|
||||
{
|
||||
HeapBlock <PixelARGB> lookupTable;
|
||||
HeapBlock<PixelARGB> lookupTable;
|
||||
const int numLookupEntries = gradient.createLookupTable (trans, lookupTable);
|
||||
jassert (numLookupEntries > 0);
|
||||
|
||||
|
|
@ -2632,7 +2639,7 @@ public:
|
|||
void fillPath (const Path& path, const AffineTransform& t) override { stack->fillPath (path, t); }
|
||||
void drawImage (const Image& im, const AffineTransform& t) override { stack->drawImage (im, t); }
|
||||
void drawGlyph (int glyphNumber, const AffineTransform& t) override { stack->drawGlyph (glyphNumber, t); }
|
||||
void drawLine (const Line <float>& line) override { stack->drawLine (line); }
|
||||
void drawLine (const Line<float>& line) override { stack->drawLine (line); }
|
||||
void setFont (const Font& newFont) override { stack->font = newFont; }
|
||||
const Font& getFont() override { return stack->font; }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue