attr.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package mappers
  2. import (
  3. "github.com/kpmy/odf/mappers/attr"
  4. "github.com/kpmy/odf/model"
  5. "github.com/kpmy/odf/xmlns/office"
  6. "github.com/kpmy/odf/xmlns/style"
  7. "github.com/kpmy/odf/xmlns/svg"
  8. "github.com/kpmy/odf/xmlns/text"
  9. "github.com/kpmy/ypk/halt"
  10. "strconv"
  11. )
  12. //Attr holds a number of style nodes of document model and writes attributes. Also it holds cache of recently used attributes for reuse
  13. type Attr struct {
  14. doc model.Model
  15. ds model.Leaf //document styles
  16. ffd model.Leaf //font-face decls
  17. as model.Leaf //automatic styles
  18. ms model.Leaf //master styles
  19. asc model.Leaf //automatic styles
  20. ffdc model.Leaf //font-face decls
  21. s model.Leaf
  22. current map[string]attr.Attributes
  23. old map[string]attr.Attributes
  24. fonts map[string]model.Leaf
  25. stored bool
  26. count int
  27. }
  28. func (a *Attr) nextName() string {
  29. a.count++
  30. return "auto" + strconv.Itoa(a.count)
  31. }
  32. func (a *Attr) reset() {
  33. a.stored = true
  34. a.current = make(map[string]attr.Attributes)
  35. }
  36. //Init called when empty document is initialized
  37. func (a *Attr) Init(m model.Model) {
  38. a.doc = m
  39. wr := a.doc.NewWriter()
  40. wr.Pos(a.doc.Root())
  41. a.ds = wr.WritePos(New(office.DocumentStyles))
  42. wr.Attr(office.Version, "1.0")
  43. a.ffd = wr.WritePos(New(office.FontFaceDecls))
  44. wr.Pos(a.ds)
  45. a.as = wr.WritePos(New(office.AutomaticStyles))
  46. wr.Pos(a.ds)
  47. a.ms = wr.WritePos(New(office.MasterStyles))
  48. wr.Pos(a.ds)
  49. a.asc = New(office.AutomaticStyles)
  50. a.ffdc = New(office.FontFaceDecls)
  51. a.old = make(map[string]attr.Attributes)
  52. a.fonts = make(map[string]model.Leaf)
  53. a.reset()
  54. }
  55. //Fit finds appropriate attributes for given name and calls closure for applying attributes
  56. func (a *Attr) Fit(n model.LeafName, callback func(a attr.Attributes)) {
  57. fit := make(map[model.LeafName]attr.Attributes)
  58. for _, v := range a.current {
  59. fit[v.Fit()] = v
  60. }
  61. if a := fit[n]; a != nil {
  62. callback(a)
  63. }
  64. }
  65. //RegisterFont writes font entry to Font Face Declaration section
  66. func (a *Attr) RegisterFont(name, fontface string) {
  67. if a.fonts[name] == nil {
  68. wr := a.doc.NewWriter()
  69. wr.Pos(a.ffd)
  70. wr.WritePos(New(style.FontFace))
  71. wr.Attr(style.Name, name)
  72. wr.Attr(svg.FontFamily, fontface)
  73. //TODO deep copy fontface node
  74. wr.Pos(a.ffdc)
  75. a.fonts[name] = wr.WritePos(New(style.FontFace))
  76. wr.Attr(style.Name, name)
  77. wr.Attr(svg.FontFamily, name)
  78. }
  79. }
  80. //Flush writes styles to document model
  81. func (a *Attr) Flush() {
  82. if !a.stored {
  83. wr := a.doc.NewWriter()
  84. for _, v := range a.current {
  85. if n := v.Name(); n == "" && a.old[n] == nil {
  86. v.Name(a.nextName())
  87. wr.Pos(a.asc)
  88. wr.WritePos(New(style.Style))
  89. wr.Attr(style.Name, v.Name())
  90. v.Write(a.doc.NewWriter(wr))
  91. a.old[v.Name()] = v
  92. } else if n != "" && a.old[n] == nil {
  93. halt.As(100, v.Name())
  94. }
  95. }
  96. a.stored = true
  97. }
  98. }
  99. //OldAttr return already written attributes for new attribute if their contents equals
  100. func (a *Attr) OldAttr(n attr.Attributes) attr.Attributes {
  101. for _, v := range a.old {
  102. if v.Equal(n) {
  103. return v
  104. }
  105. }
  106. return nil
  107. }
  108. //SetDefaults sets default attributes of document, only TextAttributes and ParagraphAttributes supported by now
  109. func (a *Attr) SetDefaults(al ...attr.Attributes) {
  110. wr := a.doc.NewWriter()
  111. wr.Pos(a.ds)
  112. if a.s == nil {
  113. a.s = wr.WritePos(New(office.Styles))
  114. for _, x := range al {
  115. switch x.Fit() {
  116. case text.P, text.Span:
  117. wr.WritePos(New(style.DefaultStyle))
  118. x.Write(a.doc.NewWriter(wr))
  119. wr.Attr(style.Family, style.FamilyParagraph)
  120. default:
  121. halt.As(100, x.Fit())
  122. }
  123. }
  124. } else {
  125. wr.Delete(a.s)
  126. a.s = nil
  127. a.SetDefaults(al...)
  128. }
  129. }