Skip to content

Commit

Permalink
feat: create Xft colors and manage them in the color factory
Browse files Browse the repository at this point in the history
  • Loading branch information
atennert committed Apr 11, 2021
1 parent 3a23642 commit d92bd1f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 18 deletions.
46 changes: 37 additions & 9 deletions src/nativeMain/kotlin/de/atennert/lcarswm/drawing/ColorFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) {

private val knownColors = mutableMapOf<Color, ULong>()
private val knownGCs = mutableMapOf<Pair<Color, Drawable>, GC>()
private val knownXftColors = mutableMapOf<Color, XftColor>()

init {
closeWith(ColorFactory::cleanupColorMap)
Expand All @@ -47,10 +48,14 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) {
private fun cleanupColorMap() {
val pixels = knownColors.values.toULongArray().toCValues()
drawApi.freeColors(colorMapId, pixels, pixels.size)
knownGCs.values.forEach { drawApi.freeGC(it) }
knownColors.clear()

knownGCs.values.forEach { drawApi.freeGC(it) }
knownGCs.clear()

knownXftColors.values.forEach(nativeHeap::free)
knownXftColors.clear()

drawApi.freeColors(colorMapId, colorPixels.toULongArray().toCValues(), colorPixels.size)
drawApi.freeColormap(colorMapId)
}
Expand Down Expand Up @@ -83,26 +88,24 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) {
fun createColorGC(drawable: Drawable, color: Color): GC? {

val pixel = knownColors[color]
?: color.let {
val xColor = it.toXColor()
?: let {
val xColor = color.toXColor()
drawApi.allocColor(colorMapId, xColor.ptr)
val px = xColor.pixel
nativeHeap.free(xColor)
knownColors[color] = px
px
}

val gc = knownGCs[Pair(color, drawable)]
?: pixel.let {
val gcValues = createGcValues(it)
return knownGCs[Pair(color, drawable)]
?: let {
val gcValues = createGcValues(pixel)
val mask = GCForeground or GCGraphicsExposures or GCArcMode
val gc = drawApi.createGC(drawable, mask.convert(), gcValues.ptr)!!
knownGCs[Pair(color, drawable)] = gc
nativeHeap.free(gcValues)
knownGCs[Pair(color, drawable)] = gc
gc
}

return gc
}

private fun createGcValues(pixel: ULong): XGCValues {
Expand All @@ -112,4 +115,29 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) {
gcValues.arc_mode = ArcPieSlice
return gcValues
}

fun createXftColor(color: Color): XftColor {
val pixel = knownColors[color]
?: let {
val xColor = color.toXColor()
drawApi.allocColor(colorMapId, xColor.ptr)
val px = xColor.pixel
nativeHeap.free(xColor)
knownColors[color] = px
px
}

return knownXftColors[color]
?: let {
val xftColor = nativeHeap.alloc<XftColor>()
xftColor.color.red = color.red.convert()
xftColor.color.green = color.green.convert()
xftColor.color.blue = color.blue.convert()
xftColor.color.alpha = 0xffff.convert()
xftColor.pixel = pixel
knownXftColors[color] = xftColor

xftColor
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.atennert.lcarswm.drawing

import de.atennert.lcarswm.system.DrawApiDummy
import de.atennert.lcarswm.system.api.DrawApi
import kotlinx.cinterop.*
import xlib.*
import kotlin.test.*
Expand All @@ -19,8 +18,11 @@ class ColorFactoryTest {
val color = Color(0xFFFF, 0x9999, 0)

val gc = colorFactory.createColorGC(1.convert(), color)

assertNotNull(gc)
assertEquals(1.toULong(), drawApi.pixel)

nativeHeap.free(gc)
}

@Test
Expand All @@ -35,6 +37,9 @@ class ColorFactoryTest {
assertNotNull(gc1)
assertNotNull(gc2)
assertEquals(2.toULong(), drawApi.pixel)

nativeHeap.free(gc1)
nativeHeap.free(gc2)
}

@Test
Expand All @@ -48,6 +53,8 @@ class ColorFactoryTest {
assertNotNull(gc1)
assertEquals(gc1, gc2)
assertEquals(1.toULong(), drawApi.pixel)

nativeHeap.free(gc1)
}

@Test
Expand All @@ -60,19 +67,46 @@ class ColorFactoryTest {

assertNotNull(gc1)
assertNotNull(gc2)
assertNotEquals(gc1, gc2)
assertNotSame(gc1, gc2)
assertEquals(1.toULong(), drawApi.pixel)

nativeHeap.free(gc1)
nativeHeap.free(gc2)
}

private val drawApi = object : DrawApiDummy() {
val gcs = mutableListOf<GC>()
@Test
fun `create XFT color by color`() {
val colorFactory = ColorFactory(drawApi, screen)
val color = Color(0xFFFF, 0x9999, 0)

val xftColor = colorFactory.createXftColor(color)

assertEquals(color.red, xftColor.color.red.toInt())
assertEquals(color.green, xftColor.color.green.toInt())
assertEquals(color.blue, xftColor.color.blue.toInt())
assertEquals(drawApi.pixel, xftColor.pixel)

nativeHeap.free(xftColor)
}

@Test
fun `get same XFT color twice`() {
val colorFactory = ColorFactory(drawApi, screen)
val color = Color(0xFFFF, 0x9999, 0)

val xftColor1 = colorFactory.createXftColor(color)
val xftColor2 = colorFactory.createXftColor(color)

assertEquals(xftColor1.rawPtr, xftColor2.rawPtr)

nativeHeap.free(xftColor1)
}

private val drawApi = object : DrawApiDummy() {
var pixel = 0.toULong()

fun clear() {
pixel = 0.convert()
gcs.forEach { nativeHeap.free(it) }
gcs.clear()
}

override fun createColormap(window: Window, visual: CValuesRef<Visual>, alloc: Int): Colormap {
Expand All @@ -87,9 +121,7 @@ class ColorFactoryTest {
}

override fun createGC(drawable: Drawable, mask: ULong, gcValues: CValuesRef<XGCValues>?): GC? {
val gc: GC = nativeHeap.alloc<GCVar>().ptr.reinterpret()
gcs.add(gc)
return gc
return nativeHeap.alloc<GCVar>().ptr.reinterpret()
}
}

Expand Down

1 comment on commit d92bd1f

@atennert
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepares for #8

Please sign in to comment.