[aseprite] 18/308: Convert InkShadesField in a combobox-like widget to store several shades (#85)

Tobias Hansen thansen at moszumanska.debian.org
Tue Mar 8 02:44:47 UTC 2016


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository aseprite.

commit cf7c4754cc4b2128e07faa6473eabfe7e882e813
Author: David Capello <davidcapello at gmail.com>
Date:   Tue Nov 24 18:37:13 2015 -0300

    Convert InkShadesField in a combobox-like widget to store several shades (#85)
    
    Changes:
    * Added new ui::IconButton widget to create widgets with one skin icon
      that is colored depending on the button state.
    * ContextBar::InkShadesField was divided into a couple widgets (ShadeWidget
      and IconButton to drop-down a little menu with saved shades)
    * Fixed CommonLockedSurface::drawColoredRgbaSurface() impl.
    * Removed invalid gfx::setr/g/b/a() functions.
---
 data/skins/default/sheet.png           | Bin 13952 -> 14046 bytes
 data/skins/default/skin.xml            |   2 +
 src/app/CMakeLists.txt                 |   1 +
 src/app/commands/cmd_switch_colors.cpp |   2 +-
 src/app/shade.h                        |  22 +++
 src/app/ui/context_bar.cpp             | 341 ++++++++++++++++++++++++---------
 src/app/ui/context_bar.h               |   4 +-
 src/app/ui/editor/tool_loop_impl.cpp   |   2 +-
 src/app/ui/icon_button.cpp             |  68 +++++++
 src/app/ui/icon_button.h               |  31 +++
 src/app/ui/tabs.cpp                    |   2 +-
 src/gfx/color.h                        |   7 +-
 src/she/common/locked_surface.h        |  68 +++----
 13 files changed, 419 insertions(+), 131 deletions(-)

diff --git a/data/skins/default/sheet.png b/data/skins/default/sheet.png
index af0bf50..9ce7e63 100644
Binary files a/data/skins/default/sheet.png and b/data/skins/default/sheet.png differ
diff --git a/data/skins/default/skin.xml b/data/skins/default/skin.xml
index 2cecd7b..1e8fede 100644
--- a/data/skins/default/skin.xml
+++ b/data/skins/default/skin.xml
@@ -406,6 +406,8 @@
     <part id="no_symmetry"                      x="144" y="240" w="13" h="13" />
     <part id="horizontal_symmetry"              x="160" y="240" w="13" h="13" />
     <part id="vertical_symmetry"                x="176" y="240" w="13" h="13" />
+    <part id="icon_arrow_down"                  x="144" y="256" w="7" h="4" />
+    <part id="icon_close"                       x="153" y="256" w="7" h="7" />
   </parts>
 
   <stylesheet>
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index a857b87..3be299a 100644
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -363,6 +363,7 @@ add_library(app-lib
   ui/frame_tag_window.cpp
   ui/hex_color_entry.cpp
   ui/home_view.cpp
+  ui/icon_button.cpp
   ui/input_chain.cpp
   ui/keyboard_shortcuts.cpp
   ui/main_menu_bar.cpp
diff --git a/src/app/commands/cmd_switch_colors.cpp b/src/app/commands/cmd_switch_colors.cpp
index 8922998..0132ec0 100644
--- a/src/app/commands/cmd_switch_colors.cpp
+++ b/src/app/commands/cmd_switch_colors.cpp
@@ -52,7 +52,7 @@ void SwitchColorsCommand::onExecute(Context* context)
     const auto& toolPref(Preferences::instance().tool(tool));
     if (toolPref.ink() == tools::InkType::SHADING) {
       App::instance()->getMainWindow()->
-        getContextBar()->reverseShadesColors();
+        getContextBar()->reverseShadeColors();
     }
   }
 
diff --git a/src/app/shade.h b/src/app/shade.h
new file mode 100644
index 0000000..905766c
--- /dev/null
+++ b/src/app/shade.h
@@ -0,0 +1,22 @@
+// Aseprite
+// Copyright (C) 2001-2015  David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifndef APP_SHADE_H_INCLUDED
+#define APP_SHADE_H_INCLUDED
+#pragma once
+
+#include "app/color.h"
+
+#include <vector>
+
+namespace app {
+
+  typedef std::vector<app::Color> Shade;
+
+} // namespace app
+
+#endif
diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp
index 3844438..039c962 100644
--- a/src/app/ui/context_bar.cpp
+++ b/src/app/ui/context_bar.cpp
@@ -18,6 +18,7 @@
 #include "app/modules/gui.h"
 #include "app/modules/palettes.h"
 #include "app/pref/preferences.h"
+#include "app/shade.h"
 #include "app/tools/controller.h"
 #include "app/tools/ink.h"
 #include "app/tools/ink_type.h"
@@ -28,6 +29,8 @@
 #include "app/ui/brush_popup.h"
 #include "app/ui/button_set.h"
 #include "app/ui/color_button.h"
+#include "app/ui/icon_button.h"
+#include "app/ui/skin/button_icon_impl.h"
 #include "app/ui/skin/skin_theme.h"
 #include "app/ui/skin/style.h"
 #include "app/ui_context.h"
@@ -429,122 +432,288 @@ protected:
   ContextBar* m_owner;
 };
 
-class ContextBar::InkShadesField : public Widget {
-  typedef std::vector<app::Color> Colors;
-public:
+class ContextBar::InkShadesField : public HBox {
 
-  InkShadesField() : Widget(kGenericWidget) {
-    setText("Select colors in the palette");
-  }
+  class ShadeWidget : public Widget {
+  public:
+    enum ClickType { DragAndDrop, Select };
 
-  void reverseColors() {
-    std::reverse(m_colors.begin(), m_colors.end());
-    invalidate();
-  }
+    Signal0<void> Click;
+
+    ShadeWidget(const Shade& colors, ClickType click)
+      : Widget(kGenericWidget)
+      , m_click(click)
+      , m_shade(colors)
+      , m_hotIndex(-1)
+      , m_boxSize(12) {
+      setText("Select colors in the palette");
+    }
+
+    void reverseShadeColors() {
+      std::reverse(m_shade.begin(), m_shade.end());
+      invalidate();
+    }
 
-  doc::Remap* createShadesRemap(bool left) {
-    base::UniquePtr<doc::Remap> remap;
-    Colors colors = getColors();
+    doc::Remap* createShadeRemap(bool left) {
+      base::UniquePtr<doc::Remap> remap;
+      Shade colors = getShade();
 
-    if (colors.size() > 0) {
-      remap.reset(new doc::Remap(get_current_palette()->size()));
+      if (colors.size() > 0) {
+        remap.reset(new doc::Remap(get_current_palette()->size()));
 
-      for (int i=0; i<remap->size(); ++i)
-        remap->map(i, i);
+        for (int i=0; i<remap->size(); ++i)
+          remap->map(i, i);
 
-      if (left) {
-        for (int i=1; i<int(colors.size()); ++i)
-          remap->map(colors[i].getIndex(), colors[i-1].getIndex());
+        if (left) {
+          for (int i=1; i<int(colors.size()); ++i)
+            remap->map(colors[i].getIndex(), colors[i-1].getIndex());
+        }
+        else {
+          for (int i=0; i<int(colors.size())-1; ++i)
+            remap->map(colors[i].getIndex(), colors[i+1].getIndex());
+        }
       }
-      else {
-        for (int i=0; i<int(colors.size())-1; ++i)
-          remap->map(colors[i].getIndex(), colors[i+1].getIndex());
+
+      return remap.release();
+    }
+
+    int size() const {
+      int colors = 0;
+      for (const auto& color : m_shade) {
+        if (color.getIndex() >= 0 &&
+            color.getIndex() < get_current_palette()->size())
+          ++colors;
       }
+      return colors;
     }
 
-    return remap.release();
-  }
+    Shade getShade() const {
+      Shade colors;
+      for (const auto& color : m_shade) {
+        if (color.getIndex() >= 0 &&
+            color.getIndex() < get_current_palette()->size())
+          colors.push_back(color);
+      }
+      return colors;
+    }
 
-private:
+    void setShade(const Shade& shade) {
+      m_shade = shade;
+      invalidate();
+      getParent()->getParent()->layout();
+    }
+
+  private:
+
+    void onChangeColorBarSelection() {
+      if (!isVisible())
+        return;
+
+      doc::PalettePicks picks;
+      ColorBar::instance()->getPaletteView()->getSelectedEntries(picks);
 
-  Colors getColors() const {
-    Colors colors;
-    for (const auto& color : m_colors) {
-      if (color.getIndex() >= 0 &&
-          color.getIndex() < get_current_palette()->size())
-        colors.push_back(color);
+      m_shade.resize(picks.picks());
+
+      int i = 0, j = 0;
+      for (bool pick : picks) {
+        if (pick)
+          m_shade[j++] = app::Color::fromIndex(i);
+        ++i;
+      }
+
+      getParent()->getParent()->layout();
     }
-    return colors;
-  }
 
-  void onChangeColorBarSelection() {
-    if (!isVisible())
-      return;
+    bool onProcessMessage(ui::Message* msg) override {
+      switch (msg->type()) {
+
+        case kOpenMessage:
+          ColorBar::instance()->ChangeSelection.connect(
+            Bind<void>(&ShadeWidget::onChangeColorBarSelection, this));
+          break;
+
+        case kMouseEnterMessage:
+        case kMouseLeaveMessage:
+          invalidate();
+          break;
+
+        case kMouseUpMessage: {
+          if (m_click == Select) {
+            setSelected(true);
+            Click();
+            closeWindow();
+            break;
+          }
+          break;
+        }
 
-    doc::PalettePicks picks;
-    ColorBar::instance()->getPaletteView()->getSelectedEntries(picks);
+        case kMouseMoveMessage: {
+          MouseMessage* mouseMsg = static_cast<MouseMessage*>(msg);
+          gfx::Point mousePos = mouseMsg->position() - getBounds().getOrigin();
+          gfx::Rect bounds = getClientBounds();
+          int hot = -1;
+
+          bounds.shrink(3*guiscale());
+          if (bounds.contains(mousePos)) {
+            int count = size();
+            hot = (mousePos.x - bounds.x) / m_boxSize;
+            hot = MID(0, hot, count-1);
+          }
+
+          if (m_hotIndex != hot) {
+            m_hotIndex = hot;
+            invalidate();
+          }
+          break;
+        }
 
-    m_colors.resize(picks.picks());
+        case kMouseDownMessage: {
+          break;
+        }
+      }
+      return Widget::onProcessMessage(msg);
+    }
 
-    int i = 0, j = 0;
-    for (bool pick : picks) {
-      if (pick)
-        m_colors[j++] = app::Color::fromIndex(i);
-      ++i;
+    void onPreferredSize(PreferredSizeEvent& ev) override {
+      int size = this->size();
+      if (size < 2)
+        ev.setPreferredSize(Size((16+m_boxSize)*guiscale()+getTextWidth(), 18*guiscale()));
+      else
+        ev.setPreferredSize(Size(6+m_boxSize*size, 18)*guiscale());
     }
 
-    getParent()->layout();
-  }
+    void onPaint(PaintEvent& ev) override {
+      SkinTheme* theme = SkinTheme::instance();
+      Graphics* g = ev.getGraphics();
+      gfx::Rect bounds = getClientBounds();
+
+      gfx::Color bg = getBgColor();
+      if (m_click == Select && hasMouseOver())
+        bg = theme->colors.menuitemHighlightFace();
+      g->fillRect(bg, bounds);
+
+      Shade colors = getShade();
+      if (colors.size() >= 2) {
+        int w = (6+m_boxSize*colors.size())*guiscale();
+        if (bounds.w > w)
+          bounds.w = w;
+      }
+
+      skin::Style::State state;
+      if (hasMouseOver()) state += Style::hover();
+      theme->styles.view()->paint(g, bounds, nullptr, state);
+
+      bounds.shrink(3*guiscale());
+
+      gfx::Rect box(bounds.x, bounds.y, m_boxSize*guiscale(), bounds.h);
 
-  bool onProcessMessage(ui::Message* msg) override {
-    if (msg->type() == kOpenMessage) {
-      ColorBar::instance()->ChangeSelection.connect(
-        Bind<void>(&InkShadesField::onChangeColorBarSelection, this));
+      if (colors.size() >= 2) {
+        for (int i=0; i<int(colors.size()); ++i) {
+          if (i == int(colors.size())-1)
+            box.w = bounds.x+bounds.w-box.x;
+
+          draw_color(g, box, colors[i]);
+          box.x += box.w;
+        }
+      }
+      else {
+        g->fillRect(theme->colors.editorFace(), bounds);
+        g->drawAlignedUIString(getText(), theme->colors.face(), gfx::ColorNone, bounds,
+                               ui::CENTER | ui::MIDDLE);
+      }
     }
-    return Widget::onProcessMessage(msg);
-  }
 
-  void onPreferredSize(PreferredSizeEvent& ev) override {
-    int size = getColors().size();
-    if (size < 2)
-      ev.setPreferredSize(Size(16*guiscale()+getTextWidth(), 18*guiscale()));
-    else
-      ev.setPreferredSize(Size(6+12*size, 18)*guiscale());
-  }
+    ClickType m_click;
+    Shade m_shade;
+    int m_hotIndex;
+    int m_boxSize;
+  };
 
-  void onPaint(PaintEvent& ev) override {
+public:
+  InkShadesField() :
+    m_button(SkinTheme::instance()->parts.iconArrowDown()->getBitmap(0)),
+    m_shade(Shade(), ShadeWidget::DragAndDrop) {
     SkinTheme* theme = SkinTheme::instance();
-    Graphics* g = ev.getGraphics();
-    gfx::Rect bounds = getClientBounds();
+    m_shade.setBgColor(theme->colors.workspace());
+    m_button.setBgColor(theme->colors.workspace());
 
-    skin::Style::State state;
-    if (hasMouseOver()) state += Style::hover();
+    noBorderNoChildSpacing();
+    addChild(&m_button);
+    addChild(&m_shade);
 
-    g->fillRect(theme->colors.workspace(), bounds);
-    theme->styles.view()->paint(g, bounds, nullptr, state);
+    m_button.setFocusStop(false);
+    m_button.Click.connect(Bind<void>(&InkShadesField::onShowMenu, this));
+  }
 
-    bounds.shrink(3*guiscale());
+  void reverseShadeColors() {
+    m_shade.reverseShadeColors();
+  }
 
-    gfx::Rect box(bounds.x, bounds.y, 12*guiscale(), bounds.h);
-    Colors colors = getColors();
+  doc::Remap* createShadeRemap(bool left) {
+    return m_shade.createShadeRemap(left);
+  }
 
-    if (colors.size() >= 2) {
-      for (int i=0; i<int(colors.size()); ++i) {
-        if (i == int(colors.size())-1)
-          box.w = bounds.x+bounds.w-box.x;
+private:
+  void onShowMenu() {
+    gfx::Rect bounds = m_button.getBounds();
 
-        draw_color(g, box, colors[i]);
-        box.x += box.w;
+    Menu menu;
+    MenuItem
+      reverse("Reverse Shade"),
+      save("Save Shade");
+    menu.addChild(&reverse);
+    menu.addChild(&save);
+
+    bool hasShade = (m_shade.size() >= 2);
+    reverse.setEnabled(hasShade);
+    save.setEnabled(hasShade);
+    reverse.Click.connect(Bind<void>(&InkShadesField::reverseShadeColors, this));
+    save.Click.connect(Bind<void>(&InkShadesField::onSaveShade, this));
+
+    if (!m_shades.empty()) {
+      SkinTheme* theme = SkinTheme::instance();
+
+      menu.addChild(new MenuSeparator);
+
+      int i = 0;
+      for (const Shade& shade : m_shades) {
+        auto shadeWidget = new ShadeWidget(shade, ShadeWidget::Select);
+        shadeWidget->setExpansive(true);
+        shadeWidget->setBgColor(theme->colors.menuitemNormalFace());
+        shadeWidget->Click.connect(
+          [&]{
+            m_shade.setShade(shade);
+          });
+
+        auto close = new IconButton(theme->parts.iconClose()->getBitmap(0));
+        close->setBgColor(theme->colors.menuitemNormalFace());
+        close->Click.connect(
+          Bind<void>(
+            [this, i, close]{
+              m_shades.erase(m_shades.begin()+i);
+              close->closeWindow();
+            }));
+
+        auto item = new HBox();
+        item->noBorderNoChildSpacing();
+        item->addChild(shadeWidget);
+        item->addChild(close);
+        menu.addChild(item);
+        ++i;
       }
     }
-    else {
-      g->fillRect(theme->colors.editorFace(), bounds);
-      g->drawAlignedUIString(getText(), theme->colors.face(), gfx::ColorNone, bounds,
-                             ui::CENTER | ui::MIDDLE);
-    }
+
+    menu.showPopup(gfx::Point(bounds.x, bounds.y+bounds.h));
+    m_button.invalidate();
+  }
+
+  void onSaveShade() {
+    m_shades.push_back(m_shade.getShade());
   }
 
-  std::vector<app::Color> m_colors;
+  IconButton m_button;
+  ShadeWidget m_shade;
+  std::vector<Shade> m_shades;
 };
 
 class ContextBar::InkOpacityField : public IntEntry
@@ -1502,14 +1671,14 @@ doc::BrushRef ContextBar::createBrushFromPreferences(ToolPreferences::Brush* bru
   return brush;
 }
 
-doc::Remap* ContextBar::createShadesRemap(bool left)
+doc::Remap* ContextBar::createShadeRemap(bool left)
 {
-  return m_inkShades->createShadesRemap(left);
+  return m_inkShades->createShadeRemap(left);
 }
 
-void ContextBar::reverseShadesColors()
+void ContextBar::reverseShadeColors()
 {
-  m_inkShades->reverseColors();
+  m_inkShades->reverseShadeColors();
 }
 
 } // namespace app
diff --git a/src/app/ui/context_bar.h b/src/app/ui/context_bar.h
index 0d0bda8..ead1172 100644
--- a/src/app/ui/context_bar.h
+++ b/src/app/ui/context_bar.h
@@ -70,8 +70,8 @@ namespace app {
     static doc::BrushRef createBrushFromPreferences(
       ToolPreferences::Brush* brushPref = nullptr);
 
-    doc::Remap* createShadesRemap(bool left);
-    void reverseShadesColors();
+    doc::Remap* createShadeRemap(bool left);
+    void reverseShadeColors();
 
     // Signals
     Signal0<void> BrushChange;
diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp
index 5eb3f34..8592bc0 100644
--- a/src/app/ui/editor/tool_loop_impl.cpp
+++ b/src/app/ui/editor/tool_loop_impl.cpp
@@ -169,7 +169,7 @@ public:
 
     if (m_toolPref.ink() == tools::InkType::SHADING) {
       m_shadingRemap.reset(
-        App::instance()->getMainWindow()->getContextBar()->createShadesRemap(
+        App::instance()->getMainWindow()->getContextBar()->createShadeRemap(
           button == tools::ToolLoop::Left));
     }
   }
diff --git a/src/app/ui/icon_button.cpp b/src/app/ui/icon_button.cpp
new file mode 100644
index 0000000..b4840c3
--- /dev/null
+++ b/src/app/ui/icon_button.cpp
@@ -0,0 +1,68 @@
+// Aseprite
+// Copyright (C) 2001-2015  David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "app/ui/icon_button.h"
+
+#include "app/ui/skin/skin_theme.h"
+#include "she/surface.h"
+#include "ui/message.h"
+#include "ui/paint_event.h"
+#include "ui/preferred_size_event.h"
+#include "ui/system.h"
+
+namespace app {
+
+using namespace ui;
+using namespace app::skin;
+
+IconButton::IconButton(she::Surface* icon)
+  : Button("")
+  , m_icon(icon)
+{
+  setBgColor(SkinTheme::instance()->colors.menuitemNormalFace());
+}
+
+void IconButton::onPreferredSize(PreferredSizeEvent& ev)
+{
+  ev.setPreferredSize(
+    gfx::Size(m_icon->width(),
+              m_icon->height()) + 4*guiscale());
+}
+
+void IconButton::onPaint(PaintEvent& ev)
+{
+  SkinTheme* theme = SkinTheme::instance();
+  Graphics* g = ev.getGraphics();
+  gfx::Color fg, bg;
+
+  if (isSelected()) {
+    fg = theme->colors.menuitemHighlightText();
+    bg = theme->colors.menuitemHighlightFace();
+  }
+  else if (isEnabled() && hasMouseOver()) {
+    fg = theme->colors.menuitemHotText();
+    bg = theme->colors.menuitemHotFace();
+  }
+  else {
+    fg = theme->colors.menuitemNormalText();
+    bg = getBgColor();
+  }
+
+  g->fillRect(bg, g->getClipBounds());
+
+  gfx::Rect bounds = getClientBounds();
+  g->drawColoredRgbaSurface(
+    m_icon, fg,
+    bounds.x+bounds.w/2-m_icon->width()/2,
+    bounds.y+bounds.h/2-m_icon->height()/2);
+}
+
+} // namespace app
diff --git a/src/app/ui/icon_button.h b/src/app/ui/icon_button.h
new file mode 100644
index 0000000..b9ba6f7
--- /dev/null
+++ b/src/app/ui/icon_button.h
@@ -0,0 +1,31 @@
+// Aseprite
+// Copyright (C) 2001-2015  David Capello
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+
+#ifndef APP_UI_ICON_BUTTON_H_INCLUDED
+#define APP_UI_ICON_BUTTON_H_INCLUDED
+#pragma once
+
+#include "ui/button.h"
+
+namespace app {
+
+  class IconButton : public ui::Button {
+  public:
+    IconButton(she::Surface* icon);
+
+  protected:
+    // bool onProcessMessage(ui::Message* msg) override;
+    void onPreferredSize(ui::PreferredSizeEvent& ev) override;
+    void onPaint(ui::PaintEvent& ev) override;
+
+  private:
+    she::Surface* m_icon;
+  };
+
+} // namespace app
+
+#endif
diff --git a/src/app/ui/tabs.cpp b/src/app/ui/tabs.cpp
index 996156f..591df3b 100644
--- a/src/app/ui/tabs.cpp
+++ b/src/app/ui/tabs.cpp
@@ -940,7 +940,7 @@ void Tabs::createFloatingOverlay(Tab* tab)
         gfx::Color c = lock->getPixel(x, y);
         c = (c != gfx::rgba(255, 0, 255, 0) &&
              c != gfx::rgba(255, 0, 255, 255) ?
-             gfx::seta(c, 255):
+             gfx::rgba(gfx::getr(c), gfx::getg(c), gfx::getb(c), 255):
              gfx::ColorNone);
         lock->putPixel(c, x, y);
       }
diff --git a/src/gfx/color.h b/src/gfx/color.h
index f16c39c..c541d12 100644
--- a/src/gfx/color.h
+++ b/src/gfx/color.h
@@ -1,5 +1,5 @@
 // Aseprite Gfx Library
-// Copyright (C) 2001-2014 David Capello
+// Copyright (C) 2001-2015 David Capello
 //
 // This file is released under the terms of the MIT license.
 // Read LICENSE.txt for more information.
@@ -32,11 +32,6 @@ namespace gfx {
   inline ColorComponent getb(Color c) { return (c >> ColorBShift) & 0xff; }
   inline ColorComponent geta(Color c) { return (c >> ColorAShift) & 0xff; }
 
-  inline Color setr(Color c, ColorComponent v) { return Color((c & ~ColorRShift) | (v << ColorRShift)); }
-  inline Color setg(Color c, ColorComponent v) { return Color((c & ~ColorGShift) | (v << ColorGShift)); }
-  inline Color setb(Color c, ColorComponent v) { return Color((c & ~ColorBShift) | (v << ColorBShift)); }
-  inline Color seta(Color c, ColorComponent v) { return Color((c & ~ColorAShift) | (v << ColorAShift)); }
-
   inline bool is_transparent(Color c) { return geta(c) == 0; }
 
 } // namespace gfx
diff --git a/src/she/common/locked_surface.h b/src/she/common/locked_surface.h
index 063faf4..cd7cf86 100644
--- a/src/she/common/locked_surface.h
+++ b/src/she/common/locked_surface.h
@@ -15,43 +15,39 @@
 
 namespace she {
 
-namespace  {
+namespace {
 
-#define INT_MULT(a, b, t)                               \
+#define MUL_UN8(a, b, t)                               \
   ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
 
-gfx::Color blend(const gfx::Color back, gfx::Color front)
+gfx::Color blend(const gfx::Color backdrop, gfx::Color src)
 {
+  if (gfx::geta(backdrop) == 0)
+    return src;
+  else if (gfx::geta(src) == 0)
+    return backdrop;
+
+  int Br, Bg, Bb, Ba;
+  int Sr, Sg, Sb, Sa;
+  int Rr, Rg, Rb, Ra;
+
+  Br = gfx::getr(backdrop);
+  Bg = gfx::getg(backdrop);
+  Bb = gfx::getb(backdrop);
+  Ba = gfx::geta(backdrop);
+
+  Sr = gfx::getr(src);
+  Sg = gfx::getg(src);
+  Sb = gfx::getb(src);
+  Sa = gfx::geta(src);
+
   int t;
+  Ra = Ba + Sa - MUL_UN8(Ba, Sa, t);
+  Rr = Br + (Sr-Br) * Sa / Ra;
+  Rg = Bg + (Sg-Bg) * Sa / Ra;
+  Rb = Bb + (Sb-Bb) * Sa / Ra;
 
-  if (gfx::geta(back) == 0) {
-    return front;
-  }
-  else if (gfx::geta(front) == 0) {
-    return back;
-  }
-  else {
-    int B_r, B_g, B_b, B_a;
-    int F_r, F_g, F_b, F_a;
-    int D_r, D_g, D_b, D_a;
-
-    B_r = gfx::getr(back);
-    B_g = gfx::getg(back);
-    B_b = gfx::getb(back);
-    B_a = gfx::geta(back);
-
-    F_r = gfx::getr(front);
-    F_g = gfx::getg(front);
-    F_b = gfx::getb(front);
-    F_a = gfx::geta(front);
-
-    D_a = B_a + F_a - INT_MULT(B_a, F_a, t);
-    D_r = B_r + (F_r-B_r) * F_a / D_a;
-    D_g = B_g + (F_g-B_g) * F_a / D_a;
-    D_b = B_b + (F_b-B_b) * F_a / D_a;
-
-    return gfx::rgba(D_r, D_g, D_b, D_a);
-  }
+  return gfx::rgba(Rr, Rg, Rb, Ra);
 }
 
 } // anoynmous namespace
@@ -79,9 +75,13 @@ public:
         if (gfx::geta(bg) > 0)
           dstColor = blend(dstColor, bg);
 
-        int srcAlpha = (((*ptr) & format.alphaMask) >> format.alphaShift);
-        if (srcAlpha > 0)
-          dstColor = blend(dstColor, gfx::seta(fg, srcAlpha));
+        uint32_t src = (((*ptr) & format.alphaMask) >> format.alphaShift);
+        if (src > 0) {
+          src = gfx::rgba(gfx::getr(fg),
+                          gfx::getg(fg),
+                          gfx::getb(fg), src);
+          dstColor = blend(dstColor, src);
+        }
 
         putPixel(dstColor, clip.dst.x+u, clip.dst.y+v);
         ++ptr;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/aseprite.git



More information about the Pkg-games-commits mailing list