gerb 0.0.1-alpha+2023-04-27

Font editor for UFO 3 fonts.
Documentation
/*
 * gerb
 *
 * Copyright 2022 - Manos Pitsidianakis
 *
 * This file is part of gerb.
 *
 * gerb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * gerb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gerb. If not, see <http://www.gnu.org/licenses/>.
 */

#![deny(
    /* groups */
    clippy::correctness,
    clippy::suspicious,
    clippy::complexity,
    clippy::perf,
    clippy::style,
    clippy::cargo,
    clippy::nursery,
    /* restriction */
    clippy::dbg_macro,
    clippy::rc_buffer,
    clippy::as_underscore,
    clippy::assertions_on_result_states,
    /* pedantic */
    clippy::cast_lossless,
    clippy::cast_possible_wrap,
    clippy::ptr_as_ptr,
    clippy::bool_to_int_with_if,
    clippy::borrow_as_ptr,
    clippy::case_sensitive_file_extension_comparisons,
    clippy::cast_lossless,
    clippy::cast_ptr_alignment,
    clippy::naive_bytecount,
    rustdoc::broken_intra_doc_links,

)]
// known problems/false negative
#![allow(
    clippy::use_self,
    clippy::multiple_crate_versions, // [ref:TODO] bundle generational-arena? it seems unmaintained.
    clippy::missing_const_for_fn,
    clippy::fallible_impl_from, // [ref:TODO]
    clippy::option_if_let_else, // [ref:TODO]
    clippy::cognitive_complexity, // [ref:TODO]
)]

#[macro_use]
extern crate glib;

pub use serde_json;

#[cfg(feature = "python")]
pub mod api;
pub mod app;
pub mod editor;
pub mod error;
#[cfg(feature = "git")]
pub mod git;
pub mod glyphs;
pub mod project;
pub mod resources;
pub mod ufo;
pub mod unicode;
pub mod utils;
pub mod views;
pub mod window;

const fn _get_package_git_sha() -> Option<&'static str> {
    option_env!("PACKAGE_GIT_SHA")
}

const _PACKAGE_COMMIT_SHA: Option<&str> = _get_package_git_sha();

pub fn get_git_sha() -> std::borrow::Cow<'static, str> {
    if let Some(r) = _PACKAGE_COMMIT_SHA {
        return r.into();
    }
    /*
    build_info::build_info!(fn build_info);
    let info = build_info();
    if let Some(v) = info
        .version_control
        .as_ref()
        .and_then(|v| v.git())
        .map(|g| g.commit_short_id.clone())
    {
        v.into()
    } else {
        "<unknown>".into()
    }
    */
    "<unknown>".into()
}

pub const APPLICATION_NAME: &str = "gerb";
pub const APPLICATION_ID: &str = "io.github.epilys.gerb";
pub const ISSUE_TRACKER: &str = "https://github.com/epilys/gerb/issues";
/*
pub const VERSION_INFO: &str = build_info::format!("{}", $.crate_info.version);
pub const BUILD_INFO: &str = build_info::format!("{}\t{}\t{}\t{}", $.crate_info.version, $.compiler, $.timestamp, $.crate_info.enabled_features);
pub const CLI_INFO: &str = build_info::format!("\n                 ,adPPYb,d8  \n                a8\"    `Y88  \n                8b       88  \n                \"8a,   ,d88  \n                 `\"YbbdP\"Y8  \n                 aa,    ,88  \n                  \"Y8bbdP\"   \n\n{} Copyright (C) 2022 Emmanouil Pitsidianakis\nThis program comes with ABSOLUTELY NO WARRANTY.\nThis is free software, and you are welcome to\nredistribute it under certain conditions; See\nLICENSE.md for more details.\n\nVersion: {}\nAuthors: {}\nLicense: GPL version 3 or later\nCompiler: {}\nBuild-Date: {}\nEnabled-features: {}", $.crate_info.name, $.crate_info.version, $.crate_info.authors, $.compiler, $.timestamp, $.crate_info.enabled_features);
*/

pub const VERSION_INFO: &str = "<unknown>";
pub const BUILD_INFO: &str = "<unknown>";
pub const CLI_INFO: &str = "<unknown>";
/* Annotations:
 *
 * Global tags (in tagref format <https://github.com/stepchowfun/tagref>) for source code
 * annotation:
 *
 * - [tag:hardcoded_color_value] Replace hardcoded color values with user configurable ones.
 * - [tag:needs_unit_test]
 * - [tag:needs_user_doc]
 * - [tag:needs_dev_doc]
 * - [tag:FIXME]
 * - [tag:TODO]
 * - [tag:VERIFY] Verify whether this is the correct way to do something
 */

pub mod prelude {
    pub use super::*;
    pub use app::Application;
    pub use app::*;
    pub use app::{types::*, Settings};
    pub use editor::*;
    pub use error::Error;
    pub use glyphs::metadata::GlyphMetadata;
    pub use glyphs::{Continuity, Glyph, GlyphPointIndex, Guideline};
    pub use gtk::prelude::*;
    pub use gtk::subclass::prelude::ObjectSubclassIsExt;
    pub use indexmap::{IndexMap, IndexSet};
    pub use project::Project;
    pub use ufo;
    pub use ufo::objects::FontInfo;
    pub use ufo::{LayerContents, MetaInfo};
    pub use utils::colors::*;
    pub use utils::points::*;
    pub use utils::property_window::*;
    pub use utils::range_query::Coordinate;
    pub use utils::shortcuts::{Shortcut, ShortcutAction};
    // cairo context API wrapper:
    pub use utils::{ContextExt, ContextRef};
    // utility types:
    pub use utils::{Either, FieldRef, UI_EDITABLE, UI_PATH, UI_READABLE};
    // utility traits:
    pub use utils::{Modified, StyleReadOnly};
    pub use views::{
        canvas, canvas::CanvasSettings, Canvas, Collection, Overlay, Transformation, UnitPoint,
        ViewPoint,
    };
    pub use window::Workspace;

    pub use glib::prelude::*;
    pub use glib::subclass::Signal;
    pub use glib::{
        ParamFlags, ParamSpec, ParamSpecBoolean, ParamSpecBoxed, ParamSpecDouble, ParamSpecObject,
        ParamSpecString, Value,
    };
    pub use gtk::prelude::ToValue;
    pub use gtk::subclass::prelude::*;
    pub use gtk::{cairo, gdk, gdk_pixbuf, gio, glib};
    pub use std::borrow::Cow;
    pub use std::cell::RefCell;
    pub use std::cell::{Cell, Ref, RefMut};
    pub use std::collections::HashSet;
    pub use std::path::{Path, PathBuf};
    pub use std::rc::Rc;
    pub use std::str::FromStr;

    pub use once_cell::sync::{Lazy, OnceCell};
    pub use uuid::Uuid;

    mod macros {
        #[macro_export]
        macro_rules! impl_modified {
            ($ty:ty) => {
                $crate::impl_modified!($ty, MODIFIED);
            };
            ($ty:ty, $property_name:ident) => {
                impl $crate::utils::Modified for $ty {
                    const PROPERTY_NAME: &'static str = Self::$property_name;
                }
            };
        }

        #[macro_export]
        macro_rules! impl_deref {
            ($ty:ty, $inner:ty) => {
                impl std::ops::Deref for $ty {
                    type Target = $inner;

                    fn deref(&self) -> &Self::Target {
                        self.imp()
                    }
                }
            };
        }

        #[macro_export]
        macro_rules! impl_friendly_name {
            ($ty:ty) => {
                impl $crate::utils::property_window::FriendlyNameInSettings for $ty {}
            };
            ($ty:ty, $friendly_name:expr) => {
                impl $crate::utils::property_window::FriendlyNameInSettings for $ty {
                    fn friendly_name(&self) -> Cow<'static, str> {
                        $friendly_name.into()
                    }

                    fn static_friendly_name() -> Cow<'static, str> {
                        $friendly_name.into()
                    }
                }
            };
        }

        #[macro_export]
        macro_rules! impl_property_window {
            ($ty:ty) => {
                impl $crate::utils::property_window::FriendlyNameInSettings for $ty {}
                impl $crate::utils::property_window::CreatePropertyWindow for $ty {}
            };
            ($ty:ty$(,)? $({ $friendly_name:expr })?) => {
                $(
                    $crate::impl_friendly_name!($ty, $friendly_name);
                )*
                impl $crate::utils::property_window::CreatePropertyWindow for $ty {}
            };
            (delegate $ty:ty => { $($access:tt)+ }, $($field:tt)+) => {
                impl $crate::utils::property_window::FriendlyNameInSettings for $ty {}
                impl $crate::utils::property_window::CreatePropertyWindow for $ty {
                    fn new_property_window(
                        &self,
                        app: &$crate::prelude::Application,
                        create: bool,
                    ) -> $crate::prelude::PropertyWindow
                    where
                        Self: glib::IsA<glib::Object>,
                    {
                        let inner=self.$($field)*.$($access)*;
                        inner.new_property_window(app, create)
                    }
                }
            };
        }

        /// Helper macro to define user editable GObject properties.
        #[macro_export]
        macro_rules! def_param {
            (str $name:expr) => {
                glib::ParamSpecString::new(
                    $name,
                    $name,
                    $name,
                    Some(""),
                    ParamFlags::READWRITE | UI_EDITABLE,
                )
            };
            (i64 $name:expr, $default:expr) => {
                glib::ParamSpecInt64::new(
                    $name,
                    $name,
                    $name,
                    0,
                    std::i64::MAX,
                    $default,
                    ParamFlags::READWRITE | UI_EDITABLE,
                )
            };
            (i64 $name:expr) => {
                $crate::def_param!(i64 $name, 1)
            };
            (u64 $name:expr, $default:expr) => {
                glib::ParamSpecUInt64::new(
                    $name,
                    $name,
                    $name,
                    0,
                    std::u64::MAX,
                    $default,
                    ParamFlags::READWRITE | UI_EDITABLE,
                )
            };
            (u64 $name:expr) => {
                $crate::def_param!(u64 $name, 1)
            };
            (f64 $name:expr, $min:expr, $default:expr) => {
                glib::ParamSpecDouble::new(
                    $name,
                    $name,
                    $name,
                    $min,
                    std::f64::MAX,
                    $default,
                    ParamFlags::READWRITE | UI_EDITABLE,
                )
            };
        }

        /// Helper macro to easily "inherit" property names from another type.
        /// The convention is that property names are stored as type constant string slices.
        #[macro_export]
        macro_rules! inherit_property {
            ($t:ty, $($prop:ident),+$(,)?) => {
                $(
                pub const $prop: &str = <$t>::$prop;
                )*
            }
        }

        /// Helper macro to call return; if a gtk dialog response calls for it
        #[macro_export]
        macro_rules! return_if_not_ok_or_accept {
            ($response:expr) => {{
                let response = $response; // evaluate
                if matches!(
                    response,
                    gtk::ResponseType::Cancel
                        | gtk::ResponseType::DeleteEvent
                        | gtk::ResponseType::Close
                ) {
                    return;
                }
                response
            }};
        }
    }
    pub use macros::*;
}