A: GIF Play component

This commit is contained in:
杨红岩 2024-04-19 22:35:41 +08:00
parent 78a9a11839
commit 08fc3d01ca
9 changed files with 949 additions and 0 deletions

32
cef/gifplay/header.go Normal file
View File

@ -0,0 +1,32 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package gifplay
import (
"bytes"
"encoding/binary"
)
type TGIFHeader struct {
Signature [3]byte // 页眉签名始终为“GIF”
Version [3]byte // GIF格式版本“87a”或“89a”
ScreenWidth uint16 // 以像素为单位的显示屏宽度
ScreenHeight uint16 // 以像素为单位的显示屏高度
Packedbit byte // 屏幕和彩色地图信息
BackgroundColor byte // 背景色索引
AspectRatio byte // 像素纵横比
}
func (m *TGIFHeader) BytesToConvert(data []byte) {
var buf bytes.Buffer
buf.Write(data)
binary.Read(&buf, binary.LittleEndian, m)
}

53
cef/gifplay/image.go Normal file
View File

@ -0,0 +1,53 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package gifplay
import (
"bytes"
"encoding/binary"
"github.com/energye/energy/v2/pkgs/ext"
)
type TGIFImage struct {
Bitmap *ext.TBitmap
PosX uint16
PosY uint16
Delay uint16
Method byte
}
type TGIFImageDescriptor struct {
Left, // 显示器上图像的X位置
Top, // 显示器上图像的Y位置
Width, // 图像的宽度(像素)
Height uint16 // 图像的高度(像素)
Packedbit byte // 图像和颜色表数据信息
}
func (m *TGIFImageDescriptor) BytesToConvert(data []byte) {
var buf bytes.Buffer
buf.Write(data)
binary.Read(&buf, binary.LittleEndian, m)
}
type TGIFGraphicsControlExtension struct {
BlockSize byte // 剩余字段的大小始终为04h
Packedbit byte // 要使用的图形处理方法
DelayTime uint16 // 等待数十秒
ColorIndex byte // 透明颜色索引
Terminator byte // 块终止符始终为0
}
func (m *TGIFGraphicsControlExtension) BytesToConvert(data []byte) {
var buf bytes.Buffer
buf.Write(data)
binary.Read(&buf, binary.LittleEndian, m)
}

61
cef/gifplay/list.go Normal file
View File

@ -0,0 +1,61 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package gifplay
type TGIFList struct {
items []*TGIFImage
count int32
}
func (m *TGIFList) Add(AGifImage *TGIFImage) int32 {
m.items = append(m.items, AGifImage)
m.count++
return m.count
}
//func (m *TGIFList) Extract(Item *TGIFImage) *TGIFImage {
//
//}
//
//func (m *TGIFList) Remove(AGifImage *TGIFImage) int32 {
//
//}
//
//func (m *TGIFList) IndexOf(AGifImage *TGIFImage) int32 {
//
//}
func (m *TGIFList) First() *TGIFImage {
return m.items[0]
}
func (m *TGIFList) Last() *TGIFImage {
return m.items[len(m.items)-1]
}
func (m *TGIFList) Count() int32 {
return m.count
}
func (m *TGIFList) Insert(index int32, AGifImage *TGIFImage) {
m.items[index] = AGifImage
}
func (m *TGIFList) GetItem(index int32) *TGIFImage {
if index < m.count {
return m.items[index]
}
return nil
}
func (m *TGIFList) SetItem(index int32, AGifImage *TGIFImage) {
m.items[index] = AGifImage
}

398
cef/gifplay/loader.go Normal file
View File

@ -0,0 +1,398 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package gifplay
import (
"bytes"
"github.com/energye/energy/v2/pkgs/ext"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
"unsafe"
)
type TGIFLoader struct {
gifHeader *TGIFHeader
gifDescriptor *TGIFImageDescriptor
gifGraphicsCtrlExt *TGIFGraphicsControlExtension
gifUseGraphCtrlExt bool
gifBackgroundColor byte
interlaced bool
scanLine []byte
lineSize int32
disposalMethod byte
empty bool
filePath string
gifStream *lcl.TMemoryStream
height int32
isTransparent bool
width int32
palette *TPalette
localHeight int32
localWidth int32
}
func (m *TGIFLoader) LoadAllBitmap(gifBitmaps *TGIFList) bool {
if m.filePath == "" && m.gifStream == nil {
return false
}
var gifStream *lcl.TMemoryStream
if m.gifStream != nil {
gifStream = m.gifStream
} else {
gifStream = lcl.NewMemoryStream()
gifStream.LoadFromFile(m.filePath)
gifStream.SetPosition(0)
}
m.ReadHeader(gifStream)
if m.gifHeader.Version[0] != '8' && m.gifHeader.Version[1] != '9' && m.gifHeader.Version[2] != 'a' {
return false
}
var introducer byte
// 跳过第一个块扩展(如果存在)
for {
introducer = m.SkipBlock(gifStream)
if introducer == ID_IMAGE_DESCRIPTOR || introducer == ID_TRAILER {
break
}
}
for {
m.ReadGifBitmap(gifStream)
// 解码扫描线缓冲区中的Gif位图
m.ReadScanLine(gifStream)
// 为放置扫描线像素创建临时Fp图像
intfImage := ext.NewLazIntfImage(m.localWidth, m.localHeight)
intfImage.DataDescription(ext.Init_BPP32_B8G8R8A8_M1_BIO_TTB, m.localWidth, m.localHeight)
m.WriteScanLine(intfImage)
gifBitmap := &TGIFImage{
Bitmap: ext.NewBitmap(),
PosX: m.gifDescriptor.Left,
PosY: m.gifDescriptor.Top,
Method: m.disposalMethod,
Delay: m.gifGraphicsCtrlExt.DelayTime,
}
gifBitmap.Bitmap.LoadFromIntfImage(intfImage)
gifBitmaps.Add(gifBitmap)
intfImage.Free()
m.scanLine = nil
m.gifUseGraphCtrlExt = false
for {
introducer = m.SkipBlock(gifStream)
if introducer == ID_IMAGE_DESCRIPTOR || introducer == ID_TRAILER {
break
}
}
if introducer == ID_TRAILER {
break
}
}
return true
}
func (m *TGIFLoader) ReadPalette(stream *lcl.TMemoryStream, size int) {
m.palette.Clear()
m.palette.count = 0
var entry TRGB
sizeOf := int32(unsafe.Sizeof(entry)) //3
for i := 0; i < size; i++ {
_, d := stream.Read(sizeOf)
entry.BytesToConvert(d)
r := uint16(entry.Red)
g := uint16(entry.Green)
b := uint16(entry.Blue)
color := &ext.TColor{
Red: r | (r << 8),
Green: g | (g << 8),
Blue: b | (b << 8),
Alpha: AlphaOpaque,
}
m.palette.Add(color)
}
}
func (m *TGIFLoader) ReadScanLine(stream *lcl.TMemoryStream) {
var (
unpackedSize, packedSize int64
data, bits, code uint32
sourcePtr PByte
inCode uint32
codeSize uint32
codeMask uint32
freeCode uint32
oldCode uint32
prefix [CODE_TABLE_SIZE]uint32
suffix, stack = make([]byte, CODE_TABLE_SIZE), make([]byte, CODE_TABLE_SIZE)
stackPointer PByte
b, initialCodeSize, firstChar byte
clearCode, eoiCode uint16
)
// 解压缩字典的初始化
_, d := stream.Read(1)
initialCodeSize = d[0]
// 压缩尾部
OldPos := stream.Position()
packedSize = 0
for {
_, d = stream.Read(1)
b = d[0]
if b > 0 {
packedSize += int64(b)
stream.Seek(int64(b), types.SoCurrent)
}
if b == 0 {
break
}
}
stream.SetPosition(OldPos)
var sourceBuf bytes.Buffer
for {
_, d = stream.Read(1)
b = d[0]
if b > 0 {
_, d = stream.Read(int32(b))
sourceBuf.Write(d)
}
if b == 0 {
break
}
}
sourceData := sourceBuf.Bytes()
sourceBuf.Reset()
sourcePtr = PByte(unsafe.Pointer(&sourceData[0]))
target := uintptr(unsafe.Pointer(&m.scanLine[0]))
codeSize = uint32(initialCodeSize + 1)
clearCode = 1 << initialCodeSize
eoiCode = clearCode + 1
freeCode = uint32(clearCode + 2)
oldCode = CODE_TABLE_SIZE
codeMask = (1 << codeSize) - 1
unpackedSize = int64(m.localWidth * m.localHeight)
for I := 0; I < int(clearCode); I++ {
prefix[I] = CODE_TABLE_SIZE
suffix[I] = byte(I)
}
stackPointer = uintptr(unsafe.Pointer(&stack[0]))
firstChar = 0
data = 0
bits = 0
//解压缩LZW gif
for unpackedSize > 0 && packedSize > 0 {
source := uint32(*(*byte)(unsafe.Pointer(sourcePtr)))
data += source << bits
bits += 8
for bits >= codeSize {
code = data & codeMask
data >>= codeSize
bits -= codeSize
if code == uint32(eoiCode) {
break
}
if code == uint32(clearCode) {
codeSize = uint32(initialCodeSize + 1)
codeMask = 1<<codeSize - 1
freeCode = uint32(clearCode + 2)
oldCode = CODE_TABLE_SIZE
continue
}
if code > freeCode {
break
}
if oldCode == CODE_TABLE_SIZE {
firstChar = suffix[code]
*(*byte)(unsafe.Pointer(target)) = firstChar
target++
unpackedSize--
oldCode = code
continue
}
inCode = code
if code == freeCode {
*(*byte)(unsafe.Pointer(stackPointer)) = firstChar
stackPointer++
code = oldCode
}
for code > uint32(clearCode) {
*(*byte)(unsafe.Pointer(stackPointer)) = suffix[code]
stackPointer++
code = prefix[code]
}
firstChar = suffix[code]
*(*byte)(unsafe.Pointer(stackPointer)) = firstChar
stackPointer++
prefix[freeCode] = oldCode
suffix[freeCode] = firstChar
if freeCode == codeMask && codeSize < 12 {
codeSize++
codeMask = (1 << codeSize) - 1
}
if freeCode < CODE_TABLE_SIZE-1 {
freeCode++
}
oldCode = inCode
for {
stackPointer--
*(*byte)(unsafe.Pointer(target)) = *(*byte)(unsafe.Pointer(stackPointer))
target++
unpackedSize--
if stackPointer == uintptr(unsafe.Pointer(&stack[0])) {
break
}
}
}
sourcePtr++
packedSize--
}
}
func (m *TGIFLoader) ReadHeader(stream *lcl.TMemoryStream) {
var gifHeader TGIFHeader
sizeOf := int32(unsafe.Sizeof(gifHeader)) - 1 //13
_, d := stream.Read(sizeOf)
gifHeader.BytesToConvert(d)
m.gifHeader = &gifHeader
m.gifBackgroundColor = gifHeader.BackgroundColor
m.width = int32(gifHeader.ScreenWidth)
m.height = int32(gifHeader.ScreenHeight)
m.localWidth = int32(gifHeader.ScreenWidth)
m.localHeight = int32(gifHeader.ScreenHeight)
m.isTransparent = false
m.ReadGlobalPalette(stream)
}
func (m *TGIFLoader) ReadGlobalPalette(stream *lcl.TMemoryStream) {
if m.gifHeader.Packedbit&ID_COLOR_TABLE != 0 {
colorTableSize := m.gifHeader.Packedbit&ID_COLOR_TABLE_SIZE + 1
m.ReadPalette(stream, 1<<colorTableSize)
}
}
func (m *TGIFLoader) ReadGraphCtrlExt() {
m.isTransparent = (m.gifGraphicsCtrlExt.Packedbit & ID_TRANSPARENT) != 0
m.disposalMethod = (m.gifGraphicsCtrlExt.Packedbit & 0x1C) >> 2
if m.isTransparent {
// 如果透明位图更改alpha通道
m.gifBackgroundColor = m.gifGraphicsCtrlExt.ColorIndex
color := m.palette.Get(int(m.gifBackgroundColor))
color.Alpha = AlphaTransparent
m.palette.Set(int(m.gifBackgroundColor), color)
}
}
func (m *TGIFLoader) SkipBlock(stream *lcl.TMemoryStream) byte {
var introducer, labels, skipByte byte
_, d := stream.Read(1)
introducer = d[0]
if introducer == EXT_INTRODUCER {
_, d = stream.Read(1)
labels = d[0]
switch labels {
case EXT_COMMENT, EXT_APPLICATION:
for {
_, d = stream.Read(1)
skipByte = d[0]
if skipByte == 0 {
break
}
stream.Seek(int64(skipByte), types.SoCurrent)
}
case EXT_GRAPHICS_CONTROL:
var gifGraphicsCtrlExt TGIFGraphicsControlExtension
_, d = stream.Read(int32(unsafe.Sizeof(gifGraphicsCtrlExt))) //6
gifGraphicsCtrlExt.BytesToConvert(d)
m.gifGraphicsCtrlExt = &gifGraphicsCtrlExt
m.gifUseGraphCtrlExt = true
case EXT_PLAIN_TEXT:
_, d = stream.Read(1)
skipByte = d[0]
stream.Seek(int64(skipByte), types.SoCurrent)
for {
_, d = stream.Read(1)
skipByte = d[0]
if skipByte == 0 {
break
}
stream.Seek(int64(skipByte), types.SoCurrent)
}
}
}
return introducer
}
func (m *TGIFLoader) WriteScanLine(intfImage *ext.TLazIntfImage) {
var (
row, col int
pass, every byte
scanLineIdx int
)
if m.interlaced {
for pass = 1; pass <= 4; pass++ {
switch pass {
case 1:
row = 0
every = 8
case 2:
row = 4
every = 8
case 3:
row = 2
every = 4
case 4:
row = 1
every = 2
}
for {
for col = 0; col < int(m.localWidth); col++ {
color := *m.palette.Get(int(m.scanLine[scanLineIdx]))
intfImage.Colors(int32(col), int32(row), color)
scanLineIdx++
}
row += int(every)
if row >= int(m.localHeight) {
break
}
}
}
} else {
for row = 0; row < int(m.localHeight); row++ {
for col = 0; col < int(m.localWidth); col++ {
color := *m.palette.Get(int(m.scanLine[scanLineIdx]))
intfImage.Colors(int32(col), int32(row), color)
scanLineIdx++
}
}
}
}
func (m *TGIFLoader) ReadGifBitmap(stream *lcl.TMemoryStream) {
var gifDescriptor TGIFImageDescriptor
sizeOf := int32(unsafe.Sizeof(gifDescriptor)) - 1 //9
_, d := stream.Read(sizeOf)
gifDescriptor.BytesToConvert(d)
m.gifDescriptor = &gifDescriptor
m.localWidth = int32(m.gifDescriptor.Width)
m.localHeight = int32(m.gifDescriptor.Height)
m.interlaced = m.gifDescriptor.Packedbit&ID_INTERLACED == ID_INTERLACED
m.lineSize = m.localWidth * (m.localHeight + 1)
m.scanLine = make([]byte, m.lineSize)
if m.gifDescriptor.Packedbit&ID_COLOR_TABLE != 0 {
colorTableSize := m.gifDescriptor.Packedbit&ID_COLOR_TABLE_SIZE + 1
m.ReadPalette(stream, 1<<colorTableSize)
}
if m.gifUseGraphCtrlExt {
m.ReadGraphCtrlExt()
}
}
func (m *TGIFLoader) Free() {
m.palette.Free()
}

44
cef/gifplay/palette.go Normal file
View File

@ -0,0 +1,44 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package gifplay
import "github.com/energye/energy/v2/pkgs/ext"
type TPalette struct {
colors []*ext.TColor
count int
}
func (m *TPalette) Clear() {
m.colors = make([]*ext.TColor, 0)
}
func (m *TPalette) Free() {
m.colors = nil
m.count = 0
}
func (m *TPalette) Add(color *ext.TColor) {
m.colors = append(m.colors, color)
m.count++
}
func (m *TPalette) Get(index int) *ext.TColor {
return m.colors[index]
}
func (m *TPalette) Set(index int, color *ext.TColor) {
m.colors[index] = color
}
func (m *TPalette) Count() int {
return m.count
}

237
cef/gifplay/play.go Normal file
View File

@ -0,0 +1,237 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
// GIF Play component
package gifplay
import (
"bytes"
"encoding/binary"
"github.com/energye/energy/v2/pkgs/ext"
"github.com/energye/golcl/lcl"
"github.com/energye/golcl/lcl/types"
)
const (
EXT_INTRODUCER byte = 0x21
EXT_GRAPHICS_CONTROL byte = 0xF9
EXT_PLAIN_TEXT byte = 0x01
EXT_APPLICATION byte = 0xFF
EXT_COMMENT byte = 0xFE
DSC_LOCAL_IMAGE byte = 0x2C
ID_TRANSPARENT byte = 0x01
ID_COLOR_TABLE_SIZE byte = 0x07
ID_SORT byte = 0x20
ID_INTERLACED byte = 0x40
ID_COLOR_TABLE byte = 0x80
ID_IMAGE_DESCRIPTOR byte = 0x2C
ID_TRAILER byte = 0x3B
CODE_TABLE_SIZE = 4096
)
const (
AlphaTransparent uint16 = 0x0000
AlphaOpaque uint16 = 0xFFFF
)
const (
SoFromBeginning = iota
SoFromCurrent
SoFromEnd
)
type PByte = uintptr
type TRGB struct {
Red, Green, Blue byte
}
//type buffer struct {
// buf []byte
//}
//
//func (b *buffer) Read(p []byte) (n int, err error) {
// if b.buf == nil {
// if len(p) == 0 {
// return 0, nil
// }
// return 0, io.EOF
// }
// n = copy(p, b.buf)
// return n, nil
//}
func (m *TRGB) BytesToConvert(data []byte) {
var buf bytes.Buffer
buf.Write(data)
binary.Read(&buf, binary.LittleEndian, m)
}
type TGIFPlay struct {
*lcl.TPanel
animate bool
empty bool
filePath string
gifBitmaps *TGIFList
onFrameChanged lcl.TNotifyEvent
onStart lcl.TNotifyEvent
onStop lcl.TNotifyEvent
wait *lcl.TTimer
currentImage int32
gifHeightidth int32
gifWidth int32
bufferImg *ext.TBitmap
currentView *ext.TBitmap
}
func NewGIFPlay(owner lcl.IComponent) (gifPlay *TGIFPlay) {
control := lcl.NewPanel(owner)
control.SetAutoSize(true)
control.SetBounds(0, 0, 90, 90)
gifPlay = &TGIFPlay{
TPanel: control,
}
gifPlay.empty = true
gifPlay.currentImage = 0
gifPlay.currentView = ext.NewBitmap()
gifPlay.bufferImg = ext.NewBitmap()
gifPlay.wait = lcl.NewTimer(owner)
gifPlay.wait.SetInterval(100)
gifPlay.wait.SetEnabled(false)
gifPlay.wait.SetOnTimer(gifPlay.OnTime)
gifPlay.SetAnimate(true)
gifPlay.SetOnPaint(gifPlay.OnPaint)
return
}
func (m *TGIFPlay) OnPaint(sender lcl.IObject) {
if !m.empty && m.IsValid() {
if m.currentImage < m.gifBitmaps.count {
m.bufferImg.Canvas().Brush().SetColor(m.Color())
currentImage := m.gifBitmaps.GetItem(m.currentImage)
if m.currentImage == 0 {
m.bufferImg.Canvas().FillRect(types.Rect(0, 0, m.Width(), m.Height()))
}
if currentImage.Delay != 0 {
m.wait.SetInterval(uint32(currentImage.Delay * 10))
}
m.bufferImg.Canvas().Draw(int32(currentImage.PosX), int32(currentImage.PosY), currentImage.Bitmap)
m.currentView.Assign(m.bufferImg)
switch currentImage.Method {
//case 0: 未指定...
//case 1: 无更改背景
case 2:
m.bufferImg.Canvas().FillRect(types.Rect(int32(currentImage.PosX), int32(currentImage.PosY),
currentImage.Bitmap.Width()+int32(currentImage.PosX), currentImage.Bitmap.Height()+int32(currentImage.PosY)))
case 3:
m.bufferImg.Canvas().FillRect(types.Rect(0, 0, m.Width(), m.Height()))
}
}
m.Canvas().Draw(0, 0, m.currentView)
}
}
func (m *TGIFPlay) OnTime(sender lcl.IObject) {
if !m.empty && m.IsValid() {
if m.currentImage >= m.gifBitmaps.count {
m.currentImage = 0
} else {
m.currentImage++
}
m.Repaint()
}
}
func (m *TGIFPlay) GifChanged() {
canvas := m.bufferImg.Canvas()
canvas.Brush().SetColor(m.Color())
canvas.FillRect(types.Rect(0, 0, m.Width(), m.Height()))
currentImage := m.gifBitmaps.GetItem(m.currentImage)
canvas.Draw(int32(currentImage.PosX), int32(currentImage.PosY), currentImage.Bitmap)
m.currentView.Assign(m.bufferImg)
m.Invalidate()
}
func (m *TGIFPlay) ResetImage() {
if m.gifBitmaps != nil {
m.gifBitmaps.items = make([]*TGIFImage, 0)
m.gifBitmaps.count = 0
}
m.currentImage = 0
canvas := m.currentView.Canvas()
canvas.Brush().SetColor(m.Color())
canvas.FillRect(types.TRect{Left: 0, Top: 0, Right: m.Width(), Bottom: m.Height()})
}
func (m *TGIFPlay) LoadFromFile(filePath string) {
if m.filePath == filePath {
return
}
m.filePath = filePath
m.ResetImage()
if m.filePath == "" {
return
}
if !m.empty {
m.GifChanged()
}
m.empty = true
gifLoader := &TGIFLoader{
filePath: filePath,
gifStream: nil,
gifUseGraphCtrlExt: false,
width: 20,
height: 20,
palette: &TPalette{},
}
if m.currentView == nil {
m.currentView = ext.NewBitmap()
}
if m.gifBitmaps == nil {
m.gifBitmaps = &TGIFList{}
}
m.empty = !gifLoader.LoadAllBitmap(m.gifBitmaps)
m.DefineSize(gifLoader.width, gifLoader.height)
gifLoader.Free()
}
func (m *TGIFPlay) DefineSize(width, height int32) {
if width == m.gifWidth && height == m.gifHeightidth {
return
}
m.gifWidth = width
m.gifHeightidth = height
m.SetWidth(m.gifWidth)
m.SetHeight(m.gifHeightidth)
m.bufferImg.SetWidth(m.gifWidth)
m.bufferImg.SetHeight(m.gifHeightidth)
}
func (m *TGIFPlay) SetAnimate(v bool) {
if m.animate == v {
return
}
m.animate = v
m.wait.SetEnabled(v)
if m.animate {
m.doStart()
} else {
m.doStop()
}
}
func (m *TGIFPlay) doStart() {
}
func (m *TGIFPlay) doStop() {
}

76
pkgs/ext/lazintfimage.go Normal file
View File

@ -0,0 +1,76 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package ext
import (
"github.com/energye/energy/v2/common/imports"
"unsafe"
)
type DataDescription = int32
const (
Init_BPP32_B8G8R8_BIO_TTB DataDescription = iota
Init_BPP32_B8G8R8_M1_BIO_TTB
Init_BPP32_B8G8R8A8_BIO_TTB
Init_BPP32_B8G8R8A8_M1_BIO_TTB
)
type TLazIntfImage struct {
instance unsafe.Pointer
}
type TColor struct {
Red, Green, Blue, Alpha uint16
}
func NewLazIntfImage(width, height int32) *TLazIntfImage {
m := &TLazIntfImage{}
r1, _, _ := imports.LibLCLExt().Proc(LazIntfImage_Create).Call(uintptr(width), uintptr(height))
m.instance = unsafe.Pointer(r1)
return m
}
// Instance
//
// 返回对象实例指针。
func (m *TLazIntfImage) Instance() uintptr {
return uintptr(m.instance)
}
// IsValid
//
// 检测地址是否为空。
func (m *TLazIntfImage) IsValid() bool {
return m.instance != nil
}
func (m *TLazIntfImage) DataDescription(dataDescription DataDescription, width, height int32) {
if !m.IsValid() {
return
}
imports.LibLCLExt().Proc(LazIntfImage_DataDescription).Call(m.Instance(), uintptr(dataDescription), uintptr(width), uintptr(height))
}
func (m *TLazIntfImage) Colors(x, y int32, color TColor) {
if !m.IsValid() {
return
}
imports.LibLCLExt().Proc(LazIntfImage_Colors).Call(m.Instance(), uintptr(x), uintptr(y), uintptr(unsafe.Pointer(&color)))
}
func (m *TLazIntfImage) Free() {
if !m.IsValid() {
return
}
imports.LibLCLExt().Proc(LazIntfImage_Free).Call(m.Instance())
m.instance = nil
}

34
pkgs/ext/lcl_bitmap.go Normal file
View File

@ -0,0 +1,34 @@
//----------------------------------------
//
// Copyright © yanghy. All Rights Reserved.
//
// Licensed under Apache License Version 2.0, January 2004
//
// https://www.apache.org/licenses/LICENSE-2.0
//
//----------------------------------------
package ext
import (
"github.com/energye/energy/v2/common/imports"
"github.com/energye/golcl/lcl"
)
type TBitmap struct {
*lcl.TBitmap
}
func NewBitmap() *TBitmap {
m := &TBitmap{
TBitmap: lcl.NewBitmap(),
}
return m
}
func (m *TBitmap) LoadFromIntfImage(intfImage *TLazIntfImage) {
if !m.IsValid() || !intfImage.IsValid() {
return
}
imports.LibLCLExt().Proc(Bitmap_LoadFromIntfImage).Call(m.Instance(), intfImage.Instance())
}

View File

@ -45,6 +45,13 @@ func init() {
dllimports.NewEnergyImport("Ext_Form_Activate", 0),
dllimports.NewEnergyImport("Ext_Form_Deactivate", 0),
dllimports.NewEnergyImport("Ext_Assigned", 0),
// TBitmap
dllimports.NewEnergyImport("Bitmap_LoadFromIntfImage", 0),
// TLazIntfImage
dllimports.NewEnergyImport("LazIntfImage_Create", 0),
dllimports.NewEnergyImport("LazIntfImage_DataDescription", 0),
dllimports.NewEnergyImport("LazIntfImage_Colors", 0),
dllimports.NewEnergyImport("LazIntfImage_Free", 0),
}
imports.LibLCLExt().SetImportTable(lclExtImportDefs)
}
@ -56,6 +63,13 @@ const (
Ext_Form_Activate
Ext_Form_Deactivate
Ext_Assigned
// TBitmap
Bitmap_LoadFromIntfImage
// TLazIntfImage
LazIntfImage_Create
LazIntfImage_DataDescription
LazIntfImage_Colors
LazIntfImage_Free
)
func PanelBevelColor(panel *lcl.TPanel) types.TColor {