From 59e13a3f06eedbc797f797da71c6810634b22cd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sun, 3 Aug 2008 13:40:41 +0000 Subject: [PATCH] Patch by Andrej Spielmann (GSoC): * Simplified the subpixel related methods for the AGG "pixel format" template interface, the ones for the solid cover simply pass through the existing methods, so only one subpixel blending function is left which does the actual work (this removes a lot of the previously added code) * Implemented a new rasterizer based on the original AGG rasterizer which implements subpixel anti-aliasing for any generic AGG vector pipelines. It is now optionally used in Painter and AGGTextRenderer (for vector fonts, ie rotated, sheared or big enough fonts) depending on the global subpixel setting. * Put all subpixel variables into the new GlobalSubpixelSettings.h|cpp * Simplified DesktopSettings related classes a bit and renamed previous FontSubpixelAntialiasing to just SubpixelAntialiasing. * The private libbe functions for subpixel related settings moved from Font.cpp to InterfaceDefs.cpp where other such functions live. They are not related to fonts only anymore. * Removed the subpixel related settings again from the Fonts preflet and added them to the Appearance preflet instead. All of the above implements subpixel anti-aliasing on a global scale, which to my knowledge no other OS is doing at the moment. Any vector rendering can optionally use subpixel anti-aliasing in Haiku now. The bitmap cached fonts are still affected by the Freetype complile time #define to enable the patented subpixel rasterization (three times wide glyphs). Vector fonts and shapes are not affected though at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26755 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/libs/agg/agg_renderer_base.h | 17 +- headers/private/app/ServerProtocol.h | 9 +- src/kits/interface/Font.cpp | 53 - src/kits/interface/InterfaceDefs.cpp | 102 ++ src/preferences/appearance/APRView.cpp | 50 +- src/preferences/appearance/APRView.h | 4 +- src/preferences/appearance/APRWindow.cpp | 90 +- src/preferences/appearance/APRWindow.h | 16 + .../AntialiasingSettingsView.cpp} | 156 +- .../appearance/AntialiasingSettingsView.h | 59 + src/preferences/appearance/Jamfile | 1 + src/preferences/fonts/AdvancedSettingsView.h | 56 - src/preferences/fonts/FontView.h | 1 - src/preferences/fonts/Jamfile | 1 - src/preferences/fonts/MainWindow.cpp | 33 +- src/preferences/fonts/MainWindow.h | 2 - src/servers/app/DesktopSettings.cpp | 155 +- src/servers/app/DesktopSettings.h | 8 +- src/servers/app/DesktopSettingsPrivate.h | 11 +- src/servers/app/FontCacheEntry.cpp | 40 +- src/servers/app/FontCacheEntry.h | 9 - src/servers/app/FontEngine.cpp | 40 +- src/servers/app/FontEngine.h | 7 + src/servers/app/ProfileMessageSupport.cpp | 9 +- src/servers/app/ServerApp.cpp | 48 +- src/servers/app/agg_scanline_storage_subpix.h | 1304 ++++++++--------- src/servers/app/agg_scanline_u_subpix.h | 185 +-- .../app/drawing/Painter/AGGTextRenderer.cpp | 42 +- .../app/drawing/Painter/AGGTextRenderer.h | 6 +- .../Painter/GlobalSubpixelSettings.cpp | 14 + .../drawing/Painter/GlobalSubpixelSettings.h | 29 + src/servers/app/drawing/Painter/Jamfile | 1 + src/servers/app/drawing/Painter/Painter.cpp | 161 +- src/servers/app/drawing/Painter/Painter.h | 9 +- .../agg_rasterizer_scanline_aa_subpix.h | 547 +++++++ .../app/drawing/Painter/agg_renderer_region.h | 628 ++++---- .../Painter/agg_renderer_scanline_subpix.h | 112 +- .../drawing/Painter/agg_scanline_p_subpix.h | 167 +++ .../agg_scanline_p_subpix_avrg_filtering.h | 195 +++ .../agg_scanline_u_subpix_avrg_filtering.h | 165 +++ src/servers/app/drawing/Painter/defines.h | 17 +- .../drawing_modes/DrawingModeAddSUBPIX.h | 61 +- .../drawing_modes/DrawingModeAlphaCCSUBPIX.h | 77 +- .../drawing_modes/DrawingModeAlphaCOSUBPIX.h | 75 +- .../DrawingModeAlphaCOSolidSUBPIX.h | 49 +- .../drawing_modes/DrawingModeAlphaPCSUBPIX.h | 50 +- .../drawing_modes/DrawingModeAlphaPOSUBPIX.h | 48 +- .../DrawingModeAlphaPOSolidSUBPIX.h | 50 +- .../drawing_modes/DrawingModeBlendSUBPIX.h | 60 +- .../drawing_modes/DrawingModeCopySUBPIX.h | 73 +- .../DrawingModeCopySolidSUBPIX.h | 37 +- .../drawing_modes/DrawingModeCopyTextSUBPIX.h | 41 +- .../drawing_modes/DrawingModeEraseSUBPIX.h | 58 +- .../drawing_modes/DrawingModeInvertSUBPIX.h | 59 +- .../drawing_modes/DrawingModeMaxSUBPIX.h | 63 +- .../drawing_modes/DrawingModeMinSUBPIX.h | 63 +- .../drawing_modes/DrawingModeOverSUBPIX.h | 58 +- .../DrawingModeOverSolidSUBPIX.h | 41 +- .../drawing_modes/DrawingModeSelectSUBPIX.h | 55 +- .../drawing_modes/DrawingModeSubtractSUBPIX.h | 63 +- .../Painter/drawing_modes/PixelFormat.cpp | 31 +- .../Painter/drawing_modes/PixelFormat.h | 14 - src/tests/servers/app/Jamfile | 1 + 63 files changed, 3131 insertions(+), 2555 deletions(-) rename src/preferences/{fonts/AdvancedSettingsView.cpp => appearance/AntialiasingSettingsView.cpp} (52%) create mode 100644 src/preferences/appearance/AntialiasingSettingsView.h delete mode 100644 src/preferences/fonts/AdvancedSettingsView.h create mode 100644 src/servers/app/drawing/Painter/GlobalSubpixelSettings.cpp create mode 100644 src/servers/app/drawing/Painter/GlobalSubpixelSettings.h create mode 100644 src/servers/app/drawing/Painter/agg_rasterizer_scanline_aa_subpix.h create mode 100644 src/servers/app/drawing/Painter/agg_scanline_p_subpix.h create mode 100644 src/servers/app/drawing/Painter/agg_scanline_p_subpix_avrg_filtering.h create mode 100644 src/servers/app/drawing/Painter/agg_scanline_u_subpix_avrg_filtering.h diff --git a/headers/libs/agg/agg_renderer_base.h b/headers/libs/agg/agg_renderer_base.h index b42168b05c..6521d7a405 100644 --- a/headers/libs/agg/agg_renderer_base.h +++ b/headers/libs/agg/agg_renderer_base.h @@ -206,21 +206,6 @@ namespace agg m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover); } - //-------------------------------------------------------------------- - void blend_hline_subpix(int x1, int y, int x2, - const color_type& c, cover_type cover) - { - if(x1 > x2) { int t = x2; x2 = x1; x1 = t; } - if(y > ymax()) return; - if(y < ymin()) return; - if(x1 > xmax()) return; - if(x2 < xmin()) return; - - if(x1 < xmin()) x1 = xmin(); - if(x2 > xmax()) x2 = xmax(); - - m_ren->blend_hline_subpix(x1, y, x2 - x1 + 1, c, cover); - } //-------------------------------------------------------------------- void blend_vline(int x, int y1, int y2, @@ -309,7 +294,7 @@ namespace agg { len -= 3 * (xmin() - x); if(len <= 0) return; - covers += 3*(xmin() - x); + covers += 3 * (xmin() - x); x = xmin(); } if(x + len / 3 > xmax()) diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 04494c7065..73067f465a 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -189,10 +189,15 @@ enum { AS_GET_SHOW_ALL_DRAGGERS, AS_SET_SHOW_ALL_DRAGGERS, - AS_SET_FONT_SUBPIXEL_ANTIALIASING, - AS_GET_FONT_SUBPIXEL_ANTIALIASING, + // Subpixel antialiasing & hinting + AS_SET_SUBPIXEL_ANTIALIASING, + AS_GET_SUBPIXEL_ANTIALIASING, AS_SET_HINTING, AS_GET_HINTING, + AS_SET_SUBPIXEL_AVERAGE_WEIGHT, + AS_GET_SUBPIXEL_AVERAGE_WEIGHT, + AS_SET_SUBPIXEL_ORDERING, + AS_GET_SUBPIXEL_ORDERING, // Graphics calls AS_SET_HIGH_COLOR, diff --git a/src/kits/interface/Font.cpp b/src/kits/interface/Font.cpp index 3139740aae..4d96e11b9f 100644 --- a/src/kits/interface/Font.cpp +++ b/src/kits/interface/Font.cpp @@ -406,59 +406,6 @@ _get_system_default_font_(const char* which, font_family family, } -void -_set_font_subpixel_antialiasing_(bool subpix) -{ - BPrivate::AppServerLink link; - - link.StartMessage(AS_SET_FONT_SUBPIXEL_ANTIALIASING); - link.Attach(subpix); - link.Flush(); -} - - -status_t -_get_font_subpixel_antialiasing_(bool* subpix) -{ - BPrivate::AppServerLink link; - - link.StartMessage(AS_GET_FONT_SUBPIXEL_ANTIALIASING); - int32 status = B_ERROR; - if (link.FlushWithReply(status) != B_OK - || status < B_OK) - return status; - link.Read(subpix); - return B_OK; -} - - -void -_set_hinting_(bool hinting) -{ - BPrivate::AppServerLink link; - - link.StartMessage(AS_SET_HINTING); - link.Attach(hinting); - link.Flush(); -} - - -status_t -_get_hinting_(bool* hinting) -{ - - BPrivate::AppServerLink link; - - link.StartMessage(AS_GET_HINTING); - int32 status = B_ERROR; - if (link.FlushWithReply(status) != B_OK - || status < B_OK) - return status; - link.Read(hinting); - return B_OK; -} - - /*! \brief Returns the number of installed font families \return The number of installed font families diff --git a/src/kits/interface/InterfaceDefs.cpp b/src/kits/interface/InterfaceDefs.cpp index ba89b2c229..2a6fd2c6cd 100644 --- a/src/kits/interface/InterfaceDefs.cpp +++ b/src/kits/interface/InterfaceDefs.cpp @@ -195,6 +195,107 @@ get_mode_parameter(uint32 mode, int32& width, int32& height, uint32& colorSpace) } // namespace BPrivate +void +set_subpixel_antialiasing(bool subpix) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_SET_SUBPIXEL_ANTIALIASING); + link.Attach(subpix); + link.Flush(); +} + + +status_t +get_subpixel_antialiasing(bool* subpix) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_GET_SUBPIXEL_ANTIALIASING); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status < B_OK) + return status; + link.Read(subpix); + return B_OK; +} + + +void +set_hinting(bool hinting) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_SET_HINTING); + link.Attach(hinting); + link.Flush(); +} + + +status_t +get_hinting(bool* hinting) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_GET_HINTING); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status < B_OK) + return status; + link.Read(hinting); + return B_OK; +} + + +void +set_average_weight(uint8 averageWeight) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_SET_SUBPIXEL_AVERAGE_WEIGHT); + link.Attach(averageWeight); + link.Flush(); +} + + +status_t +get_average_weight(uint8* averageWeight) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_GET_SUBPIXEL_AVERAGE_WEIGHT); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status < B_OK) + return status; + link.Read(averageWeight); + return B_OK; +} + + +void +set_is_subpixel_ordering_regular(bool subpixelOrdering) +{ + BPrivate::AppServerLink link; + + link.StartMessage(AS_SET_SUBPIXEL_ORDERING); + link.Attach(subpixelOrdering); + link.Flush(); +} + + +status_t +get_is_subpixel_ordering_regular(bool* subpixelOrdering) +{ + + BPrivate::AppServerLink link; + + link.StartMessage(AS_GET_SUBPIXEL_ORDERING); + int32 status = B_ERROR; + if (link.FlushWithReply(status) != B_OK || status < B_OK) + return status; + link.Read(subpixelOrdering); + return B_OK; +} + + const color_map * system_colors() { @@ -965,6 +1066,7 @@ set_decorator(const int32 &index) return B_OK; } + } // namespace BPrivate // These methods were marked with "Danger, will Robinson!" in diff --git a/src/preferences/appearance/APRView.cpp b/src/preferences/appearance/APRView.cpp index c1311507b5..50060ff15d 100644 --- a/src/preferences/appearance/APRView.cpp +++ b/src/preferences/appearance/APRView.cpp @@ -18,6 +18,7 @@ #include #include "APRView.h" +#include "APRWindow.h" #include "defs.h" #include "ColorWell.h" #include "ColorWhichItem.h" @@ -152,26 +153,7 @@ APRView::APRView(const BRect &frame, const char *name, int32 resize, int32 flags fPicker = new BColorControl(BPoint(fScrollView->Frame().left,fScrollView->Frame().bottom+kBorderSpace),B_CELLS_32x8,5.0,"fPicker", new BMessage(UPDATE_COLOR)); - AddChild(fPicker); - - fDefaults = new BButton(BRect(0,0,1,1),"DefaultsButton","Defaults", - new BMessage(DEFAULT_SETTINGS), - B_FOLLOW_LEFT |B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE); - fDefaults->ResizeToPreferred(); - fDefaults->SetEnabled(false); - fDefaults->MoveTo(fPicker->Frame().left,fPicker->Frame().bottom+kBorderSpace); - AddChild(fDefaults); - - - BRect cvrect(fDefaults->Frame()); - cvrect.OffsetBy(cvrect.Width() + kItemSpace,0); - - fRevert = new BButton(cvrect,"RevertButton","Revert", - new BMessage(REVERT_SETTINGS), - B_FOLLOW_LEFT |B_FOLLOW_TOP, B_WILL_DRAW | B_NAVIGABLE); - fRevert->ResizeToPreferred(); - fRevert->SetEnabled(false); - AddChild(fRevert); + AddChild(fPicker); } APRView::~APRView(void) @@ -184,21 +166,15 @@ APRView::AttachedToWindow(void) { fPicker->SetTarget(this); fAttrList->SetTarget(this); - fDefaults->SetTarget(this); - fRevert->SetTarget(this); fColorWell->SetTarget(this); fPicker->SetValue(fCurrentSet.StringToColor(fAttrString.String())); if (fDecorMenu) fDecorMenu->SetTargetForItems(BMessenger(this)); - - Window()->ResizeTo(MAX(fPicker->Frame().right,fPicker->Frame().right) + 10, - fDefaults->Frame().bottom + 10); + LoadSettings(); fAttrList->Select(0); - - fDefaults->SetEnabled(fCurrentSet.IsDefaultable()); } void @@ -235,11 +211,9 @@ APRView::MessageReceived(BMessage *msg) // Update current fAttribute in the settings fCurrentSet.SetColor(fAttribute, col); - UpdateCurrentColor(); - - fDefaults->SetEnabled(fCurrentSet.IsDefaultable()); - fRevert->SetEnabled(true); - + UpdateCurrentColor(); + + Window()->PostMessage(kMsgUpdate); break; } case ATTRIBUTE_CHOSEN: { @@ -254,7 +228,7 @@ APRView::MessageReceived(BMessage *msg) fAttrString=whichitem->Text(); UpdateControlsFromAttr(whichitem->Text()); - fDefaults->SetEnabled(fCurrentSet.IsDefaultable()); + Window()->PostMessage(kMsgUpdate); break; } case REVERT_SETTINGS: { @@ -262,13 +236,11 @@ APRView::MessageReceived(BMessage *msg) UpdateControlsFromAttr(fAttrString.String()); UpdateAllColors(); - fRevert->SetEnabled(false); - + Window()->PostMessage(kMsgUpdate); break; } case DEFAULT_SETTINGS: { fCurrentSet = ColorSet::DefaultColorSet(); - fDefaults->SetEnabled(false); UpdateControlsFromAttr(fAttrString.String()); UpdateAllColors(); @@ -281,6 +253,7 @@ APRView::MessageReceived(BMessage *msg) BPrivate::set_decorator(fDecorMenu->IndexOf(item)); #endif } + Window()->PostMessage(kMsgUpdate); break; } default: @@ -302,6 +275,11 @@ void APRView::LoadSettings(void) fPrevSet = fCurrentSet; } +bool APRView::IsDefaultable(void) +{ + return fCurrentSet.IsDefaultable(); +} + void APRView::UpdateAllColors(void) { for (uint32 i = 0; i < sColorCount; i++) diff --git a/src/preferences/appearance/APRView.h b/src/preferences/appearance/APRView.h index ee715fe809..04f38c5235 100644 --- a/src/preferences/appearance/APRView.h +++ b/src/preferences/appearance/APRView.h @@ -40,6 +40,7 @@ public: void MessageReceived(BMessage *msg); void LoadSettings(void); + bool IsDefaultable(void); protected: @@ -49,9 +50,6 @@ protected: BColorControl *fPicker; - BButton *fRevert; - BButton *fDefaults; - BListView *fAttrList; color_which fAttribute; diff --git a/src/preferences/appearance/APRWindow.cpp b/src/preferences/appearance/APRWindow.cpp index c499bc3df4..ca89090c17 100644 --- a/src/preferences/appearance/APRWindow.cpp +++ b/src/preferences/appearance/APRWindow.cpp @@ -6,19 +6,101 @@ * DarkWyrm (darkwyrm@earthlink.net) */ +#include #include +#include #include "APRWindow.h" #include "APRView.h" #include "defs.h" +static const uint32 kMsgSetDefaults = 'dflt'; +static const uint32 kMsgRevert = 'rvrt'; + APRWindow::APRWindow(BRect frame) - : BWindow(frame, "Appearance", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, - B_ALL_WORKSPACES ) + : BWindow(frame, "Appearance", B_TITLED_WINDOW, B_NOT_ZOOMABLE, + B_ALL_WORKSPACES) { - APRView *colorview = new APRView(Bounds(),"Colors",B_FOLLOW_ALL, B_WILL_DRAW); - AddChild(colorview); + BRect rect = Bounds(); + BView* view = new BView(rect, "background", B_FOLLOW_ALL, B_WILL_DRAW); + view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(view); + + rect.left = 10; + rect.top = rect.bottom - 10; + fDefaultsButton = new BButton(rect, "defaults", "Defaults", + new BMessage(kMsgSetDefaults), B_FOLLOW_LEFT + | B_FOLLOW_BOTTOM, B_WILL_DRAW); + fDefaultsButton->ResizeToPreferred(); + fDefaultsButton->SetEnabled(false); + float buttonHeight = fDefaultsButton->Bounds().Height(); + fDefaultsButton->MoveBy(0, -buttonHeight); + view->AddChild(fDefaultsButton); + + rect = fDefaultsButton->Frame(); + rect.OffsetBy(fDefaultsButton->Bounds().Width() + 10, 0); + + fRevertButton = new BButton(rect, "revert", "Revert", + new BMessage(kMsgRevert), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW); + fRevertButton->ResizeToPreferred(); + fRevertButton->SetEnabled(false); + view->AddChild(fRevertButton); + + rect = Bounds(); + rect.top += 5; + rect.bottom -= 20 + buttonHeight; + rect.left += 5; + BTabView *tabView = new BTabView(rect, "tabview", B_WIDTH_FROM_LABEL); + + rect = tabView->ContainerView()->Bounds().InsetByCopy(5, 8); + + fAntialiasingSettings = new AntialiasingSettingsView(rect, "Antialiasing"); + fColorsView = new APRView(rect,"Colors",B_FOLLOW_ALL, B_WILL_DRAW); + + tabView->AddTab(fColorsView); + tabView->AddTab(fAntialiasingSettings); + + view->AddChild(tabView); + fColorsView->ResizeToPreferred(); + fAntialiasingSettings -> ResizeToPreferred(); + + fDefaultsButton -> SetEnabled(fColorsView -> IsDefaultable() + || fAntialiasingSettings -> IsDefaultable()); + fDefaultsButton -> SetTarget(this); + fRevertButton -> SetTarget(this); } + +void +APRWindow::MessageReceived(BMessage *message) +{ + switch (message->what) { + case kMsgUpdate: + fDefaultsButton->SetEnabled(fColorsView->IsDefaultable() + || fAntialiasingSettings->IsDefaultable()); + fRevertButton->SetEnabled(true); + break; + case kMsgSetDefaults: + fColorsView -> MessageReceived(new BMessage(DEFAULT_SETTINGS)); + fAntialiasingSettings->SetDefaults(); + fDefaultsButton->SetEnabled(false); + fRevertButton->SetEnabled(true); + break; + + case kMsgRevert: + fColorsView -> MessageReceived(new BMessage(REVERT_SETTINGS)); + fAntialiasingSettings->Revert(); + fDefaultsButton->SetEnabled(fColorsView->IsDefaultable() + || fAntialiasingSettings->IsDefaultable()); + fRevertButton->SetEnabled(false); + break; + + default: + BWindow::MessageReceived(message); + break; + } +} + + bool APRWindow::QuitRequested(void) { diff --git a/src/preferences/appearance/APRWindow.h b/src/preferences/appearance/APRWindow.h index 7fe6bf5859..8207df655d 100644 --- a/src/preferences/appearance/APRWindow.h +++ b/src/preferences/appearance/APRWindow.h @@ -9,14 +9,30 @@ #define APR_WINDOW_H #include +#include #include #include +#include + +#include "APRView.h" +#include "AntialiasingSettingsView.h" class APRWindow : public BWindow { public: APRWindow(BRect frame); bool QuitRequested(void); + void MessageReceived(BMessage *message); + +private: + APRView* fColorsView; + BButton* fDefaultsButton; + BButton* fRevertButton; + + AntialiasingSettingsView* fAntialiasingSettings; + }; +static const int32 kMsgUpdate = 'updt'; + #endif diff --git a/src/preferences/fonts/AdvancedSettingsView.cpp b/src/preferences/appearance/AntialiasingSettingsView.cpp similarity index 52% rename from src/preferences/fonts/AdvancedSettingsView.cpp rename to src/preferences/appearance/AntialiasingSettingsView.cpp index 37d1556ccb..34b5b5ea18 100644 --- a/src/preferences/fonts/AdvancedSettingsView.cpp +++ b/src/preferences/appearance/AntialiasingSettingsView.cpp @@ -1,59 +1,64 @@ /* - * Copyright 2008, Haiku. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Andrej Spielmann, + * Copyright 2008, Andrej Spielmann, + * All rights reserved. Distributed under the terms of the MIT License. */ +#include "AntialiasingSettingsView.h" -#include "AdvancedSettingsView.h" -#include "MainWindow.h" +#include +#include #include #include #include #include #include +#include -#include +#include "APRWindow.h" #define INSTANT_UPDATE // if defined, the changes will take place immediately and not only on exit -#define DISABLE_HINTING_CONTROL +//#define DISABLE_HINTING_CONTROL // if defined, the hinting menu is disabled (hinting not properly // implemented) static const int32 kMsgSetAntialiasing = 'anti'; static const int32 kMsgSetHinting = 'hint'; +static const int32 kMsgSetAverageWeight = 'avrg'; static const char* kSubpixelLabel = "Subpixel antialiasing"; static const char* kGrayscaleLabel = "Grayscale antialiasing"; static const char* kNoHintingLabel = "Off"; static const char* kFullHintingLabel = "On"; -// private font API -extern void _set_font_subpixel_antialiasing_(bool subpix); -extern status_t _get_font_subpixel_antialiasing_(bool* subpix); -extern void _set_hinting_(bool subpix); -extern status_t _get_hinting_(bool* subpix); +extern void set_subpixel_antialiasing(bool subpix); +extern status_t get_subpixel_antialiasing(bool* subpix); +extern void set_hinting(bool hinting); +extern status_t get_hinting(bool* hinting); +extern void set_average_weight(unsigned char averageWeight); +extern status_t get_average_weight(unsigned char* averageWeight); // #pragma mark - -AdvancedSettingsView::AdvancedSettingsView(BRect _rect, const char* name) +AntialiasingSettingsView::AntialiasingSettingsView(BRect _rect, const char* name) : BView(_rect, name, B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) { - if (_get_font_subpixel_antialiasing_(&fCurrentSubpixelAntialiasing) != B_OK) + if (get_subpixel_antialiasing(&fCurrentSubpixelAntialiasing) != B_OK) fCurrentSubpixelAntialiasing = false; fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing; - if (_get_hinting_(&fCurrentHinting) != B_OK) + if (get_hinting(&fCurrentHinting) != B_OK) fCurrentHinting = true; fSavedHinting = fCurrentHinting; + + if (get_average_weight(&fCurrentAverageWeight) != B_OK) + fCurrentAverageWeight = 100; + fSavedAverageWeight = fCurrentAverageWeight; - fDivider = StringWidth("Character hinting:") + 5; + fDivider = StringWidth("Strength of colours in sbpx AA:") + 5; fAntialiasingMenu = new BPopUpMenu("Antialiasing menu"); fHintingMenu = new BPopUpMenu("Hinting menu"); @@ -68,8 +73,27 @@ AdvancedSettingsView::AdvancedSettingsView(BRect _rect, const char* name) AddChild(fAntialiasingMenuField); _BuildAntialiasingMenu(); - // hinting menu + //Average weight in subpixel filtering float shift = fAntialiasingMenuField->Bounds().Height()+5; + rect.top +=shift; + rect.bottom += shift; + fAverageWeightControl = new BTextControl(rect, "averageWeightControl", + "Strength of colours in sbpx AA:", NULL, + new BMessage(kMsgSetAverageWeight), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + fAverageWeightControl -> SetDivider(fDivider); + fAverageWeightControl -> TextView() -> SetMaxBytes(3); + fAverageWeightControl -> ResizeToPreferred(); + AddChild(fAverageWeightControl); + for (int i = 0; i < 256; i++) { + if (i < '0' || i > '9') { + fAverageWeightControl->TextView()->DisallowChar(i); + fAverageWeightControl->TextView()->DisallowChar(i); + } + } + fAverageWeightControl -> SetEnabled(false); + + // hinting menu + shift = fAverageWeightControl->Bounds().Height()+5; rect.top += shift; rect.bottom += shift; fHintingMenuField = new BMenuField(rect, "hinting", @@ -86,20 +110,22 @@ AdvancedSettingsView::AdvancedSettingsView(BRect _rect, const char* name) _SetCurrentAntialiasing(); _SetCurrentHinting(); + _SetCurrentAverageWeight(); } -AdvancedSettingsView::~AdvancedSettingsView() +AntialiasingSettingsView::~AntialiasingSettingsView() { #ifndef INSTANT_UPDATE - _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); - _set_hinting(fCurrentHinting); + set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); + set_hinting(fCurrentHinting); + set_average_weight(fCurrentAverageWeight); #endif } void -AdvancedSettingsView::GetPreferredSize(float *_width, float *_height) +AntialiasingSettingsView::GetPreferredSize(float *_width, float *_height) { // don't change the width if it is large enough if (_width) { @@ -115,16 +141,17 @@ AdvancedSettingsView::GetPreferredSize(float *_width, float *_height) void -AdvancedSettingsView::SetDivider(float divider) +AntialiasingSettingsView::SetDivider(float divider) { - fAntialiasingMenuField->SetDivider(divider); - fHintingMenuField->SetDivider(divider); + fAntialiasingMenuField -> SetDivider(divider); + fHintingMenuField -> SetDivider(divider); + fAverageWeightControl -> SetDivider(divider); fDivider = divider; } void -AdvancedSettingsView::RelayoutIfNeeded() +AntialiasingSettingsView::RelayoutIfNeeded() { float width, height; GetPreferredSize(&width, &height); @@ -136,19 +163,20 @@ AdvancedSettingsView::RelayoutIfNeeded() void -AdvancedSettingsView::AttachedToWindow() +AntialiasingSettingsView::AttachedToWindow() { if (Parent() != NULL) SetViewColor(Parent()->ViewColor()); else SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - fAntialiasingMenu->SetTargetForItems(this); - fHintingMenu->SetTargetForItems(this); + fAntialiasingMenu -> SetTargetForItems(this); + fHintingMenu -> SetTargetForItems(this); + fAverageWeightControl -> SetTarget(this); } void -AdvancedSettingsView::MessageReceived(BMessage *msg) +AntialiasingSettingsView::MessageReceived(BMessage *msg) { switch (msg->what) { case kMsgSetAntialiasing: @@ -158,8 +186,9 @@ AdvancedSettingsView::MessageReceived(BMessage *msg) || subpixelAntialiasing == fCurrentSubpixelAntialiasing) break; fCurrentSubpixelAntialiasing = subpixelAntialiasing; + fAverageWeightControl -> SetEnabled(fCurrentSubpixelAntialiasing); #ifdef INSTANT_UPDATE - _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); + set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); #endif Window()->PostMessage(kMsgUpdate); break; @@ -172,7 +201,30 @@ AdvancedSettingsView::MessageReceived(BMessage *msg) break; fCurrentHinting = hinting; #ifdef INSTANT_UPDATE - _set_hinting_(fCurrentHinting); + set_hinting(fCurrentHinting); +#endif + Window()->PostMessage(kMsgUpdate); + break; + } + case kMsgSetAverageWeight: + { + int subpixelWeight; + unsigned char averageWeight; + if (fAverageWeightControl -> Text() != NULL) { + subpixelWeight = atoi(fAverageWeightControl -> Text()); + if (subpixelWeight > 255) { + subpixelWeight = 255; + BString subpixelWeightString; + subpixelWeightString << subpixelWeight; + fAverageWeightControl -> SetText( + subpixelWeightString.String()); + } + averageWeight = 255 - subpixelWeight; + if (averageWeight == fCurrentAverageWeight) break; + } else break; + fCurrentAverageWeight = averageWeight; +#ifdef INSTANT_UPDATE + set_average_weight(fCurrentAverageWeight); #endif Window()->PostMessage(kMsgUpdate); break; @@ -184,7 +236,7 @@ AdvancedSettingsView::MessageReceived(BMessage *msg) void -AdvancedSettingsView::_BuildAntialiasingMenu() +AntialiasingSettingsView::_BuildAntialiasingMenu() { BMessage* message = new BMessage(kMsgSetAntialiasing); message->AddBool("antialiasing", false); @@ -203,7 +255,7 @@ AdvancedSettingsView::_BuildAntialiasingMenu() void -AdvancedSettingsView::_BuildHintingMenu() +AntialiasingSettingsView::_BuildHintingMenu() { BMessage* message = new BMessage(kMsgSetHinting); message->AddBool("hinting", false); @@ -222,17 +274,18 @@ AdvancedSettingsView::_BuildHintingMenu() void -AdvancedSettingsView::_SetCurrentAntialiasing() +AntialiasingSettingsView::_SetCurrentAntialiasing() { BMenuItem *item = fAntialiasingMenu->FindItem( fCurrentSubpixelAntialiasing ? kSubpixelLabel : kGrayscaleLabel); if (item != NULL) item->SetMarked(true); + if (fCurrentSubpixelAntialiasing) fAverageWeightControl -> SetEnabled(true); } void -AdvancedSettingsView::_SetCurrentHinting() +AntialiasingSettingsView::_SetCurrentHinting() { BMenuItem *item = fHintingMenu->FindItem( fCurrentHinting ? kFullHintingLabel : kNoHintingLabel); @@ -242,38 +295,51 @@ AdvancedSettingsView::_SetCurrentHinting() void -AdvancedSettingsView::SetDefaults() -{ +AntialiasingSettingsView::_SetCurrentAverageWeight() +{ + BString subpixelWeightString; + subpixelWeightString << (255 - fCurrentAverageWeight); + fAverageWeightControl -> SetText(subpixelWeightString.String()); +} + + +void +AntialiasingSettingsView::SetDefaults() +{ } bool -AdvancedSettingsView::IsDefaultable() +AntialiasingSettingsView::IsDefaultable() { return false; } bool -AdvancedSettingsView::IsRevertable() +AntialiasingSettingsView::IsRevertable() { return (fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing) - || (fCurrentHinting != fSavedHinting); + || (fCurrentHinting != fSavedHinting) + || (fCurrentAverageWeight != fSavedAverageWeight); } void -AdvancedSettingsView::Revert() +AntialiasingSettingsView::Revert() { if (!IsRevertable()) return; fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; fCurrentHinting = fSavedHinting; + fCurrentAverageWeight = fSavedAverageWeight; #ifdef INSTANT_UPDATE - _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); - _set_hinting_(fCurrentHinting); + set_subpixel_antialiasing(fCurrentSubpixelAntialiasing); + set_hinting(fCurrentHinting); + set_average_weight(fCurrentAverageWeight); #endif _SetCurrentAntialiasing(); _SetCurrentHinting(); + _SetCurrentAverageWeight(); } diff --git a/src/preferences/appearance/AntialiasingSettingsView.h b/src/preferences/appearance/AntialiasingSettingsView.h new file mode 100644 index 0000000000..b7db0bf44a --- /dev/null +++ b/src/preferences/appearance/AntialiasingSettingsView.h @@ -0,0 +1,59 @@ +/* + * Copyright 2008, Andrej Spielmann, + * All rights reserved. Distributed under the terms of the MIT License. + */ +#ifndef ANTIALIASING_SETTINGS_VIEW_H +#define ANTIALIASING_SETTINGS_VIEW_H + + +#include + +class BBox; +class BMenuField; +class BPopUpMenu; +class BTextControl; + + +class AntialiasingSettingsView : public BView { +public: + AntialiasingSettingsView(BRect rect, + const char* name); + virtual ~AntialiasingSettingsView(); + + virtual void GetPreferredSize(float *_width, float *_height); + virtual void RelayoutIfNeeded(); + virtual void AttachedToWindow(); + virtual void MessageReceived(BMessage *msg); + + void SetDivider(float divider); + + void SetDefaults(); + void Revert(); + bool IsDefaultable(); + bool IsRevertable(); + +private: + void _BuildAntialiasingMenu(); + void _SetCurrentAntialiasing(); + void _BuildHintingMenu(); + void _SetCurrentHinting(); + void _SetCurrentAverageWeight(); + +protected: + float fDivider; + + BMenuField* fAntialiasingMenuField; + BPopUpMenu* fAntialiasingMenu; + BMenuField* fHintingMenuField; + BPopUpMenu* fHintingMenu; + BTextControl* fAverageWeightControl; + + bool fSavedSubpixelAntialiasing; + bool fCurrentSubpixelAntialiasing; + bool fSavedHinting; + bool fCurrentHinting; + unsigned char fSavedAverageWeight; + unsigned char fCurrentAverageWeight; +}; + +#endif // ANTIALIASING_SETTINGS_VIEW_H diff --git a/src/preferences/appearance/Jamfile b/src/preferences/appearance/Jamfile index 825f0b2c92..f727a73229 100644 --- a/src/preferences/appearance/Jamfile +++ b/src/preferences/appearance/Jamfile @@ -5,6 +5,7 @@ UsePrivateHeaders app [ FDirName servers app ] ; Preference Appearance : APRMain.cpp + AntialiasingSettingsView.cpp APRView.cpp APRWindow.cpp ColorSet.cpp diff --git a/src/preferences/fonts/AdvancedSettingsView.h b/src/preferences/fonts/AdvancedSettingsView.h deleted file mode 100644 index f871d6f048..0000000000 --- a/src/preferences/fonts/AdvancedSettingsView.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2001-2005, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * Andrej Spielmann, - */ -#ifndef ADVANCED_SETTINGS_VIEW_H -#define ADVANCED_SETTINGS_VIEW_H - - -#include - -class BBox; -class BMenuField; -class BPopUpMenu; - - -class AdvancedSettingsView : public BView { - public: - AdvancedSettingsView(BRect rect, const char* name); - virtual ~AdvancedSettingsView(); - - virtual void GetPreferredSize(float *_width, float *_height); - virtual void RelayoutIfNeeded(); - virtual void AttachedToWindow(); - virtual void MessageReceived(BMessage *msg); - - void SetDivider(float divider); - - void SetDefaults(); - void Revert(); - bool IsDefaultable(); - bool IsRevertable(); - - private: - void _BuildAntialiasingMenu(); - void _SetCurrentAntialiasing(); - void _BuildHintingMenu(); - void _SetCurrentHinting(); - - protected: - float fDivider; - - BMenuField* fAntialiasingMenuField; - BPopUpMenu* fAntialiasingMenu; - BMenuField* fHintingMenuField; - BPopUpMenu* fHintingMenu; - - bool fSavedSubpixelAntialiasing; - bool fCurrentSubpixelAntialiasing; - bool fSavedHinting; - bool fCurrentHinting; -}; - -#endif /* ADVANCED_SETTINGS_VIEW_H */ diff --git a/src/preferences/fonts/FontView.h b/src/preferences/fonts/FontView.h index 153617908d..abe58c5b6a 100644 --- a/src/preferences/fonts/FontView.h +++ b/src/preferences/fonts/FontView.h @@ -12,7 +12,6 @@ #include "FontSelectionView.h" -#include "AdvancedSettingsView.h" class FontView : public BView { diff --git a/src/preferences/fonts/Jamfile b/src/preferences/fonts/Jamfile index 7a8d7a746a..837525b5b2 100644 --- a/src/preferences/fonts/Jamfile +++ b/src/preferences/fonts/Jamfile @@ -5,7 +5,6 @@ AddSubDirSupportedPlatforms libbe_test ; Preference Fonts : FontSelectionView.cpp - AdvancedSettingsView.cpp FontsSettings.cpp FontView.cpp main.cpp diff --git a/src/preferences/fonts/MainWindow.cpp b/src/preferences/fonts/MainWindow.cpp index c778a1c4e6..4cdb6eaa71 100644 --- a/src/preferences/fonts/MainWindow.cpp +++ b/src/preferences/fonts/MainWindow.cpp @@ -63,8 +63,6 @@ MainWindow::MainWindow() rect = tabView->ContainerView()->Bounds().InsetByCopy(5, 8); fFontsView = new FontView(rect); - fAdvancedSettings = new AdvancedSettingsView(rect, "Advanced"); - tabView->AddTab(fFontsView); fFontsView->UpdateFonts(); @@ -104,23 +102,6 @@ MainWindow::MainWindow() _Center(); } - tabView->AddTab(fAdvancedSettings); - - fAdvancedSettings->RelayoutIfNeeded(); - fAdvancedSettings->GetPreferredSize(&width, &height); - - widthDiff = width + 10 - tabView->ContainerView()->Bounds().Width(); - if (widthDiff > 0) { - tabView->ResizeBy(widthDiff, 0); - tabView->ContainerView()->ResizeBy(widthDiff, 0); - } - - heightDiff = height + 16 - tabView->ContainerView()->Bounds().Height(); - if (heightDiff > 0) { - tabView->ResizeBy(0, heightDiff); - tabView->ContainerView()->ResizeBy(0, heightDiff); - } - fRunner = new BMessageRunner(this, new BMessage(kMsgCheckFonts), 3000000); // every 3 seconds @@ -149,25 +130,19 @@ MainWindow::MessageReceived(BMessage *message) { switch (message->what) { case kMsgUpdate: - fDefaultsButton->SetEnabled(fFontsView->IsDefaultable() - || fAdvancedSettings->IsDefaultable()); - fRevertButton->SetEnabled(fFontsView->IsRevertable() - || fAdvancedSettings->IsRevertable()); + fDefaultsButton->SetEnabled(fFontsView->IsDefaultable()); + fRevertButton->SetEnabled(fFontsView->IsRevertable()); break; case kMsgSetDefaults: fFontsView->SetDefaults(); - fAdvancedSettings->SetDefaults(); fDefaultsButton->SetEnabled(false); - fRevertButton->SetEnabled(fFontsView->IsRevertable() - || fAdvancedSettings->IsRevertable()); + fRevertButton->SetEnabled(fFontsView->IsRevertable()); break; case kMsgRevert: fFontsView->Revert(); - fAdvancedSettings->Revert(); - fDefaultsButton->SetEnabled(fFontsView->IsDefaultable() - || fAdvancedSettings->IsDefaultable()); + fDefaultsButton->SetEnabled(fFontsView->IsDefaultable()); fRevertButton->SetEnabled(false); break; diff --git a/src/preferences/fonts/MainWindow.h b/src/preferences/fonts/MainWindow.h index b154040ec4..8f800545c0 100644 --- a/src/preferences/fonts/MainWindow.h +++ b/src/preferences/fonts/MainWindow.h @@ -12,7 +12,6 @@ #include "FontsSettings.h" -#include "AdvancedSettingsView.h" #include @@ -38,7 +37,6 @@ class MainWindow : public BWindow { BButton* fRevertButton; FontsSettings fSettings; - AdvancedSettingsView* fAdvancedSettings; }; static const int32 kMsgUpdate = 'updt'; diff --git a/src/servers/app/DesktopSettings.cpp b/src/servers/app/DesktopSettings.cpp index 600c1de546..13c0ea7850 100644 --- a/src/servers/app/DesktopSettings.cpp +++ b/src/servers/app/DesktopSettings.cpp @@ -15,6 +15,7 @@ #include "FontCache.h" #include "FontCacheEntry.h" #include "FontManager.h" +#include "GlobalSubpixelSettings.h" #include "ServerConfig.h" #include @@ -73,10 +74,10 @@ DesktopSettingsPrivate::_SetDefaults() memcpy(fShared.colors, BPrivate::kDefaultColors, sizeof(rgb_color) * kNumColors); - fFontSubpixelAntialiasing = false; - FontCacheEntry::SetDefaultRenderType(glyph_ren_native_gray8); - fHinting = true; - FontCacheEntry::SetDefaultHinting(true); + gSubpixelAntialiasing = false; + gDefaultHinting = true; + gSubpixelAverageWeight = 120; + gSubpixelOrderingRGB = true; } @@ -144,7 +145,6 @@ DesktopSettingsPrivate::_Load() const char* family; const char* style; float size; - bool subpix; bool hinting; if (settings.FindString("plain family", &family) == B_OK && settings.FindString("plain style", &style) == B_OK @@ -168,14 +168,8 @@ DesktopSettingsPrivate::_Load() fFixedFont.SetStyle(fontStyle); fFixedFont.SetSize(size); } - if (settings.FindBool("font subpix", &subpix) == B_OK) { - fFontSubpixelAntialiasing = subpix; - FontCacheEntry::SetDefaultRenderType( - (subpix) ? glyph_ren_subpix : glyph_ren_native_gray8); - } if (settings.FindBool("hinting", &hinting) == B_OK) { - fHinting = hinting; - FontCacheEntry::SetDefaultHinting(fHinting); + gDefaultHinting = hinting; } gFontManager->Unlock(); } @@ -233,8 +227,26 @@ DesktopSettingsPrivate::_Load() fMenuInfo.click_to_open = clickToOpen; bool triggersAlwaysShown; - if (settings.FindBool("triggers always shown", &triggersAlwaysShown) == B_OK) + if (settings.FindBool("triggers always shown", &triggersAlwaysShown) + == B_OK) { fMenuInfo.triggers_always_shown = triggersAlwaysShown; + } + + bool subpix; + if (settings.FindBool("subpixel antialiasing", &subpix) == B_OK) + gSubpixelAntialiasing = subpix; + + int8 averageWeight; + if (settings.FindInt8("subpixel average weight", &averageWeight) + == B_OK) { + gSubpixelAverageWeight = averageWeight; + } + + bool subpixelOrdering; + if (settings.FindBool("subpixel ordering", &subpixelOrdering) + == B_OK) { + gSubpixelOrderingRGB = subpixelOrdering; + } for (int32 i = 0; i < kNumColors; i++) { char colorName[12]; @@ -269,7 +281,8 @@ DesktopSettingsPrivate::Save(uint32 mask) } BFile file; - status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); + status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE + | B_READ_WRITE); if (status == B_OK) { status = settings.Flatten(&file, NULL); } @@ -293,11 +306,11 @@ DesktopSettingsPrivate::Save(uint32 mask) settings.AddString("fixed style", fFixedFont.Style()); settings.AddFloat("fixed size", fFixedFont.Size()); - settings.AddBool("font subpix",fFontSubpixelAntialiasing); - settings.AddBool("hinting",fHinting); + settings.AddBool("hinting", gDefaultHinting); BFile file; - status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); + status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE + | B_READ_WRITE); if (status == B_OK) { status = settings.Flatten(&file, NULL); } @@ -311,7 +324,8 @@ DesktopSettingsPrivate::Save(uint32 mask) settings.AddInt32("mode", (int32)fMouseMode); BFile file; - status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); + status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE + | B_READ_WRITE); if (status == B_OK) { status = settings.Flatten(&file, NULL); } @@ -325,7 +339,8 @@ DesktopSettingsPrivate::Save(uint32 mask) settings.AddBool("show", fShowAllDraggers); BFile file; - status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); + status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE + | B_READ_WRITE); if (status == B_OK) { status = settings.Flatten(&file, NULL); } @@ -339,10 +354,16 @@ DesktopSettingsPrivate::Save(uint32 mask) settings.AddFloat("font size", fMenuInfo.font_size); settings.AddString("font family", fMenuInfo.f_family); settings.AddString("font style", fMenuInfo.f_style); - settings.AddInt32("bg color", (const int32&)fMenuInfo.background_color); + settings.AddInt32("bg color", + (const int32&)fMenuInfo.background_color); settings.AddInt32("separator", fMenuInfo.separator); settings.AddBool("click to open", fMenuInfo.click_to_open); - settings.AddBool("triggers always shown", fMenuInfo.triggers_always_shown); + settings.AddBool("triggers always shown", + fMenuInfo.triggers_always_shown); + + settings.AddBool("subpixel antialiasing", gSubpixelAntialiasing); + settings.AddInt8("subpixel average weight", gSubpixelAverageWeight); + settings.AddBool("subpixel ordering", gSubpixelOrderingRGB); for (int32 i = 0; i < kNumColors; i++) { char colorName[12]; @@ -352,7 +373,8 @@ DesktopSettingsPrivate::Save(uint32 mask) } BFile file; - status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); + status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE + | B_READ_WRITE); if (status == B_OK) { status = settings.Flatten(&file, NULL); } @@ -544,39 +566,62 @@ DesktopSettingsPrivate::UIColor(color_which which) const void -DesktopSettingsPrivate::SetFontSubpixelAntialiasing(bool subpix) +DesktopSettingsPrivate::SetSubpixelAntialiasing(bool subpix) { - if (fFontSubpixelAntialiasing != subpix) { - fFontSubpixelAntialiasing = subpix; - FontCacheEntry::SetDefaultRenderType( - (subpix)?glyph_ren_subpix:glyph_ren_native_gray8); - Save(kFontSettings); - } + gSubpixelAntialiasing = subpix; + Save(kAppearanceSettings); } bool -DesktopSettingsPrivate::FontSubpixelAntialiasing() const +DesktopSettingsPrivate::SubpixelAntialiasing() const { - return fFontSubpixelAntialiasing; + return gSubpixelAntialiasing; } void DesktopSettingsPrivate::SetHinting(bool hinting) { - if (fHinting != hinting) { - fHinting = hinting; - FontCacheEntry::SetDefaultHinting(hinting); - Save(kFontSettings); - } + gDefaultHinting = hinting; + Save(kFontSettings); } bool DesktopSettingsPrivate::Hinting() const { - return fHinting; + return gDefaultHinting; +} + + +void +DesktopSettingsPrivate::SetSubpixelAverageWeight(uint8 averageWeight) +{ + gSubpixelAverageWeight = averageWeight; + Save(kAppearanceSettings); +} + + +uint8 +DesktopSettingsPrivate::SubpixelAverageWeight() const +{ + return gSubpixelAverageWeight; +} + + +void +DesktopSettingsPrivate::SetSubpixelOrderingRegular(bool subpixelOrdering) +{ + gSubpixelOrderingRGB = subpixelOrdering; + Save(kAppearanceSettings); +} + + +bool +DesktopSettingsPrivate::IsSubpixelOrderingRegular() const +{ + return gSubpixelOrderingRGB; } // #pragma mark - read access @@ -672,9 +717,9 @@ DesktopSettings::UIColor(color_which which) const bool -DesktopSettings::FontSubpixelAntialiasing() const +DesktopSettings::SubpixelAntialiasing() const { - return fSettings->FontSubpixelAntialiasing(); + return fSettings->SubpixelAntialiasing(); } @@ -684,6 +729,21 @@ DesktopSettings::Hinting() const return fSettings->Hinting(); } + +uint8 +DesktopSettings::SubpixelAverageWeight() const +{ + return fSettings->SubpixelAverageWeight(); +} + + +bool +DesktopSettings::IsSubpixelOrderingRegular() const +{ + // True corresponds to RGB, false means BGR + return fSettings->IsSubpixelOrderingRegular(); +} + // #pragma mark - write access @@ -763,9 +823,9 @@ LockedDesktopSettings::SetUIColor(color_which which, const rgb_color color) void -LockedDesktopSettings::SetFontSubpixelAntialiasing(bool subpix) +LockedDesktopSettings::SetSubpixelAntialiasing(bool subpix) { - fSettings->SetFontSubpixelAntialiasing(subpix); + fSettings->SetSubpixelAntialiasing(subpix); } @@ -775,3 +835,16 @@ LockedDesktopSettings::SetHinting(bool hinting) fSettings->SetHinting(hinting); } + +void +LockedDesktopSettings::SetSubpixelAverageWeight(uint8 averageWeight) +{ + fSettings->SetSubpixelAverageWeight(averageWeight); +} + +void +LockedDesktopSettings::SetSubpixelOrderingRegular(bool subpixelOrdering) +{ + fSettings->SetSubpixelOrderingRegular(subpixelOrdering); +} + diff --git a/src/servers/app/DesktopSettings.h b/src/servers/app/DesktopSettings.h index bb4b30e3ae..073ecd740a 100644 --- a/src/servers/app/DesktopSettings.h +++ b/src/servers/app/DesktopSettings.h @@ -53,8 +53,10 @@ class DesktopSettings { rgb_color UIColor(color_which which) const; - bool FontSubpixelAntialiasing() const; + bool SubpixelAntialiasing() const; bool Hinting() const; + uint8 SubpixelAverageWeight() const; + bool IsSubpixelOrderingRegular() const; protected: DesktopSettingsPrivate* fSettings; @@ -78,8 +80,10 @@ class LockedDesktopSettings : public DesktopSettings { void SetUIColor(color_which which, const rgb_color color); - void SetFontSubpixelAntialiasing(bool subpix); + void SetSubpixelAntialiasing(bool subpix); void SetHinting(bool hinting); + void SetSubpixelAverageWeight(uint8 averageWeight); + void SetSubpixelOrderingRegular(bool subpixelOrdering); private: Desktop* fDesktop; diff --git a/src/servers/app/DesktopSettingsPrivate.h b/src/servers/app/DesktopSettingsPrivate.h index 5d8bb180da..dfc640875e 100644 --- a/src/servers/app/DesktopSettingsPrivate.h +++ b/src/servers/app/DesktopSettingsPrivate.h @@ -56,10 +56,14 @@ class DesktopSettingsPrivate { void SetUIColor(color_which which, const rgb_color color); rgb_color UIColor(color_which which) const; - void SetFontSubpixelAntialiasing(bool subpix); - bool FontSubpixelAntialiasing() const; + void SetSubpixelAntialiasing(bool subpix); + bool SubpixelAntialiasing() const; void SetHinting(bool hinting); bool Hinting() const; + void SetSubpixelAverageWeight(uint8 averageWeight); + uint8 SubpixelAverageWeight() const; + void SetSubpixelOrderingRegular(bool SubpixelOrdering); + bool IsSubpixelOrderingRegular() const; private: void _SetDefaults(); @@ -77,9 +81,6 @@ class DesktopSettingsPrivate { int32 fWorkspacesCount; BMessage fWorkspaceMessages[kMaxWorkspaces]; - bool fFontSubpixelAntialiasing; - bool fHinting; - server_read_only_memory& fShared; }; diff --git a/src/servers/app/FontCacheEntry.cpp b/src/servers/app/FontCacheEntry.cpp index 05fe5b9f2b..e8865dcd88 100644 --- a/src/servers/app/FontCacheEntry.cpp +++ b/src/servers/app/FontCacheEntry.cpp @@ -33,16 +33,12 @@ #include "utf8_functions.h" +#include "GlobalSubpixelSettings.h" + + BLocker FontCacheEntry::sUsageUpdateLock("FontCacheEntry usage lock"); -glyph_rendering -FontCacheEntry::sDefaultRenderType; - -bool -FontCacheEntry::sDefaultHinting; - - class FontCacheEntry::GlyphCachePool { public: enum block_size_e { block_size = 16384-16 }; @@ -127,7 +123,7 @@ FontCacheEntry::Init(const ServerFont& font) // TODO: encoding from font FT_Encoding charMap = FT_ENCODING_NONE; - bool hinting = sDefaultHinting; // TODO: font.Hinting(); + bool hinting = gDefaultHinting; // TODO: font.Hinting(); if (!fEngine.Init(font.Path(), 0, font.Size(), charMap, renderingType, hinting)) { @@ -224,11 +220,12 @@ FontCacheEntry::GenerateSignature(char* signature, const ServerFont& font) // TODO: read more of these from the font FT_Encoding charMap = FT_ENCODING_NONE; - bool hinting = sDefaultHinting; // TODO: font.Hinting(); + bool hinting = gDefaultHinting; // TODO: font.Hinting(); + uint8 averageWeight = gSubpixelAverageWeight; - sprintf(signature, "%ld,%u,%d,%d,%.1f,%d", + sprintf(signature, "%ld,%u,%d,%d,%.1f,%d,%d", font.GetFamilyAndStyle(), charMap, - font.Face(), int(renderingType), font.Size(), hinting); + font.Face(), int(renderingType), font.Size(), hinting, averageWeight); } // UpdateUsage @@ -247,31 +244,20 @@ FontCacheEntry::UpdateUsage() } -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 = sDefaultRenderType; + glyph_rendering renderingType = gSubpixelAntialiasing ? + glyph_ren_subpix : glyph_ren_native_gray8; + if (font.Rotation() != 0.0 || font.Shear() != 90.0 || font.FalseBoldWidth() != 0.0 || font.Flags() & B_DISABLE_ANTIALIASING || font.Size() > 30 - || !sDefaultHinting) { + || !gDefaultHinting) { renderingType = glyph_ren_outline; } + return renderingType; } diff --git a/src/servers/app/FontCacheEntry.h b/src/servers/app/FontCacheEntry.h index 71eba77691..1d0e936148 100644 --- a/src/servers/app/FontCacheEntry.h +++ b/src/servers/app/FontCacheEntry.h @@ -94,13 +94,6 @@ 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(); @@ -119,8 +112,6 @@ 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 7d1bb2e24d..7cf4b0373f 100644 --- a/src/servers/app/FontEngine.cpp +++ b/src/servers/app/FontEngine.cpp @@ -36,7 +36,7 @@ #include #include - +#include "GlobalSubpixelSettings.h" static const bool kFlipY = true; @@ -365,21 +365,6 @@ decompose_ft_bitmap_gray8(const FT_Bitmap& bitmap, int x, int y, } -#define AVERAGE_BASED_SUBPIXEL_FILTERING -// NOTE stippi: My basic idea is that filtering tries to minimize colored -// edges, but it does so by blurring the coverage values. This will also -// affect neighboring pixels and add blur where there were perfectly sharp -// edges. Andrej's method of filtering adds a special case for perfectly -// sharp edges, but the drawback here is that there will be a visible -// transition between blurred and non-blurred subpixels. I had the idea that -// when simply fading the subpixels towards the plain gray-scale-aa values, -// there must be a sweet spot for when colored edges become non-disturbing -// and there is still a benefit of sharpness compared to straight gray-scale- -// aa. The define above enables this method against the colored edges. My -// method still has a drawback, since jaggies in diagonal lines will be more -// visible again than with the filter method. - - // decompose_ft_bitmap_subpix template void @@ -387,13 +372,6 @@ decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y, bool flip_y, Scanline& sl, ScanlineStorage& storage) { #ifdef AVERAGE_BASED_SUBPIXEL_FILTERING - // The weight with which the average of the subpixels is applied to counter - // color fringes (0 = full sharpness ... 255 = grayscale anti-aliasing) - // TODO: This could be a config option, but don't forget to include the - // value in the font cache entry signature generation! - const uint8 averageWeight = 100; - const uint8 subpixelWeight = 255 - averageWeight; - const uint8* buf = (const uint8*)bitmap.buffer; int pitch = bitmap.pitch; sl.reset(x, x + bitmap.width / 3); @@ -420,20 +398,11 @@ decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y, } } else { const uint8* p = buf; - uint32 coverR; - uint32 coverG; - uint32 coverB; int w = bitmap.width / 3; for (int j = 0; j < w; j++) { - uint32 average = (p[0] + p[1] + p[2] + 2) / 3; - coverR = (p[0] * subpixelWeight + average * averageWeight) >> 8; - coverG = (p[1] * subpixelWeight + average * averageWeight) >> 8; - coverB = (p[2] * subpixelWeight + average * averageWeight) >> 8; - - if (coverR || coverG || coverB) - sl.add_cell(x + j, coverR, coverG, coverB); - + if (p[0] || p[1] || p[2]) + sl.add_cell(x + j, p[0], p[1], p[2]); p += 3; } } @@ -444,7 +413,8 @@ decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y, storage.render(sl); } } -#else // filter based anti-colored edges method +#else +// filter based anti-colored edges method // Filtering weights const uint8 filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 }; diff --git a/src/servers/app/FontEngine.h b/src/servers/app/FontEngine.h index 497fef66fe..b0e5f7e473 100644 --- a/src/servers/app/FontEngine.h +++ b/src/servers/app/FontEngine.h @@ -42,6 +42,9 @@ #include "agg_scanline_storage_subpix.h" #include "agg_scanline_u_subpix.h" +#include "agg_scanline_u_subpix_avrg_filtering.h" + +#include "GlobalSubpixelSettings.h" enum glyph_rendering { @@ -147,7 +150,11 @@ class FontEngine { CurveConverterType fCurves; agg::scanline_u8 fScanlineAA; agg::scanline_bin fScanlineBin; +#ifdef AVERAGE_BASED_SUBPIXEL_FILTERING + agg::scanline_u8_subpix_avrg_filtering fScanlineSubpix; +#else agg::scanline_u8_subpix fScanlineSubpix; +#endif ScanlineStorageAA fScanlineStorageAA; ScanlineStorageBin fScanlineStorageBin; diff --git a/src/servers/app/ProfileMessageSupport.cpp b/src/servers/app/ProfileMessageSupport.cpp index 48253f7880..87e6699b7a 100644 --- a/src/servers/app/ProfileMessageSupport.cpp +++ b/src/servers/app/ProfileMessageSupport.cpp @@ -175,10 +175,15 @@ string_for_message_code(uint32 code, BString& string) case AS_GET_SHOW_ALL_DRAGGERS: string = "AS_GET_SHOW_ALL_DRAGGERS"; break; case AS_SET_SHOW_ALL_DRAGGERS: string = "AS_SET_SHOW_ALL_DRAGGERS"; break; - case AS_SET_FONT_SUBPIXEL_ANTIALIASING: string = "AS_SET_FONT_SUBPIXEL_ANTIALIASING"; break; - case AS_GET_FONT_SUBPIXEL_ANTIALIASING: string = "AS_GET_FONT_SUBPIXEL_ANTIALIASING"; break; + // Subpixel antialiasing & hinting + case AS_SET_SUBPIXEL_ANTIALIASING: string = "AS_SET_SUBPIXEL_ANTIALIASING"; break; + case AS_GET_SUBPIXEL_ANTIALIASING: string = "AS_GET_SUBPIXEL_ANTIALIASING"; break; case AS_SET_HINTING: string = "AS_SET_HINTING"; break; case AS_GET_HINTING: string = "AS_GET_HINTING"; break; + case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: string = "AS_SET_SUBPIXEL_AVERAGE_WEIGHT"; break; + case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: string = "AS_GET_SUBPIXEL_AVERAGE_WEIGHT"; break; + case AS_SET_SUBPIXEL_ORDERING: string = "AS_SET_SUBPIXEL_ORDERING"; break; + case AS_GET_SUBPIXEL_ORDERING: string = "AS_GET_SUBPIXEL_ORDERING"; break; // Graphics calls case AS_SET_HIGH_COLOR: string = "AS_SET_HIGH_COLOR"; break; diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index 09ca4fc6b7..bc26eb00a2 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -2537,22 +2537,22 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) break; } - case AS_SET_FONT_SUBPIXEL_ANTIALIASING: + case AS_SET_SUBPIXEL_ANTIALIASING: { bool subpix; if (link.Read(&subpix) == B_OK) { LockedDesktopSettings settings(fDesktop); - settings.SetFontSubpixelAntialiasing(subpix); + settings.SetSubpixelAntialiasing(subpix); } fDesktop->Redraw(); break; } - case AS_GET_FONT_SUBPIXEL_ANTIALIASING: + case AS_GET_SUBPIXEL_ANTIALIASING: { DesktopSettings settings(fDesktop); fLink.StartMessage(B_OK); - fLink.Attach(settings.FontSubpixelAntialiasing()); + fLink.Attach(settings.SubpixelAntialiasing()); fLink.Flush(); break; } @@ -2576,6 +2576,46 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) fLink.Flush(); break; } + + case AS_SET_SUBPIXEL_AVERAGE_WEIGHT: + { + uint8 averageWeight; + if (link.Read(&averageWeight) == B_OK) { + LockedDesktopSettings settings(fDesktop); + settings.SetSubpixelAverageWeight(averageWeight); + } + fDesktop->Redraw(); + break; + } + + case AS_GET_SUBPIXEL_AVERAGE_WEIGHT: + { + DesktopSettings settings(fDesktop); + fLink.StartMessage(B_OK); + fLink.Attach(settings.SubpixelAverageWeight()); + fLink.Flush(); + break; + } + + case AS_SET_SUBPIXEL_ORDERING: + { + bool subpixelOrdering; + if (link.Read(&subpixelOrdering) == B_OK) { + LockedDesktopSettings settings(fDesktop); + settings.SetSubpixelOrderingRegular(subpixelOrdering); + } + fDesktop->Redraw(); + break; + } + + case AS_GET_SUBPIXEL_ORDERING: + { + DesktopSettings settings(fDesktop); + fLink.StartMessage(B_OK); + fLink.Attach(settings.IsSubpixelOrderingRegular()); + fLink.Flush(); + break; + } default: printf("ServerApp %s received unhandled message code %ld\n", diff --git a/src/servers/app/agg_scanline_storage_subpix.h b/src/servers/app/agg_scanline_storage_subpix.h index 24db6d3f71..2df7fe2a84 100644 --- a/src/servers/app/agg_scanline_storage_subpix.h +++ b/src/servers/app/agg_scanline_storage_subpix.h @@ -22,658 +22,658 @@ namespace agg { - //--------------------------------------------scanline_storage_subpix - template class scanline_storage_subpix - { - public: - typedef T cover_type; - - //--------------------------------------------------------------- - struct span_data - { - int32 x; - int32 len; // If negative, it's a solid span, covers is valid - int covers_id; // The index of the cells in the scanline_cell_storage - }; - - //--------------------------------------------------------------- - struct scanline_data - { - int y; - unsigned num_spans; - unsigned start_span; - }; - - - //--------------------------------------------------------------- - class embedded_scanline - { - public: - - //----------------------------------------------------------- - class const_iterator - { - public: - struct span - { - int32 x; - int32 len; // If negative, it's a solid span, covers is valid - const T* covers; - }; - - const_iterator() : m_storage(0) {} - const_iterator(const embedded_scanline& sl) : - m_storage(sl.m_storage), - m_span_idx(sl.m_scanline.start_span) - { - init_span(); - } - - const span& operator*() const { return m_span; } - const span* operator->() const { return &m_span; } - - void operator ++ () - { - ++m_span_idx; - init_span(); - } - - private: - void init_span() - { - const span_data& s = m_storage->span_by_index(m_span_idx); - m_span.x = s.x; - m_span.len = s.len; - m_span.covers = m_storage->covers_by_index(s.covers_id); - } - - const scanline_storage_subpix* m_storage; - unsigned m_span_idx; - span m_span; - }; - - friend class const_iterator; - - - //----------------------------------------------------------- - embedded_scanline(const scanline_storage_subpix& storage) : - m_storage(&storage) - { - init(0); - } - - //----------------------------------------------------------- - void reset(int, int) {} - unsigned num_spans() const { return m_scanline.num_spans; } - int y() const { return m_scanline.y; } - const_iterator begin() const { return const_iterator(*this); } - - //----------------------------------------------------------- - void init(unsigned scanline_idx) - { - m_scanline_idx = scanline_idx; - m_scanline = m_storage->scanline_by_index(m_scanline_idx); - } - - private: - const scanline_storage_subpix* m_storage; - scanline_data m_scanline; - unsigned m_scanline_idx; - }; - - - //--------------------------------------------------------------- - scanline_storage_subpix() : - m_covers(), - m_spans(256-2), // Block increment size - m_scanlines(), - m_min_x( 0x7FFFFFFF), - m_min_y( 0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF), - m_cur_scanline(0) - { - m_fake_scanline.y = 0; - m_fake_scanline.num_spans = 0; - m_fake_scanline.start_span = 0; - m_fake_span.x = 0; - m_fake_span.len = 0; - m_fake_span.covers_id = 0; - } - - // Renderer Interface - //--------------------------------------------------------------- - void prepare() - { - m_covers.remove_all(); - m_scanlines.remove_all(); - m_spans.remove_all(); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; - m_cur_scanline = 0; - } - - //--------------------------------------------------------------- - template void render(const Scanline& sl) - { - scanline_data sl_this; - - int y = sl.y(); - if(y < m_min_y) m_min_y = y; - if(y > m_max_y) m_max_y = y; - - sl_this.y = y; - sl_this.num_spans = sl.num_spans(); - sl_this.start_span = m_spans.size(); - typename Scanline::const_iterator span_iterator = sl.begin(); - - unsigned num_spans = sl_this.num_spans; - for(;;) - { - span_data sp; - - sp.x = span_iterator->x; - sp.len = span_iterator->len; - int len = abs(int(sp.len)); - sp.covers_id = - m_covers.add_cells(span_iterator->covers, - (unsigned(len))); - m_spans.add(sp); - int x1 = sp.x; - int x2 = sp.x + len/3 - 1; - if(x1 < m_min_x) m_min_x = x1; - if(x2 > m_max_x) m_max_x = x2; - if(--num_spans == 0) break; - ++span_iterator; - } - m_scanlines.add(sl_this); - } - - - //--------------------------------------------------------------- - // Iterate scanlines interface - int min_x() const { return m_min_x; } - int min_y() const { return m_min_y; } - int max_x() const { return m_max_x; } - int max_y() const { return m_max_y; } - - //--------------------------------------------------------------- - bool rewind_scanlines() - { - m_cur_scanline = 0; - return m_scanlines.size() > 0; - } - - - //--------------------------------------------------------------- - template bool sweep_scanline(Scanline& sl) - { - sl.reset_spans(); - for(;;) - { - if(m_cur_scanline >= m_scanlines.size()) return false; - const scanline_data& sl_this = m_scanlines[m_cur_scanline]; - - unsigned num_spans = sl_this.num_spans; - unsigned span_idx = sl_this.start_span; - do - { - const span_data& sp = m_spans[span_idx++]; - const T* covers = covers_by_index(sp.covers_id); - if(sp.len < 0) - { - sl.add_span(sp.x, unsigned(-sp.len), *covers); - } - else - { - sl.add_cells(sp.x, sp.len, covers); - } - } - while(--num_spans); - ++m_cur_scanline; - if(sl.num_spans()) - { - sl.finalize(sl_this.y); - break; - } - } - return true; - } - - - //--------------------------------------------------------------- - // Specialization for embedded_scanline - bool sweep_scanline(embedded_scanline& sl) - { - do - { - if(m_cur_scanline >= m_scanlines.size()) return false; - sl.init(m_cur_scanline); - ++m_cur_scanline; - } - while(sl.num_spans() == 0); - return true; - } - - //--------------------------------------------------------------- - unsigned byte_size() const - { - unsigned i; - unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y - - for(i = 0; i < m_scanlines.size(); ++i) - { - size += sizeof(int32) * 3; // scanline size in bytes - - const scanline_data& sl_this = m_scanlines[i]; - - unsigned num_spans = sl_this.num_spans; - unsigned span_idx = sl_this.start_span; - do - { - const span_data& sp = m_spans[span_idx++]; - - size += sizeof(int32) * 2; // X, span_len - if(sp.len < 0) - { - size += sizeof(T); // cover - } - else - { - size += sizeof(T) * unsigned(sp.len); // covers - } - } - while(--num_spans); - } - return size; - } - - - //--------------------------------------------------------------- - static void write_int32(int8u* dst, int32 val) - { - dst[0] = ((const int8u*)&val)[0]; - dst[1] = ((const int8u*)&val)[1]; - dst[2] = ((const int8u*)&val)[2]; - dst[3] = ((const int8u*)&val)[3]; - } - - - //--------------------------------------------------------------- - void serialize(int8u* data) const - { - unsigned i; - - write_int32(data, min_x()); // min_x - data += sizeof(int32); - write_int32(data, min_y()); // min_y - data += sizeof(int32); - write_int32(data, max_x()); // max_x - data += sizeof(int32); - write_int32(data, max_y()); // max_y - data += sizeof(int32); - - for(i = 0; i < m_scanlines.size(); ++i) - { - const scanline_data& sl_this = m_scanlines[i]; - - int8u* size_ptr = data; - data += sizeof(int32); // Reserve space for scanline size in bytes - - write_int32(data, sl_this.y); // Y - data += sizeof(int32); - - write_int32(data, sl_this.num_spans); // num_spans - data += sizeof(int32); - - unsigned num_spans = sl_this.num_spans; - unsigned span_idx = sl_this.start_span; - do - { - const span_data& sp = m_spans[span_idx++]; - const T* covers = covers_by_index(sp.covers_id); - - write_int32(data, sp.x); // X - data += sizeof(int32); - - write_int32(data, sp.len); // span_len - data += sizeof(int32); - - if(sp.len < 0) - { - memcpy(data, covers, sizeof(T)); - data += sizeof(T); - } - else - { - memcpy(data, covers, unsigned(sp.len) * sizeof(T)); - data += sizeof(T) * unsigned(sp.len); - } - } - while(--num_spans); - write_int32(size_ptr, int32(unsigned(data - size_ptr))); - } - } - - - //--------------------------------------------------------------- - const scanline_data& scanline_by_index(unsigned i) const - { - return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; - } - - //--------------------------------------------------------------- - const span_data& span_by_index(unsigned i) const - { - return (i < m_spans.size()) ? m_spans[i] : m_fake_span; - } - - //--------------------------------------------------------------- - const T* covers_by_index(int i) const - { - return m_covers[i]; - } - - private: - scanline_cell_storage m_covers; - pod_bvector m_spans; - pod_bvector m_scanlines; - span_data m_fake_span; - scanline_data m_fake_scanline; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - unsigned m_cur_scanline; - }; - - - typedef scanline_storage_subpix scanline_storage_subpix8; //--------scanline_storage_subpix8 - typedef scanline_storage_subpix scanline_storage_subpix16; //--------scanline_storage_subpix16 - typedef scanline_storage_subpix scanline_storage_subpix32; //--------scanline_storage_subpix32 - - - //--------------------------------------serialized_scanlines_adaptor_subpix - template class serialized_scanlines_adaptor_subpix - { - public: - typedef T cover_type; - - //--------------------------------------------------------------------- - class embedded_scanline - { - public: - typedef T cover_type; - - //----------------------------------------------------------------- - class const_iterator - { - public: - struct span - { - int32 x; - int32 len; // If negative, it's a solid span, "covers" is valid - const T* covers; - }; - - const_iterator() : m_ptr(0) {} - const_iterator(const embedded_scanline& sl) : - m_ptr(sl.m_ptr), - m_dx(sl.m_dx) - { - init_span(); - } - - const span& operator*() const { return m_span; } - const span* operator->() const { return &m_span; } - - void operator ++ () - { - if(m_span.len < 0) - { - m_ptr += sizeof(T); - } - else - { - m_ptr += m_span.len * sizeof(T); - } - init_span(); - } - - private: - int read_int32() - { - int32 val; - ((int8u*)&val)[0] = *m_ptr++; - ((int8u*)&val)[1] = *m_ptr++; - ((int8u*)&val)[2] = *m_ptr++; - ((int8u*)&val)[3] = *m_ptr++; - return val; - } - - void init_span() - { - m_span.x = read_int32() + m_dx; - m_span.len = read_int32(); - m_span.covers = m_ptr; - } - - const int8u* m_ptr; - span m_span; - int m_dx; - }; - - friend class const_iterator; - - - //----------------------------------------------------------------- - embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} - - //----------------------------------------------------------------- - void reset(int, int) {} - unsigned num_spans() const { return m_num_spans; } - int y() const { return m_y; } - const_iterator begin() const { return const_iterator(*this); } - - - private: - //----------------------------------------------------------------- - int read_int32() - { - int32 val; - ((int8u*)&val)[0] = *m_ptr++; - ((int8u*)&val)[1] = *m_ptr++; - ((int8u*)&val)[2] = *m_ptr++; - ((int8u*)&val)[3] = *m_ptr++; - return val; - } - - public: - //----------------------------------------------------------------- - void init(const int8u* ptr, int dx, int dy) - { - m_ptr = ptr; - m_y = read_int32() + dy; - m_num_spans = unsigned(read_int32()); - m_dx = dx; - } - - private: - const int8u* m_ptr; - int m_y; - unsigned m_num_spans; - int m_dx; - }; - - - - public: - //-------------------------------------------------------------------- - serialized_scanlines_adaptor_subpix() : - m_data(0), - m_end(0), - m_ptr(0), - m_dx(0), - m_dy(0), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) - {} - - //-------------------------------------------------------------------- - serialized_scanlines_adaptor_subpix(const int8u* data, unsigned size, - double dx, double dy) : - m_data(data), - m_end(data + size), - m_ptr(data), - m_dx(iround(dx)), - m_dy(iround(dy)), - m_min_x(0x7FFFFFFF), - m_min_y(0x7FFFFFFF), - m_max_x(-0x7FFFFFFF), - m_max_y(-0x7FFFFFFF) - {} - - //-------------------------------------------------------------------- - void init(const int8u* data, unsigned size, double dx, double dy) - { - m_data = data; - m_end = data + size; - m_ptr = data; - m_dx = iround(dx); - m_dy = iround(dy); - m_min_x = 0x7FFFFFFF; - m_min_y = 0x7FFFFFFF; - m_max_x = -0x7FFFFFFF; - m_max_y = -0x7FFFFFFF; - } - - private: - //-------------------------------------------------------------------- - int read_int32() - { - int32 val; - ((int8u*)&val)[0] = *m_ptr++; - ((int8u*)&val)[1] = *m_ptr++; - ((int8u*)&val)[2] = *m_ptr++; - ((int8u*)&val)[3] = *m_ptr++; - return val; - } - - //-------------------------------------------------------------------- - unsigned read_int32u() - { - int32u val; - ((int8u*)&val)[0] = *m_ptr++; - ((int8u*)&val)[1] = *m_ptr++; - ((int8u*)&val)[2] = *m_ptr++; - ((int8u*)&val)[3] = *m_ptr++; - return val; - } - - public: - // Iterate scanlines interface - //-------------------------------------------------------------------- - bool rewind_scanlines() - { - m_ptr = m_data; - if(m_ptr < m_end) - { - m_min_x = read_int32() + m_dx; - m_min_y = read_int32() + m_dy; - m_max_x = read_int32() + m_dx; - m_max_y = read_int32() + m_dy; - } - return m_ptr < m_end; - } - - //-------------------------------------------------------------------- - int min_x() const { return m_min_x; } - int min_y() const { return m_min_y; } - int max_x() const { return m_max_x; } - int max_y() const { return m_max_y; } - - //-------------------------------------------------------------------- - template bool sweep_scanline(Scanline& sl) - { - sl.reset_spans(); - for(;;) - { - if(m_ptr >= m_end) return false; - - read_int32(); // Skip scanline size in bytes - int y = read_int32() + m_dy; - unsigned num_spans = read_int32(); - - do - { - int x = read_int32() + m_dx; - int len = read_int32(); - - if(len < 0) - { - sl.add_span(x, unsigned(-len), *m_ptr); - m_ptr += sizeof(T); - } - else - { - sl.add_cells(x, len, m_ptr); - m_ptr += len * sizeof(T); - } - } - while(--num_spans); - - if(sl.num_spans()) - { - sl.finalize(y); - break; - } - } - return true; - } - - - //-------------------------------------------------------------------- - // Specialization for embedded_scanline - bool sweep_scanline(embedded_scanline& sl) - { - do - { - if(m_ptr >= m_end) return false; - - unsigned byte_size = read_int32u(); - sl.init(m_ptr, m_dx, m_dy); - m_ptr += byte_size - sizeof(int32); - } - while(sl.num_spans() == 0); - return true; - } - - private: - const int8u* m_data; - const int8u* m_end; - const int8u* m_ptr; - int m_dx; - int m_dy; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - }; - - - - typedef serialized_scanlines_adaptor_subpix - serialized_scanlines_adaptor_subpix8; //serialized_scanlines_adaptor_subpix8 - - typedef serialized_scanlines_adaptor_subpix - serialized_scanlines_adaptor_subpix16; //serialized_scanlines_adaptor_subpix16 - - typedef serialized_scanlines_adaptor_subpix - serialized_scanlines_adaptor_subpix32; //serialized_scanlines_adaptor_subpix32 + //--------------------------------------------scanline_storage_subpix + template class scanline_storage_subpix + { + public: + typedef T cover_type; + + //--------------------------------------------------------------- + struct span_data + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + int covers_id; // The index of the cells in the scanline_cell_storage + }; + + //--------------------------------------------------------------- + struct scanline_data + { + int y; + unsigned num_spans; + unsigned start_span; + }; + + + //--------------------------------------------------------------- + class embedded_scanline + { + public: + + //----------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, covers is valid + const T* covers; + }; + + const_iterator() : m_storage(0) {} + const_iterator(const embedded_scanline& sl) : + m_storage(sl.m_storage), + m_span_idx(sl.m_scanline.start_span) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + ++m_span_idx; + init_span(); + } + + private: + void init_span() + { + const span_data& s = m_storage->span_by_index(m_span_idx); + m_span.x = s.x; + m_span.len = s.len; + m_span.covers = m_storage->covers_by_index(s.covers_id); + } + + const scanline_storage_subpix* m_storage; + unsigned m_span_idx; + span m_span; + }; + + friend class const_iterator; + + + //----------------------------------------------------------- + embedded_scanline(const scanline_storage_subpix& storage) : + m_storage(&storage) + { + init(0); + } + + //----------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_scanline.num_spans; } + int y() const { return m_scanline.y; } + const_iterator begin() const { return const_iterator(*this); } + + //----------------------------------------------------------- + void init(unsigned scanline_idx) + { + m_scanline_idx = scanline_idx; + m_scanline = m_storage->scanline_by_index(m_scanline_idx); + } + + private: + const scanline_storage_subpix* m_storage; + scanline_data m_scanline; + unsigned m_scanline_idx; + }; + + + //--------------------------------------------------------------- + scanline_storage_subpix() : + m_covers(), + m_spans(256-2), // Block increment size + m_scanlines(), + m_min_x( 0x7FFFFFFF), + m_min_y( 0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF), + m_cur_scanline(0) + { + m_fake_scanline.y = 0; + m_fake_scanline.num_spans = 0; + m_fake_scanline.start_span = 0; + m_fake_span.x = 0; + m_fake_span.len = 0; + m_fake_span.covers_id = 0; + } + + // Renderer Interface + //--------------------------------------------------------------- + void prepare() + { + m_covers.remove_all(); + m_scanlines.remove_all(); + m_spans.remove_all(); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + m_cur_scanline = 0; + } + + //--------------------------------------------------------------- + template void render(const Scanline& sl) + { + scanline_data sl_this; + + int y = sl.y(); + if(y < m_min_y) m_min_y = y; + if(y > m_max_y) m_max_y = y; + + sl_this.y = y; + sl_this.num_spans = sl.num_spans(); + sl_this.start_span = m_spans.size(); + typename Scanline::const_iterator span_iterator = sl.begin(); + + unsigned num_spans = sl_this.num_spans; + for(;;) + { + span_data sp; + + sp.x = span_iterator->x; + sp.len = span_iterator->len; + int len = abs(int(sp.len)); + sp.covers_id = + m_covers.add_cells(span_iterator->covers, + (unsigned(len))); + m_spans.add(sp); + int x1 = sp.x; + int x2 = sp.x + len/3 - 1; + if(x1 < m_min_x) m_min_x = x1; + if(x2 > m_max_x) m_max_x = x2; + if(--num_spans == 0) break; + ++span_iterator; + } + m_scanlines.add(sl_this); + } + + + //--------------------------------------------------------------- + // Iterate scanlines interface + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //--------------------------------------------------------------- + bool rewind_scanlines() + { + m_cur_scanline = 0; + return m_scanlines.size() > 0; + } + + + //--------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_cur_scanline >= m_scanlines.size()) return false; + const scanline_data& sl_this = m_scanlines[m_cur_scanline]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + if(sp.len < 0) + { + sl.add_span(sp.x, unsigned(-sp.len), *covers); + } + else + { + sl.add_cells(sp.x, sp.len, covers); + } + } + while(--num_spans); + ++m_cur_scanline; + if(sl.num_spans()) + { + sl.finalize(sl_this.y); + break; + } + } + return true; + } + + + //--------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_cur_scanline >= m_scanlines.size()) return false; + sl.init(m_cur_scanline); + ++m_cur_scanline; + } + while(sl.num_spans() == 0); + return true; + } + + //--------------------------------------------------------------- + unsigned byte_size() const + { + unsigned i; + unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y + + for(i = 0; i < m_scanlines.size(); ++i) + { + size += sizeof(int32) * 3; // scanline size in bytes + + const scanline_data& sl_this = m_scanlines[i]; + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + + size += sizeof(int32) * 2; // X, span_len + if(sp.len < 0) + { + size += sizeof(T); // cover + } + else + { + size += sizeof(T) * unsigned(sp.len); // covers + } + } + while(--num_spans); + } + return size; + } + + + //--------------------------------------------------------------- + static void write_int32(int8u* dst, int32 val) + { + dst[0] = ((const int8u*)&val)[0]; + dst[1] = ((const int8u*)&val)[1]; + dst[2] = ((const int8u*)&val)[2]; + dst[3] = ((const int8u*)&val)[3]; + } + + + //--------------------------------------------------------------- + void serialize(int8u* data) const + { + unsigned i; + + write_int32(data, min_x()); // min_x + data += sizeof(int32); + write_int32(data, min_y()); // min_y + data += sizeof(int32); + write_int32(data, max_x()); // max_x + data += sizeof(int32); + write_int32(data, max_y()); // max_y + data += sizeof(int32); + + for(i = 0; i < m_scanlines.size(); ++i) + { + const scanline_data& sl_this = m_scanlines[i]; + + int8u* size_ptr = data; + data += sizeof(int32); // Reserve space for scanline size in bytes + + write_int32(data, sl_this.y); // Y + data += sizeof(int32); + + write_int32(data, sl_this.num_spans); // num_spans + data += sizeof(int32); + + unsigned num_spans = sl_this.num_spans; + unsigned span_idx = sl_this.start_span; + do + { + const span_data& sp = m_spans[span_idx++]; + const T* covers = covers_by_index(sp.covers_id); + + write_int32(data, sp.x); // X + data += sizeof(int32); + + write_int32(data, sp.len); // span_len + data += sizeof(int32); + + if(sp.len < 0) + { + memcpy(data, covers, sizeof(T)); + data += sizeof(T); + } + else + { + memcpy(data, covers, unsigned(sp.len) * sizeof(T)); + data += sizeof(T) * unsigned(sp.len); + } + } + while(--num_spans); + write_int32(size_ptr, int32(unsigned(data - size_ptr))); + } + } + + + //--------------------------------------------------------------- + const scanline_data& scanline_by_index(unsigned i) const + { + return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; + } + + //--------------------------------------------------------------- + const span_data& span_by_index(unsigned i) const + { + return (i < m_spans.size()) ? m_spans[i] : m_fake_span; + } + + //--------------------------------------------------------------- + const T* covers_by_index(int i) const + { + return m_covers[i]; + } + + private: + scanline_cell_storage m_covers; + pod_bvector m_spans; + pod_bvector m_scanlines; + span_data m_fake_span; + scanline_data m_fake_scanline; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + unsigned m_cur_scanline; + }; + + + typedef scanline_storage_subpix scanline_storage_subpix8; //--------scanline_storage_subpix8 + typedef scanline_storage_subpix scanline_storage_subpix16; //--------scanline_storage_subpix16 + typedef scanline_storage_subpix scanline_storage_subpix32; //--------scanline_storage_subpix32 + + + //--------------------------------------serialized_scanlines_adaptor_subpix + template class serialized_scanlines_adaptor_subpix + { + public: + typedef T cover_type; + + //--------------------------------------------------------------------- + class embedded_scanline + { + public: + typedef T cover_type; + + //----------------------------------------------------------------- + class const_iterator + { + public: + struct span + { + int32 x; + int32 len; // If negative, it's a solid span, "covers" is valid + const T* covers; + }; + + const_iterator() : m_ptr(0) {} + const_iterator(const embedded_scanline& sl) : + m_ptr(sl.m_ptr), + m_dx(sl.m_dx) + { + init_span(); + } + + const span& operator*() const { return m_span; } + const span* operator->() const { return &m_span; } + + void operator ++ () + { + if(m_span.len < 0) + { + m_ptr += sizeof(T); + } + else + { + m_ptr += m_span.len * sizeof(T); + } + init_span(); + } + + private: + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + void init_span() + { + m_span.x = read_int32() + m_dx; + m_span.len = read_int32(); + m_span.covers = m_ptr; + } + + const int8u* m_ptr; + span m_span; + int m_dx; + }; + + friend class const_iterator; + + + //----------------------------------------------------------------- + embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} + + //----------------------------------------------------------------- + void reset(int, int) {} + unsigned num_spans() const { return m_num_spans; } + int y() const { return m_y; } + const_iterator begin() const { return const_iterator(*this); } + + + private: + //----------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + //----------------------------------------------------------------- + void init(const int8u* ptr, int dx, int dy) + { + m_ptr = ptr; + m_y = read_int32() + dy; + m_num_spans = unsigned(read_int32()); + m_dx = dx; + } + + private: + const int8u* m_ptr; + int m_y; + unsigned m_num_spans; + int m_dx; + }; + + + + public: + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_subpix() : + m_data(0), + m_end(0), + m_ptr(0), + m_dx(0), + m_dy(0), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + serialized_scanlines_adaptor_subpix(const int8u* data, unsigned size, + double dx, double dy) : + m_data(data), + m_end(data + size), + m_ptr(data), + m_dx(iround(dx)), + m_dy(iround(dy)), + m_min_x(0x7FFFFFFF), + m_min_y(0x7FFFFFFF), + m_max_x(-0x7FFFFFFF), + m_max_y(-0x7FFFFFFF) + {} + + //-------------------------------------------------------------------- + void init(const int8u* data, unsigned size, double dx, double dy) + { + m_data = data; + m_end = data + size; + m_ptr = data; + m_dx = iround(dx); + m_dy = iround(dy); + m_min_x = 0x7FFFFFFF; + m_min_y = 0x7FFFFFFF; + m_max_x = -0x7FFFFFFF; + m_max_y = -0x7FFFFFFF; + } + + private: + //-------------------------------------------------------------------- + int read_int32() + { + int32 val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + //-------------------------------------------------------------------- + unsigned read_int32u() + { + int32u val; + ((int8u*)&val)[0] = *m_ptr++; + ((int8u*)&val)[1] = *m_ptr++; + ((int8u*)&val)[2] = *m_ptr++; + ((int8u*)&val)[3] = *m_ptr++; + return val; + } + + public: + // Iterate scanlines interface + //-------------------------------------------------------------------- + bool rewind_scanlines() + { + m_ptr = m_data; + if(m_ptr < m_end) + { + m_min_x = read_int32() + m_dx; + m_min_y = read_int32() + m_dy; + m_max_x = read_int32() + m_dx; + m_max_y = read_int32() + m_dy; + } + return m_ptr < m_end; + } + + //-------------------------------------------------------------------- + int min_x() const { return m_min_x; } + int min_y() const { return m_min_y; } + int max_x() const { return m_max_x; } + int max_y() const { return m_max_y; } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + sl.reset_spans(); + for(;;) + { + if(m_ptr >= m_end) return false; + + read_int32(); // Skip scanline size in bytes + int y = read_int32() + m_dy; + unsigned num_spans = read_int32(); + + do + { + int x = read_int32() + m_dx; + int len = read_int32(); + + if(len < 0) + { + sl.add_span(x, unsigned(-len), *m_ptr); + m_ptr += sizeof(T); + } + else + { + sl.add_cells(x, len, m_ptr); + m_ptr += len * sizeof(T); + } + } + while(--num_spans); + + if(sl.num_spans()) + { + sl.finalize(y); + break; + } + } + return true; + } + + + //-------------------------------------------------------------------- + // Specialization for embedded_scanline + bool sweep_scanline(embedded_scanline& sl) + { + do + { + if(m_ptr >= m_end) return false; + + unsigned byte_size = read_int32u(); + sl.init(m_ptr, m_dx, m_dy); + m_ptr += byte_size - sizeof(int32); + } + while(sl.num_spans() == 0); + return true; + } + + private: + const int8u* m_data; + const int8u* m_end; + const int8u* m_ptr; + int m_dx; + int m_dy; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + }; + + + + typedef serialized_scanlines_adaptor_subpix + serialized_scanlines_adaptor_subpix8; //serialized_scanlines_adaptor_subpix8 + + typedef serialized_scanlines_adaptor_subpix + serialized_scanlines_adaptor_subpix16; //serialized_scanlines_adaptor_subpix16 + + typedef serialized_scanlines_adaptor_subpix + serialized_scanlines_adaptor_subpix32; //serialized_scanlines_adaptor_subpix32 } diff --git a/src/servers/app/agg_scanline_u_subpix.h b/src/servers/app/agg_scanline_u_subpix.h index d0dbeaa64f..c901910862 100644 --- a/src/servers/app/agg_scanline_u_subpix.h +++ b/src/servers/app/agg_scanline_u_subpix.h @@ -17,99 +17,118 @@ namespace agg { - //======================================================scanline_u8_subpix - //------------------------------------------------------------------------ - class scanline_u8_subpix - { - public: - typedef scanline_u8_subpix self_type; - typedef int8u cover_type; - typedef int16 coord_type; + //======================================================scanline_u8_subpix + //------------------------------------------------------------------------ + class scanline_u8_subpix + { + public: + typedef scanline_u8_subpix self_type; + typedef int8u cover_type; + typedef int16 coord_type; - //-------------------------------------------------------------------- - struct span - { - coord_type x; - coord_type len; - cover_type* covers; - }; + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; + cover_type* covers; + }; - typedef span* iterator; - typedef const span* const_iterator; + typedef span* iterator; + typedef const span* const_iterator; - //-------------------------------------------------------------------- - scanline_u8_subpix() : - m_min_x(0), - m_last_x(0x7FFFFFF0), - m_cur_span(0) - {} + //-------------------------------------------------------------------- + scanline_u8_subpix() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} - //-------------------------------------------------------------------- - void reset(int min_x, int max_x) - { - unsigned max_len = 3*(max_x - min_x + 2); - if(max_len > m_spans.size()) - { - m_spans.resize(max_len); - m_covers.resize(max_len); - } - m_last_x = 0x7FFFFFF0; - m_min_x = min_x; - m_cur_span = &m_spans[0]; - } + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = 3*(max_x - min_x + 2); + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } - //-------------------------------------------------------------------- - void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3) - { - x -= m_min_x; - m_covers[3*x] = (cover_type)cover1; - m_covers[3*x+1] = (cover_type)cover2; - m_covers[3*x+2] = (cover_type)cover3; - if(x == m_last_x+1) - { - m_cur_span->len += 3; - } - else - { - m_cur_span++; - m_cur_span->x = (coord_type)(x + m_min_x); - m_cur_span->len = 3; - m_cur_span->covers = &m_covers[3*x]; - } - m_last_x = x; - } + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3) + { + x -= m_min_x; + m_covers[3 * x] = (cover_type)cover1; + m_covers[3 * x + 1] = (cover_type)cover2; + m_covers[3 * x + 2] = (cover_type)cover3; + if(x == m_last_x + 1) + { + m_cur_span->len += 3; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 3; + m_cur_span->covers = &m_covers[3 * x]; + } + m_last_x = x; + } - //-------------------------------------------------------------------- - void finalize(int y) - { - m_y = y; - } + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[3 * x], cover, 3 * len); + if(x == m_last_x+1) + { + m_cur_span->len += 3 * (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 3 * (coord_type)len; + m_cur_span->covers = &m_covers[3 * x]; + } + m_last_x = x + len - 1; + } - //-------------------------------------------------------------------- - void reset_spans() - { - m_last_x = 0x7FFFFFF0; - m_cur_span = &m_spans[0]; - } + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } - //-------------------------------------------------------------------- - int y() const { return m_y; } - unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } - const_iterator begin() const { return &m_spans[1]; } - iterator begin() { return &m_spans[1]; } + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } - private: - scanline_u8_subpix(const self_type&); - const self_type& operator = (const self_type&); + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + iterator begin() { return &m_spans[1]; } - private: - int m_min_x; - int m_last_x; - int m_y; - pod_array m_covers; - pod_array m_spans; - span* m_cur_span; - }; + private: + scanline_u8_subpix(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + pod_array m_spans; + span* m_cur_span; + }; } diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp index 85b1af7895..ce3224b13c 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.cpp +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.cpp @@ -25,6 +25,7 @@ # include #endif +#include "GlobalSubpixelSettings.h" #include "GlyphLayoutEngine.h" #include "IntRect.h" @@ -32,7 +33,9 @@ // constructor AGGTextRenderer::AGGTextRenderer(renderer_subpix_type& subpixRenderer, renderer_type& solidRenderer, renderer_bin_type& binRenderer, - scanline_unpacked_type& scanline) + scanline_unpacked_type& scanline, + scanline_unpacked_subpix_type& subpixScanline, + rasterizer_subpix_type& subpixRasterizer) : fPathAdaptor() , fGray8Adaptor() , fGray8Scanline() @@ -47,6 +50,8 @@ AGGTextRenderer::AGGTextRenderer(renderer_subpix_type& subpixRenderer, , fBinRenderer(binRenderer) , fSubpixRenderer(subpixRenderer) , fScanline(scanline) + , fSubpixScanline(subpixScanline) + , fSubpixRasterizer(subpixRasterizer) , fRasterizer() , fHinted(true) @@ -100,6 +105,7 @@ AGGTextRenderer::SetAntialiasing(bool antialiasing) } } + typedef agg::conv_transform conv_font_trans_type; @@ -136,12 +142,18 @@ class AGGTextRenderer::StringRenderer { void Start() { fRenderer.fRasterizer.reset(); + fRenderer.fSubpixRasterizer.reset(); } void Finish(double x, double y) { if (fVector) { - agg::render_scanlines(fRenderer.fRasterizer, fRenderer.fScanline, - fRenderer.fSolidRenderer); + if (gSubpixelAntialiasing) { + agg::render_scanlines(fRenderer.fSubpixRasterizer, + fRenderer.fSubpixScanline, fRenderer.fSubpixRenderer); + } else { + agg::render_scanlines(fRenderer.fRasterizer, + fRenderer.fScanline, fRenderer.fSolidRenderer); + } } if (fNextCharPos) { @@ -231,10 +243,22 @@ class AGGTextRenderer::StringRenderer { case glyph_data_outline: { fVector = true; - if (fRenderer.fContour.width() == 0.0) { - fRenderer.fRasterizer.add_path(fTransformedGlyph); + if (gSubpixelAntialiasing) { + if (fRenderer.fContour.width() == 0.0) { + fRenderer.fSubpixRasterizer.add_path( + fTransformedGlyph); + } else { + fRenderer.fSubpixRasterizer.add_path( + fTransformedContour); + } } else { - fRenderer.fRasterizer.add_path(fTransformedContour); + if (fRenderer.fContour.width() == 0.0) { + fRenderer.fRasterizer.add_path( + fTransformedGlyph); + } else { + fRenderer.fRasterizer.add_path( + fTransformedContour); + } } #if SHOW_GLYPH_BOUNDS agg::path_storage p; @@ -245,7 +269,11 @@ class AGGTextRenderer::StringRenderer { p.close_polygon(); agg::conv_stroke ps(p); ps.width(1.0); - fRenderer.fRasterizer.add_path(ps); + if (gSubpixelAntialiasing) { + fRenderer.fSubpixRasterizer.add_path(ps); + } else { + fRenderer.fRasterizer.add_path(ps); + } #endif break; diff --git a/src/servers/app/drawing/Painter/AGGTextRenderer.h b/src/servers/app/drawing/Painter/AGGTextRenderer.h index cbb49b1354..04246c4389 100644 --- a/src/servers/app/drawing/Painter/AGGTextRenderer.h +++ b/src/servers/app/drawing/Painter/AGGTextRenderer.h @@ -25,7 +25,9 @@ class AGGTextRenderer { AGGTextRenderer(renderer_subpix_type& subpixRenderer, renderer_type& solidRenderer, renderer_bin_type& binRenderer, - scanline_unpacked_type& scanline); + scanline_unpacked_type& scanline, + scanline_unpacked_subpix_type& subpixScanline, + rasterizer_subpix_type& subpixRasterizer); virtual ~AGGTextRenderer(); void SetFont(const ServerFont &font); @@ -73,6 +75,8 @@ class AGGTextRenderer { renderer_bin_type& fBinRenderer; renderer_subpix_type& fSubpixRenderer; scanline_unpacked_type& fScanline; + scanline_unpacked_subpix_type& fSubpixScanline; + rasterizer_subpix_type& fSubpixRasterizer; rasterizer_type fRasterizer; // NOTE: the object has it's own rasterizer object // since it might be using a different gamma setting diff --git a/src/servers/app/drawing/Painter/GlobalSubpixelSettings.cpp b/src/servers/app/drawing/Painter/GlobalSubpixelSettings.cpp new file mode 100644 index 0000000000..7d7ed75d52 --- /dev/null +++ b/src/servers/app/drawing/Painter/GlobalSubpixelSettings.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2008, Andrej Spielmann . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +//! Global settings of the app server regarding antialiasing and font hinting + +#include "GlobalSubpixelSettings.h" + +// NOTE: all these are initialized in DesktopSettings.cpp +bool gSubpixelAntialiasing; +bool gDefaultHinting; +unsigned char gSubpixelAverageWeight; +bool gSubpixelOrderingRGB; diff --git a/src/servers/app/drawing/Painter/GlobalSubpixelSettings.h b/src/servers/app/drawing/Painter/GlobalSubpixelSettings.h new file mode 100644 index 0000000000..7a76e8780e --- /dev/null +++ b/src/servers/app/drawing/Painter/GlobalSubpixelSettings.h @@ -0,0 +1,29 @@ +/* + * Copyright 2008, Andrej Spielmann . + * All rights reserved. Distributed under the terms of the MIT License. + * + * Global settings of the app server regarding antialiasing and font hinting + * + */ + +#ifndef GLOBAL_SUBPIXEL_SETTINGS_H +#define GLOBAL_SUBPIXEL_SETTINGS_H + +#define AVERAGE_BASED_SUBPIXEL_FILTERING + +extern bool gSubpixelAntialiasing; +extern bool gDefaultHinting; + +// The weight with which the average of the subpixels is applied to counter +// color fringes (0 = full sharpness ... 255 = grayscale anti-aliasing) +extern unsigned char gSubpixelAverageWeight; + +// There are two types of LCD displays in general - the more common have +// sub - pixels physically ordered as RGB within a pixel, but some are BGR. +// Sub - pixel antialiasing optimised for one ordering obviously doesn't work +// on the other. +extern bool gSubpixelOrderingRGB; + +#endif // GLOBAL_SUBPIXEL_SETTINGS_H + + diff --git a/src/servers/app/drawing/Painter/Jamfile b/src/servers/app/drawing/Painter/Jamfile index 330d90b10f..f957b5b6d6 100644 --- a/src/servers/app/drawing/Painter/Jamfile +++ b/src/servers/app/drawing/Painter/Jamfile @@ -13,6 +13,7 @@ UseFreeTypeHeaders ; SEARCH_SOURCE += [ FDirName $(SUBDIR) drawing_modes ] ; StaticLibrary libpainter.a : + GlobalSubpixelSettings.cpp Painter.cpp Transformable.cpp diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index 05e2334a0d..e7a4355a37 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -40,6 +40,7 @@ #include #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" #include "PatternHandler.h" #include "RenderingBuffer.h" #include "ServerBitmap.h" @@ -61,7 +62,6 @@ using std::nothrow; #define CHECK_CLIPPING if (!fValidClipping) return BRect(0, 0, -1, -1); #define CHECK_CLIPPING_NO_RETURN if (!fValidClipping) return; - // constructor Painter::Painter() : fBuffer(), @@ -69,6 +69,9 @@ Painter::Painter() fBaseRenderer(fPixelFormat), fUnpackedScanline(), fPackedScanline(), + fSubpixPackedScanline(), + fSubpixUnpackedScanline(), + fSubpixRasterizer(), fRasterizer(), fSubpixRenderer(fBaseRenderer), fRenderer(fBaseRenderer), @@ -90,15 +93,16 @@ Painter::Painter() fLineCapMode(B_BUTT_CAP), fLineJoinMode(B_MITER_JOIN), fMiterLimit(B_DEFAULT_MITER_LIMIT), - fSubpixelAntialias(true), fPatternHandler(), - fTextRenderer(fSubpixRenderer, fRenderer, fRendererBin, fUnpackedScanline) + fTextRenderer(fSubpixRenderer, fRenderer, fRendererBin, fUnpackedScanline, + fSubpixUnpackedScanline, fSubpixRasterizer) { fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false); #if ALIASED_DRAWING fRasterizer.gamma(agg::gamma_threshold(0.5)); + fSubpixRasterizer.gamma(agg:gamma_threshold(0.5)); #endif } @@ -211,6 +215,7 @@ Painter::ConstrainClipping(const BRegion* region) if (fValidClipping) { clipping_rect cb = fClippingRegion->FrameInt(); fRasterizer.clip_box(cb.left, cb.top, cb.right + 1, cb.bottom + 1); + fSubpixRasterizer.clip_box(cb.left, cb.top, cb.right + 1, cb.bottom + 1); } } @@ -244,13 +249,6 @@ Painter::SetDrawingMode(drawing_mode mode) } } -void -Painter::SetSubpixelAntialiasing(bool subpixelAntialias) -{ - if (fSubpixelAntialias != subpixelAntialias) { - fSubpixelAntialias = subpixelAntialias; - } -} // SetBlendingMode void @@ -826,30 +824,61 @@ Painter::StrokeRoundRect(const BRect& r, float xRadius, float yRadius) const outer.rect(lt.x, lt.y, rb.x, rb.y); outer.radius(xRadius, yRadius); - fRasterizer.reset(); - fRasterizer.add_path(outer); + if (gSubpixelAntialiasing) { + fSubpixRasterizer.reset(); + fSubpixRasterizer.add_path(outer); + + // don't add an inner hole if the "size is negative", this avoids some + // defects that can be observed on R5 and could be regarded as a bug. + if (2 * fPenSize < rb.x - lt.x && 2 * fPenSize < rb.y - lt.y) { + 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)); - // don't add an inner hole if the "size is negative", this avoids some - // defects that can be observed on R5 and could be regarded as a bug. - if (2 * fPenSize < rb.x - lt.x && 2 * fPenSize < rb.y - lt.y) { - 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)); + fSubpixRasterizer.add_path(inner); + } - fRasterizer.add_path(inner); + // make the inner rect work as a hole + fSubpixRasterizer.filling_rule(agg::fill_even_odd); + + if (fPenSize > 2) + agg::render_scanlines(fSubpixRasterizer, fSubpixPackedScanline, + fSubpixRenderer); + else + agg::render_scanlines(fSubpixRasterizer, fSubpixUnpackedScanline, + fSubpixRenderer); + + fSubpixRasterizer.filling_rule(agg::fill_non_zero); + } else { + fRasterizer.reset(); + fRasterizer.add_path(outer); + + // don't add an inner hole if the "size is negative", this avoids some + // defects that can be observed on R5 and could be regarded as a bug. + if (2 * fPenSize < rb.x - lt.x && 2 * fPenSize < rb.y - lt.y) { + 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); + + if (fPenSize > 2) + agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); + else + agg::render_scanlines(fRasterizer, fUnpackedScanline, fRenderer); + + // reset to default + fRasterizer.filling_rule(agg::fill_non_zero); } - // make the inner rect work as a hole - fRasterizer.filling_rule(agg::fill_even_odd); - - if (fPenSize > 2) - 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)); } } @@ -932,20 +961,39 @@ Painter::DrawEllipse(BRect r, bool fill) const yRadius + inset, divisions); - fRasterizer.reset(); - fRasterizer.add_path(outer); - fRasterizer.add_path(inner); + if (gSubpixelAntialiasing) { + fSubpixRasterizer.reset(); + fSubpixRasterizer.add_path(outer); + fSubpixRasterizer.add_path(inner); - // make the inner ellipse work as a hole - fRasterizer.filling_rule(agg::fill_even_odd); + // make the inner ellipse work as a hole + fSubpixRasterizer.filling_rule(agg::fill_even_odd); - if (fPenSize > 4) - agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); - else - agg::render_scanlines(fRasterizer, fUnpackedScanline, fRenderer); + if (fPenSize > 4) + agg::render_scanlines(fSubpixRasterizer, fSubpixPackedScanline, + fSubpixRenderer); + else + agg::render_scanlines(fSubpixRasterizer, fSubpixUnpackedScanline, + fSubpixRenderer); - // reset to default - fRasterizer.filling_rule(agg::fill_non_zero); + // reset to default + fSubpixRasterizer.filling_rule(agg::fill_non_zero); + } else { + fRasterizer.reset(); + fRasterizer.add_path(outer); + fRasterizer.add_path(inner); + + // make the inner ellipse work as a hole + fRasterizer.filling_rule(agg::fill_even_odd); + + if (fPenSize > 4) + 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)); } @@ -1131,6 +1179,7 @@ Painter::InvertRect(const BRect& r) const return _Clipped(r); } + // #pragma mark - private // _Transform @@ -1968,10 +2017,20 @@ Painter::_StrokePath(VertexSource& path) const stroke.line_join(agg_line_join_mode_for(fLineJoinMode)); stroke.miter_limit(fMiterLimit); - fRasterizer.reset(); - fRasterizer.add_path(stroke); + if (gSubpixelAntialiasing) { + + fSubpixRasterizer.reset(); + fSubpixRasterizer.add_path(stroke); + + agg::render_scanlines(fSubpixRasterizer, + fSubpixPackedScanline, fSubpixRenderer); + } else { - agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); + fRasterizer.reset(); + fRasterizer.add_path(stroke); + + agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); + } BRect touched = _BoundingBox(path); float penSize = ceilf(fPenSize / 2.0); @@ -1985,9 +2044,17 @@ template BRect Painter::_FillPath(VertexSource& path) const { - fRasterizer.reset(); - fRasterizer.add_path(path); - agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); + if (gSubpixelAntialiasing) { + + fSubpixRasterizer.reset(); + fSubpixRasterizer.add_path(path); + agg::render_scanlines(fSubpixRasterizer, + fSubpixPackedScanline, fSubpixRenderer); + } else { + fRasterizer.reset(); + fRasterizer.add_path(path); + agg::render_scanlines(fRasterizer, fPackedScanline, fRenderer); + } return _Clipped(_BoundingBox(path)); } diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 00a39dbc9e..427b430b0a 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -7,6 +7,7 @@ * rendering pipe-lines for stroke, fills, bitmap and text rendering. * */ + #ifndef PAINTER_H #define PAINTER_H @@ -23,7 +24,6 @@ #include #include - class BBitmap; class BRegion; class DrawState; @@ -73,9 +73,6 @@ 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); @@ -272,6 +269,9 @@ mutable renderer_base fBaseRenderer; mutable scanline_unpacked_type fUnpackedScanline; mutable scanline_packed_type fPackedScanline; +mutable scanline_packed_subpix_type fSubpixPackedScanline; +mutable scanline_unpacked_subpix_type fSubpixUnpackedScanline; +mutable rasterizer_subpix_type fSubpixRasterizer; mutable rasterizer_type fRasterizer; mutable renderer_subpix_type fSubpixRenderer; mutable renderer_type fRenderer; @@ -294,7 +294,6 @@ 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/agg_rasterizer_scanline_aa_subpix.h b/src/servers/app/drawing/Painter/agg_rasterizer_scanline_aa_subpix.h new file mode 100644 index 0000000000..806f8c964e --- /dev/null +++ b/src/servers/app/drawing/Painter/agg_rasterizer_scanline_aa_subpix.h @@ -0,0 +1,547 @@ +/* + * Copyright 2008, Andrej Spielmann . + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + */ + +#ifndef AGG_RASTERIZER_SCANLINE_AA_SUBPIX_INCLUDED +#define AGG_RASTERIZER_SCANLINE_AA_SUBPIX_INCLUDED + +#include "agg_rasterizer_cells_aa.h" +#include "agg_rasterizer_sl_clip.h" +#include "agg_gamma_functions.h" + + +namespace agg +{ + template class rasterizer_scanline_aa_subpix + { + enum status + { + status_initial, + status_move_to, + status_line_to, + status_closed + }; + + public: + typedef Clip clip_type; + typedef typename Clip::conv_type conv_type; + typedef typename Clip::coord_type coord_type; + + enum aa_scale_e + { + aa_shift = 8, + aa_scale = 1 << aa_shift, + aa_mask = aa_scale - 1, + aa_scale2 = aa_scale * 2, + aa_mask2 = aa_scale2 - 1 + }; + + //-------------------------------------------------------------------- + rasterizer_scanline_aa_subpix() : + m_outline(), + m_clipper(), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + int i; + for(i = 0; i < aa_scale; i++) m_gamma[i] = i; + } + + //-------------------------------------------------------------------- + template + rasterizer_scanline_aa_subpix(const GammaF& gamma_function) : + m_outline(), + m_clipper(m_outline), + m_filling_rule(fill_non_zero), + m_auto_close(true), + m_start_x(0), + m_start_y(0), + m_status(status_initial) + { + gamma(gamma_function); + } + + //-------------------------------------------------------------------- + void reset(); + void reset_clipping(); + void clip_box(double x1, double y1, double x2, double y2); + void filling_rule(filling_rule_e filling_rule); + void auto_close(bool flag) { m_auto_close = flag; } + + //-------------------------------------------------------------------- + template void gamma(const GammaF& gamma_function) + { + int i; + for(i = 0; i < aa_scale; i++) + { + m_gamma[i] = uround(gamma_function(double(i) / aa_mask) * aa_mask); + } + } + + //-------------------------------------------------------------------- + unsigned apply_gamma(unsigned cover) const + { + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + void move_to(int x, int y); + void line_to(int x, int y); + void move_to_d(double x, double y); + void line_to_d(double x, double y); + void close_polygon(); + void add_vertex(double x, double y, unsigned cmd); + + void edge(int x1, int y1, int x2, int y2); + void edge_d(double x1, double y1, double x2, double y2); + + //------------------------------------------------------------------- + template + void add_path(VertexSource& vs, unsigned path_id=0) + { + double x; + double y; + + unsigned cmd; + vs.rewind(path_id); + if(m_outline.sorted()) reset(); + while(!is_stop(cmd = vs.vertex(&x, &y))) + { + if (is_vertex(cmd)) { + x *= 3; + } + add_vertex(x, y, cmd); + } + } + + //-------------------------------------------------------------------- + int min_x() const { return m_outline.min_x() / 3; } + int min_y() const { return m_outline.min_y(); } + int max_x() const { return m_outline.max_x() / 3; } + int max_y() const { return m_outline.max_y(); } + + //-------------------------------------------------------------------- + void sort(); + bool rewind_scanlines(); + bool navigate_scanline(int y); + + //-------------------------------------------------------------------- + AGG_INLINE unsigned calculate_alpha(int area) const + { + int cover = area >> (poly_subpixel_shift*2 + 1 - aa_shift); + + if(cover < 0) cover = -cover; + if(m_filling_rule == fill_even_odd) + { + cover &= aa_mask2; + if(cover > aa_scale) + { + cover = aa_scale2 - cover; + } + } + if(cover > aa_mask) cover = aa_mask; + return m_gamma[cover]; + } + + //-------------------------------------------------------------------- + template bool sweep_scanline(Scanline& sl) + { + for(;;) + { + if(m_scan_y > m_outline.max_y()) return false; + sl.reset_spans(); + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + const cell_aa* const* cells = m_outline.scanline_cells(m_scan_y); + int cover = 0; + int cover2 = 0; + int cover3 = 0; + + while(num_cells) + { + const cell_aa* cur_cell = *cells; + int x = cur_cell->x; + int area1 = cur_cell->area; + int area2; + int area3; + unsigned alpha1; + unsigned alpha2; + unsigned alpha3; + + int last_cover = cover3; + cover = cover3; + cover += cur_cell->cover; + + while(--num_cells) + { + cur_cell = *++cells; + if(cur_cell->x != x) break; + area1 += cur_cell->area; + cover += cur_cell->cover; + } + + if (x % 3 == 0) + { + if (cur_cell->x == x + 1) + { + area2 = cur_cell->area; + cover2 = cover + cur_cell->cover; + + while (--num_cells) + { + cur_cell = *++cells; + if (cur_cell->x != x+1) break; + area2 += cur_cell->area; + cover2 += cur_cell->cover; + } + } + else + { + area2 = 0; + cover2 = cover; + } + + if (cur_cell->x == x + 2) + { + area3 = cur_cell->area; + cover3 = cover2 + cur_cell->cover; + + while (--num_cells) + { + cur_cell = *++cells; + if (cur_cell->x != x+2) break; + area3 += cur_cell->area; + cover3 += cur_cell->cover; + } + } + else + { + area3 = 0; + cover3 = cover2; + } + } + else if (x % 3 == 1) + { + area2 = area1; + area1 = 0; + cover2 = cover; + cover = last_cover; + if (cur_cell->x == x+1) + { + area3 = cur_cell->area; + cover3 = cover2 + cur_cell->cover; + + while (--num_cells) + { + cur_cell = *++cells; + if (cur_cell->x != x+1) break; + area3 += cur_cell->area; + cover3 += cur_cell->cover; + } + } + else + { + area3 = 0; + cover3 = cover2; + } + } + else // if (x % 3 == 2) + { + area3 = area1; + area2 = 0; + area1 = 0; + cover3 = cover; + cover = last_cover; + cover2 = last_cover; + } + + alpha1 = area1 ? calculate_alpha((cover + << (poly_subpixel_shift + 1)) - area1) : 0; + alpha2 = area2 ? calculate_alpha((cover2 + << (poly_subpixel_shift + 1)) - area2) : 0; + alpha3 = area3 ? calculate_alpha((cover3 + << (poly_subpixel_shift + 1)) - area3) : 0; + if(alpha1 || alpha2 || alpha3) + { + x += 3 - (x % 3); + if (area1 && !area2 && area3) + { + alpha2 = calculate_alpha(cover + << (poly_subpixel_shift + 1)); + } + else if (num_cells && cur_cell->x >= x) + { + if (area1 && !area2) + { + alpha2 = calculate_alpha(cover + << (poly_subpixel_shift + 1)); + alpha3 = alpha2; + } + if (area2 && !area3) + { + alpha3 = calculate_alpha(cover2 + << (poly_subpixel_shift + 1)); + } + } + if (!area1) + { + if (area2) + { + alpha1 = calculate_alpha(cover + << (poly_subpixel_shift + 1)); + } + else if (area3) + { + alpha2 = calculate_alpha(cover + << (poly_subpixel_shift + 1)); + alpha1 = alpha2; + } + } + sl.add_cell(x / 3 - 1, alpha1, alpha2, alpha3); + } + + if (num_cells && cur_cell->x - x >= 3) + { + alpha1 = calculate_alpha(cover3 + << (poly_subpixel_shift + 1)); + sl.add_span(x / 3, cur_cell->x / 3 - x / 3, alpha1); + } + } + + if(sl.num_spans()) break; + ++m_scan_y; + } + + sl.finalize(m_scan_y); + ++m_scan_y; + return true; + } + + //-------------------------------------------------------------------- + bool hit_test(int tx, int ty); + + + private: + //-------------------------------------------------------------------- + // Disable copying + rasterizer_scanline_aa_subpix(const rasterizer_scanline_aa_subpix&); + const rasterizer_scanline_aa_subpix& + operator = (const rasterizer_scanline_aa_subpix&); + + private: + rasterizer_cells_aa m_outline; + clip_type m_clipper; + int m_gamma[aa_scale]; + filling_rule_e m_filling_rule; + bool m_auto_close; + coord_type m_start_x; + coord_type m_start_y; + unsigned m_status; + int m_scan_y; + }; + + + + + + + + + + + + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::reset() + { + m_outline.reset(); + m_status = status_initial; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::filling_rule(filling_rule_e filling_rule) + { + m_filling_rule = filling_rule; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::clip_box(double x1, double y1, + double x2, double y2) + { + reset(); + m_clipper.clip_box(3 * conv_type::downscale(x1), conv_type::upscale(y1), + conv_type::upscale(3 * x2), conv_type::upscale(y2)); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::reset_clipping() + { + reset(); + m_clipper.reset_clipping(); + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::close_polygon() + { + if(m_status == status_line_to) + { + m_clipper.line_to(m_outline, m_start_x, m_start_y); + m_status = status_closed; + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::move_to(int x, int y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::downscale(x), + m_start_y = conv_type::downscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::line_to(int x, int y) + { + m_clipper.line_to(m_outline, + conv_type::downscale(x), + conv_type::downscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::move_to_d(double x, double y) + { + if(m_outline.sorted()) reset(); + if(m_auto_close) close_polygon(); + m_clipper.move_to(m_start_x = conv_type::upscale(x), + m_start_y = conv_type::upscale(y)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::line_to_d(double x, double y) + { + m_clipper.line_to(m_outline, + conv_type::upscale(x), + conv_type::upscale(y)); + m_status = status_line_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::add_vertex(double x, double y, unsigned cmd) + { + if(is_move_to(cmd)) + { + move_to_d(x, y); + } + else + if(is_vertex(cmd)) + { + line_to_d(x, y); + } + else + if(is_close(cmd)) + { + close_polygon(); + } + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::edge(int x1, int y1, int x2, int y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::downscale(x1), conv_type::downscale(y1)); + m_clipper.line_to(m_outline, + conv_type::downscale(x2), + conv_type::downscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::edge_d(double x1, double y1, + double x2, double y2) + { + if(m_outline.sorted()) reset(); + m_clipper.move_to(conv_type::upscale(x1), conv_type::upscale(y1)); + m_clipper.line_to(m_outline, + conv_type::upscale(x2), + conv_type::upscale(y2)); + m_status = status_move_to; + } + + //------------------------------------------------------------------------ + template + void rasterizer_scanline_aa_subpix::sort() + { + m_outline.sort_cells(); + } + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa_subpix::rewind_scanlines() + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0) + { + return false; + } + m_scan_y = m_outline.min_y(); + return true; + } + + + //------------------------------------------------------------------------ + template + AGG_INLINE bool rasterizer_scanline_aa_subpix::navigate_scanline(int y) + { + if(m_auto_close) close_polygon(); + m_outline.sort_cells(); + if(m_outline.total_cells() == 0 || + y < m_outline.min_y() || + y > m_outline.max_y()) + { + return false; + } + m_scan_y = y; + return true; + } + + //------------------------------------------------------------------------ + template + bool rasterizer_scanline_aa_subpix::hit_test(int tx, int ty) + { + if(!navigate_scanline(ty)) return false; + scanline_hit_test sl(tx); + sweep_scanline(sl); + return sl.hit(); + } + + + +} + + + +#endif + diff --git a/src/servers/app/drawing/Painter/agg_renderer_region.h b/src/servers/app/drawing/Painter/agg_renderer_region.h index 7f85bb27de..e761129744 100644 --- a/src/servers/app/drawing/Painter/agg_renderer_region.h +++ b/src/servers/app/drawing/Painter/agg_renderer_region.h @@ -23,339 +23,327 @@ namespace agg { - //----------------------------------------------------------renderer_region - template class renderer_region - { - public: - typedef PixelFormat pixfmt_type; - typedef typename pixfmt_type::color_type color_type; - typedef renderer_base base_ren_type; - - //-------------------------------------------------------------------- - renderer_region(pixfmt_type& ren) : - m_ren(ren), - m_region(NULL), - m_curr_cb(0), - m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) - { - } - - //-------------------------------------------------------------------- - const pixfmt_type& ren() const { return m_ren.ren(); } - pixfmt_type& ren() { return m_ren.ren(); } - - //-------------------------------------------------------------------- - unsigned width() const { return m_ren.width(); } - unsigned height() const { return m_ren.height(); } - - //-------------------------------------------------------------------- - const rect_i& clip_box() const { return m_ren.clip_box(); } - int xmin() const { return m_ren.xmin(); } - int ymin() const { return m_ren.ymin(); } - int xmax() const { return m_ren.xmax(); } - int ymax() const { return m_ren.ymax(); } - - //-------------------------------------------------------------------- - const rect_i& bounding_clip_box() const { return m_bounds; } - int bounding_xmin() const { return m_bounds.x1; } - int bounding_ymin() const { return m_bounds.y1; } - int bounding_xmax() const { return m_bounds.x2; } - int bounding_ymax() const { return m_bounds.y2; } - - //-------------------------------------------------------------------- - void first_clip_box() - { - m_curr_cb = 0; - if(m_region && m_region->CountRects() > 0) - { - clipping_rect cb = m_region->RectAtInt(0); - m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom); - } - else - m_ren.clip_box_naked(0, 0, -1, -1); - } - - //-------------------------------------------------------------------- - bool next_clip_box() - { - if(m_region && (int)(++m_curr_cb) < m_region->CountRects()) - { - clipping_rect cb = m_region->RectAtInt(m_curr_cb); - m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom); - return true; - } - return false; - } - - //-------------------------------------------------------------------- - void reset_clipping(bool visibility) - { - m_ren.reset_clipping(visibility); - m_region = NULL; - m_curr_cb = 0; - m_bounds = m_ren.clip_box(); - } - - //-------------------------------------------------------------------- - void set_clipping_region(BRegion* region) - { - m_region = region; - if (m_region) { - clipping_rect r = m_region->FrameInt(); - if (r.left <= r.right && r.top <= r.bottom) { - // clip rect_i to frame buffer bounds - r.left = max_c(0, r.left); - r.top = max_c(0, r.top); - r.right = min_c((int)width() - 1, r.right); - r.bottom = min_c((int)height() - 1, r.bottom); - - if(r.left < m_bounds.x1) m_bounds.x1 = r.left; - if(r.top < m_bounds.y1) m_bounds.y1 = r.top; - if(r.right > m_bounds.x2) m_bounds.x2 = r.right; - if(r.bottom > m_bounds.y2) m_bounds.y2 = r.bottom; - } - } - } - - //-------------------------------------------------------------------- - void clear(const color_type& c) - { - m_ren.clear(c); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - first_clip_box(); - do - { - if(m_ren.inbox(x, y)) - { - m_ren.ren().copy_pixel(x, y, c); - break; - } - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, cover_type cover) - { - first_clip_box(); - do - { - if(m_ren.inbox(x, y)) - { - m_ren.ren().blend_pixel(x, y, c, cover); - break; - } - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) const - { - first_clip_box(); - do - { - if(m_ren.inbox(x, y)) - { - return m_ren.ren().pixel(x, y); - } - } - while(next_clip_box()); - return color_type::no_color(); - } - - //-------------------------------------------------------------------- - void copy_hline(int x1, int y, int x2, const color_type& c) - { - first_clip_box(); - do - { - m_ren.copy_hline(x1, y, x2, c); - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y1, int y2, const color_type& c) - { - first_clip_box(); - do - { - m_ren.copy_vline(x, y1, y2, c); - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void blend_hline(int x1, int y, int x2, - const color_type& c, cover_type cover) - { - first_clip_box(); - do - { - m_ren.blend_hline(x1, y, x2, c, cover); - } - while(next_clip_box()); - } + //----------------------------------------------------------renderer_region + template class renderer_region + { + public: + typedef PixelFormat pixfmt_type; + typedef typename pixfmt_type::color_type color_type; + typedef renderer_base base_ren_type; //-------------------------------------------------------------------- - void blend_hline_subpix(int x1, int y, int x2, - const color_type& c, cover_type cover) - { - first_clip_box(); - do - { - m_ren.blend_hline_subpix(x1, y, x2, c, cover); - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y1, int y2, - const color_type& c, cover_type cover) - { - first_clip_box(); - do - { - m_ren.blend_vline(x, y1, y2, c, cover); - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) - { - first_clip_box(); - do - { - m_ren.copy_bar(x1, y1, x2, y2, c); - } - while(next_clip_box()); - } - - //-------------------------------------------------------------------- - void blend_bar(int x1, int y1, int x2, int y2, - const color_type& c, cover_type cover) - { - first_clip_box(); - do - { - m_ren.blend_bar(x1, y1, x2, y2, c, cover); - } - while(next_clip_box()); - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, int len, - const color_type& c, const cover_type* covers) - { - first_clip_box(); - do - { - m_ren.blend_solid_hspan(x, y, len, c, covers); - } - while(next_clip_box()); - } + renderer_region(pixfmt_type& ren) : + m_ren(ren), + m_region(NULL), + m_curr_cb(0), + m_bounds(m_ren.xmin(), m_ren.ymin(), m_ren.xmax(), m_ren.ymax()) + { + } //-------------------------------------------------------------------- - void blend_solid_hspan_subpix(int x, int y, int len, - const color_type& c, const cover_type* covers) - { - first_clip_box(); - do - { - m_ren.blend_solid_hspan_subpix(x, y, len, c, covers); - } - while(next_clip_box()); - } + const pixfmt_type& ren() const { return m_ren.ren(); } + pixfmt_type& ren() { return m_ren.ren(); } - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, int len, - const color_type& c, const cover_type* covers) - { - first_clip_box(); - do - { - m_ren.blend_solid_vspan(x, y, len, c, covers); - } - while(next_clip_box()); - } + //-------------------------------------------------------------------- + unsigned width() const { return m_ren.width(); } + unsigned height() const { return m_ren.height(); } - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - first_clip_box(); - do - { - m_ren.blend_color_hspan(x, y, len, colors, covers, cover); - } - while(next_clip_box()); - } + //-------------------------------------------------------------------- + const rect_i& clip_box() const { return m_ren.clip_box(); } + int xmin() const { return m_ren.xmin(); } + int ymin() const { return m_ren.ymin(); } + int xmax() const { return m_ren.xmax(); } + int ymax() const { return m_ren.ymax(); } - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - first_clip_box(); - do - { - m_ren.blend_color_hspan(x, y, len, colors, covers, cover); - } - while(next_clip_box()); - } + //-------------------------------------------------------------------- + const rect_i& bounding_clip_box() const { return m_bounds; } + int bounding_xmin() const { return m_bounds.x1; } + int bounding_ymin() const { return m_bounds.y1; } + int bounding_xmax() const { return m_bounds.x2; } + int bounding_ymax() const { return m_bounds.y2; } - //-------------------------------------------------------------------- - void blend_color_hspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover); - } + //-------------------------------------------------------------------- + void first_clip_box() + { + m_curr_cb = 0; + if(m_region && m_region->CountRects() > 0) + { + clipping_rect cb = m_region->RectAtInt(0); + m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom); + } + else + m_ren.clip_box_naked(0, 0, -1, -1); + } - //-------------------------------------------------------------------- - void blend_color_vspan_no_clip(int x, int y, int len, - const color_type* colors, - const cover_type* covers, - cover_type cover = cover_full) - { - m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover); - } + //-------------------------------------------------------------------- + bool next_clip_box() + { + if(m_region && (int)(++m_curr_cb) < m_region->CountRects()) + { + clipping_rect cb = m_region->RectAtInt(m_curr_cb); + m_ren.clip_box_naked(cb.left, cb.top, cb.right, cb.bottom); + return true; + } + return false; + } - //-------------------------------------------------------------------- - void copy_from(const rendering_buffer& from, - const rect_i* rc=0, - int x_to=0, - int y_to=0) - { - first_clip_box(); - do - { - m_ren.copy_from(from, rc, x_to, y_to); - } - while(next_clip_box()); - } + //-------------------------------------------------------------------- + void reset_clipping(bool visibility) + { + m_ren.reset_clipping(visibility); + m_region = NULL; + m_curr_cb = 0; + m_bounds = m_ren.clip_box(); + } - private: - renderer_region(const renderer_region&); - const renderer_region& - operator = (const renderer_region&); + //-------------------------------------------------------------------- + void set_clipping_region(BRegion* region) + { + m_region = region; + if (m_region) { + clipping_rect r = m_region->FrameInt(); + if (r.left <= r.right && r.top <= r.bottom) { + // clip rect_i to frame buffer bounds + r.left = max_c(0, r.left); + r.top = max_c(0, r.top); + r.right = min_c((int)width() - 1, r.right); + r.bottom = min_c((int)height() - 1, r.bottom); - base_ren_type m_ren; + if(r.left < m_bounds.x1) m_bounds.x1 = r.left; + if(r.top < m_bounds.y1) m_bounds.y1 = r.top; + if(r.right > m_bounds.x2) m_bounds.x2 = r.right; + if(r.bottom > m_bounds.y2) m_bounds.y2 = r.bottom; + } + } + } + + //-------------------------------------------------------------------- + void clear(const color_type& c) + { + m_ren.clear(c); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().copy_pixel(x, y, c); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + m_ren.ren().blend_pixel(x, y, c, cover); + break; + } + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + first_clip_box(); + do + { + if(m_ren.inbox(x, y)) + { + return m_ren.ren().pixel(x, y); + } + } + while(next_clip_box()); + return color_type::no_color(); + } + + //-------------------------------------------------------------------- + void copy_hline(int x1, int y, int x2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_hline(x1, y, x2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y1, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_vline(x, y1, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_hline(int x1, int y, int x2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_hline(x1, y, x2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y1, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_vline(x, y1, y2, c, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void copy_bar(int x1, int y1, int x2, int y2, const color_type& c) + { + first_clip_box(); + do + { + m_ren.copy_bar(x1, y1, x2, y2, c); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_bar(int x1, int y1, int x2, int y2, + const color_type& c, cover_type cover) + { + first_clip_box(); + do + { + m_ren.blend_bar(x1, y1, x2, y2, c, cover); + } + while(next_clip_box()); + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_hspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan_subpix(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_hspan_subpix(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, int len, + const color_type& c, const cover_type* covers) + { + first_clip_box(); + do + { + m_ren.blend_solid_vspan(x, y, len, c, covers); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + first_clip_box(); + do + { + m_ren.blend_color_hspan(x, y, len, colors, covers, cover); + } + while(next_clip_box()); + } + + //-------------------------------------------------------------------- + void blend_color_hspan_no_clip(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + m_ren.blend_color_hspan_no_clip(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void blend_color_vspan_no_clip(int x, int y, int len, + const color_type* colors, + const cover_type* covers, + cover_type cover = cover_full) + { + m_ren.blend_color_vspan_no_clip(x, y, len, colors, covers, cover); + } + + //-------------------------------------------------------------------- + void copy_from(const rendering_buffer& from, + const rect_i* rc=0, + int x_to=0, + int y_to=0) + { + first_clip_box(); + do + { + m_ren.copy_from(from, rc, x_to, y_to); + } + while(next_clip_box()); + } + + private: + renderer_region(const renderer_region&); + const renderer_region& + operator = (const renderer_region&); + + base_ren_type m_ren; BRegion* m_region; - unsigned m_curr_cb; - rect_i m_bounds; - }; + unsigned m_curr_cb; + rect_i m_bounds; + }; } diff --git a/src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h b/src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h index 2f0e21b6f3..c6c29ba515 100644 --- a/src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h +++ b/src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h @@ -18,68 +18,66 @@ namespace agg { - //============================================render_scanline_subpix_solid - template - void render_scanline_subpix_solid(const Scanline& sl, - BaseRenderer& ren, - const ColorT& color) - { - int y = sl.y(); - unsigned num_spans = sl.num_spans(); - typename Scanline::const_iterator span = sl.begin(); + //============================================render_scanline_subpix_solid + template + void render_scanline_subpix_solid(const Scanline& sl, + BaseRenderer& ren, + const ColorT& color) + { + int y = sl.y(); + unsigned num_spans = sl.num_spans(); + typename Scanline::const_iterator span = sl.begin(); - for(;;) - { - int x = span->x; - if(span->len > 0) - { - ren.blend_solid_hspan_subpix(x, y, (unsigned)span->len, - color, - span->covers); - } - else - { - ren.blend_hline_subpix(x, y, (unsigned)(x - span->len - 1), - color, - *(span->covers)); - } - if(--num_spans == 0) break; - ++span; - } - } + for(;;) + { + int x = span->x; + if(span->len > 0) + { + ren.blend_solid_hspan_subpix(x, y, (unsigned)span->len, + color, + span->covers); + } + else + { + ren.blend_hline(x, y, (unsigned)(x - (span->len / 3) - 1), + color, + *(span->covers)); + } + if(--num_spans == 0) break; + ++span; + } + } + //==========================================renderer_scanline_subpix_solid + template class renderer_scanline_subpix_solid + { + public: + typedef BaseRenderer base_ren_type; + typedef typename base_ren_type::color_type color_type; - //==========================================renderer_scanline_subpix_solid - template class renderer_scanline_subpix_solid - { - public: - typedef BaseRenderer base_ren_type; - typedef typename base_ren_type::color_type color_type; + //-------------------------------------------------------------------- + renderer_scanline_subpix_solid() : m_ren(0) {} + renderer_scanline_subpix_solid(base_ren_type& ren) : m_ren(&ren) {} + void attach(base_ren_type& ren) + { + m_ren = &ren; + } - //-------------------------------------------------------------------- - renderer_scanline_subpix_solid() : m_ren(0) {} - renderer_scanline_subpix_solid(base_ren_type& ren) : m_ren(&ren) {} - void attach(base_ren_type& ren) - { - m_ren = &ren; - } + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } - //-------------------------------------------------------------------- - void color(const color_type& c) { m_color = c; } - const color_type& color() const { return m_color; } + //-------------------------------------------------------------------- + void prepare() {} - //-------------------------------------------------------------------- - void prepare() {} - - //-------------------------------------------------------------------- - template void render(const Scanline& sl) - { - render_scanline_subpix_solid(sl, *m_ren, m_color); - } - - private: - base_ren_type* m_ren; - color_type m_color; - }; + //-------------------------------------------------------------------- + template void render(const Scanline& sl) + { + render_scanline_subpix_solid(sl, *m_ren, m_color); + } + private: + base_ren_type* m_ren; + color_type m_color; + }; } diff --git a/src/servers/app/drawing/Painter/agg_scanline_p_subpix.h b/src/servers/app/drawing/Painter/agg_scanline_p_subpix.h new file mode 100644 index 0000000000..a238c11719 --- /dev/null +++ b/src/servers/app/drawing/Painter/agg_scanline_p_subpix.h @@ -0,0 +1,167 @@ +/* + * Copyright 2008, Andrej Spielmann . + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + * Class scanline_p8_subpix_avrg_filtering, a slightly modified version of + * scanline_p8 customized to store 3 covers per pixel + * + */ + +#ifndef AGG_SCANLINE_P_SUBPIX_INCLUDED +#define AGG_SCANLINE_P_SUBPIX_INCLUDED + +#include "agg_array.h" + +namespace agg +{ + + //======================================================scanline_p8_subpix + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_p8_subpix + { + public: + typedef scanline_p8_subpix self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + scanline_p8_subpix() : + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = 3*(max_x - min_x + 3); + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3) + { + m_cover_ptr[0] = (cover_type)cover1; + m_cover_ptr[1] = (cover_type)cover2; + m_cover_ptr[2] = (cover_type)cover3; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += 3; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 3; + } + m_last_x = x; + m_cover_ptr += 3; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, 3 * len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += 3 * (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 3 * (int16)len; + } + m_cover_ptr += 3 * len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= 3 * (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cover_ptr += 3; + m_cur_span->x = (int16)x; + m_cur_span->len = 3 * (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8_subpix(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + pod_array m_spans; + span* m_cur_span; + }; + +} + + +#endif + diff --git a/src/servers/app/drawing/Painter/agg_scanline_p_subpix_avrg_filtering.h b/src/servers/app/drawing/Painter/agg_scanline_p_subpix_avrg_filtering.h new file mode 100644 index 0000000000..5ff6553c33 --- /dev/null +++ b/src/servers/app/drawing/Painter/agg_scanline_p_subpix_avrg_filtering.h @@ -0,0 +1,195 @@ +/* + * Copyright 2008, Andrej Spielmann . + * Copyright 2008, Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + * Class scanline_p8_subpix_avrg_filtering, a slightly modified version of + * scanline_p8 customized to store 3 covers per pixel and to implement + * average-based color filtering + * + */ + +#ifndef AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED +#define AGG_SCANLINE_P_SUBPIX_AVRG_FILTERING_INCLUDED + +#include "GlobalSubpixelSettings.h" + +namespace agg +{ + //========================================scanline_p8_subpix_avrg_filtering + // + // This is a general purpose scaline container which supports the interface + // used in the rasterizer::render(). See description of scanline_u8 + // for details. + // + //------------------------------------------------------------------------ + class scanline_p8_subpix_avrg_filtering + { + public: + typedef scanline_p8_subpix self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; // If negative, it's a solid span, covers is valid + const cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + scanline_p8_subpix_avrg_filtering() : + m_last_x(0x7FFFFFF0), + m_covers(), + m_cover_ptr(0), + m_spans(), + m_cur_span(0) + { + } + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = 3*(max_x - min_x + 3); + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3) + { + + // NOTE stippi: My basic idea is that filtering tries to minimize colored + // edges, but it does so by blurring the coverage values. This will also + // affect neighboring pixels and add blur where there were perfectly sharp + // edges. Andrej's method of filtering adds a special case for perfectly + // sharp edges, but the drawback here is that there will be a visible + // transition between blurred and non-blurred subpixels. I had the idea that + // when simply fading the subpixels towards the plain gray-scale-aa values, + // there must be a sweet spot for when colored edges become non-disturbing + // and there is still a benefit of sharpness compared to straight gray-scale- + // aa. The define above enables this method against the colored edges. My + // method still has a drawback, since jaggies in diagonal lines will be more + // visible again than with the filter method. + + unsigned char averageWeight = gSubpixelAverageWeight; + unsigned char subpixelWeight = 255 - averageWeight; + + unsigned int coverR; + unsigned int coverG; + unsigned int coverB; + + unsigned int average = (cover1 + cover2 + cover3 + 2) / 3; + + coverR = (cover1 * subpixelWeight + average * averageWeight) >> 8; + coverG = (cover2 * subpixelWeight + average * averageWeight) >> 8; + coverB = (cover3 * subpixelWeight + average * averageWeight) >> 8; + + m_cover_ptr[0] = (cover_type)coverR; + m_cover_ptr[1] = (cover_type)coverG; + m_cover_ptr[2] = (cover_type)coverB; + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += 3; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 3; + } + m_last_x = x; + m_cover_ptr += 3; + } + + //-------------------------------------------------------------------- + void add_cells(int x, unsigned len, const cover_type* covers) + { + memcpy(m_cover_ptr, covers, 3 * len * sizeof(cover_type)); + if(x == m_last_x+1 && m_cur_span->len > 0) + { + m_cur_span->len += 3 * (int16)len; + } + else + { + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cur_span->x = (int16)x; + m_cur_span->len = 3 * (int16)len; + } + m_cover_ptr += 3 * len; + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + if(x == m_last_x+1 && + m_cur_span->len < 0 && + cover == *m_cur_span->covers) + { + m_cur_span->len -= 3 * (int16)len; + } + else + { + *m_cover_ptr = (cover_type)cover; + m_cur_span++; + m_cur_span->covers = m_cover_ptr; + m_cover_ptr += 3; + m_cur_span->x = (int16)x; + m_cur_span->len = 3 * (int16)(-int(len)); + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cover_ptr = &m_covers[0]; + m_cur_span = &m_spans[0]; + m_cur_span->len = 0; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + + private: + scanline_p8_subpix_avrg_filtering(const self_type&); + const self_type& operator = (const self_type&); + + int m_last_x; + int m_y; + pod_array m_covers; + cover_type* m_cover_ptr; + pod_array m_spans; + span* m_cur_span; + }; + +} + + +#endif + diff --git a/src/servers/app/drawing/Painter/agg_scanline_u_subpix_avrg_filtering.h b/src/servers/app/drawing/Painter/agg_scanline_u_subpix_avrg_filtering.h new file mode 100644 index 0000000000..6c4fdbfffc --- /dev/null +++ b/src/servers/app/drawing/Painter/agg_scanline_u_subpix_avrg_filtering.h @@ -0,0 +1,165 @@ +/* + * Copyright 2008, Andrej Spielmann . + * Copyright 2008, Stephan Aßmus . + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + * Class scanline_u8_subpix_avrg_filtering, a slightly modified version of + * scanline_u8 customized to store 3 covers per pixel and to implement + * average-based color filtering + * + */ + +#ifndef AGG_SCANLINE_U_SUBPIX_AVRG_FILTERING_INCLUDED +#define AGG_SCANLINE_U_SUBPIX_AVRG_FILTERING_INCLUDED + +#include "GlobalSubpixelSettings.h" + +namespace agg +{ + //=======================================scanline_u8_subpix_avrg_filtering + //------------------------------------------------------------------------ + class scanline_u8_subpix_avrg_filtering + { + public: + typedef scanline_u8_subpix_avrg_filtering self_type; + typedef int8u cover_type; + typedef int16 coord_type; + + //-------------------------------------------------------------------- + struct span + { + coord_type x; + coord_type len; + cover_type* covers; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + scanline_u8_subpix_avrg_filtering() : + m_min_x(0), + m_last_x(0x7FFFFFF0), + m_cur_span(0) + {} + + //-------------------------------------------------------------------- + void reset(int min_x, int max_x) + { + unsigned max_len = 3*(max_x - min_x + 2); + if(max_len > m_spans.size()) + { + m_spans.resize(max_len); + m_covers.resize(max_len); + } + m_last_x = 0x7FFFFFF0; + m_min_x = min_x; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + void add_cell(int x, unsigned cover1, unsigned cover2, unsigned cover3) + { + + // NOTE stippi: My basic idea is that filtering tries to minimize colored + // edges, but it does so by blurring the coverage values. This will also + // affect neighboring pixels and add blur where there were perfectly sharp + // edges. Andrej's method of filtering adds a special case for perfectly + // sharp edges, but the drawback here is that there will be a visible + // transition between blurred and non-blurred subpixels. I had the idea that + // when simply fading the subpixels towards the plain gray-scale-aa values, + // there must be a sweet spot for when colored edges become non-disturbing + // and there is still a benefit of sharpness compared to straight gray-scale- + // aa. The define above enables this method against the colored edges. My + // method still has a drawback, since jaggies in diagonal lines will be more + // visible again than with the filter method. + + unsigned char averageWeight = gSubpixelAverageWeight; + unsigned char subpixelWeight = 255 - averageWeight; + + unsigned int coverR; + unsigned int coverG; + unsigned int coverB; + + unsigned int average = (cover1 + cover2 + cover3 + 2) / 3; + + coverR = (cover1 * subpixelWeight + average * averageWeight) >> 8; + coverG = (cover2 * subpixelWeight + average * averageWeight) >> 8; + coverB = (cover3 * subpixelWeight + average * averageWeight) >> 8; + + x -= m_min_x; + m_covers[3 * x] = (cover_type)coverR; + m_covers[3 * x + 1] = (cover_type)coverG; + m_covers[3 * x + 2] = (cover_type)coverB; + if(x == m_last_x + 1) + { + m_cur_span->len += 3; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 3; + m_cur_span->covers = &m_covers[3 * x]; + } + m_last_x = x; + } + + //-------------------------------------------------------------------- + void add_span(int x, unsigned len, unsigned cover) + { + x -= m_min_x; + memset(&m_covers[3 * x], cover, 3 * len); + if(x == m_last_x+1) + { + m_cur_span->len += 3 * (coord_type)len; + } + else + { + m_cur_span++; + m_cur_span->x = (coord_type)(x + m_min_x); + m_cur_span->len = 3 * (coord_type)len; + m_cur_span->covers = &m_covers[3 * x]; + } + m_last_x = x + len - 1; + } + + //-------------------------------------------------------------------- + void finalize(int y) + { + m_y = y; + } + + //-------------------------------------------------------------------- + void reset_spans() + { + m_last_x = 0x7FFFFFF0; + m_cur_span = &m_spans[0]; + } + + //-------------------------------------------------------------------- + int y() const { return m_y; } + unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); } + const_iterator begin() const { return &m_spans[1]; } + iterator begin() { return &m_spans[1]; } + + private: + scanline_u8_subpix_avrg_filtering(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array m_covers; + pod_array m_spans; + span* m_cur_span; + }; + +} + +#endif + diff --git a/src/servers/app/drawing/Painter/defines.h b/src/servers/app/drawing/Painter/defines.h index 0bf24f8672..f0420b0808 100644 --- a/src/servers/app/drawing/Painter/defines.h +++ b/src/servers/app/drawing/Painter/defines.h @@ -22,11 +22,18 @@ #include #include +#include "agg_rasterizer_scanline_aa_subpix.h" #include "agg_renderer_region.h" #include "agg_renderer_scanline_subpix.h" +#include "agg_scanline_p_subpix.h" +#include "agg_scanline_p_subpix_avrg_filtering.h" +#include "agg_scanline_u_subpix.h" +#include "agg_scanline_u_subpix_avrg_filtering.h" +#include "GlobalSubpixelSettings.h" #include "PixelFormat.h" + #define ALIASED_DRAWING 0 typedef PixelFormat pixfmt; @@ -45,13 +52,21 @@ typedef agg::scanline_u8 scanline_unpacked_type; typedef agg::scanline_p8 scanline_packed_type; - typedef agg::renderer_scanline_aa_solid renderer_type; +#ifdef AVERAGE_BASED_SUBPIXEL_FILTERING + typedef agg::scanline_p8_subpix_avrg_filtering scanline_packed_subpix_type; + typedef agg::scanline_u8_subpix_avrg_filtering scanline_unpacked_subpix_type; +#else + typedef agg::scanline_p8_subpix scanline_packed_subpix_type; + typedef agg::scanline_u8_subpix scanline_unpacked_subpix_type; #endif + typedef agg::renderer_scanline_aa_solid renderer_type; +#endif // !ALIASED_DRAWING 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; + typedef agg::rasterizer_scanline_aa_subpix<> rasterizer_subpix_type; #endif // DEFINES_H diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h index 3aea497dfc..4f6f03694f 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h @@ -11,7 +11,7 @@ #define DRAWING_MODE_ADD_SUBPIX_H #include "DrawingMode.h" - +#include "GlobalSubpixelSettings.h" // BLEND_ADD_SUBPIX #define BLEND_ADD_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -25,70 +25,19 @@ } -// BLEND_ADD -#define BLEND_ADD(d, r, g, b, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - uint8 rt = min_c(255, _p.data8[2] + (r)); \ - uint8 gt = min_c(255, _p.data8[1] + (g)); \ - uint8 bt = min_c(255, _p.data8[0] + (b)); \ - BLEND(d, rt, gt, bt, a); \ -} - - -//ASSIGN_ADD -#define ASSIGN_ADD(d, r, g, b) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - d[0] = min_c(255, _p.data8[0] + (b)); \ - d[1] = min_c(255, _p.data8[1] + (g)); \ - d[2] = min_c(255, _p.data8[2] + (r)); \ - d[3] = 255; \ -} - - -// blend_hline_add_subpix -void -blend_hline_add_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if (cover == 255) { - do { - rgb_color color = pattern->ColorAt(x, y); - - ASSIGN_ADD(p, color.red, color.green, color.blue); - - p += 4; - x++; - len -= 3; - } while (len); - } else { - do { - rgb_color color = pattern->ColorAt(x, y); - - BLEND_ADD(p, color.red, color.green, color.blue, cover); - - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_add_subpix void blend_solid_hspan_add_subpix(int x, int y, unsigned len, const color_type& c, const uint8* covers, agg_buffer* buffer, const PatternHandler* pattern) { + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; uint8* p = buffer->row_ptr(y) + (x << 2); do { rgb_color color = pattern->ColorAt(x, y); BLEND_ADD_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h index 57af38f3c9..fe46a019c7 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_ALPHA_CC_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_ALPHA_CC_SUBPIX #define BLEND_ALPHA_CC_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,71 +20,6 @@ } -// BLEND_ALPHA_CC -#define BLEND_ALPHA_CC(d, r, g, b, a) \ -{ \ - BLEND_COMPOSITE16(d, r, g, b, a); \ -} - - -// ASSIGN_ALPHA_CC -#define ASSIGN_ALPHA_CC(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_alpha_cc_subpix -void -blend_hline_alpha_cc_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - rgb_color color = pattern->HighColor(); - uint16 alpha = color.alpha * cover; - if (alpha == 255 * 255) { - // cache the low and high color as 32bit values - // high color - uint32 vh; - uint8* p8 = (uint8*)&vh; - p8[0] = color.blue; - p8[1] = color.green; - p8[2] = color.red; - p8[3] = 255; - // low color - color = pattern->LowColor(); - uint32 vl; - p8 = (uint8*)&vl; - p8[0] = color.blue; - p8[1] = color.green; - p8[2] = color.red; - p8[3] = 255; - // row offset as 32 bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - if (pattern->IsHighColor(x, y)) - *p32 = vh; - else - *p32 = vl; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - rgb_color color = pattern->ColorAt(x, y); - BLEND_ALPHA_CC(p, color.red, color.green, color.blue, alpha); - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_alpha_cc_subpix void blend_solid_hspan_alpha_cc_subpix(int x, int y, unsigned len, @@ -95,13 +31,16 @@ blend_solid_hspan_alpha_cc_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - alphaRed = hAlpha * covers[0]; - alphaGreen = hAlpha * covers[1]; - alphaBlue = hAlpha * covers[2]; + alphaRed = hAlpha * covers[subpixelL]; + alphaGreen = hAlpha * covers[subpixelM]; + alphaBlue = hAlpha * covers[subpixelR]; rgb_color color = pattern->ColorAt(x, y); BLEND_ALPHA_CC_SUBPIX(p, color.red, color.green, color.blue, - alphaBlue,alphaGreen, alphaRed); + alphaBlue, alphaGreen, alphaRed); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h index e2d6f81f14..817e0ab7e5 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_ALPHA_CO_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_ALPHA_CO_SUBPIX #define BLEND_ALPHA_CO_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,71 +20,6 @@ } -// BLEND_ALPHA_CO -#define BLEND_ALPHA_CO(d, r, g, b, a) \ -{ \ - BLEND16(d, r, g, b, a); \ -} - - -// ASSIGN_ALPHA_CO -#define ASSIGN_ALPHA_CO(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_alpha_co_subpix -void -blend_hline_alpha_co_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - rgb_color color = pattern->HighColor(); - uint16 alpha = color.alpha * cover; - if (alpha == 255 * 255) { - // cache the low and high color as 32bit values - // high color - uint32 vh; - uint8* p8 = (uint8*)&vh; - p8[0] = color.blue; - p8[1] = color.green; - p8[2] = color.red; - p8[3] = 255; - // low color - color = pattern->LowColor(); - uint32 vl; - p8 = (uint8*)&vl; - p8[0] = color.blue; - p8[1] = color.green; - p8[2] = color.red; - p8[3] = 255; - // row offset as 32bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - if (pattern->IsHighColor(x, y)) - *p32 = vh; - else - *p32 = vl; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - rgb_color color = pattern->ColorAt(x, y); - BLEND_ALPHA_CO(p, color.red, color.green, color.blue, alpha); - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_alpha_co_subpix void blend_solid_hspan_alpha_co_subpix(int x, int y, unsigned len, @@ -95,10 +31,13 @@ blend_solid_hspan_alpha_co_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - alphaRed = hAlpha * covers[0]; - alphaGreen = hAlpha * covers[1]; - alphaBlue = hAlpha * covers[2]; + alphaRed = hAlpha * covers[subpixelL]; + alphaGreen = hAlpha * covers[subpixelM]; + alphaBlue = hAlpha * covers[subpixelR]; rgb_color color = pattern->ColorAt(x, y); BLEND_ALPHA_CO_SUBPIX(p, color.red, color.green, color.blue, alphaBlue, alphaGreen, alphaRed); diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h index ffb077c971..7cfe182072 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h @@ -11,45 +11,7 @@ #define DRAWING_MODE_ALPHA_CO_SOLID_SUBPIX_H #include "DrawingModeAlphaCOSUBPIX.h" - -// blend_hline_alpha_co_solid_subpix -void -blend_hline_alpha_co_solid_subpix(int x, int y, unsigned len, - const color_type& c, uint8 cover, agg_buffer* buffer, - const PatternHandler* pattern) -{ - uint16 alpha = pattern->HighColor().alpha * cover; - if (alpha == 255 * 255) { - // cache the color as 32bit values - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = c.b; - p8[1] = c.g; - p8[2] = c.r; - p8[3] = 255; - // row offset as 32bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - *p32 = v; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - if (len < 12) { - do { - BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha); - x++; - p += 4; - len -= 3; - } while (len); - } else { - alpha = alpha >> 8; - blend_line32(p, len / 3, c.r, c.g, c.b, alpha); - } - } -} +#include "GlobalSubpixelSettings.h" // blend_solid_hspan_alpha_co_solid_subpix @@ -63,10 +25,13 @@ blend_solid_hspan_alpha_co_solid_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - alphaRed = hAlpha * covers[0]; - alphaGreen = hAlpha * covers[1]; - alphaBlue = hAlpha * covers[2]; + alphaRed = hAlpha * covers[subpixelL]; + alphaGreen = hAlpha * covers[subpixelM]; + alphaBlue = hAlpha * covers[subpixelR]; BLEND_ALPHA_CO_SUBPIX(p, c.r, c.g, c.b, alphaBlue, alphaGreen, alphaRed); covers += 3; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h index 17ac7b80ac..88ebb25ed5 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_ALPHA_PC_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_ALPHA_PC_SUBPIX #define BLEND_ALPHA_PC_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,46 +20,6 @@ } -// BLEND_ALPHA_PC -#define BLEND_ALPHA_PC(d, r, g, b, a) \ -{ \ - BLEND_COMPOSITE16(d, r, g, b, a); \ -} - - -// ASSIGN_ALPHA_PC -#define ASSIGN_ALPHA_PC(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_alpha_pc_subpix -void -blend_hline_alpha_pc_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - rgb_color color = pattern->ColorAt(x, y); - uint16 alpha = color.alpha * cover; - if (alpha) { - if (alpha == 255) { - ASSIGN_ALPHA_PC(p, color.red, color.green, color.blue); - } else { - BLEND_ALPHA_PC(p, color.red, color.green, color.blue, alpha); - } - } - x++; - p += 4; - len -= 3; - } while (len); -} - - // blend_solid_hspan_alpha_pc_subpix void blend_solid_hspan_alpha_pc_subpix(int x, int y, unsigned len, @@ -69,11 +30,14 @@ blend_solid_hspan_alpha_pc_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); - alphaRed = color.alpha * covers[0]; - alphaGreen = color.alpha * covers[1]; - alphaBlue = color.alpha * covers[2]; + alphaRed = color.alpha * covers[subpixelL]; + alphaGreen = color.alpha * covers[subpixelM]; + alphaBlue = color.alpha * covers[subpixelR]; BLEND_ALPHA_PC_SUBPIX(p, color.red, color.green, color.blue, alphaBlue, alphaGreen, alphaRed); covers += 3; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h index 1c0cc1b4b0..7cc0b1c509 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_ALPHA_PO_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_ALPHA_PO_SUBPIX #define BLEND_ALPHA_PO_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -18,44 +19,6 @@ BLEND16_SUBPIX(d, r, g, b, a1, a2, a3); \ } -// BLEND_ALPHA_PO -#define BLEND_ALPHA_PO(d, r, g, b, a) \ -{ \ - BLEND16(d, r, g, b, a); \ -} - -// ASSIGN_ALPHA_PO -#define ASSIGN_ALPHA_PO(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_alpha_po_subpix -void -blend_hline_alpha_po_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - rgb_color color = pattern->ColorAt(x, y); - uint16 alpha = color.alpha * cover; - if (alpha) { - if (alpha == 255) { - ASSIGN_ALPHA_PO(p, color.red, color.green, color.blue); - } else { - BLEND_ALPHA_PO(p, color.red, color.green, color.blue, alpha); - } - } - x++; - p += 4; - len -= 3; - } while(len); -} - // blend_solid_hspan_alpha_po_subpix void @@ -67,11 +30,14 @@ blend_solid_hspan_alpha_po_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); - alphaRed = color.alpha * covers[0]; - alphaGreen = color.alpha * covers[1]; - alphaBlue = color.alpha * covers[2]; + alphaRed = color.alpha * covers[subpixelL]; + alphaGreen = color.alpha * covers[subpixelM]; + alphaBlue = color.alpha * covers[subpixelR]; BLEND_ALPHA_PO_SUBPIX(p, color.red, color.green, color.blue, alphaBlue, alphaGreen, alphaRed); covers += 3; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h index 2bb5e8317f..e52632737c 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h @@ -11,46 +11,7 @@ #define DRAWING_MODE_ALPHA_PO_SOLID_SUBPIX_H #include "DrawingModeAlphaPOSUBPIX.h" - -// blend_hline_alpha_po_solid_subpix -void -blend_hline_alpha_po_solid_subpix(int x, int y, unsigned len, - const color_type& c, uint8 cover, agg_buffer* buffer, - const PatternHandler* pattern) -{ - uint16 alpha = c.a * cover; - if (alpha == 255 * 255) { - // cache the color as 32bit values - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = c.b; - p8[1] = c.g; - p8[2] = c.r; - p8[3] = 255; - // row offset as 32bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - *p32 = v; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - if (len < 12) { - do { - BLEND_ALPHA_CO(p, c.r, c.g, c.b, alpha); - x++; - p += 4; - len -= 3; - } while (len); - } else { - alpha = alpha >> 8; - blend_line32(p, len / 3, c.r, c.g, c.b, alpha); - } - } -} - +#include "GlobalSubpixelSettings.h" // blend_solid_hspan_alpha_po_solid_subpix void @@ -62,10 +23,13 @@ blend_solid_hspan_alpha_po_solid_subpix(int x, int y, unsigned len, uint16 alphaRed; uint16 alphaGreen; uint16 alphaBlue; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - alphaRed = c.a * covers[0]; - alphaGreen = c.a * covers[1]; - alphaBlue = c.a * covers[2]; + alphaRed = c.a * covers[subpixelL]; + alphaGreen = c.a * covers[subpixelM]; + alphaBlue = c.a * covers[subpixelR]; BLEND_ALPHA_PO_SUBPIX(p, c.r, c.g, c.b, alphaBlue, alphaGreen, alphaRed); covers += 3; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h index 5cd16e0937..e0270e843a 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_BLEND_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_BLEND_SUBPIX @@ -25,70 +26,19 @@ } -// BLEND_BLEND -#define BLEND_BLEND(d, r, g, b, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - uint8 bt = (_p.data8[0] + (b)) >> 1; \ - uint8 gt = (_p.data8[1] + (g)) >> 1; \ - uint8 rt = (_p.data8[2] + (r)) >> 1; \ - BLEND(d, rt, gt, bt, a); \ -} - - -// ASSIGN_BLEND -#define ASSIGN_BLEND(d, r, g, b) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - d[0] = (_p.data8[0] + (b)) >> 1; \ - d[1] = (_p.data8[1] + (g)) >> 1; \ - d[2] = (_p.data8[2] + (r)) >> 1; \ - d[3] = 255; \ -} - - -// blend_hline_blend_subpix -void -blend_hline_blend_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if (cover == 255) { - do { - rgb_color color = pattern->ColorAt(x, y); - - ASSIGN_BLEND(p, color.red, color.green, color.blue); - - p += 4; - x++; - len -= 3; - } while (len); - } else { - do { - rgb_color color = pattern->ColorAt(x, y); - - BLEND_BLEND(p, color.red, color.green, color.blue, cover); - - p += 4; - x++; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_blend_subpix void blend_solid_hspan_blend_subpix(int x, int y, unsigned len, const color_type& c, const uint8* covers, agg_buffer* buffer, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); BLEND_BLEND_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h index 5242a5ece4..a76691292d 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_COPY_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_COPY_SUBPIX #define BLEND_COPY_SUBPIX(d, r2, g2, b2, a1, a2, a3, r1, g1, b1) \ @@ -19,72 +20,6 @@ } -// BLEND_COPY -#define BLEND_COPY(d, r2, g2, b2, a, r1, g1, b1) \ -{ \ - BLEND_FROM(d, r1, g1, b1, r2, g2, b2, a); \ -} - - -// ASSIGN_COPY -#define ASSIGN_COPY(d, r, g, b, a) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = (a); \ -} - - -// blend_hline_copy_subpix -void -blend_hline_copy_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (cover == 255) { - // cache the low and high color as 32bit values - // high color - rgb_color color = pattern->HighColor(); - uint32 vh; - uint8* p8 = (uint8*)&vh; - p8[0] = (uint8)color.blue; - p8[1] = (uint8)color.green; - p8[2] = (uint8)color.red; - p8[3] = 255; - // low color - color = pattern->LowColor(); - uint32 vl; - p8 = (uint8*)&vl; - p8[0] = (uint8)color.blue; - p8[1] = (uint8)color.green; - p8[2] = (uint8)color.red; - p8[3] = 255; - // row offset as 32bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - if (pattern->IsHighColor(x, y)) - *p32 = vh; - else - *p32 = vl; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - rgb_color l = pattern->LowColor(); - do { - rgb_color color = pattern->ColorAt(x, y); - BLEND_COPY(p, color.red, color.green, color.blue, cover, - l.red, l.green, l.blue); - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_copy_subpix void blend_solid_hspan_copy_subpix(int x, int y, unsigned len, const color_type& c, @@ -92,10 +27,14 @@ blend_solid_hspan_copy_subpix(int x, int y, unsigned len, const color_type& c, { uint8* p = buffer->row_ptr(y) + (x << 2); rgb_color l = pattern->LowColor(); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); BLEND_COPY_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0], l.red, l.green, l.blue); + covers[subpixelL], covers[subpixelM], covers[subpixelR], l.red, + l.green, l.blue); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h index 5e2a65c1d8..28c7c21df7 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h @@ -11,36 +11,7 @@ #define DRAWING_MODE_COPY_SOLID_SUBPIX_H #include "DrawingModeOverSUBPIX.h" - -// blend_hline_copy_solid_subpix -void -blend_hline_copy_solid_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (cover == 255) { - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = (uint8)c.b; - p8[1] = (uint8)c.g; - p8[2] = (uint8)c.r; - p8[3] = 255; - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - *p32 = v; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - BLEND_OVER(p, c.r, c.g, c.b, cover); - x++; - p += 4; - len -= 3; - } while (len); - } -} +#include "GlobalSubpixelSettings.h" // blend_solid_hspan_copy_solid_subpix @@ -50,8 +21,12 @@ blend_solid_hspan_copy_solid_subpix(int x, int y, unsigned len, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[subpixelL], + covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h index 3a458497b9..a0e04d6adc 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h @@ -11,38 +11,7 @@ #define DRAWING_MODE_COPY_TEXT_SUBPIX_H #include "DrawingModeCopySUBPIX.h" - -// blend_hline_copy_text_subpix -void -blend_hline_copy_text_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (cover == 255) { - // cache the color as 32bit value - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = (uint8)c.b; - p8[1] = (uint8)c.g; - p8[2] = (uint8)c.r; - p8[3] = 255; - // row offset as 32bit pointer - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - *p32 = v; - p32++; - len -= 3; - } while(len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - rgb_color l = pattern->LowColor(); - do { - BLEND_COPY(p, c.r, c.g, c.b, cover, l.red, l.green, l.blue); - p += 4; - len -= 3; - } while (len); - } -} - +#include "GlobalSubpixelSettings.h" // blend_solid_hspan_copy_text_subpix void @@ -52,9 +21,13 @@ blend_solid_hspan_copy_text_subpix(int x, int y, unsigned len, { //printf("blend_solid_hspan_copy_text(%d, %d)\n", x, len); uint8* p = buffer->row_ptr(y) + (x << 2); - //rgb_color l = pattern->LowColor(); + rgb_color l = pattern->LowColor(); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + BLEND_COPY_SUBPIX(p, c.r, c.g, c.b, covers[subpixelL], + covers[subpixelM], covers[subpixelR], l.red, l.green, l.blue); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h index 6550295fef..da05371095 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_ERASE_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_ERASE_SUBPIX #define BLEND_ERASE_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,58 +20,6 @@ } -// BLEND_ERASE -#define BLEND_ERASE(d, r, g, b, a) \ -{ \ - BLEND(d, r, g, b, a); \ -} - - -// ASSIGN_ERASE -#define ASSIGN_ERASE(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_erase_subpix -void -blend_hline_erase_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (cover == 255) { - rgb_color color = pattern->LowColor(); - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = (uint8)color.blue; - p8[1] = (uint8)color.green; - p8[2] = (uint8)color.red; - p8[3] = 255; - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - if (pattern->IsHighColor(x, y)) - *p32 = v; - p32++; - x +=3; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - rgb_color color = pattern->LowColor(); - do { - if (pattern->IsHighColor(x, y)) - BLEND_ERASE(p, color.red, color.green, color.blue, cover); - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_erase_subpix void blend_solid_hspan_erase_subpix(int x, int y, unsigned len, const color_type& c, @@ -78,10 +27,13 @@ blend_solid_hspan_erase_subpix(int x, int y, unsigned len, const color_type& c, { uint8* p = buffer->row_ptr(y) + (x << 2); rgb_color color = pattern->LowColor(); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { if (pattern->IsHighColor(x, y)) { BLEND_ERASE_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); } covers += 3; p += 4; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h index 4f86a9a45c..4a548eec97 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_INVERT_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_INVERT_SUBPIX #define BLEND_INVERT_SUBPIX(d, a1, a2, a3) \ @@ -22,64 +23,20 @@ } -// BLEND_INVERT -#define BLEND_INVERT(d, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - BLEND(d, 255 - _p.data8[2], 255 - _p.data8[1], 255 - _p.data8[0], a); \ -} - - -// ASSIGN_INVERT -#define ASSIGN_INVERT(d) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - d[0] = 255 - _p.data8[0]; \ - d[1] = 255 - _p.data8[1]; \ - d[2] = 255 - _p.data8[2]; \ - d[3] = 255; \ -} - - -// blend_hline_invert_subpix -void -blend_hline_invert_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if(cover == 255) { - do { - if (pattern->IsHighColor(x, y)) { - ASSIGN_INVERT(p); - } - x++; - p += 4; - len -= 3; - } while (len); - } else { - do { - if (pattern->IsHighColor(x, y)) { - BLEND_INVERT(p, cover); - } - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_invert_subpix void blend_solid_hspan_invert_subpix(int x, int y, unsigned len, const color_type& c, const uint8* covers, agg_buffer* buffer, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - if (pattern->IsHighColor(x, y)) - BLEND_INVERT_SUBPIX(p, covers[2], covers[1], covers[0]); + if (pattern->IsHighColor(x, y)) { + BLEND_INVERT_SUBPIX(p, covers[subpixelL], covers[subpixelM], + covers[subpixelR]); + } covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h index d25d6d5f72..f6c8b1d1b4 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_MAX_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_MAX_SUBPIX #define BLEND_MAX_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -24,73 +25,19 @@ } -// BLEND_MAX -#define BLEND_MAX(d, r, g, b, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - if (brightness_for((r), (g), (b)) \ - > brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \ - BLEND(d, (r), (g), (b), a); \ - } \ -} - - -// ASSIGN_MAX -#define ASSIGN_MAX(d, r, g, b) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - if (brightness_for((r), (g), (b)) \ - > brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ - } \ -} - - -// blend_hline_max_subpix -void -blend_hline_max_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if (cover == 255) { - do { - rgb_color color = pattern->ColorAt(x, y); - - ASSIGN_MAX(p, color.red, color.green, color.blue); - - p += 4; - x++; - len -= 3; - } while (len); - } else { - do { - rgb_color color = pattern->ColorAt(x, y); - - BLEND_MAX(p, color.red, color.green, color.blue, cover); - - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_max_subpix void blend_solid_hspan_max_subpix(int x, int y, unsigned len, const color_type& c, const uint8* covers, agg_buffer* buffer, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); BLEND_MAX_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h index b258e1fb70..58172be41d 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_MIN_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_MIN_SUBPIX #define BLEND_MIN_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -24,73 +25,19 @@ } -// BLEND_MIN -#define BLEND_MIN(d, r, g, b, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - if (brightness_for((r), (g), (b)) \ - < brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \ - BLEND(d, (r), (g), (b), a); \ - } \ -} - - -// ASSIGN_MIN -#define ASSIGN_MIN(d, r, g, b) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - if (brightness_for((r), (g), (b)) \ - < brightness_for(_p.data8[2], _p.data8[1], _p.data8[0])) { \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ - } \ -} - - -// blend_hline_min_subpix -void -blend_hline_min_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if (cover == 255) { - do { - rgb_color color = pattern->ColorAt(x, y); - - ASSIGN_MIN(p, color.red, color.green, color.blue); - - p += 4; - x++; - len -= 3; - } while (len); - } else { - do { - rgb_color color = pattern->ColorAt(x, y); - - BLEND_MIN(p, color.red, color.green, color.blue, cover); - - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_min_subpix void blend_solid_hspan_min_subpix(int x, int y, unsigned len, const color_type& c, const uint8* covers, agg_buffer* buffer, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); BLEND_MIN_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h index 91aa4edf51..d32861fce8 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_OVER_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_OVER_SUBPIX #define BLEND_OVER_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,58 +20,6 @@ } -// BLEND_OVER -#define BLEND_OVER(d, r, g, b, a) \ -{ \ - BLEND(d, r, g, b, a) \ -} - - -// ASSIGN_OVER -#define ASSIGN_OVER(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_over_subpix -void -blend_hline_over_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (cover == 255) { - rgb_color color = pattern->HighColor(); - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = (uint8)color.blue; - p8[1] = (uint8)color.green; - p8[2] = (uint8)color.red; - p8[3] = 255; - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - if (pattern->IsHighColor(x, y)) - *p32 = v; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - rgb_color color = pattern->HighColor(); - do { - if (pattern->IsHighColor(x, y)) - BLEND_OVER(p, color.red, color.green, color.blue, cover); - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_over_subpix void blend_solid_hspan_over_subpix(int x, int y, unsigned len, const color_type& c, @@ -78,10 +27,13 @@ blend_solid_hspan_over_subpix(int x, int y, unsigned len, const color_type& c, { uint8* p = buffer->row_ptr(y) + (x << 2); rgb_color color = pattern->HighColor(); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { if (pattern->IsHighColor(x, y)) { BLEND_OVER_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); } covers += 3; p += 4; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h index 0c45390438..9c05c7cd8f 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h @@ -11,40 +11,7 @@ #define DRAWING_MODE_OVER_SOLID_SUBPIX_H #include "DrawingModeOverSUBPIX.h" - -// blend_hline_over_solid_subpix -void -blend_hline_over_solid_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - if (pattern->IsSolidLow()) - return; - - if (cover == 255) { - uint32 v; - uint8* p8 = (uint8*)&v; - p8[0] = (uint8)c.b; - p8[1] = (uint8)c.g; - p8[2] = (uint8)c.r; - p8[3] = 255; - uint32* p32 = (uint32*)(buffer->row_ptr(y)) + x; - do { - *p32 = v; - p32++; - x++; - len -= 3; - } while (len); - } else { - uint8* p = buffer->row_ptr(y) + (x << 2); - do { - BLEND_OVER(p, c.r, c.g, c.b, cover); - x++; - p += 4; - len -= 3; - } while (len); - } -} - +#include "GlobalSubpixelSettings.h" // blend_solid_hspan_over_solid_subpix void @@ -56,8 +23,12 @@ blend_solid_hspan_over_solid_subpix(int x, int y, unsigned len, return; uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { - BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h index e20ab7c925..f9eacb288d 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h @@ -11,6 +11,7 @@ #define DRAWING_MODE_SELECT_SUBPIX_H #include "DrawingMode.h" +#include "GlobalSubpixelSettings.h" // BLEND_SELECT_SUBPIX #define BLEND_SELECT_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -19,55 +20,6 @@ } -// BLEND_SELECT -#define BLEND_SELECT(d, r, g, b, a) \ -{ \ - BLEND(d, r, g, b, a); \ -} - - -// ASSIGN_SELECT -#define ASSIGN_SELECT(d, r, g, b) \ -{ \ - d[0] = (b); \ - d[1] = (g); \ - d[2] = (r); \ - d[3] = 255; \ -} - - -// blend_hline_select_subpix -void -blend_hline_select_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - rgb_color high = pattern->HighColor(); - rgb_color low = pattern->LowColor(); - rgb_color color; - if (cover == 255) { - do { - if (pattern->IsHighColor(x, y) - && compare(p, high, low, &color)) - ASSIGN_SELECT(p, color.red, color.green, color.blue); - x++; - p += 4; - len -= 3; - } while (len); - } else { - do { - if (pattern->IsHighColor(x, y) - && compare(p, high, low, &color)) { - BLEND_SELECT(p, color.red, color.green, color.blue, cover); - } - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_select_subpix void blend_solid_hspan_select_subpix(int x, int y, unsigned len, const color_type& c, @@ -77,11 +29,14 @@ blend_solid_hspan_select_subpix(int x, int y, unsigned len, const color_type& c, rgb_color high = pattern->HighColor(); rgb_color low = pattern->LowColor(); rgb_color color; + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { if (pattern->IsHighColor(x, y)) { if (compare(p, high, low, &color)){ BLEND_SELECT_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); } } covers += 3; diff --git a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h index 3c2c96c594..d9bb81fdd9 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h +++ b/src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h @@ -10,10 +10,8 @@ #ifndef DRAWING_MODE_SUBTRACT_SUBPIX_H #define DRAWING_MODE_SUBTRACT_SUBPIX_H -#include - #include "DrawingMode.h" -#include "PatternHandler.h" +#include "GlobalSubpixelSettings.h" // BLEND_SUBTRACT_SUBPIX #define BLEND_SUBTRACT_SUBPIX(d, r, g, b, a1, a2, a3) \ @@ -27,60 +25,6 @@ } -// BLEND_SUBTRACT -#define BLEND_SUBTRACT(d, r, g, b, a) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - uint8 rt = max_c(0, _p.data8[2] - (r)); \ - uint8 gt = max_c(0, _p.data8[1] - (g)); \ - uint8 bt = max_c(0, _p.data8[0] - (b)); \ - BLEND(d, rt, gt, bt, a); \ -} - - -// ASSIGN_SUBTRACT -#define ASSIGN_SUBTRACT(d, r, g, b) \ -{ \ - pixel32 _p; \ - _p.data32 = *(uint32*)d; \ - d[0] = max_c(0, _p.data8[0] - (b)); \ - d[1] = max_c(0, _p.data8[1] - (g)); \ - d[2] = max_c(0, _p.data8[2] - (r)); \ - d[3] = 255; \ -} - - -// blend_hline_subtract_subpix -void -blend_hline_subtract_subpix(int x, int y, unsigned len, const color_type& c, - uint8 cover, agg_buffer* buffer, const PatternHandler* pattern) -{ - uint8* p = buffer->row_ptr(y) + (x << 2); - if (cover == 255) { - do { - rgb_color color = pattern->ColorAt(x, y); - - ASSIGN_SUBTRACT(p, color.red, color.green, color.blue); - - p += 4; - x++; - len -= 3; - } while (len); - } else { - do { - rgb_color color = pattern->ColorAt(x, y); - - BLEND_SUBTRACT(p, color.red, color.green, color.blue, cover); - - x++; - p += 4; - len -= 3; - } while (len); - } -} - - // blend_solid_hspan_subtract_subpix void blend_solid_hspan_subtract_subpix(int x, int y, unsigned len, @@ -88,10 +32,13 @@ blend_solid_hspan_subtract_subpix(int x, int y, unsigned len, const PatternHandler* pattern) { uint8* p = buffer->row_ptr(y) + (x << 2); + const int subpixelL = gSubpixelOrderingRGB ? 2 : 0; + const int subpixelM = 1; + const int subpixelR = gSubpixelOrderingRGB ? 0 : 2; do { rgb_color color = pattern->ColorAt(x, y); BLEND_SUBTRACT_SUBPIX(p, color.red, color.green, color.blue, - covers[2], covers[1], covers[0]); + covers[subpixelL], covers[subpixelM], covers[subpixelR]); covers += 3; p += 4; x++; diff --git a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp index d5499cda87..0e4508ffe3 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp +++ b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp @@ -74,15 +74,6 @@ 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, @@ -151,7 +142,6 @@ 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), @@ -181,12 +171,10 @@ 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; @@ -196,7 +184,6 @@ 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; @@ -205,7 +192,6 @@ 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; @@ -214,7 +200,6 @@ 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; @@ -227,7 +212,6 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode, if (text) { fBlendPixel = blend_pixel_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; @@ -239,7 +223,6 @@ 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; @@ -247,7 +230,6 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode, } 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; @@ -256,8 +238,7 @@ PixelFormat::SetDrawingMode(drawing_mode mode, source_alpha alphaSrcMode, break; case B_OP_ADD: fBlendPixel = blend_pixel_add; - fBlendHLine = blend_hline_add; - fBlendHLineSubpix = blend_hline_add_subpix; + fBlendHLine = blend_hline_add; fBlendSolidHSpanSubpix = blend_solid_hspan_add_subpix; fBlendSolidHSpan = blend_solid_hspan_add; fBlendSolidVSpan = blend_solid_vspan_add; @@ -266,7 +247,6 @@ 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; @@ -275,7 +255,6 @@ 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; @@ -284,7 +263,6 @@ 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; @@ -293,7 +271,6 @@ 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; @@ -314,14 +291,12 @@ 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; @@ -330,7 +305,6 @@ 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; @@ -341,14 +315,12 @@ 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; @@ -357,7 +329,6 @@ 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; diff --git a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h index 609eea36f7..d0c8bc7689 100644 --- a/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h +++ b/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h @@ -105,11 +105,6 @@ 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, @@ -149,7 +144,6 @@ class PixelFormat { blend_pixel_f fBlendPixel; blend_line fBlendHLine; - blend_line fBlendHLineSubpix; blend_line fBlendVLine; blend_solid_span fBlendSolidHSpan; blend_solid_span fBlendSolidHSpanSubpix; @@ -211,14 +205,6 @@ 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, diff --git a/src/tests/servers/app/Jamfile b/src/tests/servers/app/Jamfile index 262fc2a46d..6a764de18b 100644 --- a/src/tests/servers/app/Jamfile +++ b/src/tests/servers/app/Jamfile @@ -70,6 +70,7 @@ SharedLibrary libhaikuappserver.so : FontFamily.cpp FontManager.cpp FontStyle.cpp + GlobalSubpixelSettings.cpp HashTable.cpp IntPoint.cpp IntRect.cpp