Преглед изворни кода

добавил аттрибут цвета и стиля к аттрибутам шрифта, пробую новый механизм хранения аттрибутов для fluid интерфейса

kpmy пре 10 година
родитељ
комит
1164de24c9
9 измењених фајлова са 131 додато и 18 уклоњено
  1. 51 0
      mappers/attr/base.go
  2. 9 9
      mappers/attr/para.go
  3. 27 1
      mappers/attr/text.go
  4. 17 0
      model/stub/simple_attrs.go
  5. 6 0
      model/stub/simple_riders.go
  6. 5 1
      model/stub/simple_tree.go
  7. 8 6
      odf_test.go
  8. 7 1
      xmlns/fo/f.go
  9. 1 0
      xmlns/x.go

+ 51 - 0
mappers/attr/base.go

@@ -25,3 +25,54 @@ func (n *named) Name(s ...string) string {
 	}
 	return n.name
 }
+
+type value struct {
+	name    model.AttrName
+	wr      model.Writer
+	data    interface{}
+	builder func(value)
+}
+
+type easy struct {
+	m map[model.AttrName]value
+}
+
+func (e *easy) put(n model.AttrName, x interface{}, foo func(value)) {
+	if e.m == nil {
+		e.m = make(map[model.AttrName]value)
+	}
+	b := func(v value) {
+		v.wr.Attr(v.name, v.data)
+	}
+	if foo != nil {
+		b = foo
+	}
+	if x != nil {
+		e.m[n] = value{data: x, builder: b}
+	} else {
+		delete(e.m, n)
+	}
+}
+
+func (e *easy) equal(t *easy) (ok bool) {
+	ok = (e.m != nil) == (t.m != nil)
+	if ok && (e.m != nil) {
+		for k, v := range e.m {
+			ok = t.m[k].data == v.data
+			if !ok {
+				break
+			}
+		}
+	}
+	return
+}
+
+func (e *easy) apply(wr model.Writer) {
+	if e.m != nil {
+		for k, v := range e.m {
+			v.wr = wr
+			v.name = k
+			v.builder(v)
+		}
+	}
+}

+ 9 - 9
mappers/attr/para.go

@@ -8,15 +8,14 @@ import (
 )
 
 type ParagraphAttributes struct {
-	align     string
-	pageBreak bool
 	named
+	easy
 }
 
 func (p *ParagraphAttributes) Equal(_a Attributes) (ok bool) {
 	a, ok := _a.(*ParagraphAttributes)
 	if ok {
-		ok = p.align == a.align && p.pageBreak == a.pageBreak
+		ok = p.equal(&a.easy)
 	}
 	return
 }
@@ -26,18 +25,19 @@ func (p *ParagraphAttributes) Fit() model.LeafName { return text.P }
 func (p *ParagraphAttributes) Write(wr model.Writer) {
 	wr.Attr(style.Family, style.FamilyParagraph)
 	wr.WritePos(New(style.ParagraphProperties))
-	wr.Attr(fo.TextAlign, p.align)
-	if p.pageBreak {
-		wr.Attr(fo.BreakBefore, fo.Page)
-	}
+	p.apply(wr)
 }
 
 func (p *ParagraphAttributes) AlignRight() *ParagraphAttributes {
-	p.align = fo.Right
+	p.put(fo.TextAlign, fo.Right, nil)
 	return p
 }
 
 func (p *ParagraphAttributes) PageBreak() *ParagraphAttributes {
-	p.pageBreak = true
+	p.put(fo.BreakBefore, true, func(v value) {
+		if x := v.data.(bool); x {
+			v.wr.Attr(fo.BreakBefore, fo.Page)
+		}
+	})
 	return p
 }

+ 27 - 1
mappers/attr/text.go

@@ -1,6 +1,7 @@
 package attr
 
 import (
+	"image/color"
 	"odf/model"
 	"odf/xmlns/fo"
 	"odf/xmlns/style"
@@ -10,13 +11,16 @@ import (
 type TextAttributes struct {
 	fontFace string
 	size     int
+	col      color.Color
+	bold     bool
+	italic   bool
 	named
 }
 
 func (t *TextAttributes) Equal(_a Attributes) (ok bool) {
 	a, ok := _a.(*TextAttributes)
 	if ok {
-		ok = t.size == a.size && t.fontFace == a.fontFace
+		ok = t.size == a.size && t.fontFace == a.fontFace && t.col == a.col && t.italic == a.italic && t.bold == a.bold
 	}
 	return
 }
@@ -28,6 +32,13 @@ func (t *TextAttributes) Write(wr model.Writer) {
 	wr.WritePos(New(style.TextProperties))
 	wr.Attr(style.FontName, t.fontFace)
 	wr.Attr(fo.FontSize, t.size)
+	wr.Attr(fo.Color, t.col)
+	if t.bold {
+		wr.Attr(fo.FontWeight, fo.Bold)
+	}
+	if t.italic {
+		wr.Attr(fo.FontStyle, fo.Italic)
+	}
 }
 
 func (t *TextAttributes) Size(s int) *TextAttributes {
@@ -40,6 +51,21 @@ func (t *TextAttributes) FontFace(name string) *TextAttributes {
 	return t
 }
 
+func (t *TextAttributes) Color(col color.Color) *TextAttributes {
+	t.col = col
+	return t
+}
+
+func (t *TextAttributes) Bold() *TextAttributes {
+	t.bold = true
+	return t
+}
+
+func (t *TextAttributes) Italic() *TextAttributes {
+	t.italic = true
+	return t
+}
+
 func init() {
 	New = model.LeafFactory
 }

+ 17 - 0
model/stub/simple_attrs.go

@@ -2,6 +2,8 @@ package stub
 
 import (
 	"encoding/xml"
+	"fmt"
+	"image/color"
 	"strconv"
 )
 
@@ -46,3 +48,18 @@ func (a *MeasureAttr) MarshalXMLAttr(name xml.Name) (xa xml.Attr, err error) {
 	xa.Value = a.String()
 	return
 }
+
+type ColorAttr struct {
+	Value color.Color
+}
+
+func (a *ColorAttr) String() string {
+	r, g, b, _ := a.Value.RGBA()
+	return fmt.Sprintf("#%02X%02X%02X", uint8(r), uint8(g), uint8(b))
+}
+
+func (a *ColorAttr) MarshalXMLAttr(name xml.Name) (xa xml.Attr, err error) {
+	xa.Name = name
+	xa.Value = a.String()
+	return
+}

+ 6 - 0
model/stub/simple_riders.go

@@ -3,6 +3,7 @@ package stub
 import (
 	"github.com/kpmy/ypk/assert"
 	"github.com/kpmy/ypk/halt"
+	"image/color"
 	"odf/model"
 	"odf/xmlns"
 	"reflect"
@@ -148,6 +149,9 @@ func validateAttr(n model.AttrName, val string) {
 }
 
 func castAttr(n model.AttrName, i interface{}) (ret model.Attribute) {
+	if i == nil {
+		return nil
+	}
 	typ := xmlns.Typed[n]
 	switch typ {
 	case xmlns.NONE, xmlns.STRING:
@@ -159,6 +163,8 @@ func castAttr(n model.AttrName, i interface{}) (ret model.Attribute) {
 		ret = &StringAttr{Value: i.(string)}
 	case xmlns.MEASURE:
 		ret = &MeasureAttr{Value: i.(float64)}
+	case xmlns.COLOR:
+		ret = &ColorAttr{Value: i.(color.Color)}
 	default:
 		halt.As(100, typ, reflect.TypeOf(i))
 	}

+ 5 - 1
model/stub/simple_tree.go

@@ -21,7 +21,11 @@ func (n *sn) Attr(name model.AttrName, val ...model.Attribute) model.Attribute {
 	assert.For(len(val) <= 1, 20, "only one attribute accepted")
 	assert.For(name != "", 21)
 	if len(val) == 1 {
-		n.attr[name] = val[0]
+		if val[0] != nil {
+			n.attr[name] = val[0]
+		} else {
+			delete(n.attr, name)
+		}
 	}
 	return n.attr[name]
 }

+ 8 - 6
odf_test.go

@@ -2,6 +2,7 @@ package odf
 
 import (
 	"github.com/kpmy/ypk/assert"
+	"image/color"
 	"odf/generators"
 	"odf/mappers"
 	"odf/mappers/attr"
@@ -65,15 +66,16 @@ func TestStylesMechanism(t *testing.T) {
 	fm.RegisterFont("Courier New", "Courier New")
 	fm.SetDefaults(new(attr.TextAttributes).Size(18).FontFace("Courier New"))
 	fm.SetDefaults(new(attr.TextAttributes).Size(16).FontFace("Courier New"))
-	fm.WriteString(`Hello, World!`)
+	fm.WriteString("Hello, World!\n")
 	fm.SetAttr(new(attr.TextAttributes).Size(32).FontFace("Arial"))
-	fm.WriteString(`Hello, World!`)
-	fm.SetAttr(new(attr.TextAttributes).Size(36).FontFace("Courier New"))
-	fm.WriteString(`Hello, World!`)
+	fm.WriteString(`Hello, Go!`)
+	fm.SetAttr(new(attr.TextAttributes).Size(36).FontFace("Courier New").Bold().Italic())
+	fm.WriteString(`	Hello, Again!`)
 	fm.SetAttr(new(attr.TextAttributes).Size(32).FontFace("Arial")) //test attribute cache
-	fm.WriteString(`Hello, World!`)
+	fm.SetAttr(new(attr.TextAttributes).Size(32).FontFace("Arial").Color(color.RGBA{0x00, 0xff, 0xff, 0xff}))
+	fm.WriteString("\nNo, not you again!")
 	fm.SetAttr(new(attr.ParagraphAttributes).AlignRight().PageBreak())
-	fm.WritePara(`Page break!`)
+	fm.WritePara("Page break!\r")
 	fm.SetAttr(nil)
 	fm.WriteString(`Hello, Пщ!`)
 	generators.Generate(m, nil, output, fm.MimeType)

+ 7 - 1
xmlns/fo/f.go

@@ -9,10 +9,15 @@ const (
 	FontSize    model.AttrName = "fo:font-size"
 	TextAlign   model.AttrName = "fo:text-align"
 	BreakBefore model.AttrName = "fo:break-before"
+	Color       model.AttrName = "fo:color"
+	FontWeight  model.AttrName = "fo:font-weight"
+	FontStyle   model.AttrName = "fo:font-style"
 )
 
 const (
-	Page = "page"
+	Page   = "page"
+	Bold   = "bold"
+	Italic = "italic"
 )
 
 const (
@@ -30,4 +35,5 @@ func init() {
 	xmlns.Enums[TextAlign] = []string{Start, End, Left, Right, Center, Justify}
 	xmlns.Typed[BreakBefore] = xmlns.ENUM
 	xmlns.Enums[BreakBefore] = []string{Page}
+	xmlns.Typed[Color] = xmlns.COLOR
 }

+ 1 - 0
xmlns/x.go

@@ -45,6 +45,7 @@ const (
 	INT
 	MEASURE
 	ENUM
+	COLOR
 )
 
 type Mime string