Permalink
Browse files

Add layer blending modes (fix #318)

- Added doc::BlendMode enum and doc::BlendFunc type
- Renamed LayerImage::getBlendMode() -> blendMode()
- BLEND_MODE_COPY is BlendMode::SRC now
- BLEND_MODE_NORMAL is BlendMode::NORMAL now
- Added app::cmd::SetLayerBlendMode
  • Loading branch information...
dacap committed Jun 14, 2015
1 parent 8da36f9 commit 21ca87862cccc47da7595ea78d1ca8b9860d0703
Showing with 1,067 additions and 564 deletions.
  1. +3 −0 data/widgets/layer_properties.xml
  2. +17 −20 docs/files/ase.txt
  3. +1 −0 src/app/CMakeLists.txt
  4. +1 −1 src/app/cmd/background_from_layer.cpp
  5. +4 −3 src/app/cmd/copy_cel.cpp
  6. +3 −2 src/app/cmd/move_cel.cpp
  7. +39 −0 src/app/cmd/set_layer_blend_mode.cpp
  8. +44 −0 src/app/cmd/set_layer_blend_mode.h
  9. +4 −4 src/app/commands/cmd_fullscreen_preview.cpp
  10. +44 −4 src/app/commands/cmd_layer_properties.cpp
  11. +1 −1 src/app/commands/cmd_merge_down_layer.cpp
  12. +1 −1 src/app/document.cpp
  13. +4 −3 src/app/document.h
  14. +0 −1 src/app/document_api.cpp
  15. +7 −6 src/app/file/ase_format.cpp
  16. +30 −30 src/app/file/gif_tests.cpp
  17. +0 −1 src/app/modules/gfx.cpp
  18. +0 −1 src/app/modules/palettes.cpp
  19. +19 −18 src/app/tools/ink_processing.h
  20. +3 −2 src/app/ui/editor/cursor.cpp
  21. +0 −1 src/app/ui/editor/drawing_state.cpp
  22. +2 −2 src/app/ui/editor/editor.cpp
  23. +2 −2 src/app/ui/editor/pixels_movement.cpp
  24. +0 −1 src/app/ui/palette_view.cpp
  25. +1 −1 src/doc/CMakeLists.txt
  26. +5 −9 src/doc/algorithm/rotate.cpp
  27. +1 −2 src/doc/algorithm/rotsprite.cpp
  28. +0 −317 src/doc/blend.cpp
  29. +0 −49 src/doc/blend.h
  30. +661 −0 src/doc/blend_funcs.cpp
  31. +32 −0 src/doc/blend_funcs.h
  32. +17 −0 src/doc/blend_internals.h
  33. +43 −0 src/doc/blend_mode.h
  34. +7 −3 src/doc/color.h
  35. +0 −1 src/doc/conversion_she.cpp
  36. +2 −1 src/doc/doc.h
  37. +1 −2 src/doc/image.cpp
  38. +1 −2 src/doc/image.h
  39. +2 −2 src/doc/image_impl.h
  40. +11 −19 src/doc/image_traits.h
  41. +1 −1 src/doc/layer.cpp
  42. +4 −2 src/doc/layer.h
  43. +0 −1 src/doc/path.cpp
  44. +0 −1 src/doc/primitives.cpp
  45. +2 −2 src/doc/sort_palette.cpp
  46. +0 −1 src/render/quantization.cpp
  47. +37 −35 src/render/render.cpp
  48. +9 −8 src/render/render.h
  49. +1 −1 src/ui/combobox.cpp
@@ -6,6 +6,9 @@
<grid columns="2">
<label text="Name:" />
<entry text="" id="name" magnet="true" maxsize="256" minwidth="64" cell_align="horizontal" />
<label text="Mode:" />
<combobox id="mode" />
</grid>
<separator horizontal="true" />
<hbox>
View
@@ -150,26 +150,23 @@ Layer Chunk (0x2004)
WORD Layer child level (see NOTE.1)
WORD Default layer width in pixels (ignored)
WORD Default layer height in pixels (ignored)
WORD DEPRECATED This field is not used anymore.
Blend mode (always 0 for layer set)
BLEND_MODE_NORMAL = 0
BLEND_MODE_DISSOLVE = 1
BLEND_MODE_MULTIPLY = 2
BLEND_MODE_SCREEN = 3
BLEND_MODE_OVERLAY = 4
BLEND_MODE_HARD_LIGHT = 5
BLEND_MODE_DODGE = 6
BLEND_MODE_BURN = 7
BLEND_MODE_DARKEN = 8
BLEND_MODE_LIGHTEN = 9
BLEND_MODE_ADDITION = 10
BLEND_MODE_SUBTRACT = 11
BLEND_MODE_DIFFERENCE = 12
BLEND_MODE_HUE = 13
BLEND_MODE_SATURATION = 14
BLEND_MODE_COLOR = 15
BLEND_MODE_LUMINOSITY = 16
BLEND_MODE_COPY = 17
WORD Blend mode (always 0 for layer set)
Normal = 0
Multiply = 1
Screen = 2
Overlay = 3
Darken = 4
Lighten = 5
Color Dodge = 6
Color Burn = 7
Hard Light = 8
Soft Light = 9
Difference = 10
Exclusion = 11
Hue = 12
Saturation = 13
Color = 14
Luminosity = 15
BYTE[4] For future (set to zero)
STRING Layer name
View
@@ -113,6 +113,7 @@ add_library(app-lib
cmd/set_frame_tag_color.cpp
cmd/set_frame_tag_name.cpp
cmd/set_frame_tag_range.cpp
cmd/set_layer_blend_mode.cpp
cmd/set_layer_flags.cpp
cmd/set_layer_name.cpp
cmd/set_mask.cpp
@@ -61,7 +61,7 @@ void BackgroundFromLayer::onExecute()
render::composite_image(bg_image.get(), cel_image,
cel->x(), cel->y(),
MID(0, cel->opacity(), 255),
static_cast<LayerImage*>(layer)->getBlendMode());
static_cast<LayerImage*>(layer)->blendMode());
// now we have to copy the new image (bg_image) to the cel...
executeAndAdd(new cmd::SetCelPosition(cel, 0, 0));
View
@@ -92,12 +92,13 @@ void CopyCel::onExecute()
executeAndAdd(new cmd::SetCelData(dstCel, srcCel->dataRef()));
}
else {
int blend = (srcLayer->isBackground() ?
BLEND_MODE_COPY: BLEND_MODE_NORMAL);
BlendMode blend = (srcLayer->isBackground() ?
BlendMode::SRC:
BlendMode::NORMAL);
ImageRef tmp(Image::createCopy(dstImage.get()));
render::composite_image(tmp.get(), srcImage,
srcCel->x(), srcCel->y(), 255, blend);
srcCel->x(), srcCel->y(), 255, blend);
executeAndAdd(new cmd::CopyRect(dstImage.get(), tmp.get(), gfx::Clip(tmp->bounds())));
}
}
View
@@ -95,8 +95,9 @@ void MoveCel::onExecute()
executeAndAdd(new cmd::UnlinkCel(srcCel));
}
else {
int blend = (srcLayer->isBackground() ?
BLEND_MODE_COPY: BLEND_MODE_NORMAL);
BlendMode blend = (srcLayer->isBackground() ?
BlendMode::SRC:
BlendMode::NORMAL);
ImageRef tmp(Image::createCopy(dstImage.get()));
render::composite_image(tmp.get(), srcImage,
@@ -0,0 +1,39 @@
// 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/cmd/set_layer_blend_mode.h"
#include "doc/layer.h"
namespace app {
namespace cmd {
SetLayerBlendMode::SetLayerBlendMode(LayerImage* layer, BlendMode blendMode)
: WithLayer(layer)
, m_oldBlendMode(layer->blendMode())
, m_newBlendMode(blendMode)
{
}
void SetLayerBlendMode::onExecute()
{
static_cast<LayerImage*>(layer())->setBlendMode(m_newBlendMode);
layer()->incrementVersion();
}
void SetLayerBlendMode::onUndo()
{
static_cast<LayerImage*>(layer())->setBlendMode(m_oldBlendMode);
layer()->incrementVersion();
}
} // namespace cmd
} // namespace app
@@ -0,0 +1,44 @@
// 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_CMD_SET_LAYER_BLEND_MODE_H_INCLUDED
#define APP_CMD_SET_LAYER_BLEND_MODE_H_INCLUDED
#pragma once
#include "app/cmd.h"
#include "app/cmd/with_layer.h"
#include "doc/blend_mode.h"
namespace doc {
class LayerImage;
}
namespace app {
namespace cmd {
using namespace doc;
class SetLayerBlendMode : public Cmd
, public WithLayer {
public:
SetLayerBlendMode(LayerImage* layer, BlendMode blendMode);
protected:
void onExecute() override;
void onUndo() override;
size_t onMemSize() const override {
return sizeof(*this);
}
private:
BlendMode m_oldBlendMode;
BlendMode m_newBlendMode;
};
} // namespace cmd
} // namespace app
#endif
@@ -209,23 +209,23 @@ class PreviewWindow : public Window {
switch (m_tiled) {
case TiledMode::NONE:
render.renderImage(m_doublebuf, m_render, m_pal, x, y,
m_zoom, 255, BLEND_MODE_NORMAL);
m_zoom, 255, BlendMode::NORMAL);
break;
case TiledMode::X_AXIS:
for (u=x-w; u<ui::display_w()+w; u+=w)
render.renderImage(m_doublebuf, m_render, m_pal, u, y,
m_zoom, 255, BLEND_MODE_NORMAL);
m_zoom, 255, BlendMode::NORMAL);
break;
case TiledMode::Y_AXIS:
for (v=y-h; v<ui::display_h()+h; v+=h)
render.renderImage(m_doublebuf, m_render, m_pal, x, v,
m_zoom, 255, BLEND_MODE_NORMAL);
m_zoom, 255, BlendMode::NORMAL);
break;
case TiledMode::BOTH:
for (v=y-h; v<ui::display_h()+h; v+=h)
for (u=x-w; u<ui::display_w()+w; u+=w)
render.renderImage(m_doublebuf, m_render, m_pal, u, v,
m_zoom, 255, BLEND_MODE_NORMAL);
m_zoom, 255, BlendMode::NORMAL);
break;
}
@@ -13,9 +13,12 @@
#include "ui/ui.h"
#include "app/app.h"
#include "app/cmd/set_layer_blend_mode.h"
#include "app/cmd/set_layer_name.h"
#include "app/commands/command.h"
#include "app/context_access.h"
#include "app/modules/gui.h"
#include "app/transaction.h"
#include "doc/image.h"
#include "doc/layer.h"
@@ -51,18 +54,55 @@ bool LayerPropertiesCommand::onEnabled(Context* context)
void LayerPropertiesCommand::onExecute(Context* context)
{
const ContextReader reader(context);
const Layer* layer = reader.layer();
const LayerImage* layer = static_cast<const LayerImage*>(reader.layer());
app::gen::LayerProperties window;
window.name()->setText(layer->name().c_str());
window.name()->setMinSize(gfx::Size(128, 0));
window.name()->setExpansive(true);
window.mode()->addItem("Normal");
window.mode()->addItem("Multiply");
window.mode()->addItem("Screen");
window.mode()->addItem("Overlay");
window.mode()->addItem("Darken");
window.mode()->addItem("Lighten");
window.mode()->addItem("Color Dodge");
window.mode()->addItem("Color Burn");
window.mode()->addItem("Hard Light");
window.mode()->addItem("Soft Light");
window.mode()->addItem("Difference");
window.mode()->addItem("Exclusion");
window.mode()->addItem("Hue");
window.mode()->addItem("Saturation");
window.mode()->addItem("Color");
window.mode()->addItem("Luminosity");
window.mode()->setSelectedItemIndex((int)layer->blendMode());
window.mode()->setEnabled(!layer->isBackground());
window.openWindowInForeground();
if (window.getKiller() == window.ok()) {
ContextWriter writer(reader);
writer.layer()->setName(window.name()->getText());
update_screen_for_document(writer.document());
std::string newName = window.name()->getText();
BlendMode newBlendMode = (BlendMode)window.mode()->getSelectedItemIndex();
if (newName != layer->name() ||
newBlendMode != layer->blendMode()) {
ContextWriter writer(reader);
{
Transaction transaction(writer.context(), "Set Layer Properties");
if (newName != layer->name())
transaction.execute(new cmd::SetLayerName(writer.layer(), newName));
if (newBlendMode != layer->blendMode())
transaction.execute(new cmd::SetLayerBlendMode(static_cast<LayerImage*>(writer.layer()), newBlendMode));
transaction.commit();
}
update_screen_for_document(writer.document());
}
}
}
@@ -133,7 +133,7 @@ void MergeDownLayerCommand::onExecute(Context* context)
src_cel->x()-bounds.x,
src_cel->y()-bounds.y,
src_cel->opacity(),
static_cast<LayerImage*>(src_layer)->getBlendMode());
static_cast<LayerImage*>(src_layer)->blendMode());
transaction.execute(new cmd::SetCelPosition(dst_cel,
bounds.x, bounds.y));
View
@@ -53,7 +53,7 @@ Document::Document(Sprite* sprite)
// Extra cel
, m_extraCel(NULL)
, m_extraImage(NULL)
, m_extraCelBlendMode(BLEND_MODE_NORMAL)
, m_extraCelBlendMode(BlendMode::NORMAL)
, m_extraCelType(render::ExtraType::NONE)
// Mask
, m_mask(new Mask())
View
@@ -15,6 +15,7 @@
#include "base/observable.h"
#include "base/shared_ptr.h"
#include "base/unique_ptr.h"
#include "doc/blend_mode.h"
#include "doc/color.h"
#include "doc/document.h"
#include "doc/frame.h"
@@ -127,8 +128,8 @@ namespace app {
Cel* getExtraCel() const;
Image* getExtraCelImage() const;
render::ExtraType getExtraCelType() const { return m_extraCelType; }
int getExtraCelBlendMode() const { return m_extraCelBlendMode; }
void setExtraCelBlendMode(int mode) { m_extraCelBlendMode = mode; }
BlendMode getExtraCelBlendMode() const { return m_extraCelBlendMode; }
void setExtraCelBlendMode(BlendMode mode) { m_extraCelBlendMode = mode; }
//////////////////////////////////////////////////////////////////////
// Mask
@@ -212,7 +213,7 @@ namespace app {
// Image of the extra cel.
ImageRef m_extraImage;
int m_extraCelBlendMode;
BlendMode m_extraCelBlendMode;
render::ExtraType m_extraCelType;
// Current mask.
View
@@ -59,7 +59,6 @@
#include <set>
namespace app {
DocumentApi::DocumentApi(Document* document, Transaction& transaction)
@@ -663,16 +663,17 @@ static Layer* ase_file_read_layer_chunk(FILE* f, Sprite* sprite, Layer** previou
child_level = fgetw(f);
fgetw(f); // default width
fgetw(f); // default height
fgetw(f); // blend mode
int blendmode = fgetw(f); // blend mode
ase_file_read_padding(f, 4);
name = ase_file_read_string(f);
/* image layer */
// Image layer
if (layer_type == 0) {
layer = new LayerImage(sprite);
static_cast<LayerImage*>(layer)->setBlendMode((BlendMode)blendmode);
}
/* layer set */
// Layer set
else if (layer_type == 1) {
layer = new LayerFolder(sprite);
}
@@ -684,7 +685,7 @@ static Layer* ase_file_read_layer_chunk(FILE* f, Sprite* sprite, Layer** previou
// name
layer->setName(name.c_str());
// child level...
// Child level
if (child_level == *current_level)
(*previous_layer)->parent()->addLayer(layer);
else if (child_level > *current_level)
@@ -718,10 +719,10 @@ static void ase_file_write_layer_chunk(FILE* f, ASE_FrameHeader* frame_header, L
}
fputw(child_level, f);
/* default width & height, and blend mode */
// Default width & height, and blend mode
fputw(0, f);
fputw(0, f);
fputw(layer->isImage() ? static_cast<LayerImage*>(layer)->getBlendMode(): 0, f);
fputw(layer->isImage() ? (int)static_cast<LayerImage*>(layer)->blendMode(): 0, f);
/* padding */
ase_file_write_padding(f, 4);
Oops, something went wrong.

0 comments on commit 21ca878

Please sign in to comment.