Giter Site home page Giter Site logo

Attribute の最適化 about tsumiji HOT 6 OPEN

rrbox avatar rrbox commented on August 26, 2024
Attribute の最適化

from tsumiji.

Comments (6)

rrbox avatar rrbox commented on August 26, 2024 1

Attribute を融合(merge)するのが難しいのでは?

from tsumiji.

rrbox avatar rrbox commented on August 26, 2024

上記は生成部分のみでした。モディファイア部分も書いておきます。

public extension Attribute {
   func fontName(_ value: String) -> Attribute {
        var newContext = self.context
        newContext.fontName = value
        return .init(context: newContext)
    }
    
   func fontSize(_ value: NSNumber) -> Attribute {
        var newContext = self.context
        newContext.fontSize = value
        return .init(context: newContext)
    }
    
   func foregroundColor(_ value: Scope.ForegroundColorAttribute.Value) -> Attribute {
        var newContext = self.context
        newContext.container.foregroundColor = value
        return .init(context: newContext)
    }
    
   func backgroundColor(_ value: Scope.BackgroundColorAttribute.Value) -> Attribute {
        var newContext = self.context
        newContext.container.backgroundColor = value
        return .init(context: newContext)
    }
    
   func kern(_ value: Scope.KernAttribute.Value) -> Attribute {
        var newContext = self.context
        newContext.container.kern = value
        return .init(context: newContext)
    }
    
   func tracking(_ value: Scope.TrackingAttribute.Value) -> Attribute {
        var newContext = self.context
        newContext.container.tracking = value
        return .init(context: newContext)
    }
    
   func baselineOffset(_ value: Scope.BaselineOffsetAttribute.Value) -> Attribute {
        var newContext = self.context
        newContext.container.baselineOffset = value
        return .init(context: newContext)
    }
}

from tsumiji.

rrbox avatar rrbox commented on August 26, 2024

#34 を達成する場合は以下のような protocol を使用するといいかもしれません。

public protocol AttributeModifier {
    func modify(context: inout AttributeContext)
}

extension Attribute {
    func modified<Mod: AttributeModifier>(_ mod: Mod) -> Attribute {
        var newContext = self.context
        mod.modify(&newContext)
        .init(context: newContext)
    }
}

例: fontName

struct FontName: AttributeModifier {
    let value: String
    func modify(context: inout AttributeContext) {
        context.fontName = self.value
    }
}

public extension Attribute {
   func fontName(_ value: String) -> Attribute {
        self.modified(FontName(value))
    }
}

from tsumiji.

rrbox avatar rrbox commented on August 26, 2024

もしこれがうまく機能する場合、enum を使う API と比較して以下のようなメリットがあると思われます。

  • 仕組みがシンプルなので今後の更新が簡単になるかも。
  • 多分メモリ的なパフォーマンスがいい。 <- 最終的にできる Attribute のメモリサイズが固定なので。
  • 多分生成〜使用に必要な実行速度も速い。enum は switch の連続 + こちらは特に加工せず直接利用できる

from tsumiji.

rrbox avatar rrbox commented on August 26, 2024

この方式では、Attribute を merge することが難しいです。なぜなら、style 設計者がどのプロパティを優先したいかが分からなくなってしまうからです。しかし、方法がないわけではありません。

まず各プロパティに対応する enum を作成します(自動で Hashable になります)。

enum ModifiedProperty {
    case fontName
    case fontSize
    case ...
}

そして、子に列挙体の Set を用意しておきます。

let modifiedPropertyHistory: Set<ModifiedProperty>

あとは Attribute に builder で情報を付加するたびに、プロパティに対応する case をこの Set に挿入していくだけです。

struct Attribute {
    enum ModifiedProperty {
        case fontName
        case fontSize
        case ...
    }
    
    let context: AttributeContext
    let modifiedPropertyHistory: Set<ModifiedProperty>
}

この手法のメリット・デメリットをメモしておきます。

  • メリット
    • 仕組みがシンプルなので、変更に強い。
    • 重複した変更が起こらない。ビルダーに記述することはできるが、データ内部では重複が起きない。
      • ただし、プログラマが重複しないように気をつけて書くことで重複は回避できます。
  • デメリット
    • merge するときに modified property を switch する必要があるのがとても面倒臭い。
      • indirect enum の負荷と大差ないかもです。
    • メモリ節約にはあまりならないかもしれない。
      • ただし、Attribute の情報追加によるデータサイズ増加分は、AttributeType の挿入分のみです
      • Context 部分は固定なので、情報が少なくてもそこそこのデータサイズになります。
    • プログラマが新しい modifier を追加するのが難しいかもしれません。
      • この柔軟性はオプションなので、放棄してもいいかもしれません。
      • 列挙体ではなく、String などにすればいくらでも追加できます。
      • merge の実装が難しそうです。

from tsumiji.

rrbox avatar rrbox commented on August 26, 2024

ひとつ前のコメントのコードを実装するなら、というメモです。

public protocol AttributeModifier {
    var propertyData: Attribute.ModifiedProperty { get }
    func modify(context: inout AttributeContext)
}

extension Attribute {
    func modified<Mod: AttributeModifier>(_ mod: Mod) -> Attribute {
        var newContext = self.context
        var newHistory = self.modifiedPropertyHistory
        mod.modify(&newContext)
        newHistory.insert(mod.propertyData)
        return Attribute(context: newContext, modifiedPropertyHistory: newHistory)
    }
}

Attribute context の merge についてもメモしておきます。

extension AttributeContext {
    // 他のコンテキストを、特定のプロパティについて変異させます
    func modify(_ c: inout AttributeContext, forProperty property: Attribute.ModifiedProperty) {
        switch property {
            case .fontName:
                c.fontName = self.fontName
            case .fontSize:
                c.fontSize = self.fontSize
            case .foregroundColor:
                c.container.foregroundColor = self.foregroundColor
            // ...
            default:
                break
        }
    }
}

from tsumiji.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.