Patch by Andrej Spielmann (GSOC):

* Integrate the subpixel rendering with the existing drawing backend and
  the font rendering.
* The font cache has got an additional rendering type for extracting and
  caching glyph bitmaps that store subpixel coverage values.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26361 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus
2008-07-10 08:26:38 +00:00
parent 73b44a6aae
commit fa6a00c628
11 changed files with 473 additions and 103 deletions
+34 -7
View File
@@ -5,14 +5,15 @@
* Authors:
* Maxim Shemanarev <[email protected]>
* Stephan Aßmus <[email protected]>
* Andrej Spielmann, <[email protected]>
*/
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
@@ -35,6 +36,12 @@
BLocker
FontCacheEntry::sUsageUpdateLock("FontCacheEntry usage lock");
glyph_rendering
FontCacheEntry::sDefaultRenderType;
bool
FontCacheEntry::sDefaultHinting;
class FontCacheEntry::GlyphCachePool {
public:
@@ -49,7 +56,7 @@ class FontCacheEntry::GlyphCachePool {
const GlyphCache* FindGlyph(uint16 glyphCode) const
{
unsigned msb = (glyphCode >> 8) & 0xFF;
if (fGlyphs[msb])
if (fGlyphs[msb])
return fGlyphs[msb][glyphCode & 0xFF];
return 0;
}
@@ -120,7 +127,7 @@ FontCacheEntry::Init(const ServerFont& font)
// TODO: encoding from font
FT_Encoding charMap = FT_ENCODING_NONE;
bool hinting = true; // TODO: font.Hinting();
bool hinting = sDefaultHinting; // TODO: font.Hinting();
if (!fEngine.Init(font.Path(), 0, font.Size(), charMap,
renderingType, hinting)) {
@@ -188,6 +195,10 @@ FontCacheEntry::InitAdaptors(const GlyphCache* glyph,
gray8Adapter.init(glyph->data, glyph->data_size, x, y);
break;
case glyph_data_subpix:
gray8Adapter.init(glyph->data, glyph->data_size, x, y);
break;
case glyph_data_outline:
pathAdapter.init(glyph->data, glyph->data_size, x, y, scale);
break;
@@ -213,7 +224,7 @@ FontCacheEntry::GenerateSignature(char* signature, const ServerFont& font)
// TODO: read more of these from the font
FT_Encoding charMap = FT_ENCODING_NONE;
bool hinting = true; // TODO: font.Hinting();
bool hinting = sDefaultHinting; // TODO: font.Hinting();
sprintf(signature, "%ld,%u,%d,%d,%.1f,%d",
font.GetFamilyAndStyle(), charMap,
@@ -235,15 +246,31 @@ FontCacheEntry::UpdateUsage()
fUseCounter++;
}
void
FontCacheEntry::SetDefaultRenderType(glyph_rendering renderingType)
{
sDefaultRenderType = renderingType;
}
void
FontCacheEntry::SetDefaultHinting(bool hinting)
{
sDefaultHinting = hinting;
}
// _RenderTypeFor
/*static*/ glyph_rendering
FontCacheEntry::_RenderTypeFor(const ServerFont& font)
{
glyph_rendering renderingType = glyph_ren_native_gray8;
glyph_rendering renderingType = sDefaultRenderType;
if (font.Rotation() != 0.0 || font.Shear() != 90.0
|| font.FalseBoldWidth() != 0.0
|| font.Flags() & B_DISABLE_ANTIALIASING
|| font.Size() > 30) {
|| font.Size() > 30
|| !sDefaultHinting) {
renderingType = glyph_ren_outline;
}
return renderingType;
+11
View File
@@ -5,6 +5,7 @@
* Authors:
* Maxim Shemanarev <[email protected]>
* Stephan Aßmus <[email protected]>
* Andrej Spielmann, <[email protected]>
*/
//----------------------------------------------------------------------------
@@ -60,6 +61,7 @@ class FontCacheEntry : public MultiLocker, public Referenceable {
typedef GlyphGray8Adapter::embedded_scanline GlyphGray8Scanline;
typedef FontEngine::MonoAdapter GlyphMonoAdapter;
typedef GlyphMonoAdapter::embedded_scanline GlyphMonoScanline;
typedef FontEngine::SubpixAdapter SubpixAdapter;
typedef agg::conv_curve<GlyphPathAdapter> CurveConverter;
typedef agg::conv_contour<CurveConverter> ContourConverter;
@@ -92,6 +94,13 @@ class FontCacheEntry : public MultiLocker, public Referenceable {
static void GenerateSignature(char* signature,
const ServerFont& font);
static void SetDefaultRenderType(glyph_rendering renderType);
static glyph_rendering DefaultRenderType()
{ return sDefaultRenderType; }
static void SetDefaultHinting(bool hinting);
static bool DefaultHinting()
{ return sDefaultHinting; }
// private to FontCache class:
void UpdateUsage();
@@ -110,6 +119,8 @@ class FontCacheEntry : public MultiLocker, public Referenceable {
GlyphCachePool* fGlyphCache;
FontEngine fEngine;
static glyph_rendering sDefaultRenderType;
static bool sDefaultHinting;
static BLocker sUsageUpdateLock;
bigtime_t fLastUsedTime;
+224 -48
View File
@@ -6,14 +6,15 @@
* Maxim Shemanarev <[email protected]>
* Stephan Aßmus <[email protected]>
* Anthony Lee <[email protected]>
* Andrej Spielmann, <[email protected]>
*/
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
@@ -26,12 +27,18 @@
#include "FontEngine.h"
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_LCD_FILTER_H
#include <stdio.h>
#include <agg_bitset_iterator.h>
#include <agg_renderer_scanline.h>
static const bool kFlipY = true;
@@ -54,7 +61,7 @@ dbl_to_int26p6(double p)
template<class PathStorage>
bool
decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
{
{
typedef typename PathStorage::value_type value_type;
FT_Vector v_last;
@@ -114,7 +121,7 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x1 = int26p6_to_dbl(v_start.x);
y1 = int26p6_to_dbl(v_start.y);
if (flip_y) y1 = -y1;
path.move_to(value_type(dbl_to_int26p6(x1)),
path.move_to(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)));
while(point < limit) {
@@ -127,7 +134,7 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x1 = int26p6_to_dbl(point->x);
y1 = int26p6_to_dbl(point->y);
if (flip_y) y1 = -y1;
path.line_to(value_type(dbl_to_int26p6(x1)),
path.line_to(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)));
//path.line_to(conv(point->x), flip_y ? -conv(point->y) : conv(point->y));
continue;
@@ -155,9 +162,9 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x2 = int26p6_to_dbl(vec.x);
y2 = int26p6_to_dbl(vec.y);
if (flip_y) { y1 = -y1; y2 = -y2; }
path.curve3(value_type(dbl_to_int26p6(x1)),
path.curve3(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(y2)));
continue;
}
@@ -173,14 +180,14 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x2 = int26p6_to_dbl(v_middle.x);
y2 = int26p6_to_dbl(v_middle.y);
if (flip_y) { y1 = -y1; y2 = -y2; }
path.curve3(value_type(dbl_to_int26p6(x1)),
path.curve3(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(y2)));
//path.curve3(conv(v_control.x),
// flip_y ? -conv(v_control.y) : conv(v_control.y),
// conv(v_middle.x),
//path.curve3(conv(v_control.x),
// flip_y ? -conv(v_control.y) : conv(v_control.y),
// conv(v_middle.x),
// flip_y ? -conv(v_middle.y) : conv(v_middle.y));
v_control = vec;
@@ -192,14 +199,14 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x2 = int26p6_to_dbl(v_start.x);
y2 = int26p6_to_dbl(v_start.y);
if (flip_y) { y1 = -y1; y2 = -y2; }
path.curve3(value_type(dbl_to_int26p6(x1)),
path.curve3(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(y2)));
//path.curve3(conv(v_control.x),
// flip_y ? -conv(v_control.y) : conv(v_control.y),
// conv(v_start.x),
//path.curve3(conv(v_control.x),
// flip_y ? -conv(v_control.y) : conv(v_control.y),
// conv(v_start.x),
// flip_y ? -conv(v_start.y) : conv(v_start.y));
goto Close;
}
@@ -210,9 +217,9 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
if (point + 1 > limit || FT_CURVE_TAG(tags[1]) != FT_CURVE_TAG_CUBIC)
return false;
vec1.x = point[0].x;
vec1.x = point[0].x;
vec1.y = point[0].y;
vec2.x = point[1].x;
vec2.x = point[1].x;
vec2.y = point[1].y;
point += 2;
@@ -231,18 +238,18 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x3 = int26p6_to_dbl(vec.x);
y3 = int26p6_to_dbl(vec.y);
if (flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
path.curve4(value_type(dbl_to_int26p6(x1)),
path.curve4(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(y2)),
value_type(dbl_to_int26p6(x3)),
value_type(dbl_to_int26p6(x3)),
value_type(dbl_to_int26p6(y3)));
//path.curve4(conv(vec1.x),
// flip_y ? -conv(vec1.y) : conv(vec1.y),
// conv(vec2.x),
//path.curve4(conv(vec1.x),
// flip_y ? -conv(vec1.y) : conv(vec1.y),
// conv(vec2.x),
// flip_y ? -conv(vec2.y) : conv(vec2.y),
// conv(vec.x),
// conv(vec.x),
// flip_y ? -conv(vec.y) : conv(vec.y));
continue;
}
@@ -254,18 +261,18 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
x3 = int26p6_to_dbl(v_start.x);
y3 = int26p6_to_dbl(v_start.y);
if (flip_y) { y1 = -y1; y2 = -y2; y3 = -y3; }
path.curve4(value_type(dbl_to_int26p6(x1)),
path.curve4(value_type(dbl_to_int26p6(x1)),
value_type(dbl_to_int26p6(y1)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(x2)),
value_type(dbl_to_int26p6(y2)),
value_type(dbl_to_int26p6(x3)),
value_type(dbl_to_int26p6(x3)),
value_type(dbl_to_int26p6(y3)));
//path.curve4(conv(vec1.x),
// flip_y ? -conv(vec1.y) : conv(vec1.y),
// conv(vec2.x),
//path.curve4(conv(vec1.x),
// flip_y ? -conv(vec1.y) : conv(vec1.y),
// conv(vec2.x),
// flip_y ? -conv(vec2.y) : conv(vec2.y),
// conv(v_start.x),
// conv(v_start.x),
// flip_y ? -conv(v_start.y) : conv(v_start.y));
goto Close;
}
@@ -275,12 +282,13 @@ decompose_ft_outline(const FT_Outline& outline, bool flip_y, PathStorage& path)
path.close_polygon();
Close:
first = last + 1;
first = last + 1;
}
return true;
}
// decompose_ft_bitmap_mono
template<class Scanline, class ScanlineStorage>
void
@@ -314,6 +322,7 @@ decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, int x, int y,
}
}
// decompose_ft_bitmap_gray8
template<class Scanline, class ScanlineStorage>
void
@@ -360,6 +369,142 @@ decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, int x, int y,
}
// decompose_ft_bitmap_subpix
template<class Scanline, class ScanlineStorage>
void
decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y,
bool flip_y, Scanline& sl, ScanlineStorage& storage)
{
//Filtering weights
const uint8 filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 };
int i, j;
const uint8* buf = (const uint8*)bitmap.buffer;
int pitch = bitmap.pitch;
sl.reset(x-1, x + bitmap.width/3 + 1);
storage.prepare();
if (flip_y) {
buf += bitmap.pitch * (bitmap.rows - 1);
y += bitmap.rows;
pitch = -pitch;
}
for (i = 0; i < bitmap.rows; i++) {
sl.reset_spans();
if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
// font has built-in mono bitmap
agg::bitset_iterator bits(buf, 0);
int j;
for (j = 0; j < bitmap.width; j++) {
if (bits.bit())
sl.add_cell(x + j,
agg::cover_full, agg::cover_full, agg::cover_full);
++bits;
}
} else {
const uint8* p = buf;
uint32 coverRed;
uint32 coverGreen;
uint32 coverBlue;
int w = bitmap.width/3;
if (w && !(p[0] == p[1] && p[1] == p[2]
&& (w == 1 || (p[3] == p[4] && p[4] == p[5])))){
coverRed = 0;
coverGreen = (p[0] * filter[0]) >> 8;
coverBlue = (p[0] * filter[1] + p[1] * filter[0]) >> 8;
coverGreen = coverGreen | ( -(coverGreen >> 8));
coverBlue = coverBlue | ( -(coverBlue >> 8));
if (coverRed || coverGreen || coverBlue){
sl.add_cell(x - 1, coverRed, coverGreen, coverBlue);
}
}
for (j = 0; j < w; j++) {
if (p[0] == p[1] && p[1] == p[2]
&& (j == 0 || (p[-3] == p[-2] && p[-2] == p[-1]))
&& (j == w-1 || (p[3] == p[4] && p[4] == p[5]))){
coverRed = p[0];
coverGreen = p[0];
coverBlue = p[0];
} else if (p[0] == p[1] && p[1] == p[2]
&& (j < w-1 && p[3] == p[4] && p[4] == p[5])
&& (j == w-2 || (p[6] == p[7] && p[7] == p[8]))){
coverRed = ((j > 0 ? p[-2] * filter[4]
+ p[-1] * filter[3] : 0)
+ p[0] * filter[2] + p[1] * filter[1]
+ p[2] * filter[0])
>> 8;
coverGreen = ((j > 0 ? p[-1] * filter[4] : 0)
+ p[0] * filter[3] + p[1] * filter[2]
+ p[2] * filter[1])
>> 8;
coverBlue = (p[0] * filter[4]
+ p[1] * filter[3] + p[2] * filter[2]) >> 8;
coverRed = coverRed | ( -(coverRed >> 8));
coverGreen = coverGreen | ( -(coverGreen >> 8));
coverBlue = coverBlue | ( -(coverBlue >> 8));
} else if (p[0] == p[1] && p[1] == p[2]
&& (j > 0 && p[-3] == p[-2] && p[-2] == p[-1])
&& (j == 1 || (p[-6] == p[-5] && p[-5] == p[-4]))){
coverRed = (p[0] * filter[2] + p[1] * filter[1]
+ p[2] * filter[0]) >> 8;
coverGreen = (p[0] * filter[3] + p[1] * filter[2]
+ p[2] * filter[1]
+ (j < w-1 ? p[3] * filter[0] : 0))
>> 8;
coverBlue = (p[0] * filter[4] + p[1] * filter[3]
+ p[2] * filter[2]
+ (j < w-1 ? p[3] * filter[1]
+ p[4] * filter[0] : 0))
>> 8;
coverRed = coverRed | ( -(coverRed >> 8));
coverGreen = coverGreen | ( -(coverGreen >> 8));
coverBlue = coverBlue | ( -(coverBlue >> 8));
} else {
coverRed = ((j > 0 ? p[-2] * filter[4]
+ p[-1] * filter[3] : 0)
+ p[0] * filter[2] + p[1] * filter[1]
+ p[2] * filter[0])
>> 8;
coverGreen = ((j > 0 ? p[-1] * filter[4] : 0)
+ p[0] * filter[3] + p[1] * filter[2]
+ p[2] * filter[1]
+ (j < w-1 ? p[3] * filter[0] : 0))
>> 8;
coverBlue = (p[0] * filter[4] + p[1] * filter[3]
+ p[2] * filter[2]
+ (j < w-1 ? p[3] * filter[1]
+ p[4] * filter[0] : 0))
>> 8;
coverRed = coverRed | ( -(coverRed >> 8));
coverGreen = coverGreen | ( -(coverGreen >> 8));
coverBlue = coverBlue | ( -(coverBlue >> 8));
}
if (coverRed || coverGreen || coverBlue) {
sl.add_cell(x + j, coverRed, coverGreen, coverBlue);
}
p += 3;
}
if (w && !(p[-3] == p[-2] && p[-2] == p[-1]
&& (w == 1 || (p[-6] == p[-5] && p[-5] == p[-4])))){
coverRed = (p[-2] * filter[4] + p[-1] * filter[3]) >> 8;
coverGreen = (p[-1] * filter[4]) >> 8;
coverBlue = 0;
coverRed = coverRed | ( -(coverRed >> 8));
coverGreen = coverGreen | ( -(coverGreen >> 8));
if (coverRed || coverGreen || coverBlue){
sl.add_cell(x + w, coverRed, coverGreen, coverBlue);
}
}
}
buf += pitch;
if (sl.num_spans()) {
sl.finalize(y - i - 1);
storage.render(sl);
}
}
}
// #pragma mark -
@@ -386,8 +531,10 @@ FontEngine::FontEngine()
, fCurves(fPath)
, fScanlineAA()
, fScanlineBin()
, fScanlineSubpix()
, fScanlineStorageAA()
, fScanlineStorageBin()
, fScanlineStorageSubpix()
{
fCurves.approximation_scale(4.0);
@@ -396,6 +543,7 @@ FontEngine::FontEngine()
fLibraryInitialized = true;
}
// destructor
FontEngine::~FontEngine()
{
@@ -405,6 +553,7 @@ FontEngine::~FontEngine()
FT_Done_FreeType(fLibrary);
}
// CountFaces
unsigned
FontEngine::CountFaces() const
@@ -415,14 +564,14 @@ FontEngine::CountFaces() const
return 0;
}
// PrepareGlyph
bool
FontEngine::PrepareGlyph(unsigned glyphCode)
{
fGlyphIndex = FT_Get_Char_Index(fFace, glyphCode);
fLastError = FT_Load_Glyph(fFace, fGlyphIndex,
fHinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING);
// fHinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING);
(fHinting ? (FT_LOAD_DEFAULT | FT_LOAD_TARGET_LCD) : FT_LOAD_NO_HINTING));
if (fLastError != 0)
return false;
@@ -430,7 +579,7 @@ FontEngine::PrepareGlyph(unsigned glyphCode)
fAdvanceX = int26p6_to_dbl(fFace->glyph->advance.x);
fAdvanceY = int26p6_to_dbl(fFace->glyph->advance.y);
fInsetLeft = int26p6_to_dbl(fFace->glyph->metrics.horiBearingX);
fInsetRight = int26p6_to_dbl(fFace->glyph->metrics.horiBearingX
fInsetRight = int26p6_to_dbl(fFace->glyph->metrics.horiBearingX
+ fFace->glyph->metrics.width - fFace->glyph->metrics.horiAdvance);
switch(fGlyphRendering) {
@@ -445,17 +594,17 @@ FontEngine::PrepareGlyph(unsigned glyphCode)
fBounds.y1 = fScanlineStorageBin.min_y();
fBounds.x2 = fScanlineStorageBin.max_x();
fBounds.y2 = fScanlineStorageBin.max_y();
fDataSize = fScanlineStorageBin.byte_size();
fDataSize = fScanlineStorageBin.byte_size();
fDataType = glyph_data_mono;
return true;
}
break;
case glyph_ren_native_gray8:
fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_NORMAL);
if (fLastError == 0) {
decompose_ft_bitmap_gray8(fFace->glyph->bitmap,
decompose_ft_bitmap_gray8(fFace->glyph->bitmap,
fFace->glyph->bitmap_left, kFlipY ?
-fFace->glyph->bitmap_top : fFace->glyph->bitmap_top,
kFlipY, fScanlineAA, fScanlineStorageAA);
@@ -463,13 +612,31 @@ FontEngine::PrepareGlyph(unsigned glyphCode)
fBounds.y1 = fScanlineStorageAA.min_y();
fBounds.x2 = fScanlineStorageAA.max_x();
fBounds.y2 = fScanlineStorageAA.max_y();
fDataSize = fScanlineStorageAA.byte_size();
fDataSize = fScanlineStorageAA.byte_size();
fDataType = glyph_data_gray8;
return true;
}
break;
case glyph_ren_subpix:
fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD);
if (fLastError == 0) {
decompose_ft_bitmap_subpix(fFace->glyph->bitmap,
fFace->glyph->bitmap_left, kFlipY ?
-fFace->glyph->bitmap_top : fFace->glyph->bitmap_top,
kFlipY, fScanlineSubpix, fScanlineStorageSubpix);
fBounds.x1 = fScanlineStorageSubpix.min_x();
fBounds.y1 = fScanlineStorageSubpix.min_y();
fBounds.x2 = fScanlineStorageSubpix.max_x();
fBounds.y2 = fScanlineStorageSubpix.max_y();
fDataSize = fScanlineStorageSubpix.byte_size();
fDataType = glyph_data_subpix;
return true;
}
break;
case glyph_ren_outline:
fPath.remove_all();
if (decompose_ft_outline(fFace->glyph->outline, kFlipY, fPath)) {
@@ -500,20 +667,25 @@ FontEngine::WriteGlyphTo(uint8* data) const
break;
case glyph_data_gray8:
fScanlineStorageAA.serialize(data);
fScanlineStorageAA.serialize(data);
break;
case glyph_data_outline:
case glyph_data_subpix:
fScanlineStorageSubpix.serialize(data);
break;
case glyph_data_outline:
fPath.serialize(data);
break;
case glyph_data_invalid:
case glyph_data_invalid:
default:
break;
}
}
}
// GetKerning
bool
FontEngine::GetKerning(unsigned first, unsigned second,
@@ -561,7 +733,7 @@ FontEngine::Init(const char* fontFilePath, unsigned faceIndex, double size,
if (fLastError != 0)
return false;
switch(ren_type) {
case glyph_ren_native_mono:
fGlyphRendering = glyph_ren_native_mono;
@@ -571,6 +743,10 @@ FontEngine::Init(const char* fontFilePath, unsigned faceIndex, double size,
fGlyphRendering = glyph_ren_native_gray8;
break;
case glyph_ren_subpix:
fGlyphRendering = glyph_ren_subpix;
break;
case glyph_ren_outline:
if (FT_IS_SCALABLE(fFace))
fGlyphRendering = glyph_ren_outline;
+17 -7
View File
@@ -5,14 +5,15 @@
* Authors:
* Maxim Shemanarev <[email protected]>
* Stephan Aßmus <[email protected]>
* Andrej Spielmann, <[email protected]>
*/
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
@@ -39,11 +40,15 @@
#include <agg_conv_curve.h>
#include <agg_trans_affine.h>
#include "agg_scanline_storage_subpix.h"
#include "agg_scanline_u_subpix.h"
enum glyph_rendering {
glyph_ren_native_mono,
glyph_ren_native_gray8,
glyph_ren_outline,
glyph_ren_subpix
};
@@ -51,15 +56,18 @@ enum glyph_data_type {
glyph_data_invalid = 0,
glyph_data_mono = 1,
glyph_data_gray8 = 2,
glyph_data_outline = 3
glyph_data_outline = 3,
glyph_data_subpix = 4
};
class FontEngine {
public:
typedef agg::serialized_scanlines_adaptor_subpix<uint8> SubpixAdapter;
typedef agg::serialized_scanlines_adaptor_aa<uint8> Gray8Adapter;
typedef agg::serialized_scanlines_adaptor_bin MonoAdapter;
typedef agg::scanline_storage_aa8 ScanlineStorageAA;
typedef agg::scanline_storage_subpix8 ScanlineStorageSubpix;
typedef agg::scanline_storage_bin ScanlineStorageBin;
typedef agg::serialized_integer_path_adaptor<int32, 6> PathAdapter;
@@ -113,12 +121,12 @@ class FontEngine {
int fLastError;
bool fLibraryInitialized;
FT_Library fLibrary; // handle to library
FT_Library fLibrary; // handle to library
FT_Face fFace; // FreeType font face handle
glyph_rendering fGlyphRendering;
bool fHinting;
// members needed to generate individual glyphs according
// to glyph rendering type
unsigned fGlyphIndex;
@@ -131,7 +139,7 @@ class FontEngine {
double fInsetRight;
// these members are for caching memory allocations
// when rendering glyphs
// when rendering glyphs
typedef agg::path_storage_integer<int32, 6> PathStorageType;
typedef agg::conv_curve<PathStorageType> CurveConverterType;
@@ -139,9 +147,11 @@ class FontEngine {
CurveConverterType fCurves;
agg::scanline_u8 fScanlineAA;
agg::scanline_bin fScanlineBin;
agg::scanline_u8_subpix fScanlineSubpix;
ScanlineStorageAA fScanlineStorageAA;
ScanlineStorageBin fScanlineStorageBin;
ScanlineStorageSubpix fScanlineStorageSubpix;
};
@@ -1,6 +1,7 @@
/*
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
@@ -29,19 +30,22 @@
// constructor
AGGTextRenderer::AGGTextRenderer(renderer_type& solidRenderer,
renderer_bin_type& binRenderer, scanline_unpacked_type& scanline)
AGGTextRenderer::AGGTextRenderer(renderer_subpix_type& subpixRenderer,
renderer_type& solidRenderer, renderer_bin_type& binRenderer,
scanline_unpacked_type& scanline)
: fPathAdaptor()
, fGray8Adaptor()
, fGray8Scanline()
, fMonoAdaptor()
, fMonoScanline()
, fSubpixAdaptor()
, fCurves(fPathAdaptor)
, fContour(fCurves)
, fSolidRenderer(solidRenderer)
, fBinRenderer(binRenderer)
, fSubpixRenderer(subpixRenderer)
, fScanline(scanline)
, fRasterizer()
@@ -175,7 +179,7 @@ class AGGTextRenderer::StringRenderer {
// the glyph is different depending on wether we
// deal with non-(rotated/sheared) text, in which
// case we have a native FT bitmap. For rotated or
// sheared text, we use AGG vector outlines and
// sheared text, we use AGG vector outlines and
// a transformation pipeline, which will be applied
// _after_ we retrieve the outline, and that's why
// we simply pass x and y, which are untransformed.
@@ -210,15 +214,21 @@ class AGGTextRenderer::StringRenderer {
if (fClippingFrame.Intersects(glyphBounds)) {
switch (glyph->data_type) {
case glyph_data_mono:
agg::render_scanlines(fRenderer.fMonoAdaptor,
agg::render_scanlines(fRenderer.fMonoAdaptor,
fRenderer.fMonoScanline, fRenderer.fBinRenderer);
break;
case glyph_data_gray8:
agg::render_scanlines(fRenderer.fGray8Adaptor,
agg::render_scanlines(fRenderer.fGray8Adaptor,
fRenderer.fGray8Scanline, fRenderer.fSolidRenderer);
break;
case glyph_data_subpix:
agg::render_scanlines(fRenderer.fGray8Adaptor,
fRenderer.fGray8Scanline,
fRenderer.fSubpixRenderer);
break;
case glyph_data_outline: {
fVector = true;
if (fRenderer.fContour.width() == 0.0) {
@@ -1,6 +1,7 @@
/*
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef AGG_TEXT_RENDERER_H
#define AGG_TEXT_RENDERER_H
@@ -21,7 +22,8 @@ class FontCacheReference;
class AGGTextRenderer {
public:
AGGTextRenderer(renderer_type& solidRenderer,
AGGTextRenderer(renderer_subpix_type& subpixRenderer,
renderer_type& solidRenderer,
renderer_bin_type& binRenderer,
scanline_unpacked_type& scanline);
virtual ~AGGTextRenderer();
@@ -62,12 +64,14 @@ class AGGTextRenderer {
FontCacheEntry::GlyphGray8Scanline fGray8Scanline;
FontCacheEntry::GlyphMonoAdapter fMonoAdaptor;
FontCacheEntry::GlyphMonoScanline fMonoScanline;
FontCacheEntry::SubpixAdapter fSubpixAdaptor;
FontCacheEntry::CurveConverter fCurves;
FontCacheEntry::ContourConverter fContour;
renderer_type& fSolidRenderer;
renderer_bin_type& fBinRenderer;
renderer_subpix_type& fSubpixRenderer;
scanline_unpacked_type& fScanline;
rasterizer_type fRasterizer;
// NOTE: the object has it's own rasterizer object
+29 -14
View File
@@ -1,6 +1,7 @@
/*
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* API to the Anti-Grain Geometry based "Painter" drawing backend. Manages
* rendering pipe-lines for stroke, fills, bitmap and text rendering.
@@ -64,6 +65,7 @@ Painter::Painter()
fUnpackedScanline(),
fPackedScanline(),
fRasterizer(),
fSubpixRenderer(fBaseRenderer),
fRenderer(fBaseRenderer),
fRendererBin(fBaseRenderer),
@@ -74,6 +76,7 @@ Painter::Painter()
fValidClipping(false),
fDrawingText(false),
fAttached(false),
fSubpixelAntialias(true),
fPenSize(1.0),
fClippingRegion(NULL),
@@ -85,7 +88,7 @@ Painter::Painter()
fMiterLimit(B_DEFAULT_MITER_LIMIT),
fPatternHandler(),
fTextRenderer(fRenderer, fRendererBin, fUnpackedScanline)
fTextRenderer(fSubpixRenderer, fRenderer, fRendererBin, fUnpackedScanline)
{
fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false);
@@ -230,6 +233,14 @@ Painter::SetDrawingMode(drawing_mode mode)
}
}
void
Painter::SetSubpixelAntialiasing(bool subpixelAntialias)
{
if (fSubpixelAntialias != subpixelAntialias) {
fSubpixelAntialias = subpixelAntialias;
}
}
// SetBlendingMode
void
Painter::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc)
@@ -322,7 +333,7 @@ Painter::StrokeLine(BPoint a, BPoint b)
return;
}
}
fPath.remove_all();
if (a == b) {
@@ -381,7 +392,7 @@ Painter::StrokeLine(BPoint a, BPoint b)
a.y++;
}
}
fPath.move_to(a.x, a.y);
fPath.line_to(b.x, b.y);
@@ -685,7 +696,7 @@ Painter::FillRect(const BRect& r) const
return _Clipped(rect);
}
}
// account for stricter interpretation of coordinates in AGG
// the rectangle ranges from the top-left (.0, .0)
@@ -787,7 +798,7 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
agg::rounded_rect rect;
rect.rect(lt.x, lt.y, rb.x, rb.y);
rect.radius(xRadius, yRadius);
return _StrokePath(rect);
} else {
// NOTE: This implementation might seem a little strange, but it makes
@@ -796,10 +807,10 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
// The fact that the bounding box of the round rect is not enlarged
// by fPenSize/2 is actually on purpose, though one could argue it is unexpected.
// enclose the right and bottom edge
// enclose the right and bottom edge
rb.x++;
rb.y++;
agg::rounded_rect outer;
outer.rect(lt.x, lt.y, rb.x, rb.y);
outer.radius(xRadius, yRadius);
@@ -813,10 +824,10 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
agg::rounded_rect inner;
inner.rect(lt.x + fPenSize, lt.y + fPenSize, rb.x - fPenSize, rb.y - fPenSize);
inner.radius(max_c(0.0, xRadius - fPenSize), max_c(0.0, yRadius - fPenSize));
fRasterizer.add_path(inner);
}
// make the inner rect work as a hole
fRasterizer.filling_rule(agg::fill_even_odd);
@@ -824,10 +835,10 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const
agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer);
else
agg::render_scanlines(fRasterizer, fUnpackedScanline, fRenderer);
// reset to default
fRasterizer.filling_rule(agg::fill_non_zero);
return _Clipped(_BoundingBox(outer));
}
}
@@ -1189,6 +1200,10 @@ Painter::_SetRendererColor(const rgb_color& color) const
color.green / 255.0,
color.blue / 255.0,
color.alpha / 255.0));
fSubpixRenderer.color(agg::rgba(color.red / 255.0,
color.green / 255.0,
color.blue / 255.0,
color.alpha / 255.0));
// TODO: bitmap fonts not yet correctly setup in AGGTextRenderer
// fRendererBin.color(agg::rgba(color.red / 255.0,
// color.green / 255.0,
@@ -1364,7 +1379,7 @@ Painter::_DrawBitmap(agg::rendering_buffer& srcBuffer, color_space format,
viewRect.bottom -= diff * yScale;
bitmapRect.bottom = actualBitmapRect.bottom;
}
double xOffset = viewRect.left - bitmapRect.left;
double yOffset = viewRect.top - bitmapRect.top;
+9 -3
View File
@@ -1,6 +1,7 @@
/*
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005-2007, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* API to the Anti-Grain Geometry based "Painter" drawing backend. Manages
* rendering pipe-lines for stroke, fills, bitmap and text rendering.
@@ -72,6 +73,9 @@ class Painter {
void SetDrawingMode(drawing_mode mode);
inline drawing_mode DrawingMode() const
{ return fDrawingMode; }
void SetSubpixelAntialiasing(bool subpixelAntialias);
bool SubpixelAntialiasing() const
{ return fSubpixelAntialias; }
void SetBlendingMode(source_alpha srcAlpha,
alpha_function alphaFunc);
@@ -110,7 +114,7 @@ class Painter {
// bezier curves
BRect DrawBezier( BPoint* controlPoints,
bool filled) const;
// shapes
BRect DrawShape( const int32& opCount,
const uint32* opList,
@@ -261,6 +265,7 @@ mutable renderer_base fBaseRenderer;
mutable scanline_unpacked_type fUnpackedScanline;
mutable scanline_packed_type fPackedScanline;
mutable rasterizer_type fRasterizer;
mutable renderer_subpix_type fSubpixRenderer;
mutable renderer_type fRenderer;
mutable renderer_bin_type fRendererBin;
@@ -281,6 +286,7 @@ mutable agg::conv_curve<agg::path_storage> fCurve;
cap_mode fLineCapMode;
join_mode fLineJoinMode;
float fMiterLimit;
bool fSubpixelAntialias;
PatternHandler fPatternHandler;
+5 -2
View File
@@ -1,6 +1,7 @@
/*
* Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005-2006, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>.
* All rights reserved. Distributed under the terms of the MIT License.
*
* global definitions for the Painter frame work, mainly types for the
* AGG pipelines
@@ -22,6 +23,7 @@
#include <agg_rendering_buffer.h>
#include "agg_renderer_region.h"
#include "agg_renderer_scanline_subpix.h"
#include "PixelFormat.h"
@@ -47,6 +49,7 @@
#endif
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_bin_type;
typedef agg::renderer_scanline_subpix_solid<renderer_base> renderer_subpix_type;
typedef agg::rasterizer_scanline_aa<> rasterizer_type;
@@ -1,6 +1,7 @@
/*
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
*
@@ -34,6 +35,26 @@
#include "DrawingModeSelect.h"
#include "DrawingModeSubtract.h"
#include "DrawingModeAddSUBPIX.h"
#include "DrawingModeAlphaCCSUBPIX.h"
#include "DrawingModeAlphaCOSUBPIX.h"
#include "DrawingModeAlphaCOSolidSUBPIX.h"
#include "DrawingModeAlphaPCSUBPIX.h"
#include "DrawingModeAlphaPOSUBPIX.h"
#include "DrawingModeAlphaPOSolidSUBPIX.h"
#include "DrawingModeBlendSUBPIX.h"
#include "DrawingModeCopySUBPIX.h"
#include "DrawingModeCopySolidSUBPIX.h"
#include "DrawingModeCopyTextSUBPIX.h"
#include "DrawingModeEraseSUBPIX.h"
#include "DrawingModeInvertSUBPIX.h"
#include "DrawingModeMinSUBPIX.h"
#include "DrawingModeMaxSUBPIX.h"
#include "DrawingModeOverSUBPIX.h"
#include "DrawingModeOverSolidSUBPIX.h"
#include "DrawingModeSelectSUBPIX.h"
#include "DrawingModeSubtractSUBPIX.h"
#include "PatternHandler.h"
// blend_pixel_empty
@@ -53,6 +74,15 @@ blend_hline_empty(int x, int y, unsigned len,
printf("blend_hline_empty()\n");
}
// blend_hline_subpix_empty
void
blend_hline_empty_subpix(int x, int y, unsigned len,
const color_type& c, uint8 cover,
agg_buffer* buffer, const PatternHandler* pattern)
{
printf("blend_hline_empty_subpix()\n");
}
// blend_vline_empty
void
blend_vline_empty(int x, int y, unsigned len,
@@ -71,6 +101,15 @@ blend_solid_hspan_empty(int x, int y, unsigned len,
printf("blend_solid_hspan_empty()\n");
}
// blend_solid_hspan_subpix_empty
void
blend_solid_hspan_empty_subpix(int x, int y, unsigned len,
const color_type& c, const uint8* covers,
agg_buffer* buffer, const PatternHandler* pattern)
{
printf("blend_solid_hspan_empty_subpix()\n");
}
// blend_solid_vspan_empty
void
blend_solid_vspan_empty(int x, int y,
@@ -112,8 +151,10 @@ PixelFormat::PixelFormat(agg::rendering_buffer& rb,
fBlendPixel(blend_pixel_empty),
fBlendHLine(blend_hline_empty),
fBlendHLineSubpix(blend_hline_empty_subpix),
fBlendVLine(blend_vline_empty),
fBlendSolidHSpan(blend_solid_hspan_empty),
fBlendSolidHSpanSubpix(blend_solid_hspan_empty_subpix),
fBlendSolidVSpan(blend_solid_vspan_empty),
fBlendColorHSpan(blend_color_hspan_empty),
fBlendColorVSpan(blend_color_vspan_empty)
@@ -140,9 +181,13 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
fBlendHLine = blend_hline_over_solid;
fBlendSolidHSpan = blend_solid_hspan_over_solid;
fBlendSolidVSpan = blend_solid_vspan_over_solid;
fBlendHLineSubpix = blend_hline_over_solid_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_over_solid_subpix;
} else {
fBlendPixel = blend_pixel_over;
fBlendHLine = blend_hline_over;
fBlendHLineSubpix = blend_hline_over_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_over_subpix;
fBlendSolidHSpan = blend_solid_hspan_over;
fBlendSolidVSpan = blend_solid_vspan_over;
}
@@ -151,6 +196,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_ERASE:
fBlendPixel = blend_pixel_erase;
fBlendHLine = blend_hline_erase;
fBlendHLineSubpix = blend_hline_erase_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_erase_subpix;
fBlendSolidHSpan = blend_solid_hspan_erase;
fBlendSolidVSpan = blend_solid_vspan_erase;
fBlendColorHSpan = blend_color_hspan_erase;
@@ -158,6 +205,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_INVERT:
fBlendPixel = blend_pixel_invert;
fBlendHLine = blend_hline_invert;
fBlendHLineSubpix = blend_hline_invert_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_invert_subpix;
fBlendSolidHSpan = blend_solid_hspan_invert;
fBlendSolidVSpan = blend_solid_vspan_invert;
fBlendColorHSpan = blend_color_hspan_invert;
@@ -165,6 +214,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_SELECT:
fBlendPixel = blend_pixel_select;
fBlendHLine = blend_hline_select;
fBlendHLineSubpix = blend_hline_select_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_select_subpix;
fBlendSolidHSpan = blend_solid_hspan_select;
fBlendSolidVSpan = blend_solid_vspan_select;
fBlendColorHSpan = blend_color_hspan_select;
@@ -175,7 +226,9 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_COPY:
if (text) {
fBlendPixel = blend_pixel_copy_text;
fBlendHLine = blend_hline_copy_text;
fBlendHLine = blend_hline_copy_text;
fBlendHLineSubpix = blend_hline_copy_text_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix;
fBlendSolidHSpan = blend_solid_hspan_copy_text;
fBlendSolidVSpan = blend_solid_vspan_copy_text;
fBlendColorHSpan = blend_color_hspan_copy_text;
@@ -186,12 +239,16 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
} else if (fPatternHandler->IsSolid()) {
fBlendPixel = blend_pixel_copy_solid;
fBlendHLine = blend_hline_copy_solid;
fBlendHLineSubpix = blend_hline_copy_solid_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_copy_solid_subpix;
fBlendSolidHSpan = blend_solid_hspan_copy_solid;
fBlendSolidVSpan = blend_solid_vspan_copy_solid;
fBlendColorHSpan = blend_color_hspan_copy_solid;
} else {
fBlendPixel = blend_pixel_copy;
fBlendHLine = blend_hline_copy;
fBlendHLineSubpix = blend_hline_copy_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_copy_subpix;
fBlendSolidHSpan = blend_solid_hspan_copy;
fBlendSolidVSpan = blend_solid_vspan_copy;
fBlendColorHSpan = blend_color_hspan_copy;
@@ -199,7 +256,9 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
break;
case B_OP_ADD:
fBlendPixel = blend_pixel_add;
fBlendHLine = blend_hline_add;
fBlendHLine = blend_hline_add;
fBlendHLineSubpix = blend_hline_add_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_add_subpix;
fBlendSolidHSpan = blend_solid_hspan_add;
fBlendSolidVSpan = blend_solid_vspan_add;
fBlendColorHSpan = blend_color_hspan_add;
@@ -207,6 +266,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_SUBTRACT:
fBlendPixel = blend_pixel_subtract;
fBlendHLine = blend_hline_subtract;
fBlendHLineSubpix = blend_hline_subtract_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_subtract_subpix;
fBlendSolidHSpan = blend_solid_hspan_subtract;
fBlendSolidVSpan = blend_solid_vspan_subtract;
fBlendColorHSpan = blend_color_hspan_subtract;
@@ -214,6 +275,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_BLEND:
fBlendPixel = blend_pixel_blend;
fBlendHLine = blend_hline_blend;
fBlendHLineSubpix = blend_hline_blend_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_blend_subpix;
fBlendSolidHSpan = blend_solid_hspan_blend;
fBlendSolidVSpan = blend_solid_vspan_blend;
fBlendColorHSpan = blend_color_hspan_blend;
@@ -221,6 +284,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_MIN:
fBlendPixel = blend_pixel_min;
fBlendHLine = blend_hline_min;
fBlendHLineSubpix = blend_hline_min_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_min_subpix;
fBlendSolidHSpan = blend_solid_hspan_min;
fBlendSolidVSpan = blend_solid_vspan_min;
fBlendColorHSpan = blend_color_hspan_min;
@@ -228,6 +293,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
case B_OP_MAX:
fBlendPixel = blend_pixel_max;
fBlendHLine = blend_hline_max;
fBlendHLineSubpix = blend_hline_max_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_max_subpix;
fBlendSolidHSpan = blend_solid_hspan_max;
fBlendSolidVSpan = blend_solid_vspan_max;
fBlendColorHSpan = blend_color_hspan_max;
@@ -247,11 +314,15 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
if (fPatternHandler->IsSolid()) {
fBlendPixel = blend_pixel_alpha_co_solid;
fBlendHLine = blend_hline_alpha_co_solid;
fBlendHLineSubpix = blend_hline_alpha_co_solid_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_solid_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_co_solid;
fBlendSolidVSpan = blend_solid_vspan_alpha_co_solid;
} else {
fBlendPixel = blend_pixel_alpha_co;
fBlendHLine = blend_hline_alpha_co;
fBlendHLineSubpix = blend_hline_alpha_co_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_co;
fBlendSolidVSpan = blend_solid_vspan_alpha_co;
}
@@ -259,6 +330,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
fBlendPixel = blend_pixel_alpha_cc;
fBlendHLine = blend_hline_alpha_cc;
fBlendHLineSubpix = blend_hline_alpha_cc_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_cc_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_cc;
fBlendSolidVSpan = blend_solid_vspan_alpha_cc;
fBlendColorHSpan = blend_color_hspan_alpha_cc;
@@ -268,11 +341,15 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
if (fPatternHandler->IsSolid()) {
fBlendPixel = blend_pixel_alpha_po_solid;
fBlendHLine = blend_hline_alpha_po_solid;
fBlendHLineSubpix = blend_hline_alpha_po_solid_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_solid_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_po_solid;
fBlendSolidVSpan = blend_solid_vspan_alpha_po_solid;
} else {
fBlendPixel = blend_pixel_alpha_po;
fBlendHLine = blend_hline_alpha_po;
fBlendHLineSubpix = blend_hline_alpha_po_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_po;
fBlendSolidVSpan = blend_solid_vspan_alpha_po;
}
@@ -280,6 +357,8 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode,
} else if (alphaFncMode == B_ALPHA_COMPOSITE) {
fBlendPixel = blend_pixel_alpha_pc;
fBlendHLine = blend_hline_alpha_pc;
fBlendHLineSubpix = blend_hline_alpha_pc_subpix;
fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix;
fBlendSolidHSpan = blend_solid_hspan_alpha_pc;
fBlendSolidVSpan = blend_solid_vspan_alpha_pc;
fBlendColorHSpan = blend_color_hspan_alpha_pc;
@@ -1,6 +1,7 @@
/*
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>. All rights reserved.
* Distributed under the terms of the MIT License.
* Copyright 2005, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>
* All rights reserved. Distributed under the terms of the MIT License.
*
* Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
*
@@ -104,6 +105,11 @@ class PixelFormat {
const color_type& c,
uint8 cover);
inline void blend_hline_subpix(int x, int y,
unsigned len,
const color_type& c,
uint8 cover);
inline void blend_vline(int x, int y,
unsigned len,
const color_type& c,
@@ -114,6 +120,11 @@ class PixelFormat {
const color_type& c,
const uint8* covers);
inline void blend_solid_hspan_subpix(int x, int y,
unsigned len,
const color_type& c,
const uint8* covers);
inline void blend_solid_vspan(int x, int y,
unsigned len,
const color_type& c,
@@ -138,8 +149,10 @@ class PixelFormat {
blend_pixel_f fBlendPixel;
blend_line fBlendHLine;
blend_line fBlendHLineSubpix;
blend_line fBlendVLine;
blend_solid_span fBlendSolidHSpan;
blend_solid_span fBlendSolidHSpanSubpix;
blend_solid_span fBlendSolidVSpan;
blend_color_span fBlendColorHSpan;
blend_color_span fBlendColorVSpan;
@@ -198,6 +211,14 @@ PixelFormat::blend_hline(int x, int y, unsigned len,
fBlendHLine(x, y, len, c, cover, fBuffer, fPatternHandler);
}
// blend_hline_subpix
inline void
PixelFormat::blend_hline_subpix(int x, int y, unsigned len,
const color_type& c, uint8 cover)
{
fBlendHLineSubpix(x, y, len, c, cover, fBuffer, fPatternHandler);
}
// blend_vline
inline void
PixelFormat::blend_vline(int x, int y, unsigned len,
@@ -208,15 +229,23 @@ PixelFormat::blend_vline(int x, int y, unsigned len,
// blend_solid_hspan
inline void
PixelFormat::blend_solid_hspan(int x, int y, unsigned len,
PixelFormat::blend_solid_hspan(int x, int y, unsigned len,
const color_type& c, const uint8* covers)
{
fBlendSolidHSpan(x, y, len, c, covers, fBuffer, fPatternHandler);
}
// blend_solid_hspan_subpix
inline void
PixelFormat::blend_solid_hspan_subpix(int x, int y, unsigned len,
const color_type& c, const uint8* covers)
{
fBlendSolidHSpanSubpix(x, y, len, c, covers, fBuffer, fPatternHandler);
}
// blend_solid_vspan
inline void
PixelFormat::blend_solid_vspan(int x, int y, unsigned len,
PixelFormat::blend_solid_vspan(int x, int y, unsigned len,
const color_type& c, const uint8* covers)
{
fBlendSolidVSpan(x, y, len, c, covers, fBuffer, fPatternHandler);
@@ -224,8 +253,8 @@ PixelFormat::blend_solid_vspan(int x, int y, unsigned len,
// blend_color_hspan
inline void
PixelFormat::blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
PixelFormat::blend_color_hspan(int x, int y, unsigned len,
const color_type* colors,
const uint8* covers,
uint8 cover)
{
@@ -235,8 +264,8 @@ PixelFormat::blend_color_hspan(int x, int y, unsigned len,
// blend_color_vspan
inline void
PixelFormat::blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
PixelFormat::blend_color_vspan(int x, int y, unsigned len,
const color_type* colors,
const uint8* covers,
uint8 cover)
{