void ColorPopup::onSimpleColorClick() { m_colorType.deselectItems(); if (!g_simplePal) return; app::Color color = getColor(); // Find bestfit palette entry int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); int a = color.getAlpha(); // Search for the closest color to the RGB values int i = g_simplePal->findBestfit(r, g, b, a, 0); if (i >= 0) { color_t c = g_simplePal->getEntry(i); color = app::Color::fromRgb(doc::rgba_getr(c), doc::rgba_getg(c), doc::rgba_getb(c), doc::rgba_geta(c)); } setColorWithSignal(color, ChangeType); }
void PixelsMovement::getDraggedImageCopy(base::UniquePtr<Image>& outputImage, base::UniquePtr<Mask>& outputMask) { gfx::Rect bounds = m_currentData.transformedBounds(); base::UniquePtr<Image> image(Image::create(m_sprite->pixelFormat(), bounds.w, bounds.h)); drawImage(image, bounds.origin(), false); // Draw mask without shrinking it, so the mask size is equal to the // "image" render. base::UniquePtr<Mask> mask(new Mask); drawMask(mask, false); // Now we can shrink and crop the image. gfx::Rect oldMaskBounds = mask->bounds(); mask->shrink(); gfx::Rect newMaskBounds = mask->bounds(); if (newMaskBounds != oldMaskBounds) { newMaskBounds.x -= oldMaskBounds.x; newMaskBounds.y -= oldMaskBounds.y; image.reset(crop_image(image, newMaskBounds.x, newMaskBounds.y, newMaskBounds.w, newMaskBounds.h, 0)); } outputImage.reset(image.release()); outputMask.reset(mask.release()); }
void ColorCurveCommand::onExecute(Context* context) { // Default curve if (!the_curve) { // TODO load the curve? the_curve.reset(new ColorCurve(ColorCurve::Linear)); the_curve->addPoint(gfx::Point(0, 0)); the_curve->addPoint(gfx::Point(255, 255)); } ColorCurveFilter filter; filter.setCurve(the_curve.get()); FilterManagerImpl filterMgr(context, &filter); filterMgr.setTarget(TARGET_RED_CHANNEL | TARGET_GREEN_CHANNEL | TARGET_BLUE_CHANNEL | TARGET_GRAY_CHANNEL | TARGET_ALPHA_CHANNEL); ColorCurveWindow window(filter, filterMgr); if (window.doModal()) { // TODO save the curve? } }
bool ResourcesLoader::next(base::UniquePtr<Resource>& resource) { Resource* rawResource; if (m_queue.try_pop(rawResource)) { resource.reset(rawResource); return true; } else return false; }
SimpleColors(ColorPopup* colorPopup, TooltipManager* tooltips) { for (int i=0; i<g_simplePal->size(); ++i) { doc::color_t c = g_simplePal->getEntry(i); app::Color color = app::Color::fromRgb(doc::rgba_getr(c), doc::rgba_getg(c), doc::rgba_getb(c), doc::rgba_geta(c)); Item* item = new Item(colorPopup, color); item->InitTheme.connect( [item]{ item->setSizeHint(gfx::Size(16, 16)*ui::guiscale()); item->setStyle(skin::SkinTheme::instance()->styles.simpleColor()); }); item->initTheme(); addChild(item); tooltips->addTooltipFor( item, g_simplePal->getEntryName(i), BOTTOM); } }
void ColorPopup::setColor(const app::Color& color, const SetColorOptions options) { m_color = color; if (m_simpleColors) { int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); int a = color.getAlpha(); int i = g_simplePal->findExactMatch(r, g, b, a, -1); if (i >= 0) m_simpleColors->selectColor(i); else m_simpleColors->deselect(); } if (color.getType() == app::Color::IndexType) { if (m_colorPalette) { m_colorPalette->deselect(); m_colorPalette->selectColor(color.getIndex()); } } m_sliders.setColor(m_color); if (!m_disableHexUpdate) m_hexColorEntry.setColor(m_color); if (options == ChangeType) selectColorType(m_color.getType()); // Set the new color Shade shade = m_oldAndNew.getShade(); shade.resize(2); shade[1] = (color.getType() == app::Color::IndexType ? color.toRgb(): color); if (!m_insideChange) shade[0] = shade[1]; m_oldAndNew.setShade(shade); }
namespace app { using namespace ui; using namespace doc; enum { INDEX_MODE, RGB_MODE, HSV_MODE, HSL_MODE, GRAY_MODE, MASK_MODE, COLOR_MODES }; static base::UniquePtr<doc::Palette> g_simplePal(nullptr); class ColorPopup::SimpleColors : public HBox { public: class Item : public Button { public: Item(ColorPopup* colorPopup, const app::Color& color) : Button("") , m_colorPopup(colorPopup) , m_color(color) { } private: void onClick(Event& ev) override { m_colorPopup->setColorWithSignal(m_color, ChangeType); } void onPaint(PaintEvent& ev) override { Graphics* g = ev.graphics(); skin::SkinTheme* theme = skin::SkinTheme::instance(); gfx::Rect rc = clientBounds(); Button::onPaint(ev); rc.shrink(theme->calcBorder(this, style())); draw_color(g, rc, m_color, doc::ColorMode::RGB); } ColorPopup* m_colorPopup; app::Color m_color; }; SimpleColors(ColorPopup* colorPopup, TooltipManager* tooltips) { for (int i=0; i<g_simplePal->size(); ++i) { doc::color_t c = g_simplePal->getEntry(i); app::Color color = app::Color::fromRgb(doc::rgba_getr(c), doc::rgba_getg(c), doc::rgba_getb(c), doc::rgba_geta(c)); Item* item = new Item(colorPopup, color); item->InitTheme.connect( [item]{ item->setSizeHint(gfx::Size(16, 16)*ui::guiscale()); item->setStyle(skin::SkinTheme::instance()->styles.simpleColor()); }); item->initTheme(); addChild(item); tooltips->addTooltipFor( item, g_simplePal->getEntryName(i), BOTTOM); } } void selectColor(int index) { for (int i=0; i<g_simplePal->size(); ++i) { children()[i]->setSelected(i == index); } } void deselect() { for (int i=0; i<g_simplePal->size(); ++i) { children()[i]->setSelected(false); } } }; ColorPopup::CustomButtonSet::CustomButtonSet() : ButtonSet(COLOR_MODES) { } int ColorPopup::CustomButtonSet::countSelectedItems() { int count = 0; for (int i=0; i<COLOR_MODES; ++i) if (getItem(i)->isSelected()) ++count; return count; } void ColorPopup::CustomButtonSet::onSelectItem(Item* item, bool focusItem, ui::Message* msg) { int count = countSelectedItems(); int itemIndex = getItemIndex(item); if (itemIndex == INDEX_MODE || itemIndex == MASK_MODE || !msg || // Any key modifier will act as multiple selection (!msg->shiftPressed() && !msg->altPressed() && !msg->ctrlPressed() && !msg->cmdPressed())) { if (item && item->isSelected() && count == 1) return; for (int i=0; i<COLOR_MODES; ++i) if (getItem(i)->isSelected()) getItem(i)->setSelected(false); } else { if (getItem(INDEX_MODE)->isSelected()) getItem(INDEX_MODE)->setSelected(false); if (getItem(MASK_MODE)->isSelected()) getItem(MASK_MODE)->setSelected(false); } if (item) { // Item already selected if (count == 1 && item == findSelectedItem()) return; item->setSelected(!item->isSelected()); if (focusItem) item->requestFocus(); } } ColorPopup::ColorPopup(const ColorButtonOptions& options) : PopupWindowPin(" ", // Non-empty to create title-bar and close button ClickBehavior::CloseOnClickInOtherWindow, options.canPinSelector) , m_vbox(VERTICAL) , m_topBox(HORIZONTAL) , m_color(app::Color::fromMask()) , m_closeButton(nullptr) , m_colorPaletteContainer(options.showIndexTab ? new ui::View: nullptr) , m_colorPalette(options.showIndexTab ? new PaletteView(false, PaletteView::SelectOneColor, this, 7*guiscale()): nullptr) , m_simpleColors(nullptr) , m_oldAndNew(Shade(2), ColorShades::ClickEntries) , m_maskLabel("Transparent Color Selected") , m_canPin(options.canPinSelector) , m_insideChange(false) , m_disableHexUpdate(false) { if (options.showSimpleColors) { if (!g_simplePal) { ResourceFinder rf; rf.includeDataDir("palettes/tags.gpl"); if (rf.findFirst()) g_simplePal.reset(load_palette(rf.filename().c_str())); } if (g_simplePal) m_simpleColors = new SimpleColors(this, &m_tooltips); } ButtonSet::Item* item = m_colorType.addItem("Index"); item->setFocusStop(false); if (!options.showIndexTab) item->setVisible(false); m_colorType.addItem("RGB")->setFocusStop(false); m_colorType.addItem("HSV")->setFocusStop(false); m_colorType.addItem("HSL")->setFocusStop(false); m_colorType.addItem("Gray")->setFocusStop(false); m_colorType.addItem("Mask")->setFocusStop(false); m_topBox.setBorder(gfx::Border(0)); m_topBox.setChildSpacing(0); if (m_colorPalette) { m_colorPaletteContainer->attachToView(m_colorPalette); m_colorPaletteContainer->setExpansive(true); } m_sliders.setExpansive(true); m_topBox.addChild(&m_colorType); m_topBox.addChild(new Separator("", VERTICAL)); m_topBox.addChild(&m_hexColorEntry); m_topBox.addChild(&m_oldAndNew); // TODO fix this hack for close button in popup window // Move close button (decorative widget) inside the m_topBox { WidgetsList decorators; for (auto child : children()) { if (child->type() == kWindowCloseButtonWidget) { m_closeButton = child; removeChild(child); break; } } if (m_closeButton) { m_topBox.addChild(new BoxFiller); VBox* vbox = new VBox; vbox->addChild(m_closeButton); m_topBox.addChild(vbox); } } setText(""); // To remove title m_vbox.addChild(&m_tooltips); if (m_simpleColors) m_vbox.addChild(m_simpleColors); m_vbox.addChild(&m_topBox); if (m_colorPaletteContainer) m_vbox.addChild(m_colorPaletteContainer); m_vbox.addChild(&m_sliders); m_vbox.addChild(&m_maskLabel); addChild(&m_vbox); m_colorType.ItemChange.connect(base::Bind<void>(&ColorPopup::onColorTypeClick, this)); m_sliders.ColorChange.connect(&ColorPopup::onColorSlidersChange, this); m_hexColorEntry.ColorChange.connect(&ColorPopup::onColorHexEntryChange, this); m_oldAndNew.Click.connect(&ColorPopup::onSelectOldColor, this); // Set RGB just for the sizeHint(), and then deselect the color type // (the first setColor() call will setup it correctly.) selectColorType(app::Color::RgbType); m_colorType.deselectItems(); m_onPaletteChangeConn = App::instance()->PaletteChange.connect(&ColorPopup::onPaletteChange, this); InitTheme.connect( [this]{ setSizeHint(gfx::Size(300*guiscale(), sizeHint().h)); }); initTheme(); } ColorPopup::~ColorPopup() { } void ColorPopup::setColor(const app::Color& color, const SetColorOptions options) { m_color = color; if (m_simpleColors) { int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); int a = color.getAlpha(); int i = g_simplePal->findExactMatch(r, g, b, a, -1); if (i >= 0) m_simpleColors->selectColor(i); else m_simpleColors->deselect(); } if (color.getType() == app::Color::IndexType) { if (m_colorPalette) { m_colorPalette->deselect(); m_colorPalette->selectColor(color.getIndex()); } } m_sliders.setColor(m_color); if (!m_disableHexUpdate) m_hexColorEntry.setColor(m_color); if (options == ChangeType) selectColorType(m_color.getType()); // Set the new color Shade shade = m_oldAndNew.getShade(); shade.resize(2); shade[1] = (color.getType() == app::Color::IndexType ? color.toRgb(): color); if (!m_insideChange) shade[0] = shade[1]; m_oldAndNew.setShade(shade); } app::Color ColorPopup::getColor() const { return m_color; } bool ColorPopup::onProcessMessage(ui::Message* msg) { switch (msg->type()) { case kSetCursorMessage: { if (m_canPin) { gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position(); if (hitTest(mousePos) == HitTestCaption) { set_mouse_cursor(kMoveCursor); return true; } } break; } } return PopupWindowPin::onProcessMessage(msg); } void ColorPopup::onWindowResize() { PopupWindowPin::onWindowResize(); if (m_closeButton) { gfx::Rect rc = m_closeButton->bounds(); if (rc.x2() > bounds().x2()) { rc.x = bounds().x2() - rc.w; m_closeButton->setBounds(rc); } } } void ColorPopup::onMakeFloating() { PopupWindowPin::onMakeFloating(); if (m_canPin) { setSizeable(true); setMoveable(true); } } void ColorPopup::onMakeFixed() { PopupWindowPin::onMakeFixed(); if (m_canPin) { setSizeable(false); setMoveable(true); } } void ColorPopup::onPaletteViewIndexChange(int index, ui::MouseButtons buttons) { base::ScopedValue<bool> restore(m_insideChange, true, m_insideChange); setColorWithSignal(app::Color::fromIndex(index), ChangeType); } void ColorPopup::onColorSlidersChange(ColorSlidersChangeEvent& ev) { base::ScopedValue<bool> restore(m_insideChange, true, m_insideChange); setColorWithSignal(ev.color(), DontChangeType); findBestfitIndex(ev.color()); } void ColorPopup::onColorHexEntryChange(const app::Color& color) { base::ScopedValue<bool> restore(m_insideChange, true, m_insideChange); // Disable updating the hex entry so we don't override what the user // is writting in the text field. m_disableHexUpdate = true; setColorWithSignal(color, ChangeType); findBestfitIndex(color); // If we are in edit mode, the "m_disableHexUpdate" will be changed // to false in onPaletteChange() after the color bar timer is // triggered. In this way we don't modify the hex field when the // user is editing it and the palette "edit mode" is enabled. if (!inEditMode()) m_disableHexUpdate = false; } void ColorPopup::onSelectOldColor() { Shade shade = m_oldAndNew.getShade(); int hot = m_oldAndNew.getHotEntry(); if (hot >= 0 && hot < int(shade.size())) { setColorWithSignal(shade[hot], DontChangeType); } } void ColorPopup::onSimpleColorClick() { m_colorType.deselectItems(); if (!g_simplePal) return; app::Color color = getColor(); // Find bestfit palette entry int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); int a = color.getAlpha(); // Search for the closest color to the RGB values int i = g_simplePal->findBestfit(r, g, b, a, 0); if (i >= 0) { color_t c = g_simplePal->getEntry(i); color = app::Color::fromRgb(doc::rgba_getr(c), doc::rgba_getg(c), doc::rgba_getb(c), doc::rgba_geta(c)); } setColorWithSignal(color, ChangeType); } void ColorPopup::onColorTypeClick() { base::ScopedValue<bool> restore(m_insideChange, true, m_insideChange); if (m_simpleColors) m_simpleColors->deselect(); app::Color newColor = getColor(); switch (m_colorType.selectedItem()) { case INDEX_MODE: newColor = app::Color::fromIndex(newColor.getIndex()); break; case RGB_MODE: newColor = app::Color::fromRgb(newColor.getRed(), newColor.getGreen(), newColor.getBlue(), newColor.getAlpha()); break; case HSV_MODE: newColor = app::Color::fromHsv(newColor.getHsvHue(), newColor.getHsvSaturation(), newColor.getHsvValue(), newColor.getAlpha()); break; case HSL_MODE: newColor = app::Color::fromHsl(newColor.getHslHue(), newColor.getHslSaturation(), newColor.getHslLightness(), newColor.getAlpha()); break; case GRAY_MODE: newColor = app::Color::fromGray(newColor.getGray(), newColor.getAlpha()); break; case MASK_MODE: newColor = app::Color::fromMask(); break; } setColorWithSignal(newColor, ChangeType); } void ColorPopup::onPaletteChange() { base::ScopedValue<bool> restore(m_insideChange, inEditMode(), m_insideChange); setColor(getColor(), DontChangeType); invalidate(); if (inEditMode()) m_disableHexUpdate = false; } void ColorPopup::findBestfitIndex(const app::Color& color) { if (!m_colorPalette) return; // Find bestfit palette entry int r = color.getRed(); int g = color.getGreen(); int b = color.getBlue(); int a = color.getAlpha(); // Search for the closest color to the RGB values int i = get_current_palette()->findBestfit(r, g, b, a, 0); if (i >= 0) { m_colorPalette->deselect(); m_colorPalette->selectColor(i); } } void ColorPopup::setColorWithSignal(const app::Color& color, const SetColorOptions options) { Shade shade = m_oldAndNew.getShade(); setColor(color, options); shade.resize(2); shade[1] = color; m_oldAndNew.setShade(shade); // Fire ColorChange signal ColorChange(color); } void ColorPopup::selectColorType(app::Color::Type type) { if (m_colorPaletteContainer) m_colorPaletteContainer->setVisible(type == app::Color::IndexType); m_maskLabel.setVisible(type == app::Color::MaskType); // Count selected items. if (m_colorType.countSelectedItems() < 2) { switch (type) { case app::Color::IndexType: if (m_colorPalette) m_colorType.setSelectedItem(INDEX_MODE); else m_colorType.setSelectedItem(RGB_MODE); break; case app::Color::RgbType: m_colorType.setSelectedItem(RGB_MODE); break; case app::Color::HsvType: m_colorType.setSelectedItem(HSV_MODE); break; case app::Color::HslType: m_colorType.setSelectedItem(HSL_MODE); break; case app::Color::GrayType: m_colorType.setSelectedItem(GRAY_MODE); break; case app::Color::MaskType: m_colorType.setSelectedItem(MASK_MODE); break; } } std::vector<app::Color::Type> types; if (m_colorType.getItem(RGB_MODE)->isSelected()) types.push_back(app::Color::RgbType); if (m_colorType.getItem(HSV_MODE)->isSelected()) types.push_back(app::Color::HsvType); if (m_colorType.getItem(HSL_MODE)->isSelected()) types.push_back(app::Color::HslType); if (m_colorType.getItem(GRAY_MODE)->isSelected()) types.push_back(app::Color::GrayType); m_sliders.setColorTypes(types); // Remove focus from hidden RGB/HSV/HSL text entries auto widget = manager()->getFocus(); if (widget && !widget->isVisible()) { auto window = widget->window(); if (window && window == this) widget->releaseFocus(); } m_vbox.layout(); m_vbox.invalidate(); } bool ColorPopup::inEditMode() { return // TODO use other flag instead of m_canPin, here we want to ask if // this ColorPopup is related to the main ColorBar (instead of // other ColorButtons like the one in "Replace Color", etc.) (m_canPin) && (ColorBar::instance()->inEditMode()); } } // namespace app
ColorPopup::ColorPopup(const ColorButtonOptions& options) : PopupWindowPin(" ", // Non-empty to create title-bar and close button ClickBehavior::CloseOnClickInOtherWindow, options.canPinSelector) , m_vbox(VERTICAL) , m_topBox(HORIZONTAL) , m_color(app::Color::fromMask()) , m_closeButton(nullptr) , m_colorPaletteContainer(options.showIndexTab ? new ui::View: nullptr) , m_colorPalette(options.showIndexTab ? new PaletteView(false, PaletteView::SelectOneColor, this, 7*guiscale()): nullptr) , m_simpleColors(nullptr) , m_oldAndNew(Shade(2), ColorShades::ClickEntries) , m_maskLabel("Transparent Color Selected") , m_canPin(options.canPinSelector) , m_insideChange(false) , m_disableHexUpdate(false) { if (options.showSimpleColors) { if (!g_simplePal) { ResourceFinder rf; rf.includeDataDir("palettes/tags.gpl"); if (rf.findFirst()) g_simplePal.reset(load_palette(rf.filename().c_str())); } if (g_simplePal) m_simpleColors = new SimpleColors(this, &m_tooltips); } ButtonSet::Item* item = m_colorType.addItem("Index"); item->setFocusStop(false); if (!options.showIndexTab) item->setVisible(false); m_colorType.addItem("RGB")->setFocusStop(false); m_colorType.addItem("HSV")->setFocusStop(false); m_colorType.addItem("HSL")->setFocusStop(false); m_colorType.addItem("Gray")->setFocusStop(false); m_colorType.addItem("Mask")->setFocusStop(false); m_topBox.setBorder(gfx::Border(0)); m_topBox.setChildSpacing(0); if (m_colorPalette) { m_colorPaletteContainer->attachToView(m_colorPalette); m_colorPaletteContainer->setExpansive(true); } m_sliders.setExpansive(true); m_topBox.addChild(&m_colorType); m_topBox.addChild(new Separator("", VERTICAL)); m_topBox.addChild(&m_hexColorEntry); m_topBox.addChild(&m_oldAndNew); // TODO fix this hack for close button in popup window // Move close button (decorative widget) inside the m_topBox { WidgetsList decorators; for (auto child : children()) { if (child->type() == kWindowCloseButtonWidget) { m_closeButton = child; removeChild(child); break; } } if (m_closeButton) { m_topBox.addChild(new BoxFiller); VBox* vbox = new VBox; vbox->addChild(m_closeButton); m_topBox.addChild(vbox); } } setText(""); // To remove title m_vbox.addChild(&m_tooltips); if (m_simpleColors) m_vbox.addChild(m_simpleColors); m_vbox.addChild(&m_topBox); if (m_colorPaletteContainer) m_vbox.addChild(m_colorPaletteContainer); m_vbox.addChild(&m_sliders); m_vbox.addChild(&m_maskLabel); addChild(&m_vbox); m_colorType.ItemChange.connect(base::Bind<void>(&ColorPopup::onColorTypeClick, this)); m_sliders.ColorChange.connect(&ColorPopup::onColorSlidersChange, this); m_hexColorEntry.ColorChange.connect(&ColorPopup::onColorHexEntryChange, this); m_oldAndNew.Click.connect(&ColorPopup::onSelectOldColor, this); // Set RGB just for the sizeHint(), and then deselect the color type // (the first setColor() call will setup it correctly.) selectColorType(app::Color::RgbType); m_colorType.deselectItems(); m_onPaletteChangeConn = App::instance()->PaletteChange.connect(&ColorPopup::onPaletteChange, this); InitTheme.connect( [this]{ setSizeHint(gfx::Size(300*guiscale(), sizeHint().h)); }); initTheme(); }
void deselect() { for (int i=0; i<g_simplePal->size(); ++i) { children()[i]->setSelected(false); } }
void selectColor(int index) { for (int i=0; i<g_simplePal->size(); ++i) { children()[i]->setSelected(i == index); } }
ToolLoopBase(Editor* editor, tools::Tool* tool, tools::Ink* ink, Document* document, tools::ToolLoop::Button button, const app::Color& fgColor, const app::Color& bgColor) : m_editor(editor) , m_tool(tool) , m_brush(App::instance()->contextBar()->activeBrush(m_tool)) , m_document(document) , m_sprite(editor->sprite()) , m_layer(editor->layer()) , m_frame(editor->frame()) , m_rgbMap(nullptr) , m_docPref(Preferences::instance().document(m_document)) , m_toolPref(Preferences::instance().tool(m_tool)) , m_opacity(m_toolPref.opacity()) , m_tolerance(m_toolPref.tolerance()) , m_contiguous(m_toolPref.contiguous()) , m_button(button) , m_ink(ink->clone()) , m_controller(m_tool->getController(m_button)) , m_pointShape(m_tool->getPointShape(m_button)) , m_intertwine(m_tool->getIntertwine(m_button)) , m_tracePolicy(m_tool->getTracePolicy(m_button)) , m_symmetry(nullptr) , m_fgColor(color_utils::color_for_target_mask(fgColor, ColorTarget(m_layer))) , m_bgColor(color_utils::color_for_target_mask(bgColor, ColorTarget(m_layer))) , m_primaryColor(button == tools::ToolLoop::Left ? m_fgColor: m_bgColor) , m_secondaryColor(button == tools::ToolLoop::Left ? m_bgColor: m_fgColor) { tools::FreehandAlgorithm algorithm = m_toolPref.freehandAlgorithm(); if (m_tracePolicy == tools::TracePolicy::Accumulate || m_tracePolicy == tools::TracePolicy::AccumulateUpdateLast) { tools::ToolBox* toolbox = App::instance()->toolBox(); switch (algorithm) { case tools::FreehandAlgorithm::DEFAULT: m_intertwine = toolbox->getIntertwinerById(tools::WellKnownIntertwiners::AsLines); m_tracePolicy = tools::TracePolicy::Accumulate; break; case tools::FreehandAlgorithm::PIXEL_PERFECT: m_intertwine = toolbox->getIntertwinerById(tools::WellKnownIntertwiners::AsPixelPerfect); m_tracePolicy = tools::TracePolicy::AccumulateUpdateLast; break; case tools::FreehandAlgorithm::DOTS: m_intertwine = toolbox->getIntertwinerById(tools::WellKnownIntertwiners::None); m_tracePolicy = tools::TracePolicy::Accumulate; break; } } // Symmetry mode if (Preferences::instance().symmetryMode.enabled()) { switch (m_docPref.symmetry.mode()) { case app::gen::SymmetryMode::NONE: ASSERT(m_symmetry == nullptr); break; case app::gen::SymmetryMode::HORIZONTAL: m_symmetry.reset(new app::tools::HorizontalSymmetry(m_docPref.symmetry.xAxis())); break; case app::gen::SymmetryMode::VERTICAL: m_symmetry.reset(new app::tools::VerticalSymmetry(m_docPref.symmetry.yAxis())); break; } } // Ignore opacity for these inks if (!tools::inkHasOpacity(m_toolPref.ink()) && m_brush->type() != kImageBrushType && !m_ink->isEffect()) { m_opacity = 255; } if (m_toolPref.ink() == tools::InkType::SHADING) { m_shadingRemap.reset( App::instance()->contextBar()->createShadeRemap( button == tools::ToolLoop::Left)); } }
tools::Symmetry* getSymmetry() override { return m_symmetry.get(); }
namespace app { using namespace filters; static base::UniquePtr<ColorCurve> the_curve; class ColorCurveWindow : public FilterWindow { public: ColorCurveWindow(ColorCurveFilter& filter, FilterManagerImpl& filterMgr) : FilterWindow("Color Curve", "ColorCurve", &filterMgr, WithChannelsSelector, WithoutTiledCheckBox) , m_filter(filter) , m_editor(filter.getCurve(), gfx::Rect(0, 0, 256, 256)) { m_view.attachToView(&m_editor); m_view.setExpansive(true); m_view.setMinSize(gfx::Size(128, 64)); getContainer()->addChild(&m_view); m_editor.CurveEditorChange.connect(&ColorCurveWindow::onCurveChange, this); } protected: void onCurveChange() { // The color curve in the filter is the same refereced by the // editor. But anyway, we have to re-set the same curve in the // filter to regenerate the map used internally by the filter // (which is calculated inside setCurve() method). m_filter.setCurve(m_editor.getCurve()); restartPreview(); } private: ColorCurveFilter& m_filter; ui::View m_view; ColorCurveEditor m_editor; }; class ColorCurveCommand : public Command { public: ColorCurveCommand(); Command* clone() const override { return new ColorCurveCommand(*this); } protected: bool onEnabled(Context* context) override; void onExecute(Context* context) override; }; ColorCurveCommand::ColorCurveCommand() : Command("ColorCurve", "Color Curve", CmdRecordableFlag) { } bool ColorCurveCommand::onEnabled(Context* context) { return context->checkFlags(ContextFlags::ActiveDocumentIsWritable | ContextFlags::HasActiveSprite); } void ColorCurveCommand::onExecute(Context* context) { // Default curve if (!the_curve) { // TODO load the curve? the_curve.reset(new ColorCurve(ColorCurve::Linear)); the_curve->addPoint(gfx::Point(0, 0)); the_curve->addPoint(gfx::Point(255, 255)); } ColorCurveFilter filter; filter.setCurve(the_curve.get()); FilterManagerImpl filterMgr(context, &filter); filterMgr.setTarget(TARGET_RED_CHANNEL | TARGET_GREEN_CHANNEL | TARGET_BLUE_CHANNEL | TARGET_GRAY_CHANNEL | TARGET_ALPHA_CHANNEL); ColorCurveWindow window(filter, filterMgr); if (window.doModal()) { // TODO save the curve? } } Command* CommandFactory::createColorCurveCommand() { return new ColorCurveCommand; } } // namespace app