Category: Uncategorized

Implementing zoom with moving pivot point using libclutter

I’m making this post, because I struggled with this functionality a lot! I was implementing it (to the extent I was happy with) in the course of 4 or even 5 days! Ok, first goes an animated gif which shows my desired zoom behavior (check out Inkscape, or other graphics programs, they all work the same in this regard):

Desired zoom functionality

Basically the idea is that, the center of the scale transformation is where the mouse pointer is on the screen, so the object under the cursor does not move while scaling, whereas other objects around it do. My first, and most obvious implementation (which didn’t work as expected) was as such:

/*
 * Point center is in screen coordinates. This is where mouse pointer is on the screen.
 * The layout is : GtkWindow has ClutterStage which contains ClutterActor scaleLayer
 * (in this function named self), which contains those blue
 * circles you see on animated gif.
 *
 * ScaleLayer is simply a huge invisible plane which contains all the objects an user
 * interacts with. User can pan and zoom it as he whishes.
 */
void ScaleLayer::zoomOut (const Point &center)
{
        double scaleX, scaleY;
        // This gets our actual zoom factor.
        clutter_actor_get_scale (self, &scaleX, &scaleY);
        // We decrease the zoom factor since this is a zoomOut method.
        float newScale = scaleX / 1.1;

        float cx1, cy1;
        // Like I said 'center' is in screen coords, so we convert it to scaleLayer coords
        clutter_actor_transform_stage_point (self, center.x, center.y, &cx1, &cy1);

        float scaleLayerNW, scaleLayerNH;
        clutter_actor_get_size (self, &scaleLayerNW, &scaleLayerNH);
        // We set pivot_point
        clutter_actor_set_pivot_point (self, double(cx1) / scaleLayerNW, double(cy1) / scaleLayerNH);
        // And finalyy perform the scalling. Fair enough, isn't it?
        clutter_actor_set_scale (self, newScale, newScale);
}

Here is the outcome of the above:

Zoom fail

It is fine until you move the mouse cursor which changes the pivot point (center of the scale transformation) while scale is not == 1.0. I dunno why this happens. Apparently I do not understand affine transformations as well as I thought, or there is a bug in libclutter (I doubt it). The solution is to convert the pivot point from screen to scaleLayer coordinates before scaling (as I did), and again after scaling. The difference is in scaleLayer coordinates, so it must be converted back to screen coordinates, and the result can be used to cancel this offset you see on the second gif. Here is my current implementation:

void ScaleLayer::zoomIn (const Point &center)
{
        double x, y;
        clutter_actor_get_scale (self, &x, &y);

        if (x >= 10) {
                return;
        }

        double newScale = x * 1.1;

        if (newScale >= 10) {
                newScale = 10;
        }

        scale (center, newScale);
}

/*****************************************************************************/

void ScaleLayer::zoomOut (const Point &center)
{
        ClutterActor *stage = clutter_actor_get_parent (self);

        float stageW, stageH;
        clutter_actor_get_size (stage, &stageW, &stageH);

        float dim = std::max (stageW, stageH);
        double minScale = dim / SCALE_SURFACE_SIZE + 0.05;

        double scaleX, scaleY;
        clutter_actor_get_scale (self, &scaleX, &scaleY);

        if (scaleX <= minScale) { return; } scale (center, scaleX / 1.1); 
} 

/*****************************************************************************/ 

void ScaleLayer::scale (Point const &c, float newScale) { 
   Point center = c; float cx1, cy1; if (center == Point ()) { if (impl->lastCenter == Point ()) {
                        float stageW, stageH;
                        ClutterActor *stage = clutter_actor_get_parent (self);
                        clutter_actor_get_size (stage, &stageW, &stageH);
                        impl->lastCenter = Point (stageW / 2.0, stageH / 2.0);
                }

                center = impl->lastCenter;
        }
        else {
                impl->lastCenter = center;
        }

        clutter_actor_transform_stage_point (self, center.x, center.y, &cx1, &cy1);
        float scaleLayerNW, scaleLayerNH;
        clutter_actor_get_size (self, &scaleLayerNW, &scaleLayerNH);
        clutter_actor_set_pivot_point (self, double(cx1) / scaleLayerNW, double(cy1) / scaleLayerNH);
        clutter_actor_set_scale (self, newScale, newScale);

        // Idea taken from here : https://community.oracle.com/thread/1263955
        float cx2, cy2;
        clutter_actor_transform_stage_point (self, center.x, center.y, &cx2, &cy2);

        ClutterVertex vi1 = { 0, 0, 0 };
        ClutterVertex vo1;
        clutter_actor_apply_transform_to_point (self, &vi1, &vo1);

        ClutterVertex vi2 = { cx2 - cx1, cy2 - cy1, 0 };
        ClutterVertex vo2;
        clutter_actor_apply_transform_to_point (self, &vi2, &vo2);

        float mx = vo2.x - vo1.x;
        float my = vo2.y - vo1.y;

        clutter_actor_move_by (self, mx, my);
}

The whole project is here : https://github.com/iwasz/data-flow-gui
Here’s the thread which pointed me in right direction : https://community.oracle.com/thread/1263955

Cross compilation with GCC & QtCreator for ARM Cortex M

I used Eclipse CDT for years for C/C++ and was disappointed by its bulkiness, slowness and memory usage. I did mostly embedded, and sometimes GTK+ desktop apps (even OpenGL once or twice). I looked for a replacement, tried dozen or more IDEs and editors, and finally found out the QtCreator (my main concerns were : great code navigation – eclipse often get confused wit serious, templated C++ code), great code completion, and CMake integration. I am satisfied for now (It’s been a year now), and I use it for all but Qt. But all of a sudden, wen a new version appeared, I came across a minor flaw in CMake builder, which reported an error like “Can’t link a test program”. Obviously he cannot, because he used host compiler instead of ARM one.

So in version prior to 4.0.0 i used to configure my project with cmake like:

cd build
cmake ..
make

Then, from Qt, i simply compiled the project, and it worked flawlessly. But since QtCreator 4.0.0 it started to invoke cmake in every possible situation. Be it a IDE startup, or saving a CMakeLists.txt file. And he did it with -DCMAKE_CXX_COMPILER=xyz where “xyz” was a path configured in Tools -> Options -> Build & Run -> Compilers. If I run cmake manually, without this CMAKE_CXX_COMPILER variable set, everything was OK. I saw in the Internet, that many people had the same problem, and used QtCreator for embedded like I do (see comments here).

So I decided, that instead of forcing QtCreator to stop invoking cmake, or invoking it with different parameters, I should fix my CMakeLists.txt so it would run as QtCreator want it. Solution I found was CMAKE_FORCE_C_COMPILER and CMAKE_FORCE_CXX_COMPILER documented here. My CMakeLists.txt looks like this:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)

SET (CMAKE_VERBOSE_MAKEFILE OFF)
include (stm32.cmake)

PROJECT (robot1)

SET(USB_LIB "" CACHE STRING "")

INCLUDE_DIRECTORIES("src/")
LIST (APPEND APP_SOURCES "src/main.c")
LIST (APPEND APP_SOURCES "src/stm32f4xx_it.c")
LIST (APPEND APP_SOURCES "src/syscalls.c")
LIST (APPEND APP_SOURCES "src/system_stm32f0xx.c")
LIST (APPEND APP_SOURCES "src/config.h")
LIST (APPEND APP_SOURCES "src/stm32f0xx_hal_conf.h")

AUX_SOURCE_DIRECTORY ("${CUBE_ROOT}/Drivers/STM32F0xx_HAL_Driver/Src/" APP_SOURCES)
LIST (APPEND APP_SOURCES "${STARTUP_CODE}")

ADD_EXECUTABLE(${CMAKE_PROJECT_NAME}.elf ${APP_SOURCES})
ADD_CUSTOM_TARGET(${CMAKE_PROJECT_NAME}.bin ALL DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${CMAKE_OBJCOPY} -Obinary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin)

FIND_PROGRAM (ST_FLASH st-flash)
ADD_CUSTOM_TARGET("upload" DEPENDS ${CMAKE_PROJECT_NAME}.elf COMMAND ${ST_FLASH} --reset write ${CMAKE_PROJECT_NAME}.bin 0x8000000)

And the “toolchain file” is like this:

SET (TOOLCHAIN_PREFIX "/home/iwasz/local/share/armcortexm0-unknown-eabi" CACHE STRING "")
SET (TARGET_TRIPLET "armcortexm0-unknown-eabi" CACHE STRING "")
SET (DEVICE "STM32F072xB")
SET (CUBE_ROOT "/home/iwasz/workspace/stm32cubef0")
SET (CRYSTAL_HZ 16000000)
SET (STARTUP_CODE "src/startup_stm32f072xb.s")
SET (LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/src/STM32F072RB_FLASH.ld")
SET (TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin)
SET (TOOLCHAIN_INC_DIR ${TOOLCHAIN_PREFIX}/${TARGET_TRIPLET}/include)
SET (TOOLCHAIN_LIB_DIR ${TOOLCHAIN_PREFIX}/${TARGET_TRIPLET}/lib)

INCLUDE(CMakeForceCompiler)
SET (CMAKE_SYSTEM_NAME Generic)
SET (CMAKE_SYSTEM_PROCESSOR arm)

CMAKE_FORCE_C_COMPILER ("${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc" GNU)
CMAKE_FORCE_CXX_COMPILER ("${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-gcc" GNU)
SET (CMAKE_ASM_COMPILER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-as")
SET (CMAKE_ASM-ATT_COMPILER "${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-as")
SET (CMAKE_OBJCOPY ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objcopy)
SET (CMAKE_OBJDUMP ${TOOLCHAIN_BIN_DIR}/${TARGET_TRIPLET}-objdump)
SET (CMAKE_C_FLAGS "-std=gnu99 -fdata-sections -ffunction-sections -Wall" CACHE INTERNAL "c compiler flags")
SET (CMAKE_CXX_FLAGS "-std=c++11 -Wall -fdata-sections -ffunction-sections -MD -Wall" CACHE INTERNAL "cxx compiler flags")
SET (CMAKE_EXE_LINKER_FLAGS "-T ${LINKER_SCRIPT} -Wl,--gc-sections" CACHE INTERNAL "exe link flags")
SET (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
SET (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")

INCLUDE_DIRECTORIES(${SUPPORT_FILES})
LINK_DIRECTORIES(${SUPPORT_FILES})
ADD_DEFINITIONS(-D${DEVICE})
INCLUDE_DIRECTORIES("${CUBE_ROOT}/Drivers/STM32F0xx_HAL_Driver/Inc/")
INCLUDE_DIRECTORIES("${CUBE_ROOT}/Drivers/CMSIS/Device/ST/STM32F0xx/Include/")
INCLUDE_DIRECTORIES("${CUBE_ROOT}/Drivers/CMSIS/Include/")

ENABLE_LANGUAGE (ASM-ATT)

Two most important changes were:

  • Using CMAKE_FORCE_CXX_COMPILER macro instead of simply setting CMAKE_CXX_COMPILER var.
  • Including the toolchain file (and thus setting / forcing the compiler) before PROJECT macro.

My configuration as of writing this:

  • Qt Creator 4.0.2, Based on Qt 5.7.0 (GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 64 bit), Built on Jun 13 2016 01:05:36, From revision 47b4f2c738
  • Host system : Ubuntu 15.10, Linux ingram 4.2.0-38-generic #45-Ubuntu SMP Wed Jun 8 21:21:49 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
  • Host GCC : gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
  • Target GCC : armcortexm0-unknown-eabi-gcc (crosstool-NG crosstool-ng-1.21.0-74-g6ac93ed – iwasz) 5.2.0

BlueNRG + STM32F7-DISCO tests

IMG_20160321_020856

  • Tested 32bit cross-compiler from launchpad, it worked OK, but binaries were much bigger, and debugger lacked Python support which is required by QtCreator which is an IDE of my choice (for all C/C++ development including embedded).
  • Made my own compiler with crosstool-NG (master from GIT). Used my own tutorial, which can be found somewhere over this blog.
  • Verified that a “hello world” / “blinky” program works. It did not, because I copied code for STM32F4, and I messed the clock configuration. Examples from STM32F7-cube helped.
  • I ported my project which aimed to bring my BlueNRG dev board to life. The project consists of a USB vendor-specific class for debugging (somewhat more advanced, and tuned for the purpose than simple CDC class), slightly adapted BlueNRG example code from ST (for Nucleo), and some glue code.
  • I switched to STM32F7-disco because I couldn’t get BlueNRG to work with STM32F4-disco. F7 has Arduino connector on the back, so I thought it’d be better than bunch of loosely connected wires which was required for F4. At that time I thought that there is something wrong with my wiring.
  • On STM32F7-disco BLE still would not work. I hooked up a logic analyzer, and noticed that MISO and CLK is silent. It turned up that I have to use alternative CLK configuration on BlueNRG board which required to move 0R resistor from R10 to R11. Although it was small (0402), at first I had problem desoldering it, probably because of unleaded solder used. See image.

IMG_20160320_175826

  • Next problem I had, was with SPI_CS pin. According to the BlueNRG-dev board docs, I wanted to use D8 pin (this is PI2 pin on STM32F7-disco), but it didn’t work. Glimpse on the schematics revealed that the SPI_CS is connected to A1, which is marked as “alternative” in the docs. So IMHO this is an error in the docs.
  • Final pin configuration that worked was:
// SPI Reset Pin
#define BNRG_SPI_RESET_PIN GPIO_PIN_3
#define BNRG_SPI_RESET_PORT GPIOI
// SCLK
#define BNRG_SPI_SCLK_PIN GPIO_PIN_1
#define BNRG_SPI_SCLK_PORT GPIOI
// MISO (Master Input Slave Output)
#define BNRG_SPI_MISO_PIN GPIO_PIN_14
#define BNRG_SPI_MISO_PORT GPIOB
// MOSI (Master Output Slave Input)
#define BNRG_SPI_MOSI_PIN GPIO_PIN_15
// NSS/CSN/CS
#define BNRG_SPI_CS_PIN GPIO_PIN_10
#define BNRG_SPI_CS_PORT GPIOF
// IRQ
#define BNRG_SPI_IRQ_PIN GPIO_PIN_0
// !!!
#define BNRG_SPI_IRQ_PULL GPIO_PULLDOWN
#define BNRG_SPI_IRQ_PORT GPIOA
  • Next thing that got me puzzled for quite a time was that after initial version query command, which seemed to work OK (I got some reasonably looking responses) the communication hanged. IRQ pin went high, and wouldn’t go low. So µC thought that there is data to read and was continuously reading and reading.
  • Only after I read in UM1755 User manual that IRQ goes HI when there is data from NRG to µC, and it goes HI-Z when there is no data, I double checked the schematics, and found that BlueNRG-dev board has no pull-down resistor in it. The ST example code I had also hadn’t have IRQ pin configured in pull-down state, so I wonder how this could work. Maybe Nucleo boards have pull-down resistor soldered there.
  • For now (after 3 or 4 nights, and I consider myself as quite experienced) I got this (see photo):Screenshot from 2016-03-21 02-09-30
  • “Iwona” is probably my neighbor’s phone.
  • Quick update made the next day morning. My Linux computer is able to connect to the test project, and query it (right now it simply counts up):

Screenshot from 2016-03-21 13-05-25

tac

Tac command outputs file in reversed order (thus its name – it’s “cat” but backwards). And sponge is a pure magical one which acts as some kind of buffer which gets all the output and then puts it into whatever file in one go, completely removing its contents (this is how I get it – may be wrong). So one could output modified contents of a file to this file itself as so:

tac diamond.dat | sponge diamond.dat

 

Bloki

Mamy na Jelonkach dwie piwnice. Do dziś był w nich potworny burdel, który posprzątałem i jeśli jeszcze nie zauważyliście, to właśnie się tym chwalę. Strasznie mnie to zmęczyło i zgłodniałem też porządnie, więc poszedłem do chińczyka hał-hała nieopodal, żeby wziąć coś na wynos. I tak sobie siedziałem na zewnątrz, pogoda ładna i tak dalej i jakiś taki dobry humor mi się zrobił. Siedziałem, patrzyłem w dal, gdzie wznoszą się ściany bloków po drugiej stronie ulicy, a nad nimi latają jaskółki. I pomyślałem sobie tak. Gdybym nie miał zupełnie nic i w ogóle nigdy bym niczego nie posiadał, to także nie znał bym takiego pojęcia jak sprzątanie. No bo co może wiedzieć o sprzątaniu ktoś, kto nic nie ma. Wyobraźmy sobie jakiegoś troglodytę, który jedyne co może posprzątać, to liście na trawniku, albo gałązki pod drzewem, ale ponieważ ani trawnik, ani drzewno nie należą do niego (bo nic do niego nie należy), to po co ma to robić. I z jednej strony szczęśliwy jest taki troglodyta, bo troglodyci są znani ze wstrętu do wiosennych porządków, ale z drugiej strony, kiedy przyjdzie na niego czas, i troglodyta zdechnie, to żadna rzecz, żaden kot w pustym mieszkaniu po nim nie pozostanie. Kiedy ja zdechnę, to zostanie po mnie mnóstwo niepotrzebnych śmieci, i ktoś może sobie coś weźmie i pomyśli o mnie chociaż. A jak cała ludzkość nagle zdechnie, to zostaną po niej te bloki, puste mieszkania, puste samochody, puste resztki czegoś, co kiedyś było cywilizacją. No i to w zasadzie to wszystko co wtedy wymyśliłem, bo żona hał-hała przyniosła mi w międzyczasie żarcie na zewnątrz i wróciłem do domu.

Przyjaciele w Radomiu

    Kiedy się ma nową rzecz, na którą się czekało długo tak jak ja, to się tą rzecz oczywiście chce przetestować, nacieszyć, pobawić. Nie inaczej było w przypadku motocykla, tej piekielnej maszyny, którą nabyłem niedawno. Nacieszenie się nowym pojazdem polega na jeżdżeniu w tą i z powrotem, czasem w jakimś celu, a czasem bez. Kiedy już objeździłem całą rodzinę, pochwaliłem się krewnym i znajomym królika i o mało co nie przeziębiłem, powstał dylemat gdzie w następnej kolejności pojechać. Kiedy motocykla nie miałem, wyobrażałem sobie go jako remedium na wszystkie swoje niepowodzenia, sinusoidalne skoki humoru, czasem też całkiem spore dołki. Wyobrażałem sobie siebie jadącego sobie w dal i pogrążonego w swoich myślach, sam na sam ze sobą, odciętego od wszystkiego. Stety lub niestety myliłem się. Okazuje się bowiem, że jadąc na motocyklu człowiek jest (musi być) dwa, lub jeszcze więcej razy bardziej skupiony na tym co się dookoła niego dzieje niż w samochodzie. Tak więc jadąc na moto miałem teraz zupełną pustkę w głowie i jakkolwiek czerpiąc wielką przyjemność z podróży, moja głowa była jednak zaprzątnięta raczej tym, żeby nie dać się zabić, niż rozmyślaniami o sensie istnienia, czy jakichś tam innych pierdół. A Jechałem do Radomia Aleją Krakowską, czy trasą krakowską, jak zwał tak zwał. Radom to paskudne miasto, które pamiętam z dzieciństwa, ponieważ spędzałem tam wakacje u babci Janki i przez babcię, oraz jego paskudność odczuwam do niego spory sentyment (nie taki jak do P-na, ale zawsze). Uzbrojony w karteczkę z numerami tras (wracałem przez Kozienice) i listą miejsc do odwiedzenia (3 pozycje, ale mam słabą pamięć, stąd lista) pędziłem sobie wesoło na południe. Udało mi się tam dojechać w około godzinę, co jednak nie było zbyt rozsądne, jak potem uświadomiły mi żona i matka, no ale cóż.

    Nie jest tak, jak twierdzą niektórzy, że motocykl jest magnesem na płeć piękną i wystarczy się polansować po mieście, żeby od razu jakiś plecak podwieźć, a potem stłamsić. To znaczy może to jest prawda, ale mnie przynajmniej jest to zupełnie obce i to dobrze. Jakkolwiek laski nie kleją się do mojej maszyny, to jednak zupełnie inaczej sprawa się ma z małymi dziećmi. Mam go już miesiąc, a rozmawiałem już chyba z pięciorgiem dzieci w wieku przedszkolnym, o dzieciach gapiących się z mniej dostępnych miejsc nie wspominając. Jeden chłopiec na przykład, lat mniej więcej na oko 2 (bo ledwo mówił) zachęcany przez swojego tatę wymieniał mi wszystkie marki motocykli jakie znał. Trzeba mu było tylko trochę pomagać z pierwszą sylabą, a potem sobie seplenił. Zuch. Inny chciał się gramolić na motocykl, ale babcia na niego nawrzeszczała, jeszcze inne dzieci po prostu przechodząc ciągnęły za klamki, manetki i inne wystające rzeczy. Zupełnie mi to nie przeszkadza.

    Brak mi niestety jeszcze doświadczenia i w Radomiu przydarzył mi się pierwszy paciak. Paciak to (chyba fachowe) określenie na wywrotkę “parkingową” kiedy to toczymy się na motocyklu w celu właśnie wspomnianego parkowania, lub w jakimś innym, dość, że prędkość mamy wtedy prawie żadną. W takich momentach motocykl jest bardzo niestabilny, bowiem brak sił żyroskopowych pochodzących od kręcących się kół (kręcą się wolno, więc siła mała i słabo nas/mnie stabilizuje). I tak samo było w moim przypadku. Zauważyłem bowiem na ulicy Niedziałkowskiego w Radomiu grupę młodzieży gimnazjalnej w sile około dziesięciu na tle wielkiej swastyki wysprejowanej na murze. Szybko się oddaliłem, ale jednak ciekawość pozostała i dokopawszy się do głęboko skrywanych pokładów odwagi postanowiłem do nich wrócić, żeby zrobić im zdjęcie. Niestety nie było ich, ja zacząłem zawracać, samochód się zjawił znikąd, ja po hamulcach i pac. Wygrzebałem się spod motocykla, łażę dookoła i patrzę co by tu zrobić (wyłączył się sam). Próbuję podnieść przodem, nie daję rady. Próbuję inaczej, też nic. Wtem słyszę ożywioną rozmowę. To właśnie owi chłopcy, których szukałem wymieniali się uwagami na temat przyczyn mojego nieszczęścia. Konkluzja brzmiała : “typ się przestraszył”. No i dużo mieli racji, moja gwałtowna reakcja była skutkiem nagłego pojawienia się zagrożenia, którego się nie spodziewałem (to był jakiś stary golf). Szli w moją stronę i zastanawiali się na głos, czy mi pomóc, czy nie. Szybko (na szczęście) doszli do porozumienia, że jednak tak (“pomożemy typowi”) i jeszcze będąc w pół drogi, uspokoili mnie (cały czas szarpiącego się z kawałem żelastwa) w te słowy : “zostaw to, bo się zesrasz!”.

    Zdjęcia już im nie zrobiłem, ale wdzięczny jestem im do dzisiaj, bo strasznie ciężkie to cholerstwo. Oczywiście nie miałem gmoli ani kraszpadów, a motocykl był nowy, więc sami sobie możecie dalej dopowiedzieć co i jak. Na szczęście straty są znikome, a na gmole i kraszpady ciągle zbieram. Pozdrawiam chłopaków z Radomia.

O żuku (2)

    Pory roku mijają, sezony się kończą, przychodzi taki czas, że uśpione drzewa budzą się do życia pobudzone pierwszymi mocniejszymi promieniami słońca. Gdzieniegdzie leży jeszcze śnieg, a już pierwsze kiełki przebijają się przez niego i wystają nieśmiało niepewne, czy jakiś nagły przymrozek nie zabije ich w mgnieniu oka. Potem następuje spokojny czas lata, kiedy rośliny boją się już tylko braku wody, ale to w dużych lasach zdarza się rzadko, no przynajmniej jeśli roślina jest sprytna i wie gdzie się wysiać. Te mądre zawsze znajdują wilgotne miejsce, gdzie nigdy nie jest sucho i nigdy nie są spragnione. Później przychodzi ponura jesień, prawie wszystko w lesie co żyje i co jest małe, albo trochę większe szykuje się do snu, czy jaki tam jeszcze ma patent na przetrwanie. Niektórzy śpią, niektórzy gubią liście, inni zagrzebują się w norkach, jeszcze inni w kokonach, prawie każdy w lesie jakoś sobie tam radzi, a w razie potrzeby zawsze może liczyć na pomoc innych. Niestety, ale cały ten cykl jest tylko marzeniem dla motyla. Jak kolorowy motocyklista na autostradzie, motyl żyje szybko, ale krótko, o czym niestety żuk jakoś zapomniał, albo w sumie nie zapomniał, tylko nie chciał pamiętać.
    Żuk nie wychodził ze szpitala od dwóch dni. Siedział przy łóżku ukochanej, a ona marniała w oczach. Kolory jej zwiewnych sukienek jakby przyblakły, a i zwiewne w zasadzie już przestały być. Motylica ufnie patrzyła na niego, a on płakał i płakał, starając się to przed nią ukryć, ale nie wychodziło, bo sam wyglądał okropnie – zapuchnięty, zasmarkany i zarośnięty. Chwilami próbował rozpaczliwie gonić czas, chwilami przywoływał te wszystkie 7 szczęśliwych dni, które spędzili razem intensywnie (to wcale nie jest śmieszne – dla robali to całkiem sporo czasu) i z radością. Jego myśli goniły się, potem potykały i gubiły, plątały, tak, że w głowie miał w zasadzie mętlik. Im dłużej tam siedział i im było gorzej, tym dobitniej uświadamiał sobie ile czasu stracił na rzeczy nie istotne, ile rzeczy bezpowrotnie przeminęło w jego życiu i że ta ostatnia, najważniejsza, także zaraz przeminie, a on nie będzie mógł już nigdy patrzeć na swoją ukochaną. “Kiedy ktoś ma 1000 par oczu jak ja, i patrzy na cierpienie bliskiej osoby, to boli go to o wiele bardziej” myślał naiwnie żuk. Było już na prawdę źle, i z nią i z nim. Cierpieli razem, ale on czuł teraz gniew i bunt. Chciał widzieć tylko ją, każda inna rzecz była zbędna, każdy inny obraz przeszkadzał i żuk bał się, że jej wizerunek zatrze się w jego pamięci, że zginie gdzieś w otchłani wszystkich tych bezsensownych i niepotrzebnych rzeczy, które widzi się każdego dnia i choćby to były dobre rzeczy, to jednak nikt nie zrozumie tego jak bardzo żuk ich w tym momencie nienawidził. A potem był już tylko ledwie słyszalny szept, którego nawet ja nie zrozumiałem, rozumieli go tylko oni, oni, którzy szeptali do siebie po raz ostatni, a potem było już tylko cicho. On ostatni raz spojrzał na nią cichą i spokojną. Nie wiem co było dalej, pamiętam jeszcze tylko, ponury dźwięk, cichy stukot, jakby dzwonienie koralików spadających na posadzkę. Wyglądały jak nasiona granatu rozsypujące się po sali. Toczyły się, wirowały, co raz więcej i więcej. Było ich 1000 par. “teraz będę Cię już widział zawsze” myślał naiwnie żuk.

O żuku (1)

    Jest to historia jakich wiele, jednak ta jest wyjątkowo przykra i samego mnie nawet jej zakończenie zasmuciło, jeśli wręcz nie powiedzieć – przybiło. Nieszczęsny nasz bohater, grubawy żuk o tysiącu par oczu, choć sam wolał określenie “przy kości”, choć kości nie posiadał, a jedynie chitynowy pancerzyk, przybył jak co dzień na deskorolce do pracy. To znaczy kiedy była ładna pogoda, to jeździł na deskorolce, a kiedy była brzydka, to tramwajem, ale tego feralnego dnia było akurat słońce. Wiosna w pełni, wszystko budzi się do życia i nawet takiemu ponurakowi jak żuk, administrator sieci w małej firemce produkującej łupiny od orzechów było tego dnia lżej na sercu. Branża IT to nie jest łatwy kawałek chleba, mnóstwo jest w niej przeciwności losu i pół biedy jeśli opór stawia materia nieożywiona, z którą zawsze można sobie jakoś poradzić. Prawdziwe problemy stanowi czynnik ludzki, a raczej w naszym przypadku czynnik robaczywy, który miewa humory, wybujałe ego, przerosty formy nad treścią, przerosty tego, czy tamtego. To wszystko mając w pamięci, żuk nie za bardzo lubił swoją pracę, ale cóż było robić. Pracowało się.
    Jednak tego dnia coś było inaczej. Pojawili się nowi pracownicy z biura pracy czasowej. Mrówka, wołek zbożowy i motylica. Wszyscy troje mieli takie śmieszne czerwone koszulki z logiem firmy która ich wypożyczyła (na jakiś czas, bo to zajęcie czasowe) i generalnie zrzucano na nich wszystkie najgorsze zadania, których nikt inny nie chciał robić, albo odkładał w nieskończoność. Pracowali w milczeniu i jak większość nowych pracowników byli trochę jakby przestraszeni, trochę jakby niepewność w ich ruchach było widać. Na przerwie obiadowej usiedli wszyscy troje przy jednym stoliku na stołówce i trzymali się z daleka od wszystkich, ze sobą zresztą także niezbyt rozmawiając. Żal się zrobiło dobrodusznemu żukowi tych sierot, poczłapał więc do nich i kulturalnie zapytawszy dosiadł się do jedzących. Z tymi dwoma ponurakami, to niezbyt mu się udawało nawiązać kontakt, ale z motylicą wręcz przeciwnie. Była wesoła, niegłupia, śmiała się z żukowych dowcipów, a przede wszystkim była piękna. Kolorowe jej sukienki, falbanki powiewały na wietrze, niby to jakieś kwieciste wzory, ale tak na prawdę jakieś raczej geometryczne kształty, zygzaki, plamy, żuk nie mógł za bardzo dostrzec co to właściwie jest, dość, że wyglądało ładnie i pasowało do niej. Włosy miała całkiem długie, ale nie za długie, jakie miewają czasami głęboko wierzące dziewczęta, które chyba po prostu zapominają je przycinać, wszak mają ważniejsze rzeczy na głowie. Żuk nie był za bardzo wierzący, poza tym jak każdy mężczyzna lubił gdy dziewczęta dbały o siebie i wyglądały pięknie. Obiad skończył się zdecydowanie za szybko, zresztą i tak wyszli ze stołówki jako ostatni i żuk martwił się nawet, czy motylica nie będzie miała przez to problemów, ale zapomniał potem ją o to zapytać.
    Tego dnia nie mógł już wysiedzieć w pracy. Cały czas myślał o nowej koleżance, znalazł ją nawet na fejsbuku i dodał do znajomych, a potem resztę dnia sprawdzał czy go zaakceptowała. Niedługo potem umówili się na lody malinowe, które ślimak sprzedawał nieopodal. Dziwne, bo miał tylko malinowe, nigdy nie miał żadnych innych smaków… Spotykali się codziennie. Żuk był nawet trochę zaskoczony, bo motylica wydawała się odwzajemniać jego uczucie i to było naprawdę widać. Cały czas chciała być z nim i cały czas wysyłała do niego smsy, co go niezmiernie cieszyło. Żuk miał kiedyś dziewczynę, ale z tamtą było inaczej. Nigdy tak na prawdę nie wiedział i nigdy się nie dowiedział co w jej głowie siedziało, jeśli w ogóle coś tam było. Nigdy nie był pewny uczuć tamtej i chyba zresztą słusznie, bo wkrótce potem go rzuciła.
    Tak mijały dni (właściwie to tydzień), lecz ósmego dnia, kiedy mieli się znów spotkać po pracy, coś się stało i motylica nie przyszła. Żuk się zmartwił mając w pamięci zaangażowanie swojej ukochanej, ale zaraz potem przyszło zwątpienie – “O ja głupi, nieszczęśliwy żuk przy kości, niecnota. Co ja sobie wyobrażałem? Taka laska i ja… To się musiało skończyć” – dramatyzował.

Pan Jurek i ja

Od pewnego czasu, od kiedy to dopuszczam się haniebnego procederu palenia papierosów rozmawiam sobie czasem z panem Jurkiem, który jest dozorcą w budynku w którym pracuję. Palenie nie ma prawie żadnych zalet prócz wspomnianego przeze mnie spleenu, czy innego uczucia nostalgii towarzyszącego zaciąganiu się dymem, którego czasem doznaję, ale, no właśnie. Prawie. Niewątpliwie poznałbym w swoim życiu o wiele mniej ludzi niż znam gdyby nie papierosy. No bo cóż mają robić nieznający się ludzie, którzy palą razem jeśli nie rozmawiać? Oto jedna z historii pana Jurka.

Pan Jurek pracował kiedyś w Irlandii – z resztą nie tylko w Irlandii, bo w Stanach też był i pracował pół roku, a potem pół roku jeździł i zwiedzał – też bym tak chciał. Wróćmy do Irlandii. Wynajmował tam pokój z dwoma współlokatorami : ojcem i synem. Z synem, a było mu na imię Andrzej, dogadywał się bardzo dobrze, jak zresztą, ze wszystkimi młodymi ludźmi, których ogólnie rzecz biorąc lubi. Andrzej też go polubił, bo dobrze im się rozmawiało, a poza tym, pan Jurek był całkowitym przeciwieństwem wiecznie pijanego ojca. Nie był to ojciec jakiego chcielibyście mieć. Od małego Andrzej (i jego młodszy o rok brat) byli świadkami picia, bicia, obelg i wszystkiego tego o czym mówią o patologicznych rodzinach w wiadomościach, kiedy już dojdzie do najgorszego. “Panie Jurku. Z panem, to ja bym mógł mieszkać i mieszkać, tylko żeby tego chuja, współlokatora nie było” wskazał na swojego ojca w drugim pokoju. “Bo wie pan, mówię o nim bez szacunku, bo jak mam szanować kogoś od kogo dobrego słowa nie usłyszałem chyba nigdy, a ile się nacierpiałem to moje. Stary pijak. Nigdy u nas w domu się nie przelewało, czasem nie było co jeść, a on sobie sprowadzał kolegów i za ostatnie pieniądze pili. Kiedyś na przykład, sprowadził całe to towarzystwo, wyjął na stół flaszkę i ugościł po królewsku. Własnym dzieciom od ust odejmował, a tym pijakom podał kiełbasę, ser, co tam jeszcze w domu zostało i piją. Kiedy matka to zobaczyła, szlag jasny ją trafił, wyszła na dwór, wzięła garść piachu i rzuciła mu to na ten stół, na talerze i kieliszki. Ojciec tak się wściekł, uderzył ją tak mocno, że straciła przytomność i padła na ziemię jak kłoda.”

W tym momencie historii już myślałem, że kobietę utłukł na amen – wtrącił pan Jurek – ale na szczęście udało się ją tym razem docucić. Dalej Andrzej opowiadał tak:

“Niedługo potem, kiedy wieści od matki dotarły do szwagra, od szwagra do jego braci, od braci do ich kolegów, a od kolegów Bóg raczy wiedzieć gdzie jeszcze, postanowiono skompletować silną grupę i nauczyć chama rozumu. Ojciec był przerażony, 10 postawnych mężczyzn ganiało go po wsi, potem po podwórku, a potem przez pole buraków, na którym to wywinął orła, potem znów przez podwórko, gdzie to ojciec pochwycił siekierę do samoobrony. Wtedy role się odwróciły, bo trzeba wiedzieć, że siekiera w dłoniach także całkiem dobrze zbudowanego ojca była argumentem więcej niż przekonującym i teraz to chłopaki uciekali przed nim. Najpierw z podwórka w wieś, potem przez pole, a potem znów w kierunku podwórka. Już się zamachnął, już prawie miał szwagra tą siekierą zdzielić, ale na szczęście chybił i siekiera utkwiła w płocie”

Wtedy papierosy się skończyły i wróciliśmy każdy do swoich zajęć. Pan Jurek i ja.