From fa6a00c628f07c0310bbc97db6e69aca68461b82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 10 Jul 2008 08:26:38 +0000 Subject: [PATCH] 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 --- src/servers/app/FontCacheEntry.cpp | 41 ++- src/servers/app/FontCacheEntry.h | 11 + src/servers/app/FontEngine.cpp | 272 ++++++++++++++---- src/servers/app/FontEngine.h | 24 +- .../app/drawing/Painter/AGGTextRenderer.cpp | 24 +- .../app/drawing/Painter/AGGTextRenderer.h | 10 +- src/servers/app/drawing/Painter/Painter.cpp | 43 ++- src/servers/app/drawing/Painter/Painter.h | 12 +- src/servers/app/drawing/Painter/defines.h | 7 +- .../Painter/drawing_modes/PixelFormat.cpp | 87 +++++- .../Painter/drawing_modes/PixelFormat.h | 45 ++- 11 files changed, 473 insertions(+), 103 deletions(-) diff --git a/src/servers/app/FontCacheEntry.cpp b/src/servers/app/FontCacheEntry.cpp index 2de98f2ac9..05fe5b9f2b 100644 --- a/src/servers/app/FontCacheEntry.cpp +++ b/src/servers/app/FontCacheEntry.cpp @@ -5,14 +5,15 @@ * Authors: * Maxim Shemanarev * Stephan Aßmus + * Andrej Spielmann, */ //---------------------------------------------------------------------------- // 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; diff --git a/src/servers/app/FontCacheEntry.h b/src/servers/app/FontCacheEntry.h index 00598c8c3f..71eba77691 100644 --- a/src/servers/app/FontCacheEntry.h +++ b/src/servers/app/FontCacheEntry.h @@ -5,6 +5,7 @@ * Authors: * Maxim Shemanarev * Stephan Aßmus + * Andrej Spielmann, */ //---------------------------------------------------------------------------- @@ -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 CurveConverter; typedef agg::conv_contour 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; diff --git a/src/servers/app/FontEngine.cpp b/src/servers/app/FontEngine.cpp index 41d2cf82e7..13ab9e062f 100644 --- a/src/servers/app/FontEngine.cpp +++ b/src/servers/app/FontEngine.cpp @@ -6,14 +6,15 @@ * Maxim Shemanarev * Stephan Aßmus * Anthony Lee + * Andrej Spielmann, */ //---------------------------------------------------------------------------- // 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 #include #include + + static const bool kFlipY = true; @@ -54,7 +61,7 @@ dbl_to_int26p6(double p) template 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 void @@ -314,6 +322,7 @@ decompose_ft_bitmap_mono(const FT_Bitmap& bitmap, int x, int y, } } + // decompose_ft_bitmap_gray8 template void @@ -360,6 +369,142 @@ decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, int x, int y, } +// decompose_ft_bitmap_subpix +template +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; diff --git a/src/servers/app/FontEngine.h b/src/servers/app/FontEngine.h index 45a592051b..497fef66fe 100644 --- a/src/servers/app/FontEngine.h +++ b/src/servers/app/FontEngine.h @@ -5,14 +5,15 @@ * Authors: * Maxim Shemanarev * Stephan Aßmus + * Andrej Spielmann, */ //---------------------------------------------------------------------------- // 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 #include +#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 SubpixAdapter; typedef agg::serialized_scanlines_adaptor_aa 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 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 PathStorageType; typedef agg::conv_curve 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; }; diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp index ab082d5240..85b1af7895 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann . + * 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) { diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.h b/src/servers/app/drawing/Painter/AGGTextRenderer.h index 9726e4ff12..cbb49b1354 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.h @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann . + * 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 diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 75111e3691..6c8058b458 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann . + * 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; diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index d8c8469ece..4e520f7e1a 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann . + * 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 fCurve; cap_mode fLineCapMode; join_mode fLineJoinMode; float fMiterLimit; + bool fSubpixelAntialias; PatternHandler fPatternHandler; diff --git a/src/servers/app/drawing/Painter/defines.h b/src/servers/app/drawing/Painter/defines.h index 03808b023e..0bf24f8672 100644 --- a/src/servers/app/drawing/Painter/defines.h +++ b/src/servers/app/drawing/Painter/defines.h @@ -1,6 +1,7 @@ /* - * Copyright 2005-2006, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2006, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann . + * 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 #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_bin_type; + typedef agg::renderer_scanline_subpix_solid renderer_subpix_type; typedef agg::rasterizer_scanline_aa<> rasterizer_type; diff --git a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp index 8af27134b0..d5499cda87 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp +++ b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2005, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann + * 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; diff --git a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h index b72c00f376..609eea36f7 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h +++ b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h @@ -1,6 +1,7 @@ /* - * Copyright 2005, Stephan Aßmus . All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005, Stephan Aßmus . + * Copyright 2008, Andrej Spielmann + * 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) {