diff --git a/src/nativeMain/kotlin/de/atennert/lcarswm/drawing/ColorFactory.kt b/src/nativeMain/kotlin/de/atennert/lcarswm/drawing/ColorFactory.kt index 88a6f91a..3ce16723 100644 --- a/src/nativeMain/kotlin/de/atennert/lcarswm/drawing/ColorFactory.kt +++ b/src/nativeMain/kotlin/de/atennert/lcarswm/drawing/ColorFactory.kt @@ -24,6 +24,7 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) { private val knownColors = mutableMapOf() private val knownGCs = mutableMapOf, GC>() + private val knownXftColors = mutableMapOf() init { closeWith(ColorFactory::cleanupColorMap) @@ -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) } @@ -83,8 +88,8 @@ 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) @@ -92,17 +97,15 @@ class ColorFactory(private val drawApi: DrawApi, screen: Screen) { 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 { @@ -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.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 + } + } } \ No newline at end of file diff --git a/src/nativeTest/kotlin/de/atennert/lcarswm/drawing/ColorFactoryTest.kt b/src/nativeTest/kotlin/de/atennert/lcarswm/drawing/ColorFactoryTest.kt index 0687f334..71a83e71 100644 --- a/src/nativeTest/kotlin/de/atennert/lcarswm/drawing/ColorFactoryTest.kt +++ b/src/nativeTest/kotlin/de/atennert/lcarswm/drawing/ColorFactoryTest.kt @@ -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.* @@ -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 @@ -35,6 +37,9 @@ class ColorFactoryTest { assertNotNull(gc1) assertNotNull(gc2) assertEquals(2.toULong(), drawApi.pixel) + + nativeHeap.free(gc1) + nativeHeap.free(gc2) } @Test @@ -48,6 +53,8 @@ class ColorFactoryTest { assertNotNull(gc1) assertEquals(gc1, gc2) assertEquals(1.toULong(), drawApi.pixel) + + nativeHeap.free(gc1) } @Test @@ -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() + @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, alloc: Int): Colormap { @@ -87,9 +121,7 @@ class ColorFactoryTest { } override fun createGC(drawable: Drawable, mask: ULong, gcValues: CValuesRef?): GC? { - val gc: GC = nativeHeap.alloc().ptr.reinterpret() - gcs.add(gc) - return gc + return nativeHeap.alloc().ptr.reinterpret() } }