- Initialize theme support;
- RGBA, HSL color convert has been added; - go test updated
This commit is contained in:
parent
9cb0e9308b
commit
d6468fc114
|
@ -21,6 +21,7 @@ type File struct {
|
|||
Sheet map[string]*xlsxWorksheet
|
||||
SheetCount int
|
||||
Styles *xlsxStyleSheet
|
||||
Theme *xlsxTheme
|
||||
WorkBook *xlsxWorkbook
|
||||
WorkBookRels *xlsxWorkbookRels
|
||||
XLSX map[string][]byte
|
||||
|
@ -66,6 +67,7 @@ func OpenReader(r io.Reader) (*File, error) {
|
|||
}
|
||||
f.sheetMap = f.getSheetMap()
|
||||
f.Styles = f.stylesReader()
|
||||
f.Theme = f.themeReader()
|
||||
return f, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package excelize
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"image/color"
|
||||
_ "image/gif"
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
|
@ -1145,6 +1146,31 @@ func TestOutlineLevel(t *testing.T) {
|
|||
xlsx.SetColOutlineLevel("Sheet2", "B", 2)
|
||||
}
|
||||
|
||||
func TestThemeColor(t *testing.T) {
|
||||
t.Log(ThemeColor("000000", -0.1))
|
||||
t.Log(ThemeColor("000000", 0))
|
||||
t.Log(ThemeColor("000000", 1))
|
||||
}
|
||||
|
||||
func TestHSL(t *testing.T) {
|
||||
var hsl HSL
|
||||
t.Log(hsl.RGBA())
|
||||
t.Log(hslModel(hsl))
|
||||
t.Log(hslModel(color.Gray16{Y: uint16(1)}))
|
||||
t.Log(HSLToRGB(0, 1, 0.4))
|
||||
t.Log(HSLToRGB(0, 1, 0.6))
|
||||
t.Log(hueToRGB(0, 0, -1))
|
||||
t.Log(hueToRGB(0, 0, 2))
|
||||
t.Log(hueToRGB(0, 0, 1.0/7))
|
||||
t.Log(hueToRGB(0, 0, 0.4))
|
||||
t.Log(hueToRGB(0, 0, 2.0/4))
|
||||
t.Log(RGBToHSL(255, 255, 0))
|
||||
t.Log(RGBToHSL(0, 255, 255))
|
||||
t.Log(RGBToHSL(250, 100, 50))
|
||||
t.Log(RGBToHSL(50, 100, 250))
|
||||
t.Log(RGBToHSL(250, 50, 100))
|
||||
}
|
||||
|
||||
func trimSliceSpace(s []string) []string {
|
||||
for {
|
||||
if len(s) > 0 && s[len(s)-1] == "" {
|
||||
|
|
1
file.go
1
file.go
|
@ -36,6 +36,7 @@ func NewFile() *File {
|
|||
f.WorkBookRels = f.workbookRelsReader()
|
||||
f.Sheet["xl/worksheets/sheet1.xml"] = f.workSheetReader("Sheet1")
|
||||
f.sheetMap["Sheet1"] = "xl/worksheets/sheet1.xml"
|
||||
f.Theme = f.themeReader()
|
||||
return f
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package excelize
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math"
|
||||
)
|
||||
|
||||
// HSLModel converts any color.Color to a HSL color.
|
||||
var HSLModel = color.ModelFunc(hslModel)
|
||||
|
||||
// HSL represents a cylindrical coordinate of points in an RGB color model.
|
||||
//
|
||||
// Values are in the range 0 to 1.
|
||||
type HSL struct {
|
||||
H, S, L float64
|
||||
}
|
||||
|
||||
// RGBA returns the alpha-premultiplied red, green, blue and alpha values
|
||||
// for the HSL.
|
||||
func (c HSL) RGBA() (uint32, uint32, uint32, uint32) {
|
||||
r, g, b := HSLToRGB(c.H, c.S, c.L)
|
||||
return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
|
||||
}
|
||||
|
||||
// hslModel converts a color.Color to HSL.
|
||||
func hslModel(c color.Color) color.Color {
|
||||
if _, ok := c.(HSL); ok {
|
||||
return c
|
||||
}
|
||||
r, g, b, _ := c.RGBA()
|
||||
h, s, l := RGBToHSL(uint8(r>>8), uint8(g>>8), uint8(b>>8))
|
||||
return HSL{h, s, l}
|
||||
}
|
||||
|
||||
// RGBToHSL converts an RGB triple to a HSL triple.
|
||||
func RGBToHSL(r, g, b uint8) (h, s, l float64) {
|
||||
fR := float64(r) / 255
|
||||
fG := float64(g) / 255
|
||||
fB := float64(b) / 255
|
||||
max := math.Max(math.Max(fR, fG), fB)
|
||||
min := math.Min(math.Min(fR, fG), fB)
|
||||
l = (max + min) / 2
|
||||
if max == min {
|
||||
// Achromatic.
|
||||
h, s = 0, 0
|
||||
} else {
|
||||
// Chromatic.
|
||||
d := max - min
|
||||
if l > 0.5 {
|
||||
s = d / (2.0 - max - min)
|
||||
} else {
|
||||
s = d / (max + min)
|
||||
}
|
||||
switch max {
|
||||
case fR:
|
||||
h = (fG - fB) / d
|
||||
if fG < fB {
|
||||
h += 6
|
||||
}
|
||||
case fG:
|
||||
h = (fB-fR)/d + 2
|
||||
case fB:
|
||||
h = (fR-fG)/d + 4
|
||||
}
|
||||
h /= 6
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HSLToRGB converts an HSL triple to a RGB triple.
|
||||
func HSLToRGB(h, s, l float64) (r, g, b uint8) {
|
||||
var fR, fG, fB float64
|
||||
if s == 0 {
|
||||
fR, fG, fB = l, l, l
|
||||
} else {
|
||||
var q float64
|
||||
if l < 0.5 {
|
||||
q = l * (1 + s)
|
||||
} else {
|
||||
q = l + s - s*l
|
||||
}
|
||||
p := 2*l - q
|
||||
fR = hueToRGB(p, q, h+1.0/3)
|
||||
fG = hueToRGB(p, q, h)
|
||||
fB = hueToRGB(p, q, h-1.0/3)
|
||||
}
|
||||
r = uint8((fR * 255) + 0.5)
|
||||
g = uint8((fG * 255) + 0.5)
|
||||
b = uint8((fB * 255) + 0.5)
|
||||
return
|
||||
}
|
||||
|
||||
// hueToRGB is a helper function for HSLToRGB.
|
||||
func hueToRGB(p, q, t float64) float64 {
|
||||
if t < 0 {
|
||||
t++
|
||||
}
|
||||
if t > 1 {
|
||||
t--
|
||||
}
|
||||
if t < 1.0/6 {
|
||||
return p + (q-p)*6*t
|
||||
}
|
||||
if t < 0.5 {
|
||||
return q
|
||||
}
|
||||
if t < 2.0/3 {
|
||||
return p + (q-p)*(2.0/3-t)*6
|
||||
}
|
||||
return p
|
||||
}
|
26
styles.go
26
styles.go
|
@ -2723,3 +2723,29 @@ func drawConfFmtExp(p int, ct string, format *formatConditional) *xlsxCfRule {
|
|||
func getPaletteColor(color string) string {
|
||||
return "FF" + strings.Replace(strings.ToUpper(color), "#", "", -1)
|
||||
}
|
||||
|
||||
// themeReader provides function to get the pointer to the xl/theme/theme1.xml
|
||||
// structure after deserialization.
|
||||
func (f *File) themeReader() *xlsxTheme {
|
||||
var theme xlsxTheme
|
||||
_ = xml.Unmarshal([]byte(f.readXML("xl/theme/theme1.xml")), &theme)
|
||||
return &theme
|
||||
}
|
||||
|
||||
// ThemeColor applied the color with tint value.
|
||||
func ThemeColor(baseColor string, tint float64) string {
|
||||
if tint == 0 {
|
||||
return "FF" + baseColor
|
||||
}
|
||||
r, _ := strconv.ParseInt(baseColor[0:2], 16, 64)
|
||||
g, _ := strconv.ParseInt(baseColor[2:4], 16, 64)
|
||||
b, _ := strconv.ParseInt(baseColor[4:6], 16, 64)
|
||||
h, s, l := RGBToHSL(uint8(r), uint8(g), uint8(b))
|
||||
if tint < 0 {
|
||||
l *= (1 + tint)
|
||||
} else {
|
||||
l = l*(1-tint) + (1 - (1 - tint))
|
||||
}
|
||||
br, bg, bb := HSLToRGB(h, s, l)
|
||||
return fmt.Sprintf("FF%02X%02X%02X", br, bg, bb)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
package excelize
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// xlsxTheme directly maps the theme element in the namespace
|
||||
// http://schemas.openxmlformats.org/drawingml/2006/main
|
||||
type xlsxTheme struct {
|
||||
ThemeElements xlsxThemeElements `xml:"themeElements"`
|
||||
ObjectDefaults xlsxObjectDefaults `xml:"objectDefaults"`
|
||||
ExtraClrSchemeLst xlsxExtraClrSchemeLst `xml:"extraClrSchemeLst"`
|
||||
ExtLst *xlsxExtLst `xml:"extLst"`
|
||||
}
|
||||
|
||||
// objectDefaults element allows for the definition of default shape, line,
|
||||
// and textbox formatting properties. An application can use this information
|
||||
// to format a shape (or text) initially on insertion into a document.
|
||||
type xlsxObjectDefaults struct {
|
||||
ObjectDefaults string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxExtraClrSchemeLst element is a container for the list of extra color
|
||||
// schemes present in a document.
|
||||
type xlsxExtraClrSchemeLst struct {
|
||||
ExtraClrSchemeLst string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxThemeElements directly maps the element defines the theme formatting
|
||||
// options for the theme and is the workhorse of the theme. This is where the
|
||||
// bulk of the shared theme information is contained and used by a document.
|
||||
// This element contains the color scheme, font scheme, and format scheme
|
||||
// elements which define the different formatting aspects of what a theme
|
||||
// defines.
|
||||
type xlsxThemeElements struct {
|
||||
ClrScheme xlsxClrScheme `xml:"clrScheme"`
|
||||
FontScheme xlsxFontScheme `xml:"fontScheme"`
|
||||
FmtScheme xlsxFmtScheme `xml:"fmtScheme"`
|
||||
}
|
||||
|
||||
// xlsxClrScheme element specifies the theme color, stored in the document's
|
||||
// Theme part to which the value of this theme color shall be mapped. This
|
||||
// mapping enables multiple theme colors to be chained together.
|
||||
type xlsxClrScheme struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Children []xlsxClrSchemeEl `xml:",any"`
|
||||
}
|
||||
|
||||
// xlsxFontScheme element defines the font scheme within the theme. The font
|
||||
// scheme consists of a pair of major and minor fonts for which to use in a
|
||||
// document. The major font corresponds well with the heading areas of a
|
||||
// document, and the minor font corresponds well with the normal text or
|
||||
// paragraph areas.
|
||||
type xlsxFontScheme struct {
|
||||
Name string `xml:"name,attr"`
|
||||
MajorFont xlsxMajorFont `xml:"majorFont"`
|
||||
MinorFont xlsxMinorFont `xml:"minorFont"`
|
||||
ExtLst *xlsxExtLst `xml:"extLst"`
|
||||
}
|
||||
|
||||
// xlsxMajorFont element defines the set of major fonts which are to be used
|
||||
// under different languages or locals.
|
||||
type xlsxMajorFont struct {
|
||||
Children []xlsxFontSchemeEl `xml:",any"`
|
||||
}
|
||||
|
||||
// xlsxMinorFont element defines the set of minor fonts that are to be used
|
||||
// under different languages or locals.
|
||||
type xlsxMinorFont struct {
|
||||
Children []xlsxFontSchemeEl `xml:",any"`
|
||||
}
|
||||
|
||||
// xlsxFmtScheme element contains the background fill styles, effect styles,
|
||||
// fill styles, and line styles which define the style matrix for a theme. The
|
||||
// style matrix consists of subtle, moderate, and intense fills, lines, and
|
||||
// effects. The background fills are not generally thought of to directly be
|
||||
// associated with the matrix, but do play a role in the style of the overall
|
||||
// document. Usually, a given object chooses a single line style, a single
|
||||
// fill style, and a single effect style in order to define the overall final
|
||||
// look of the object.
|
||||
type xlsxFmtScheme struct {
|
||||
Name string `xml:"name,attr"`
|
||||
FillStyleLst xlsxFillStyleLst `xml:"fillStyleLst"`
|
||||
LnStyleLst xlsxLnStyleLst `xml:"lnStyleLst"`
|
||||
EffectStyleLst xlsxEffectStyleLst `xml:"effectStyleLst"`
|
||||
BgFillStyleLst xlsxBgFillStyleLst `xml:"bgFillStyleLst"`
|
||||
}
|
||||
|
||||
// xlsxFillStyleLst element defines a set of three fill styles that are used
|
||||
// within a theme. The three fill styles are arranged in order from subtle to
|
||||
// moderate to intense.
|
||||
type xlsxFillStyleLst struct {
|
||||
FillStyleLst string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxLnStyleLst element defines a list of three line styles for use within a
|
||||
// theme. The three line styles are arranged in order from subtle to moderate
|
||||
// to intense versions of lines. This list makes up part of the style matrix.
|
||||
type xlsxLnStyleLst struct {
|
||||
LnStyleLst string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxEffectStyleLst element defines a set of three effect styles that create
|
||||
// the effect style list for a theme. The effect styles are arranged in order
|
||||
// of subtle to moderate to intense.
|
||||
type xlsxEffectStyleLst struct {
|
||||
EffectStyleLst string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxBgFillStyleLst element defines a list of background fills that are
|
||||
// used within a theme. The background fills consist of three fills, arranged
|
||||
// in order from subtle to moderate to intense.
|
||||
type xlsxBgFillStyleLst struct {
|
||||
BgFillStyleLst string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
// xlsxClrScheme maps to children of the clrScheme element in the namespace
|
||||
// http://schemas.openxmlformats.org/drawingml/2006/main - currently I have
|
||||
// not checked it for completeness - it does as much as I need.
|
||||
type xlsxClrSchemeEl struct {
|
||||
XMLName xml.Name
|
||||
SysClr *xlsxSysClr `xml:"sysClr"`
|
||||
SrgbClr *attrValString `xml:"srgbClr"`
|
||||
}
|
||||
|
||||
// xlsxFontSchemeEl directly maps the major and minor font of the style's font
|
||||
// scheme.
|
||||
type xlsxFontSchemeEl struct {
|
||||
XMLName xml.Name
|
||||
Script string `xml:"script,attr,omitempty"`
|
||||
Typeface string `xml:"typeface,attr"`
|
||||
Panose string `xml:"panose,attr,omitempty"`
|
||||
PitchFamily string `xml:"pitchFamily,attr,omitempty"`
|
||||
Charset string `xml:"charset,attr,omitempty"`
|
||||
}
|
||||
|
||||
// xlsxSysClr element specifies a color bound to predefined operating system
|
||||
// elements.
|
||||
type xlsxSysClr struct {
|
||||
Val string `xml:"val,attr"`
|
||||
LastClr string `xml:"lastClr,attr"`
|
||||
}
|
Loading…
Reference in New Issue