Hi all, attached is the first milestone of Andrej's work. Subpixel anti-aliased text rendering is working for untransformed text and can be turned on/off via the Fonts preflet. I am happy with this patch and would like to commit it, but I will wait a bit for your input. Feel free to review and comment! Best regards, -Stephan
Index: headers/private/app/ServerProtocol.h =================================================================== --- headers/private/app/ServerProtocol.h (revision 26259) +++ headers/private/app/ServerProtocol.h (working copy) @@ -6,6 +6,7 @@ * DarkWyrm <bpmagic@xxxxxxxxxxxxxxx> * Jérôme Duval, jerome.duval@xxxxxxx * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ #ifndef APP_SERVER_PROTOCOL_H #define APP_SERVER_PROTOCOL_H @@ -187,6 +188,11 @@ AS_GET_DECORATOR_SETTINGS, AS_GET_SHOW_ALL_DRAGGERS, AS_SET_SHOW_ALL_DRAGGERS, + + AS_SET_FONT_SUBPIXEL_ANTIALIASING, + AS_GET_FONT_SUBPIXEL_ANTIALIASING, + AS_SET_HINTING, + AS_GET_HINTING, // Graphics calls AS_SET_HIGH_COLOR, Index: src/preferences/fonts/MainWindow.h =================================================================== --- src/preferences/fonts/MainWindow.h (revision 26259) +++ src/preferences/fonts/MainWindow.h (working copy) @@ -12,6 +12,7 @@ #include "FontsSettings.h" +#include "AdvancedSettingsView.h" #include <Window.h> @@ -31,12 +32,13 @@ private: void _Center(); - BMessageRunner* fRunner; - FontView* fFontsView; - BButton* fDefaultsButton; - BButton* fRevertButton; + BMessageRunner* fRunner; + FontView* fFontsView; + BButton* fDefaultsButton; + BButton* fRevertButton; - FontsSettings fSettings; + FontsSettings fSettings; + AdvancedSettingsView* fAdvancedSettings; }; static const int32 kMsgUpdate = 'updt'; Index: src/preferences/fonts/AdvancedSettingsView.cpp =================================================================== --- src/preferences/fonts/AdvancedSettingsView.cpp (revision 0) +++ src/preferences/fonts/AdvancedSettingsView.cpp (revision 0) @@ -0,0 +1,279 @@ +/* + * Copyright 2008, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> + */ + + +#include "AdvancedSettingsView.h" +#include "MainWindow.h" + +#include <Box.h> +#include <MenuField.h> +#include <MenuItem.h> +#include <PopUpMenu.h> +#include <String.h> + +#include <stdio.h> + + +#define INSTANT_UPDATE + // if defined, the changes will take place immediately and not only on exit +#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 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); + + +// #pragma mark - + + +AdvancedSettingsView::AdvancedSettingsView(BRect _rect, const char* name) + : BView(_rect, name, B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW) +{ + if (_get_font_subpixel_antialiasing_(&fCurrentSubpixelAntialiasing) != B_OK) + fCurrentSubpixelAntialiasing = false; + fSavedSubpixelAntialiasing = fCurrentSubpixelAntialiasing; + + if (_get_hinting_(&fCurrentHinting) != B_OK) + fCurrentHinting = true; + fSavedHinting = fCurrentHinting; + + fDivider = StringWidth("Character hinting:") + 5; + + fAntialiasingMenu = new BPopUpMenu("Antialiasing menu"); + fHintingMenu = new BPopUpMenu("Hinting menu"); + + // antialiasing menu + BRect rect(Bounds()); + fAntialiasingMenuField = new BMenuField(rect, "antialiasing", + "Antialiasing type:", fAntialiasingMenu, false); + fAntialiasingMenuField->SetDivider(fDivider); + fAntialiasingMenuField->SetAlignment(B_ALIGN_RIGHT); + fAntialiasingMenuField->ResizeToPreferred(); + AddChild(fAntialiasingMenuField); + _BuildAntialiasingMenu(); + + // hinting menu + float shift = fAntialiasingMenuField->Bounds().Height()+5; + rect.top += shift; + rect.bottom += shift; + fHintingMenuField = new BMenuField(rect, "hinting", + "Character hinting:", fHintingMenu, false); + fHintingMenuField->SetDivider(fDivider); + fHintingMenuField->SetAlignment(B_ALIGN_RIGHT); + fHintingMenuField->ResizeToPreferred(); + AddChild(fHintingMenuField); + _BuildHintingMenu(); + +#ifdef DISABLE_HINTING_CONTROL + fHintingMenuField->SetEnabled(false); +#endif + + _SetCurrentAntialiasing(); + _SetCurrentHinting(); +} + + +AdvancedSettingsView::~AdvancedSettingsView() +{ +#ifndef INSTANT_UPDATE + _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); + _set_hinting(fCurrentHinting); +#endif +} + + +void +AdvancedSettingsView::GetPreferredSize(float *_width, float *_height) +{ + // don't change the width if it is large enough + if (_width) { + *_width = (StringWidth(kSubpixelLabel) > StringWidth(kGrayscaleLabel) ? + StringWidth(kSubpixelLabel) : StringWidth(kGrayscaleLabel)) + + fDivider + 30; + if (*_width < Bounds().Width()) + *_width = Bounds().Width(); + } + + *_height = fHintingMenuField->Frame().bottom; +} + + +void +AdvancedSettingsView::SetDivider(float divider) +{ + fAntialiasingMenuField->SetDivider(divider); + fHintingMenuField->SetDivider(divider); + fDivider = divider; +} + + +void +AdvancedSettingsView::RelayoutIfNeeded() +{ + float width, height; + GetPreferredSize(&width, &height); + + if (width > Bounds().Width() || height > Bounds().Height()) { + ResizeTo(width, height); + } +} + + +void +AdvancedSettingsView::AttachedToWindow() +{ + if (Parent() != NULL) + SetViewColor(Parent()->ViewColor()); + else + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + fAntialiasingMenu->SetTargetForItems(this); + fHintingMenu->SetTargetForItems(this); +} + + +void +AdvancedSettingsView::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case kMsgSetAntialiasing: + { + bool subpixelAntialiasing; + if (msg->FindBool("antialiasing", &subpixelAntialiasing) != B_OK + || subpixelAntialiasing == fCurrentSubpixelAntialiasing) + break; + fCurrentSubpixelAntialiasing = subpixelAntialiasing; +#ifdef INSTANT_UPDATE + _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); +#endif + Window()->PostMessage(kMsgUpdate); + break; + } + case kMsgSetHinting: + { + bool hinting; + if (msg->FindBool("hinting", &hinting) != B_OK + || hinting == fCurrentHinting) + break; + fCurrentHinting = hinting; +#ifdef INSTANT_UPDATE + _set_hinting_(fCurrentHinting); +#endif + Window()->PostMessage(kMsgUpdate); + break; + } + default: + BView::MessageReceived(msg); + } +} + + +void +AdvancedSettingsView::_BuildAntialiasingMenu() +{ + BMessage* message = new BMessage(kMsgSetAntialiasing); + message->AddBool("antialiasing", false); + + BMenuItem* item = new BMenuItem(kGrayscaleLabel, message); + + fAntialiasingMenu->AddItem(item); + + BMessage* message2 = new BMessage(kMsgSetAntialiasing); + message2->AddBool("antialiasing", true); + + BMenuItem* item2 = new BMenuItem(kSubpixelLabel, message2); + + fAntialiasingMenu->AddItem(item2); +} + + +void +AdvancedSettingsView::_BuildHintingMenu() +{ + BMessage* message = new BMessage(kMsgSetHinting); + message->AddBool("hinting", false); + + BMenuItem* item = new BMenuItem(kNoHintingLabel, message); + + fHintingMenu->AddItem(item); + + BMessage* message2 = new BMessage(kMsgSetHinting); + message2->AddBool("hinting", true); + + BMenuItem* item2 = new BMenuItem(kFullHintingLabel, message2); + + fHintingMenu->AddItem(item2); +} + + +void +AdvancedSettingsView::_SetCurrentAntialiasing() +{ + BMenuItem *item = fAntialiasingMenu->FindItem( + fCurrentSubpixelAntialiasing ? kSubpixelLabel : kGrayscaleLabel); + if (item != NULL) + item->SetMarked(true); +} + + +void +AdvancedSettingsView::_SetCurrentHinting() +{ + BMenuItem *item = fHintingMenu->FindItem( + fCurrentHinting ? kFullHintingLabel : kNoHintingLabel); + if (item != NULL) + item->SetMarked(true); +} + + +void +AdvancedSettingsView::SetDefaults() +{ +} + + +bool +AdvancedSettingsView::IsDefaultable() +{ + return false; +} + + +bool +AdvancedSettingsView::IsRevertable() +{ + return (fCurrentSubpixelAntialiasing != fSavedSubpixelAntialiasing) + || (fCurrentHinting != fSavedHinting); +} + + +void +AdvancedSettingsView::Revert() +{ + if (!IsRevertable()) + return; + + fCurrentSubpixelAntialiasing = fSavedSubpixelAntialiasing; + fCurrentHinting = fSavedHinting; +#ifdef INSTANT_UPDATE + _set_font_subpixel_antialiasing_(fCurrentSubpixelAntialiasing); + _set_hinting_(fCurrentHinting); +#endif + _SetCurrentAntialiasing(); + _SetCurrentHinting(); +} Index: src/preferences/fonts/FontView.h =================================================================== --- src/preferences/fonts/FontView.h (revision 26259) +++ src/preferences/fonts/FontView.h (working copy) @@ -12,6 +12,7 @@ #include "FontSelectionView.h" +#include "AdvancedSettingsView.h" class FontView : public BView { @@ -29,9 +30,9 @@ bool IsRevertable(); private: - FontSelectionView *fPlainView; - FontSelectionView *fBoldView; - FontSelectionView *fFixedView; + FontSelectionView *fPlainView; + FontSelectionView *fBoldView; + FontSelectionView *fFixedView; }; #endif /* FONT_VIEW_H */ Index: src/preferences/fonts/Jamfile =================================================================== --- src/preferences/fonts/Jamfile (revision 26259) +++ src/preferences/fonts/Jamfile (working copy) @@ -5,6 +5,7 @@ Preference Fonts : FontSelectionView.cpp + AdvancedSettingsView.cpp FontsSettings.cpp FontView.cpp main.cpp Index: src/preferences/fonts/AdvancedSettingsView.h =================================================================== --- src/preferences/fonts/AdvancedSettingsView.h (revision 0) +++ src/preferences/fonts/AdvancedSettingsView.h (revision 0) @@ -0,0 +1,56 @@ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> + */ +#ifndef ADVANCED_SETTINGS_VIEW_H +#define ADVANCED_SETTINGS_VIEW_H + + +#include <View.h> + +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 */ Index: src/preferences/fonts/MainWindow.cpp =================================================================== --- src/preferences/fonts/MainWindow.cpp (revision 26259) +++ src/preferences/fonts/MainWindow.cpp (working copy) @@ -6,6 +6,7 @@ * Mark Hogben * DarkWyrm <bpmagic@xxxxxxxxxxxxxxx> * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ @@ -25,7 +26,7 @@ MainWindow::MainWindow() - : BWindow(BRect(100, 100, 445, 340), "Fonts", B_TITLED_WINDOW, + : BWindow(BRect(100, 100, 445, 410), "Fonts", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) { BRect rect = Bounds(); @@ -60,6 +61,8 @@ rect = tabView->ContainerView()->Bounds().InsetByCopy(5, 8); fFontsView = new FontView(rect); + + fAdvancedSettings = new AdvancedSettingsView(rect, "Advanced"); tabView->AddTab(fFontsView); @@ -83,7 +86,8 @@ tabView->ContainerView()->ResizeBy(0, heightDiff); } - ResizeTo(tabView->Bounds().Width() + 10, tabView->Frame().bottom + 20 + buttonHeight); + ResizeTo(tabView->Bounds().Width() + 10, tabView->Frame().bottom + 20 + + buttonHeight); view->AddChild(tabView); fFontsView->ResizeToPreferred(); @@ -98,6 +102,23 @@ if (!screen.Frame().InsetByCopy(10, 10).Intersects(Frame())) _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 @@ -127,19 +148,25 @@ { switch (message->what) { case kMsgUpdate: - fDefaultsButton->SetEnabled(fFontsView->IsDefaultable()); - fRevertButton->SetEnabled(fFontsView->IsRevertable()); + fDefaultsButton->SetEnabled(fFontsView->IsDefaultable() + || fAdvancedSettings->IsDefaultable()); + fRevertButton->SetEnabled(fFontsView->IsRevertable() + || fAdvancedSettings->IsRevertable()); break; case kMsgSetDefaults: fFontsView->SetDefaults(); + fAdvancedSettings->SetDefaults(); fDefaultsButton->SetEnabled(false); - fRevertButton->SetEnabled(fFontsView->IsRevertable()); + fRevertButton->SetEnabled(fFontsView->IsRevertable() + || fAdvancedSettings->IsRevertable()); break; case kMsgRevert: fFontsView->Revert(); - fDefaultsButton->SetEnabled(fFontsView->IsDefaultable()); + fAdvancedSettings->Revert(); + fDefaultsButton->SetEnabled(fFontsView->IsDefaultable() + || fAdvancedSettings->IsDefaultable()); fRevertButton->SetEnabled(false); break; Index: headers/libs/agg/agg_renderer_base.h =================================================================== --- headers/libs/agg/agg_renderer_base.h (revision 26259) +++ headers/libs/agg/agg_renderer_base.h (working copy) @@ -205,7 +205,23 @@ 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, const color_type& c, cover_type cover) @@ -280,7 +296,30 @@ } m_ren->blend_solid_hspan(x, y, len, c, covers); } + + //-------------------------------------------------------------------- + void blend_solid_hspan_subpix(int x, int y, int len, + const color_type& c, + const cover_type* covers) + { + if(y > ymax()) return; + if(y < ymin()) return; + if(x < xmin()) + { + len -= 3 * (xmin() - x); + if(len <= 0) return; + covers += 3*(xmin() - x); + x = xmin(); + } + if(x + len / 3 > xmax()) + { + len = 3 * (xmax() - x + 1); + if(len <= 0) return; + } + m_ren->blend_solid_hspan_subpix(x, y, len, c, covers); + } + //-------------------------------------------------------------------- void blend_solid_vspan(int x, int y, int len, const color_type& c, Index: src/servers/app/DesktopSettings.h =================================================================== --- src/servers/app/DesktopSettings.h (revision 26239) +++ src/servers/app/DesktopSettings.h (working copy) @@ -4,6 +4,7 @@ * * Authors: * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ #ifndef DESKTOP_SETTINGS_H #define DESKTOP_SETTINGS_H @@ -51,6 +52,9 @@ const BMessage* WorkspacesMessage(int32 index) const; rgb_color UIColor(color_which which) const; + + bool FontSubpixelAntialiasing() const; + bool Hinting() const; protected: DesktopSettingsPrivate* fSettings; @@ -73,6 +77,9 @@ void SetShowAllDraggers(bool show); void SetUIColor(color_which which, const rgb_color color); + + void SetFontSubpixelAntialiasing(bool subpix); + void SetHinting(bool hinting); private: Desktop* fDesktop; Index: src/servers/app/FontCacheEntry.cpp =================================================================== --- src/servers/app/FontCacheEntry.cpp (revision 26239) +++ src/servers/app/FontCacheEntry.cpp (working copy) @@ -5,6 +5,7 @@ * Authors: * Maxim Shemanarev <mcseemagg@xxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ //---------------------------------------------------------------------------- @@ -35,7 +36,13 @@ 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 }; @@ -120,7 +127,7 @@ // TODO: encoding from font FT_Encoding charMap = FT_ENCODING_NONE; - bool hinting = true; // TODO: font.Hinting(); + bool hinting = sDefaultHinting; // TODO: font.Hinting(); if (!fEngine.Init(font.Path(), 0, font.Size(), charMap, renderingType, hinting)) { @@ -187,6 +194,10 @@ case glyph_data_gray8: gray8Adapter.init(glyph->data, glyph->data_size, x, y); break; + + case glyph_data_subpix: + gray8Adapter.init(glyph->data, glyph->data_size, x, y); + break; case glyph_data_outline: pathAdapter.init(glyph->data, glyph->data_size, x, y, scale); @@ -213,7 +224,7 @@ // TODO: read more of these from the font FT_Encoding charMap = FT_ENCODING_NONE; - bool hinting = true; // TODO: font.Hinting(); + bool hinting = sDefaultHinting; // TODO: font.Hinting(); sprintf(signature, "%ld,%u,%d,%d,%.1f,%d", font.GetFamilyAndStyle(), charMap, @@ -235,15 +246,29 @@ fUseCounter++; } +void +FontCacheEntry::SetDefaultRenderType(glyph_rendering renderingType) +{ + sDefaultRenderType = renderingType; +} + +void +FontCacheEntry::SetDefaultHinting(bool hinting) +{ + sDefaultHinting = hinting; +} + + // _RenderTypeFor /*static*/ glyph_rendering FontCacheEntry::_RenderTypeFor(const ServerFont& font) { - glyph_rendering renderingType = glyph_ren_native_gray8; + glyph_rendering renderingType = sDefaultRenderType; if (font.Rotation() != 0.0 || font.Shear() != 90.0 || font.FalseBoldWidth() != 0.0 || font.Flags() & B_DISABLE_ANTIALIASING - || font.Size() > 30) { + || font.Size() > 30 + || !sDefaultHinting) { renderingType = glyph_ren_outline; } return renderingType; Index: src/servers/app/FontEngine.cpp =================================================================== --- src/servers/app/FontEngine.cpp (revision 26239) +++ src/servers/app/FontEngine.cpp (working copy) @@ -6,6 +6,7 @@ * Maxim Shemanarev <mcseemagg@xxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> * Anthony Lee <don.anthony.lee@xxxxxxxxx> + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ //---------------------------------------------------------------------------- @@ -26,12 +27,18 @@ #include "FontEngine.h" +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_LCD_FILTER_H + #include <stdio.h> #include <agg_bitset_iterator.h> #include <agg_renderer_scanline.h> + + static const bool kFlipY = true; @@ -359,7 +366,145 @@ } } +// decompose_ft_bitmap_subpix +template<class Scanline, class ScanlineStorage> +void +decompose_ft_bitmap_subpix(const FT_Bitmap& bitmap, int x, int y, + bool flip_y, Scanline& sl, ScanlineStorage& storage) +{ + //Filtering weights + const uint8 filter[5] = { 0x10, 0x40, 0x70, 0x40, 0x10 }; + int i, j; + const uint8* buf = (const uint8*)bitmap.buffer; + int pitch = bitmap.pitch; + sl.reset(x-1, x + bitmap.width/3 + 1); + storage.prepare(); + if (flip_y) { + buf += bitmap.pitch * (bitmap.rows - 1); + y += bitmap.rows; + pitch = -pitch; + } + for (i = 0; i < bitmap.rows; i++) { + sl.reset_spans(); + + if (bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { + // font has built-in mono bitmap + agg::bitset_iterator bits(buf, 0); + int j; + for (j = 0; j < bitmap.width; j++) { + if (bits.bit()) + sl.add_cell(x + j, + agg::cover_full, agg::cover_full, agg::cover_full); + ++bits; + } + } else { + const uint8* p = buf; + uint32 coverRed; + uint32 coverGreen; + uint32 coverBlue; + int w = bitmap.width/3; + if (w && !((p[0] == p[1] && p[1] == p[2]) + && (w == 1 || (p[3] == p[4] && p[4] == p[5])))){ + coverRed = 0; + coverGreen = (p[0] * filter[0]) >> 8; + coverBlue = (p[0] * filter[1] + p[1] * filter[0]) >> 8; + coverGreen = coverGreen | ( -(coverGreen >> 8)); + coverBlue = coverBlue | ( -(coverBlue >> 8)); + if (coverRed || coverGreen || coverBlue){ + sl.add_cell(x - 1, coverRed, coverGreen, coverBlue); + } + } + for (j = 0; j < w; j++) { + if ((p[0] == p[1] && p[1] == p[2]) + && (j == 0 || (p[-3] == p[-2] && p[-2] == p[-1])) + && (j == w-1 || (p[3] == p[4] && p[4] == p[5]))){ + coverRed = p[0]; + coverGreen = p[0]; + coverBlue = p[0]; + } + else if ((p[0] == p[1] && p[1] == p[2]) + && (j < w-1 && p[3] == p[4] && p[4] == p[5]) + && (j == w-2 || (p[6] == p[7] && p[7] == p[8]))){ + coverRed = (((j > 0) ? (p[-2] * filter[4] + + p[-1] * filter[3]) : 0) + + p[0] * filter[2] + p[1] * filter[1] + + p[2] * filter[0]) + >> 8; + coverGreen = (((j > 0) ? (p[-1] * filter[4]) : 0) + + p[0] * filter[3] + p[1] * filter[2] + + p[2] * filter[1]) + >> 8; + coverBlue = (p[0] * filter[4] + + p[1] * filter[3] + p[2] * filter[2]) >> 8; + coverRed = coverRed | ( -(coverRed >> 8)); + coverGreen = coverGreen | ( -(coverGreen >> 8)); + coverBlue = coverBlue | ( -(coverBlue >> 8)); + } + else if ((p[0] == p[1] && p[1] == p[2]) + && (j > 0 && p[-3] == p[-2] && p[-2] == p[-1]) + && (j == 1 || (p[-6] == p[-5] && p[-5] == p[-4]))){ + coverRed = (p[0] * filter[2] + p[1] * filter[1] + + p[2] * filter[0]) >> 8; + coverGreen = (p[0] * filter[3] + p[1] * filter[2] + + p[2] * filter[1] + + ((j < w-1) ? (p[3] * filter[0]) : 0)) + >> 8; + coverBlue = (p[0] * filter[4] + p[1] * filter[3] + + p[2] * filter[2] + + ((j < w-1) ? (p[3] * filter[1] + + p[4] * filter[0]) : 0)) + >> 8; + coverRed = coverRed | ( -(coverRed >> 8)); + coverGreen = coverGreen | ( -(coverGreen >> 8)); + coverBlue = coverBlue | ( -(coverBlue >> 8)); + } + else { + coverRed = (((j > 0)?(p[-2] * filter[4] + + p[-1] * filter[3]):0) + + p[0] * filter[2] + p[1] * filter[1] + + p[2] * filter[0]) + >> 8; + coverGreen = (((j > 0) ? (p[-1] * filter[4]) : 0) + + p[0] * filter[3] + p[1] * filter[2] + + p[2] * filter[1] + + ((j < w-1) ? (p[3] * filter[0]) : 0)) + >> 8; + coverBlue = (p[0] * filter[4] + p[1] * filter[3] + + p[2] * filter[2] + + ((j < w-1) ? (p[3] * filter[1] + + p[4] * filter[0]) : 0)) + >> 8; + coverRed = coverRed | ( -(coverRed >> 8)); + coverGreen = coverGreen | ( -(coverGreen >> 8)); + coverBlue = coverBlue | ( -(coverBlue >> 8)); + } + if (coverRed || coverGreen || coverBlue) { + sl.add_cell(x + j, coverRed, coverGreen, coverBlue); + } + p+=3; + } + if (w && !((p[-3] == p[-2] && p[-2] == p[-1]) + && (w == 1 || (p[-6] == p[-5] && p[-5] == p[-4])))){ + coverRed = (p[-2] * filter[4] + p[-1] * filter[3]) >> 8; + coverGreen = (p[-1] * filter[4]) >> 8; + coverBlue = 0; + coverRed = coverRed | ( -(coverRed >> 8)); + coverGreen = coverGreen | ( -(coverGreen >> 8)); + if (coverRed || coverGreen || coverBlue){ + sl.add_cell(x + w, coverRed, coverGreen, coverBlue); + } + } + } + + buf += pitch; + if (sl.num_spans()) { + sl.finalize(y - i - 1); + storage.render(sl); + } + } +} + // #pragma mark - @@ -386,8 +531,10 @@ , fCurves(fPath) , fScanlineAA() , fScanlineBin() + , fScanlineSubpix() , fScanlineStorageAA() , fScanlineStorageBin() + , fScanlineStorageSubpix() { fCurves.approximation_scale(4.0); @@ -421,7 +568,7 @@ { fGlyphIndex = FT_Get_Char_Index(fFace, glyphCode); fLastError = FT_Load_Glyph(fFace, fGlyphIndex, - fHinting ? FT_LOAD_DEFAULT : FT_LOAD_NO_HINTING); + (fHinting ? (FT_LOAD_DEFAULT | FT_LOAD_TARGET_LCD) : FT_LOAD_NO_HINTING)); // fHinting ? FT_LOAD_FORCE_AUTOHINT : FT_LOAD_NO_HINTING); if (fLastError != 0) @@ -469,7 +616,25 @@ } break; - + + case glyph_ren_subpix: + fLastError = FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD); + if (fLastError == 0) { + decompose_ft_bitmap_subpix(fFace->glyph->bitmap, + fFace->glyph->bitmap_left, kFlipY ? + -fFace->glyph->bitmap_top : fFace->glyph->bitmap_top, + kFlipY, fScanlineSubpix, fScanlineStorageSubpix); + fBounds.x1 = fScanlineStorageSubpix.min_x(); + fBounds.y1 = fScanlineStorageSubpix.min_y(); + fBounds.x2 = fScanlineStorageSubpix.max_x(); + fBounds.y2 = fScanlineStorageSubpix.max_y(); + fDataSize = fScanlineStorageSubpix.byte_size(); + fDataType = glyph_data_subpix; + return true; + } + break; + + case glyph_ren_outline: fPath.remove_all(); if (decompose_ft_outline(fFace->glyph->outline, kFlipY, fPath)) { @@ -502,6 +667,10 @@ case glyph_data_gray8: fScanlineStorageAA.serialize(data); break; + + case glyph_data_subpix: + fScanlineStorageSubpix.serialize(data); + break; case glyph_data_outline: fPath.serialize(data); @@ -570,6 +739,10 @@ case glyph_ren_native_gray8: fGlyphRendering = glyph_ren_native_gray8; break; + + case glyph_ren_subpix: + fGlyphRendering = glyph_ren_subpix; + break; case glyph_ren_outline: if (FT_IS_SCALABLE(fFace)) @@ -580,7 +753,7 @@ } FT_Set_Pixel_Sizes(fFace, - unsigned(size * 64.0) >> 6, // pixel_width + (unsigned(size * 64.0) >> 6), // pixel_width unsigned(size * 64.0) >> 6); // pixel_height if (charMap != FT_ENCODING_NONE) { Index: src/servers/app/agg_scanline_storage_subpix.h =================================================================== --- src/servers/app/agg_scanline_storage_subpix.h (revision 0) +++ src/servers/app/agg_scanline_storage_subpix.h (revision 0) @@ -0,0 +1,682 @@ +/* + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + * Class scanline_storage_subpix, a slightly modified version of + * scanline_storage customized to store 3 covers per pixel + * + */ + +#ifndef AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED +#define AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED + +#include <string.h> +#include <stdlib.h> +#include <math.h> +#include "agg_array.h" +#include "agg_scanline_storage_aa.h" + + +namespace agg +{ + //--------------------------------------------scanline_storage_subpix + template<class T> 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<class Scanline> 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<class Scanline> 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<T> m_covers; + pod_bvector<span_data, 10> m_spans; + pod_bvector<scanline_data, 8> 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<int8u> scanline_storage_subpix8; //--------scanline_storage_subpix8 + typedef scanline_storage_subpix<int16u> scanline_storage_subpix16; //--------scanline_storage_subpix16 + typedef scanline_storage_subpix<int32u> scanline_storage_subpix32; //--------scanline_storage_subpix32 + + + //--------------------------------------serialized_scanlines_adaptor_subpix + template<class T> 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<class Scanline> 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<int8u> + serialized_scanlines_adaptor_subpix8; //serialized_scanlines_adaptor_subpix8 + + typedef serialized_scanlines_adaptor_subpix<int16u> + serialized_scanlines_adaptor_subpix16; //serialized_scanlines_adaptor_subpix16 + + typedef serialized_scanlines_adaptor_subpix<int32u> + serialized_scanlines_adaptor_subpix32; //serialized_scanlines_adaptor_subpix32 + +} + + +#endif + Index: src/servers/app/ServerApp.cpp =================================================================== --- src/servers/app/ServerApp.cpp (revision 26239) +++ src/servers/app/ServerApp.cpp (working copy) @@ -9,6 +9,7 @@ * Stefano Ceccherini (burton666@xxxxxxxxx) * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx * Jérôme Duval, jerome.duval@xxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ /*! @@ -2534,6 +2535,46 @@ fLink.Flush(); break; } + + case AS_SET_FONT_SUBPIXEL_ANTIALIASING: + { + bool subpix; + if (link.Read<bool>(&subpix) == B_OK) { + LockedDesktopSettings settings(fDesktop); + settings.SetFontSubpixelAntialiasing(subpix); + } + fDesktop->Redraw(); + break; + } + + case AS_GET_FONT_SUBPIXEL_ANTIALIASING: + { + DesktopSettings settings(fDesktop); + fLink.StartMessage(B_OK); + fLink.Attach<bool>(settings.FontSubpixelAntialiasing()); + fLink.Flush(); + break; + } + + case AS_SET_HINTING: + { + bool hinting; + if (link.Read<bool>(&hinting) == B_OK) { + LockedDesktopSettings settings(fDesktop); + settings.SetHinting(hinting); + } + fDesktop->Redraw(); + break; + } + + case AS_GET_HINTING: + { + DesktopSettings settings(fDesktop); + fLink.StartMessage(B_OK); + fLink.Attach<bool>(settings.Hinting()); + fLink.Flush(); + break; + } default: printf("ServerApp %s received unhandled message code %ld\n", Index: src/servers/app/FontCacheEntry.h =================================================================== --- src/servers/app/FontCacheEntry.h (revision 26239) +++ src/servers/app/FontCacheEntry.h (working copy) @@ -5,6 +5,7 @@ * Authors: * Maxim Shemanarev <mcseemagg@xxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ //---------------------------------------------------------------------------- @@ -60,6 +61,7 @@ typedef GlyphGray8Adapter::embedded_scanline GlyphGray8Scanline; typedef FontEngine::MonoAdapter GlyphMonoAdapter; typedef GlyphMonoAdapter::embedded_scanline GlyphMonoScanline; + typedef FontEngine::SubpixAdapter SubpixAdapter; typedef agg::conv_curve<GlyphPathAdapter> CurveConverter; typedef agg::conv_contour<CurveConverter> ContourConverter; @@ -92,6 +94,13 @@ static void GenerateSignature(char* signature, const ServerFont& font); + + static void SetDefaultRenderType(glyph_rendering renderType); + static glyph_rendering DefaultRenderType() + { return sDefaultRenderType; } + static void SetDefaultHinting(bool hinting); + static bool DefaultHinting() + { return sDefaultHinting; } // private to FontCache class: void UpdateUsage(); @@ -110,6 +119,8 @@ GlyphCachePool* fGlyphCache; FontEngine fEngine; + static glyph_rendering sDefaultRenderType; + static bool sDefaultHinting; static BLocker sUsageUpdateLock; bigtime_t fLastUsedTime; Index: src/servers/app/FontEngine.h =================================================================== --- src/servers/app/FontEngine.h (revision 26239) +++ src/servers/app/FontEngine.h (working copy) @@ -5,6 +5,7 @@ * Authors: * Maxim Shemanarev <mcseemagg@xxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ //---------------------------------------------------------------------------- @@ -39,11 +40,15 @@ #include <agg_conv_curve.h> #include <agg_trans_affine.h> +#include "agg_scanline_storage_subpix.h" +#include "agg_scanline_u_subpix.h" + enum glyph_rendering { glyph_ren_native_mono, glyph_ren_native_gray8, glyph_ren_outline, + glyph_ren_subpix }; @@ -51,15 +56,18 @@ glyph_data_invalid = 0, glyph_data_mono = 1, glyph_data_gray8 = 2, - glyph_data_outline = 3 + glyph_data_outline = 3, + glyph_data_subpix = 4 }; class FontEngine { public: + typedef agg::serialized_scanlines_adaptor_subpix<uint8> SubpixAdapter; typedef agg::serialized_scanlines_adaptor_aa<uint8> Gray8Adapter; typedef agg::serialized_scanlines_adaptor_bin MonoAdapter; typedef agg::scanline_storage_aa8 ScanlineStorageAA; + typedef agg::scanline_storage_subpix8 ScanlineStorageSubpix; typedef agg::scanline_storage_bin ScanlineStorageBin; typedef agg::serialized_integer_path_adaptor<int32, 6> PathAdapter; @@ -139,9 +147,11 @@ CurveConverterType fCurves; agg::scanline_u8 fScanlineAA; agg::scanline_bin fScanlineBin; + agg::scanline_u8_subpix fScanlineSubpix; ScanlineStorageAA fScanlineStorageAA; ScanlineStorageBin fScanlineStorageBin; + ScanlineStorageSubpix fScanlineStorageSubpix; }; Index: src/servers/app/drawing/Painter/AGGTextRenderer.h =================================================================== --- src/servers/app/drawing/Painter/AGGTextRenderer.h (revision 26239) +++ src/servers/app/drawing/Painter/AGGTextRenderer.h (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. */ #ifndef AGG_TEXT_RENDERER_H #define AGG_TEXT_RENDERER_H @@ -21,7 +22,8 @@ class AGGTextRenderer { public: - AGGTextRenderer(renderer_type& solidRenderer, + AGGTextRenderer(renderer_subpix_type& subpixRenderer, + renderer_type& solidRenderer, renderer_bin_type& binRenderer, scanline_unpacked_type& scanline); virtual ~AGGTextRenderer(); @@ -62,12 +64,14 @@ FontCacheEntry::GlyphGray8Scanline fGray8Scanline; FontCacheEntry::GlyphMonoAdapter fMonoAdaptor; FontCacheEntry::GlyphMonoScanline fMonoScanline; + FontCacheEntry::SubpixAdapter fSubpixAdaptor; FontCacheEntry::CurveConverter fCurves; FontCacheEntry::ContourConverter fContour; renderer_type& fSolidRenderer; renderer_bin_type& fBinRenderer; + renderer_subpix_type& fSubpixRenderer; scanline_unpacked_type& fScanline; rasterizer_type fRasterizer; // NOTE: the object has it's own rasterizer object Index: src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h =================================================================== --- src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h (revision 0) +++ src/servers/app/drawing/Painter/agg_renderer_scanline_subpix.h (revision 0) @@ -0,0 +1,85 @@ +/* + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + */ + +#include <Region.h> + +#include "agg_basics.h" +#include "agg_array.h" +#include "agg_renderer_base.h" +#include "agg_renderer_scanline.h" + + +namespace agg +{ + + //============================================render_scanline_subpix_solid + template<class Scanline, class BaseRenderer, class ColorT> + 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; + } + } + + + //==========================================renderer_scanline_subpix_solid + template<class BaseRenderer> 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; + } + + //-------------------------------------------------------------------- + void color(const color_type& c) { m_color = c; } + const color_type& color() const { return m_color; } + + //-------------------------------------------------------------------- + void prepare() {} + + //-------------------------------------------------------------------- + template<class Scanline> void render(const Scanline& sl) + { + render_scanline_subpix_solid(sl, *m_ren, m_color); + } + + private: + base_ren_type* m_ren; + color_type m_color; + }; + +} Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeBlendSUBPIX.h (revision 0) @@ -0,0 +1,98 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ADD on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_BLEND_SUBPIX_H +#define DRAWING_MODE_BLEND_SUBPIX_H + +#include "DrawingMode.h" + + +// BLEND_BLEND_SUBPIX +#define BLEND_BLEND_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + 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_SUBPIX(d, rt, gt, bt, a1, a2, a3); \ +} + +// 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++; + } while(--len); + } else { + do { + rgb_color color = pattern->ColorAt(x, y); + + BLEND_BLEND(p, color.red, color.green, color.blue, cover); + + x++; + p += 4; + 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); + 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + + +#endif // DRAWING_MODE_BLEND_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeSubtractSUBPIX.h (revision 0) @@ -0,0 +1,100 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_SUBTRACT on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_SUBTRACT_SUBPIX_H +#define DRAWING_MODE_SUBTRACT_SUBPIX_H + +#include <SupportDefs.h> + +#include "DrawingMode.h" +#include "PatternHandler.h" + +// BLEND_SUBTRACT_SUBPIX +#define BLEND_SUBTRACT_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + 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_SUBPIX(d, rt, gt, bt, a1, a2, a3); \ +} + +// 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, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_SUBTRACT_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSolidSUBPIX.h (revision 0) @@ -0,0 +1,80 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_CO_SOLID_SUBPIX_H +#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); + } + } +} + +// blend_solid_hspan_alpha_co_solid_subpix +void +blend_solid_hspan_alpha_co_solid_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); + uint8 hAlpha = pattern->HighColor().alpha; + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + alphaRed = hAlpha * covers[0]; + alphaGreen = hAlpha * covers[1]; + alphaBlue = hAlpha * covers[2]; + BLEND_ALPHA_CO_SUBPIX(p, c.r, c.g, c.b, + alphaBlue, alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + + +#endif // DRAWING_MODE_ALPHA_CO_SOLID_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeInvertSUBPIX.h (revision 0) @@ -0,0 +1,91 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_INVERT on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_INVERT_SUBPIX_H +#define DRAWING_MODE_INVERT_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_INVERT_SUBPIX +#define BLEND_INVERT_SUBPIX(d, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + BLEND_SUBPIX(d, 255 - _p.data8[2], 255 - _p.data8[1], 255 - _p.data8[0], \ + a1, a2, a3); \ +} + +// 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); + do { + if (pattern->IsHighColor(x, y)) { + BLEND_INVERT_SUBPIX(p, covers[2], covers[1], covers[0]); + } + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + + +#endif // DRAWING_MODE_INVERT_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPCSUBPIX.h (revision 0) @@ -0,0 +1,84 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Pixel Composite" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_PC_SUBPIX_H +#define DRAWING_MODE_ALPHA_PC_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_ALPHA_PC_SUBPIX +#define BLEND_ALPHA_PC_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND_COMPOSITE16_SUBPIX(d, r, g, b, a1, a2, a3); \ +} + +// 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, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 2); + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + rgb_color color = pattern->ColorAt(x, y); + alphaRed = color.alpha * covers[0]; + alphaGreen = color.alpha * covers[1]; + alphaBlue = color.alpha * covers[2]; + BLEND_ALPHA_PC_SUBPIX(p, color.red, color.green, color.blue, + alphaBlue, alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ALPHA_PC_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSUBPIX.h (revision 0) @@ -0,0 +1,93 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_OVER on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_OVER_SUBPIX_H +#define DRAWING_MODE_OVER_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_OVER_SUBPIX +#define BLEND_OVER_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND_SUBPIX(d, r, g, b, a1, a2, a3) \ +} + +// 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 > 0); + } +} + +// blend_solid_hspan_over_subpix +void +blend_solid_hspan_over_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); + rgb_color color = pattern->HighColor(); + do { + if (pattern->IsHighColor(x, y)) { + BLEND_OVER_SUBPIX(p, color.red, color.green, color.blue, + covers[2], covers[1], covers[0]); + } + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_OVER_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h (revision 26239) +++ src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx> + * All rights reserved. Distributed under the terms of the MIT License. * * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) * @@ -103,6 +104,11 @@ unsigned len, 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, @@ -113,6 +119,11 @@ unsigned len, const color_type& c, const uint8* covers); + + inline void blend_solid_hspan_subpix(int x, int y, + unsigned len, + const color_type& c, + const uint8* covers); inline void blend_solid_vspan(int x, int y, unsigned len, @@ -138,8 +149,10 @@ blend_pixel_f fBlendPixel; blend_line fBlendHLine; + blend_line fBlendHLineSubpix; blend_line fBlendVLine; blend_solid_span fBlendSolidHSpan; + blend_solid_span fBlendSolidHSpanSubpix; blend_solid_span fBlendSolidVSpan; blend_color_span fBlendColorHSpan; blend_color_span fBlendColorVSpan; @@ -198,6 +211,14 @@ 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, @@ -214,6 +235,14 @@ fBlendSolidHSpan(x, y, len, c, covers, fBuffer, fPatternHandler); } +// blend_solid_hspan_subpix +inline void +PixelFormat::blend_solid_hspan_subpix(int x, int y, unsigned len, + const color_type& c, const uint8* covers) +{ + fBlendSolidHSpanSubpix(x, y, len, c, covers, fBuffer, fPatternHandler); +} + // blend_solid_vspan inline void PixelFormat::blend_solid_vspan(int x, int y, unsigned len, Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeSelectSUBPIX.h (revision 0) @@ -0,0 +1,93 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_SELECT on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_SELECT_SUBPIX_H +#define DRAWING_MODE_SELECT_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_SELECT_SUBPIX +#define BLEND_SELECT_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND_SUBPIX(d, r, g, b, a1, a2, a3); \ +} + +// 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, const uint8* covers, + 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; + 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_SELECT_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSolidSUBPIX.h (revision 0) @@ -0,0 +1,78 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_PO_SOLID_SUBPIX_H +#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); + } + } +} + +// blend_solid_hspan_alpha_po_solid_subpix +void +blend_solid_hspan_alpha_po_solid_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); + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + alphaRed = c.a * covers[0]; + alphaGreen = c.a * covers[1]; + alphaBlue = c.a * covers[2]; + BLEND_ALPHA_PO_SUBPIX(p, c.r, c.g, c.b, + alphaBlue, alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ALPHA_PO_SOLID_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopyTextSUBPIX.h (revision 0) @@ -0,0 +1,68 @@ +/* + * Copyright 2006, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_COPY for text on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_COPY_TEXT_SUBPIX_H +#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); + } +} + +// blend_solid_hspan_copy_text_subpix +void +blend_solid_hspan_copy_text_subpix(int x, int y, unsigned len, + const color_type& c, const uint8* covers, + agg_buffer* buffer, + const PatternHandler* pattern) +{ +//printf("blend_solid_hspan_copy_text(%d, %d)\n", x, len); + uint8* p = buffer->row_ptr(y) + (x << 2); + //rgb_color l = pattern->LowColor(); + do { + BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_COPY_TEXT_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeMinSUBPIX.h (revision 0) @@ -0,0 +1,98 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_MIN on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_MIN_SUBPIX_H +#define DRAWING_MODE_MIN_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_MIN_SUBPIX +#define BLEND_MIN_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + uint8 rt = min_c(_p.data8[2], (r)); \ + uint8 gt = min_c(_p.data8[1], (g)); \ + uint8 bt = min_c(_p.data8[0], (b)); \ + BLEND_SUBPIX(d, rt, gt, bt, a1, a2, a3); \ +} + +// BLEND_MIN +#define BLEND_MIN(d, r, g, b, a) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + uint8 rt = min_c(_p.data8[2], (r)); \ + uint8 gt = min_c(_p.data8[1], (g)); \ + uint8 bt = min_c(_p.data8[0], (b)); \ + BLEND(d, rt, gt, bt, a); \ +} + +// ASSIGN_MIN +#define ASSIGN_MIN(d, r, g, b) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + d[0] = min_c(_p.data8[0], (b)); \ + d[1] = min_c(_p.data8[1], (g)); \ + d[2] = min_c(_p.data8[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); + } +} + +// Maybe this would make more sense without any filtering? +// 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); + 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_MIN_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingMode.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingMode.h (revision 26239) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingMode.h (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. * * Base class for different drawing modes. * @@ -34,6 +35,16 @@ d[3] = 255; \ } +#define BLEND_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \ + d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \ + d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \ + d[3] = 255; \ +} + // BLEND_FROM // // This macro assumes source alpha in range 0..255 and @@ -49,6 +60,14 @@ d[3] = 255; \ } +#define BLEND_FROM_SUBPIX(d, r1, g1, b1, r2, g2, b2, a1, a2, a3) \ +{ \ + d[0] = (((((b2) - (b1)) * (a1)) + ((b1) << 8)) >> 8); \ + d[1] = (((((g2) - (g1)) * (a2)) + ((g1) << 8)) >> 8); \ + d[2] = (((((r2) - (r1)) * (a3)) + ((r1) << 8)) >> 8); \ + d[3] = 255; \ +} + // BLEND16 // // This macro assumes source alpha in range 0..65025 and @@ -65,8 +84,17 @@ d[3] = 255; \ } +// BLEND16_SUBPIX +#define BLEND16_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 16)) >> 16); \ + d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 16)) >> 16); \ + d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 16)) >> 16); \ + d[3] = 255; \ +} - // BLEND_COMPOSITE // // This macro assumes source alpha in range 0..255 and @@ -99,6 +127,43 @@ } \ } +// BLEND_COMPOSITE_SUBPIX +#define BLEND_COMPOSITE_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + if (_p.data8[3] == 255) { \ + d[0] = (((((b) - _p.data8[0]) * (a1)) + (_p.data8[0] << 8)) >> 8); \ + d[1] = (((((g) - _p.data8[1]) * (a2)) + (_p.data8[1] << 8)) >> 8); \ + d[2] = (((((r) - _p.data8[2]) * (a3)) + (_p.data8[2] << 8)) >> 8); \ + d[3] = 255; \ + } else { \ + if (_p.data8[3] == 0) { \ + d[0] = (b); \ + d[1] = (g); \ + d[2] = (r); \ + d[3] = (a1 + a2 + a3)/3; \ + } else { \ + uint8 alphaRest1 = 255 - (a1); \ + uint8 alphaRest2 = 255 - (a2); \ + uint8 alphaRest3 = 255 - (a3); \ + uint32 alphaTemp1 = (65025 - alphaRest1 * (255 - _p.data8[3])); \ + uint32 alphaTemp2 = (65025 - alphaRest2 * (255 - _p.data8[3])); \ + uint32 alphaTemp3 = (65025 - alphaRest3 * (255 - _p.data8[3])); \ + uint32 alphaDest1 = _p.data8[3] * alphaRest1; \ + uint32 alphaDest2 = _p.data8[3] * alphaRest2; \ + uint32 alphaDest3 = _p.data8[3] * alphaRest3; \ + uint32 alphaSrc1 = 255 * (a1); \ + uint32 alphaSrc2 = 255 * (a2); \ + uint32 alphaSrc3 = 255 * (a3); \ + d[0] = (_p.data8[0] * alphaDest1 + (b) * alphaSrc1) / alphaTemp1; \ + d[1] = (_p.data8[1] * alphaDest2 + (g) * alphaSrc2) / alphaTemp2; \ + d[2] = (_p.data8[2] * alphaDest3 + (r) * alphaSrc3) / alphaTemp3; \ + d[3] = (alphaTemp1 + alphaTemp2 + alphaTemp3)/765; \ + } \ + } \ +} + // BLEND_COMPOSITE16 // // This macro assumes source alpha in range 0..65025 and @@ -110,6 +175,14 @@ BLEND_COMPOSITE(d, r, g, b, _a); \ } +// BLEND_COMPOSITE16_SUBPIX +#define BLEND_COMPOSITE16_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + uint16 _a1 = (a1) / 255; \ + uint16 _a2 = (a2) / 255; \ + uint16 _a3 = (a3) / 255; \ + BLEND_COMPOSITE_SUBPIX(d, r, g, b, _a1, _a2, _a3); \ +} static inline uint8 @@ -121,6 +194,5 @@ return uint8((308 * red + 600 * green + 116 * blue) / 1024); } - #endif // DRAWING_MODE_H Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaPOSUBPIX.h (revision 0) @@ -0,0 +1,84 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_PO_SUBPIX_H +#define DRAWING_MODE_ALPHA_PO_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_ALPHA_PO_SUBPIX +#define BLEND_ALPHA_PO_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + 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 +blend_solid_hspan_alpha_po_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); + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + rgb_color color = pattern->ColorAt(x, y); + alphaRed = color.alpha * covers[0]; + alphaGreen = color.alpha * covers[1]; + alphaBlue = color.alpha * covers[2]; + BLEND_ALPHA_PO_SUBPIX(p, color.red, color.green, color.blue, + alphaBlue, alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ALPHA_PO_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeMaxSUBPIX.h (revision 0) @@ -0,0 +1,98 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_MAX on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_MAX_SUBPIX_H +#define DRAWING_MODE_MAX_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_MAX_SUBPIX +#define BLEND_MAX_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + uint8 rt = max_c(_p.data8[2], (r)); \ + uint8 gt = max_c(_p.data8[1], (g)); \ + uint8 bt = max_c(_p.data8[0], (b)); \ + BLEND_SUBPIX(d, rt, gt, bt, a1, a2, a3); \ +} + +// BLEND_MAX +#define BLEND_MAX(d, r, g, b, a) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + uint8 rt = max_c(_p.data8[2], (r)); \ + uint8 gt = max_c(_p.data8[1], (g)); \ + uint8 bt = max_c(_p.data8[0], (b)); \ + BLEND(d, rt, gt, bt, a); \ +} + +// ASSIGN_MAX +#define ASSIGN_MAX(d, r, g, b) \ +{ \ + pixel32 _p; \ + _p.data32 = *(uint32*)d; \ + d[0] = max_c(_p.data8[0], (b)); \ + d[1] = max_c(_p.data8[1], (g)); \ + d[2] = max_c(_p.data8[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); + } +} + +// Maybe this would make more sense without any filtering? +// 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); + 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_MAX_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAddSUBPIX.h (revision 0) @@ -0,0 +1,99 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ADD on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ADD_SUBPIX_H +#define DRAWING_MODE_ADD_SUBPIX_H + +#include "DrawingMode.h" + + +// BLEND_ADD_SUBPIX +#define BLEND_ADD_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + 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_SUBPIX(d, rt, gt, bt, a1, a2, a3); \ +} + + +// 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++; + } 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) +{ + 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 += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + + +#endif // DRAWING_MODE_ADD_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCCSUBPIX.h (revision 0) @@ -0,0 +1,110 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Constant Composite" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_CC_SUBPIX_H +#define DRAWING_MODE_ALPHA_CC_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_ALPHA_CC_SUBPIX +#define BLEND_ALPHA_CC_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND_COMPOSITE16_SUBPIX(d, r, g, b, a1, a2, a3); \ +} + +// 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, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 2); + uint8 hAlpha = pattern->HighColor().alpha; + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + alphaRed = hAlpha * covers[0]; + alphaGreen = hAlpha * covers[1]; + alphaBlue = hAlpha * covers[2]; + rgb_color color = pattern->ColorAt(x, y); + BLEND_ALPHA_CC_SUBPIX(p, color.red, color.green, color.blue, + alphaBlue,alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ALPHA_CC_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeEraseSUBPIX.h (revision 0) @@ -0,0 +1,92 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ERASE on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ERASE_SUBPIX_H +#define DRAWING_MODE_ERASE_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_ERASE_SUBPIX +#define BLEND_ERASE_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND_SUBPIX(d, r, g, b, a1, a2, a3); \ +} + +// 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, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 2); + rgb_color color = pattern->LowColor(); + do { + if (pattern->IsHighColor(x, y)) { + BLEND_ERASE_SUBPIX(p, color.red, color.green, color.blue, covers[2], covers[1], covers[0]); + } + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ERASE_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySolidSUBPIX.h (revision 0) @@ -0,0 +1,64 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_COPY ignoring the pattern (solid) on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_COPY_SOLID_SUBPIX_H +#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); + } +} + +// blend_solid_hspan_copy_solid_subpix +void +blend_solid_hspan_copy_solid_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); + do { + BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_COPY_SOLID_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeOverSolidSUBPIX.h (revision 0) @@ -0,0 +1,69 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_OVER on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_OVER_SOLID_SUBPIX_H +#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); + } +} + +// blend_solid_hspan_over_solid_subpix +void +blend_solid_hspan_over_solid_subpix(int x, int y, unsigned len, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + if (pattern->IsSolidLow()) + return; + + uint8* p = buffer->row_ptr(y) + (x << 2); + do { + BLEND_OVER_SUBPIX(p, c.r, c.g, c.b, covers[2], covers[1], covers[0]); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_OVER_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeAlphaCOSUBPIX.h (revision 0) @@ -0,0 +1,110 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_ALPHA in "Constant Overlay" mode on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_ALPHA_CO_SUBPIX_H +#define DRAWING_MODE_ALPHA_CO_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_ALPHA_CO_SUBPIX +#define BLEND_ALPHA_CO_SUBPIX(d, r, g, b, a1, a2, a3) \ +{ \ + BLEND16_SUBPIX(d, r, g, b, a1, a2, a3); \ +} + +// 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, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 2); + uint8 hAlpha = pattern->HighColor().alpha; + uint16 alphaRed; + uint16 alphaGreen; + uint16 alphaBlue; + do { + alphaRed = hAlpha * covers[0]; + alphaGreen = hAlpha * covers[1]; + alphaBlue = hAlpha * covers[2]; + rgb_color color = pattern->ColorAt(x, y); + BLEND_ALPHA_CO_SUBPIX(p, color.red, color.green, color.blue, + alphaBlue, alphaGreen, alphaRed); + covers += 3; + p += 4; + x++; + len -= 3; + } while(len); +} + +#endif // DRAWING_MODE_ALPHA_CO_SUBPIX_H + Index: src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp (revision 26239) +++ src/servers/app/drawing/Painter/drawing_modes/PixelFormat.cpp (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx> + * All rights reserved. Distributed under the terms of the MIT License. * * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) * @@ -34,6 +35,26 @@ #include "DrawingModeSelect.h" #include "DrawingModeSubtract.h" +#include "DrawingModeAddSUBPIX.h" +#include "DrawingModeAlphaCCSUBPIX.h" +#include "DrawingModeAlphaCOSUBPIX.h" +#include "DrawingModeAlphaCOSolidSUBPIX.h" +#include "DrawingModeAlphaPCSUBPIX.h" +#include "DrawingModeAlphaPOSUBPIX.h" +#include "DrawingModeAlphaPOSolidSUBPIX.h" +#include "DrawingModeBlendSUBPIX.h" +#include "DrawingModeCopySUBPIX.h" +#include "DrawingModeCopySolidSUBPIX.h" +#include "DrawingModeCopyTextSUBPIX.h" +#include "DrawingModeEraseSUBPIX.h" +#include "DrawingModeInvertSUBPIX.h" +#include "DrawingModeMinSUBPIX.h" +#include "DrawingModeMaxSUBPIX.h" +#include "DrawingModeOverSUBPIX.h" +#include "DrawingModeOverSolidSUBPIX.h" +#include "DrawingModeSelectSUBPIX.h" +#include "DrawingModeSubtractSUBPIX.h" + #include "PatternHandler.h" // blend_pixel_empty @@ -53,6 +74,15 @@ printf("blend_hline_empty()\n"); } +// blend_hline_subpix_empty +void +blend_hline_empty_subpix(int x, int y, unsigned len, + const color_type& c, uint8 cover, + agg_buffer* buffer, const PatternHandler* pattern) +{ + printf("blend_hline_empty_subpix()\n"); +} + // blend_vline_empty void blend_vline_empty(int x, int y, unsigned len, @@ -71,6 +101,15 @@ printf("blend_solid_hspan_empty()\n"); } +// blend_solid_hspan_subpix_empty +void +blend_solid_hspan_empty_subpix(int x, int y, unsigned len, + const color_type& c, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + printf("blend_solid_hspan_empty_subpix()\n"); +} + // blend_solid_vspan_empty void blend_solid_vspan_empty(int x, int y, @@ -112,8 +151,10 @@ fBlendPixel(blend_pixel_empty), fBlendHLine(blend_hline_empty), + fBlendHLineSubpix(blend_hline_empty_subpix), fBlendVLine(blend_vline_empty), fBlendSolidHSpan(blend_solid_hspan_empty), + fBlendSolidHSpanSubpix(blend_solid_hspan_empty_subpix), fBlendSolidVSpan(blend_solid_vspan_empty), fBlendColorHSpan(blend_color_hspan_empty), fBlendColorVSpan(blend_color_vspan_empty) @@ -140,9 +181,13 @@ fBlendHLine = blend_hline_over_solid; fBlendSolidHSpan = blend_solid_hspan_over_solid; fBlendSolidVSpan = blend_solid_vspan_over_solid; + fBlendHLineSubpix = blend_hline_over_solid_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_over_solid_subpix; } else { fBlendPixel = blend_pixel_over; fBlendHLine = blend_hline_over; + fBlendHLineSubpix = blend_hline_over_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_over_subpix; fBlendSolidHSpan = blend_solid_hspan_over; fBlendSolidVSpan = blend_solid_vspan_over; } @@ -151,6 +196,8 @@ case B_OP_ERASE: fBlendPixel = blend_pixel_erase; fBlendHLine = blend_hline_erase; + fBlendHLineSubpix = blend_hline_erase_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_erase_subpix; fBlendSolidHSpan = blend_solid_hspan_erase; fBlendSolidVSpan = blend_solid_vspan_erase; fBlendColorHSpan = blend_color_hspan_erase; @@ -158,6 +205,8 @@ case B_OP_INVERT: fBlendPixel = blend_pixel_invert; fBlendHLine = blend_hline_invert; + fBlendHLineSubpix = blend_hline_invert_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_invert_subpix; fBlendSolidHSpan = blend_solid_hspan_invert; fBlendSolidVSpan = blend_solid_vspan_invert; fBlendColorHSpan = blend_color_hspan_invert; @@ -165,6 +214,8 @@ case B_OP_SELECT: fBlendPixel = blend_pixel_select; fBlendHLine = blend_hline_select; + fBlendHLineSubpix = blend_hline_select_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_select_subpix; fBlendSolidHSpan = blend_solid_hspan_select; fBlendSolidVSpan = blend_solid_vspan_select; fBlendColorHSpan = blend_color_hspan_select; @@ -175,7 +226,9 @@ case B_OP_COPY: if (text) { fBlendPixel = blend_pixel_copy_text; - fBlendHLine = blend_hline_copy_text; + fBlendHLine = blend_hline_copy_text; + fBlendHLineSubpix = blend_hline_copy_text_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_copy_text_subpix; fBlendSolidHSpan = blend_solid_hspan_copy_text; fBlendSolidVSpan = blend_solid_vspan_copy_text; fBlendColorHSpan = blend_color_hspan_copy_text; @@ -186,12 +239,16 @@ } else if (fPatternHandler->IsSolid()) { fBlendPixel = blend_pixel_copy_solid; fBlendHLine = blend_hline_copy_solid; + fBlendHLineSubpix = blend_hline_copy_solid_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_copy_solid_subpix; fBlendSolidHSpan = blend_solid_hspan_copy_solid; fBlendSolidVSpan = blend_solid_vspan_copy_solid; fBlendColorHSpan = blend_color_hspan_copy_solid; } else { fBlendPixel = blend_pixel_copy; fBlendHLine = blend_hline_copy; + fBlendHLineSubpix = blend_hline_copy_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_copy_subpix; fBlendSolidHSpan = blend_solid_hspan_copy; fBlendSolidVSpan = blend_solid_vspan_copy; fBlendColorHSpan = blend_color_hspan_copy; @@ -199,7 +256,9 @@ break; case B_OP_ADD: fBlendPixel = blend_pixel_add; - fBlendHLine = blend_hline_add; + fBlendHLine = blend_hline_add; + fBlendHLineSubpix = blend_hline_add_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_add_subpix; fBlendSolidHSpan = blend_solid_hspan_add; fBlendSolidVSpan = blend_solid_vspan_add; fBlendColorHSpan = blend_color_hspan_add; @@ -207,6 +266,8 @@ case B_OP_SUBTRACT: fBlendPixel = blend_pixel_subtract; fBlendHLine = blend_hline_subtract; + fBlendHLineSubpix = blend_hline_subtract_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_subtract_subpix; fBlendSolidHSpan = blend_solid_hspan_subtract; fBlendSolidVSpan = blend_solid_vspan_subtract; fBlendColorHSpan = blend_color_hspan_subtract; @@ -214,6 +275,8 @@ case B_OP_BLEND: fBlendPixel = blend_pixel_blend; fBlendHLine = blend_hline_blend; + fBlendHLineSubpix = blend_hline_blend_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_blend_subpix; fBlendSolidHSpan = blend_solid_hspan_blend; fBlendSolidVSpan = blend_solid_vspan_blend; fBlendColorHSpan = blend_color_hspan_blend; @@ -221,6 +284,8 @@ case B_OP_MIN: fBlendPixel = blend_pixel_min; fBlendHLine = blend_hline_min; + fBlendHLineSubpix = blend_hline_min_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_min_subpix; fBlendSolidHSpan = blend_solid_hspan_min; fBlendSolidVSpan = blend_solid_vspan_min; fBlendColorHSpan = blend_color_hspan_min; @@ -228,6 +293,8 @@ case B_OP_MAX: fBlendPixel = blend_pixel_max; fBlendHLine = blend_hline_max; + fBlendHLineSubpix = blend_hline_max_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_max_subpix; fBlendSolidHSpan = blend_solid_hspan_max; fBlendSolidVSpan = blend_solid_vspan_max; fBlendColorHSpan = blend_color_hspan_max; @@ -247,11 +314,15 @@ if (fPatternHandler->IsSolid()) { fBlendPixel = blend_pixel_alpha_co_solid; fBlendHLine = blend_hline_alpha_co_solid; + fBlendHLineSubpix = blend_hline_alpha_co_solid_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_solid_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_co_solid; fBlendSolidVSpan = blend_solid_vspan_alpha_co_solid; } else { fBlendPixel = blend_pixel_alpha_co; fBlendHLine = blend_hline_alpha_co; + fBlendHLineSubpix = blend_hline_alpha_co_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_co_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_co; fBlendSolidVSpan = blend_solid_vspan_alpha_co; } @@ -259,6 +330,8 @@ } else if (alphaFncMode == B_ALPHA_COMPOSITE) { fBlendPixel = blend_pixel_alpha_cc; fBlendHLine = blend_hline_alpha_cc; + fBlendHLineSubpix = blend_hline_alpha_cc_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_cc_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_cc; fBlendSolidVSpan = blend_solid_vspan_alpha_cc; fBlendColorHSpan = blend_color_hspan_alpha_cc; @@ -268,11 +341,15 @@ if (fPatternHandler->IsSolid()) { fBlendPixel = blend_pixel_alpha_po_solid; fBlendHLine = blend_hline_alpha_po_solid; + fBlendHLineSubpix = blend_hline_alpha_po_solid_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_solid_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_po_solid; fBlendSolidVSpan = blend_solid_vspan_alpha_po_solid; } else { fBlendPixel = blend_pixel_alpha_po; fBlendHLine = blend_hline_alpha_po; + fBlendHLineSubpix = blend_hline_alpha_po_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_po_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_po; fBlendSolidVSpan = blend_solid_vspan_alpha_po; } @@ -280,6 +357,8 @@ } else if (alphaFncMode == B_ALPHA_COMPOSITE) { fBlendPixel = blend_pixel_alpha_pc; fBlendHLine = blend_hline_alpha_pc; + fBlendHLineSubpix = blend_hline_alpha_pc_subpix; + fBlendSolidHSpanSubpix = blend_solid_hspan_alpha_pc_subpix; fBlendSolidHSpan = blend_solid_hspan_alpha_pc; fBlendSolidVSpan = blend_solid_vspan_alpha_pc; fBlendColorHSpan = blend_color_hspan_alpha_pc; Index: src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h =================================================================== --- src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h (revision 0) +++ src/servers/app/drawing/Painter/drawing_modes/DrawingModeCopySUBPIX.h (revision 0) @@ -0,0 +1,106 @@ +/* + * Copyright 2005, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * DrawingMode implementing B_OP_COPY on B_RGBA32. + * + */ + +#ifndef DRAWING_MODE_COPY_SUBPIX_H +#define DRAWING_MODE_COPY_SUBPIX_H + +#include "DrawingMode.h" + +// BLEND_COPY_SUBPIX +#define BLEND_COPY_SUBPIX(d, r2, g2, b2, a1, a2, a3, r1, g1, b1) \ +{ \ + BLEND_FROM_SUBPIX(d, r1, g1, b1, r2, g2, b2, a1, a2, a3); \ +} + +// 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, const uint8* covers, + agg_buffer* buffer, const PatternHandler* pattern) +{ + uint8* p = buffer->row_ptr(y) + (x << 2); + rgb_color l = pattern->LowColor(); + 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 += 3; + p += 4; + x++; + if (len>3) len -= 3; else len = 0; + } while(len); +} + +#endif // DRAWING_MODE_COPY_SUBPIX_H + Index: src/servers/app/drawing/Painter/Painter.cpp =================================================================== --- src/servers/app/drawing/Painter/Painter.cpp (revision 26239) +++ src/servers/app/drawing/Painter/Painter.cpp (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. * * API to the Anti-Grain Geometry based "Painter" drawing backend. Manages * rendering pipe-lines for stroke, fills, bitmap and text rendering. @@ -57,6 +58,7 @@ fUnpackedScanline(), fPackedScanline(), fRasterizer(), + fSubpixRenderer(fBaseRenderer), fRenderer(fBaseRenderer), fRendererBin(fBaseRenderer), @@ -67,6 +69,7 @@ fValidClipping(false), fDrawingText(false), fAttached(false), + fSubpixelAntialias(true), fPenSize(1.0), fClippingRegion(NULL), @@ -78,7 +81,7 @@ fMiterLimit(B_DEFAULT_MITER_LIMIT), fPatternHandler(), - fTextRenderer(fRenderer, fRendererBin, fUnpackedScanline) + fTextRenderer(fSubpixRenderer, fRenderer, fRendererBin, fUnpackedScanline) { fPixelFormat.SetDrawingMode(fDrawingMode, fAlphaSrcMode, fAlphaFncMode, false); @@ -223,6 +226,14 @@ } } +void +Painter::SetSubpixelAntialiasing(bool subpixelAntialias) +{ + if (fSubpixelAntialias != subpixelAntialias) { + fSubpixelAntialias = subpixelAntialias; + } +} + // SetBlendingMode void Painter::SetBlendingMode(source_alpha srcAlpha, alpha_function alphaFunc) @@ -1172,6 +1183,10 @@ color.green / 255.0, color.blue / 255.0, color.alpha / 255.0)); + fSubpixRenderer.color(agg::rgba(color.red / 255.0, + color.green / 255.0, + color.blue / 255.0, + color.alpha / 255.0)); // TODO: bitmap fonts not yet correctly setup in AGGTextRenderer // fRendererBin.color(agg::rgba(color.red / 255.0, // color.green / 255.0, Index: src/servers/app/drawing/Painter/defines.h =================================================================== --- src/servers/app/drawing/Painter/defines.h (revision 26239) +++ src/servers/app/drawing/Painter/defines.h (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005-2006, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2006, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. * * global definitions for the Painter frame work, mainly types for the * AGG pipelines @@ -22,6 +23,7 @@ #include <agg_rendering_buffer.h> #include "agg_renderer_region.h" +#include "agg_renderer_scanline_subpix.h" #include "PixelFormat.h" @@ -47,6 +49,7 @@ #endif typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_bin_type; + typedef agg::renderer_scanline_subpix_solid<renderer_base> renderer_subpix_type; typedef agg::rasterizer_scanline_aa<> rasterizer_type; Index: src/servers/app/drawing/Painter/Painter.h =================================================================== --- src/servers/app/drawing/Painter/Painter.h (revision 26239) +++ src/servers/app/drawing/Painter/Painter.h (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. * * API to the Anti-Grain Geometry based "Painter" drawing backend. Manages * rendering pipe-lines for stroke, fills, bitmap and text rendering. @@ -72,6 +73,9 @@ 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); @@ -261,6 +265,7 @@ mutable scanline_unpacked_type fUnpackedScanline; mutable scanline_packed_type fPackedScanline; mutable rasterizer_type fRasterizer; +mutable renderer_subpix_type fSubpixRenderer; mutable renderer_type fRenderer; mutable renderer_bin_type fRendererBin; @@ -281,6 +286,7 @@ cap_mode fLineCapMode; join_mode fLineJoinMode; float fMiterLimit; + bool fSubpixelAntialias; PatternHandler fPatternHandler; Index: src/servers/app/drawing/Painter/AGGTextRenderer.cpp =================================================================== --- src/servers/app/drawing/Painter/AGGTextRenderer.cpp (revision 26239) +++ src/servers/app/drawing/Painter/AGGTextRenderer.cpp (working copy) @@ -1,6 +1,7 @@ /* - * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. All rights reserved. - * Distributed under the terms of the MIT License. + * Copyright 2005-2007, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. */ @@ -29,19 +30,22 @@ // constructor -AGGTextRenderer::AGGTextRenderer(renderer_type& solidRenderer, - renderer_bin_type& binRenderer, scanline_unpacked_type& scanline) +AGGTextRenderer::AGGTextRenderer(renderer_subpix_type& subpixRenderer, + renderer_type& solidRenderer, renderer_bin_type& binRenderer, + scanline_unpacked_type& scanline) : fPathAdaptor() , fGray8Adaptor() , fGray8Scanline() , fMonoAdaptor() , fMonoScanline() + , fSubpixAdaptor() , fCurves(fPathAdaptor) , fContour(fCurves) , fSolidRenderer(solidRenderer) , fBinRenderer(binRenderer) + , fSubpixRenderer(subpixRenderer) , fScanline(scanline) , fRasterizer() @@ -218,6 +222,12 @@ agg::render_scanlines(fRenderer.fGray8Adaptor, fRenderer.fGray8Scanline, fRenderer.fSolidRenderer); break; + + case glyph_data_subpix: + agg::render_scanlines(fRenderer.fGray8Adaptor, + fRenderer.fGray8Scanline, + fRenderer.fSubpixRenderer); + break; case glyph_data_outline: { fVector = true; Index: src/servers/app/drawing/Painter/agg_renderer_region.h =================================================================== --- src/servers/app/drawing/Painter/agg_renderer_region.h (revision 26239) +++ src/servers/app/drawing/Painter/agg_renderer_region.h (working copy) @@ -1,5 +1,6 @@ /* * Copyright 2005-2006, Stephan Aßmus <superstippi@xxxxxx>. + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. * All rights reserved. Distributed under the terms of the MIT License. * * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) @@ -200,6 +201,18 @@ } while(next_clip_box()); } + + //-------------------------------------------------------------------- + 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, @@ -248,6 +261,18 @@ } 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, Index: src/servers/app/Desktop.h =================================================================== --- src/servers/app/Desktop.h (revision 26239) +++ src/servers/app/Desktop.h (working copy) @@ -6,6 +6,7 @@ * Adrian Oanca <adioanca@xxxxxxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ #ifndef DESKTOP_H #define DESKTOP_H @@ -190,6 +191,7 @@ #endif // USE_MULTI_LOCKER void MarkDirty(BRegion& region); + void Redraw(); BRegion& BackgroundRegion() { return fBackgroundRegion; } Index: src/servers/app/DesktopSettings.cpp =================================================================== --- src/servers/app/DesktopSettings.cpp (revision 26239) +++ src/servers/app/DesktopSettings.cpp (working copy) @@ -5,12 +5,15 @@ * Authors: * Stephan Aßmus <superstippi@xxxxxx> * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ #include "DesktopSettings.h" #include "DesktopSettingsPrivate.h" #include "Desktop.h" +#include "FontCache.h" +#include "FontCacheEntry.h" #include "FontManager.h" #include "ServerConfig.h" @@ -69,6 +72,11 @@ fWorkspacesCount = 4; memcpy(fShared.colors, BPrivate::kDefaultColors, sizeof(rgb_color) * kNumColors); + + fFontSubpixelAntialiasing = false; + FontCacheEntry::SetDefaultRenderType(glyph_ren_native_gray8); + fHinting = true; + FontCacheEntry::SetDefaultHinting(true); } @@ -136,6 +144,8 @@ 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 && settings.FindFloat("plain size", &size) == B_OK) { @@ -158,7 +168,16 @@ fFixedFont.SetStyle(fontStyle); fFixedFont.SetSize(size); } - gFontManager->Unlock(); + 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); + } + gFontManager->Unlock(); } } @@ -273,6 +292,9 @@ settings.AddString("fixed family", fFixedFont.Family()); settings.AddString("fixed style", fFixedFont.Style()); settings.AddFloat("fixed size", fFixedFont.Size()); + + settings.AddBool("font subpix",fFontSubpixelAntialiasing); + settings.AddBool("hinting",fHinting); BFile file; status = file.SetTo(path.Path(), B_CREATE_FILE | B_ERASE_FILE | B_READ_WRITE); @@ -520,7 +542,39 @@ return fShared.colors[index]; } +void +DesktopSettingsPrivate::SetFontSubpixelAntialiasing(bool subpix) +{ + if (fFontSubpixelAntialiasing != subpix) { + fFontSubpixelAntialiasing = subpix; + FontCacheEntry::SetDefaultRenderType( + (subpix)?glyph_ren_subpix:glyph_ren_native_gray8); + Save(kFontSettings); + } +} +bool +DesktopSettingsPrivate::FontSubpixelAntialiasing() const +{ + return fFontSubpixelAntialiasing; +} + +void +DesktopSettingsPrivate::SetHinting(bool hinting) +{ + if (fHinting != hinting) { + fHinting = hinting; + FontCacheEntry::SetDefaultHinting(hinting); + Save(kFontSettings); + } +} + +bool +DesktopSettingsPrivate::Hinting() const +{ + return fHinting; +} + // #pragma mark - read access @@ -612,7 +666,18 @@ return fSettings->UIColor(which); } +bool +DesktopSettings::FontSubpixelAntialiasing() const +{ + return fSettings->FontSubpixelAntialiasing(); +} +bool +DesktopSettings::Hinting() const +{ + return fSettings->Hinting(); +} + // #pragma mark - write access @@ -690,4 +755,16 @@ fSettings->SetUIColor(which, color); } +void +LockedDesktopSettings::SetFontSubpixelAntialiasing(bool subpix) +{ + fSettings->SetFontSubpixelAntialiasing(subpix); +} +void +LockedDesktopSettings::SetHinting(bool hinting) +{ + fSettings->SetHinting(hinting); +} + + Index: src/servers/app/ProfileMessageSupport.cpp =================================================================== --- src/servers/app/ProfileMessageSupport.cpp (revision 26239) +++ src/servers/app/ProfileMessageSupport.cpp (working copy) @@ -9,7 +9,7 @@ #include "ProfileMessageSupport.h" -#include "ServerProtocol.h" +#include <ServerProtocol.h> void @@ -174,6 +174,11 @@ case AS_GET_DECORATOR_SETTINGS: string = "AS_GET_DECORATOR_SETTINGS"; break; 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; + case AS_SET_HINTING: string = "AS_SET_HINTING"; break; + case AS_GET_HINTING: string = "AS_GET_HINTING"; break; // Graphics calls case AS_SET_HIGH_COLOR: string = "AS_SET_HIGH_COLOR"; break; Index: src/servers/app/Desktop.cpp =================================================================== --- src/servers/app/Desktop.cpp (revision 26239) +++ src/servers/app/Desktop.cpp (working copy) @@ -6,6 +6,7 @@ * Adrian Oanca <adioanca@xxxxxxxxxxxxx> * Stephan Aßmus <superstippi@xxxxxx> * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ /*! Class used to encapsulate desktop management */ @@ -2462,6 +2463,14 @@ void +Desktop::Redraw() +{ + BRegion dirty(fVirtualScreen.Frame()); + MarkDirty(dirty); +} + + +void Desktop::_RebuildClippingForAllWindows(BRegion& stillAvailableOnScreen) { // the available region on screen starts with the entire screen area Index: src/servers/app/DesktopSettingsPrivate.h =================================================================== --- src/servers/app/DesktopSettingsPrivate.h (revision 26239) +++ src/servers/app/DesktopSettingsPrivate.h (working copy) @@ -4,6 +4,7 @@ * * Authors: * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Andrej Spielmann, <andrej.spielmann@xxxxxxxxxxxx> */ #ifndef DESKTOP_SETTINGS_PRIVATE_H #define DESKTOP_SETTINGS_PRIVATE_H @@ -54,6 +55,12 @@ void SetUIColor(color_which which, const rgb_color color); rgb_color UIColor(color_which which) const; + + void SetFontSubpixelAntialiasing(bool subpix); + bool FontSubpixelAntialiasing() const; + void SetHinting(bool hinting); + bool Hinting() const; + private: void _SetDefaults(); status_t _Load(); @@ -69,6 +76,9 @@ bool fShowAllDraggers; int32 fWorkspacesCount; BMessage fWorkspaceMessages[kMaxWorkspaces]; + + bool fFontSubpixelAntialiasing; + bool fHinting; server_read_only_memory& fShared; }; Index: src/servers/app/agg_scanline_u_subpix.h =================================================================== --- src/servers/app/agg_scanline_u_subpix.h (revision 0) +++ src/servers/app/agg_scanline_u_subpix.h (revision 0) @@ -0,0 +1,117 @@ +/* + * Copyright 2008, Andrej Spielmann <andrej.spielmann@xxxxxxxxxxxx>. + * All rights reserved. Distributed under the terms of the MIT License. + * + * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) + * + * + * Class scanline_u8_subpix, a slightly modified version of + * scanline_u8 customized to store 3 covers per pixel + * + */ + +#ifndef AGG_SCANLINE_U_SUBPIX_INCLUDED +#define AGG_SCANLINE_U_SUBPIX_INCLUDED + +#include <agg_array.h> + +namespace agg +{ + //======================================================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; + }; + + typedef span* iterator; + typedef const span* const_iterator; + + //-------------------------------------------------------------------- + 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 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 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(const self_type&); + const self_type& operator = (const self_type&); + + private: + int m_min_x; + int m_last_x; + int m_y; + pod_array<cover_type> m_covers; + pod_array<span> m_spans; + span* m_cur_span; + }; + +} + +#endif + Property changes on: src/servers/app/agg_scanline_u_subpix.h ___________________________________________________________________ Name: svn:executable + *