Browse Source

More extensive CI tests

Signed-off-by: falkTX <falktx@falktx.com>
pull/473/head
falkTX 7 months ago
parent
commit
7cd48190cf
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
5 changed files with 183 additions and 193 deletions
  1. +122
    -0
      .github/workflows/build.yml
  2. +0
    -78
      .github/workflows/makefile.yml
  3. +5
    -74
      distrho/extra/Base64.hpp
  4. +48
    -31
      distrho/src/jackbridge/JackBridge.cpp
  5. +8
    -10
      examples/CairoUI/DemoWidgetBanner.hpp

+ 122
- 0
.github/workflows/build.yml View File

@@ -0,0 +1,122 @@
name: build

on:
push:
branches:
- '*'
pull_request:
branches:
- '*'

jobs:
build:
strategy:
matrix:
os:
# wrong use of AU MIDIPacket
# - macos-12
# - macos-13
# - macos-14
# webgui failure
# - ubuntu-20.04
- ubuntu-22.04
- ubuntu-24.04
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up dependencies
if: ${{ runner.os == 'Linux' }}
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update -qq
sudo apt-get install -yq libasound2-dev libcairo2-dev libdbus-1-dev libgl1-mesa-dev liblo-dev libpulse-dev libsdl2-dev libx11-dev libxcursor-dev libxext-dev libxrandr-dev xvfb
- name: Set num jobs
if: ${{ runner.os == 'Linux' }}
run: echo "JOBS=$(nproc)" >> $GITHUB_ENV
- name: Set num jobs
if: ${{ runner.os != 'Linux' }}
run: echo "JOBS=$(sysctl -n hw.logicalcpu)" >> $GITHUB_ENV
- name: Without any warnings
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: Run tests
if: ${{ runner.os == 'Linux' }}
run: |
xvfb-run make -C tests run
- name: As C++98 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++98
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: As C++11 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++11
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: As C++14 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++14
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: As C++17 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++17
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: As C++20 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++20
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: No namespace
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -DDONT_SET_USING_DISTRHO_NAMESPACE -DDONT_SET_USING_DGL_NAMESPACE
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: Custom namespace
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -DDISTRHO_NAMESPACE=WubbWubb -DDGL_NAMESPACE=DabDab
run: |
make clean >/dev/null
make -j ${{ env.JOBS }}
- name: With OpenGL 3.x
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} USE_OPENGL3=true
- name: Without Cairo
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} HAVE_CAIRO=false
- name: Without OpenGL
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j ${{ env.JOBS }} HAVE_OPENGL=false

+ 0
- 78
.github/workflows/makefile.yml View File

@@ -1,78 +0,0 @@
name: makefile

on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
env:
DEBIAN_FRONTEND: noninteractive

jobs:
linux-x86_64:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -yq libasound2-dev libcairo2-dev libdbus-1-dev libgl1-mesa-dev liblo-dev libpulse-dev libsdl2-dev libx11-dev libxcursor-dev libxext-dev libxrandr-dev xvfb
- name: Without any warnings
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j $(nproc)
- name: Run tests
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
xvfb-run make -C tests run
- name: As C++98 mode
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -std=gnu++98
run: |
make clean >/dev/null
make -j $(nproc)
- name: No namespace
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -DDONT_SET_USING_DISTRHO_NAMESPACE -DDONT_SET_USING_DGL_NAMESPACE
run: |
make clean >/dev/null
make -j $(nproc)
- name: Custom namespace
env:
CFLAGS: -Werror
CXXFLAGS: -Werror -DDISTRHO_NAMESPACE=WubbWubb -DDGL_NAMESPACE=DabDab
run: |
make clean >/dev/null
make -j $(nproc)
- name: With OpenGL 3.x
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j $(nproc) USE_OPENGL3=true
- name: Without Cairo
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j $(nproc) HAVE_CAIRO=
- name: Without OpenGL
env:
CFLAGS: -Werror
CXXFLAGS: -Werror
run: |
make clean >/dev/null
make -j $(nproc) HAVE_OPENGL=

+ 5
- 74
distrho/extra/Base64.hpp View File

@@ -21,7 +21,7 @@


#include <vector> #include <vector>


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html // base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html


/* /*
@@ -48,7 +48,7 @@
René Nyffenegger rene.nyffenegger@adp-gmbh.ch René Nyffenegger rene.nyffenegger@adp-gmbh.ch
*/ */


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// Helpers // Helpers


#ifndef DOXYGEN #ifndef DOXYGEN
@@ -77,82 +77,13 @@ uint8_t findBase64CharIndex(const char c)
static constexpr inline static constexpr inline
bool isBase64Char(const char c) bool isBase64Char(const char c)
{ {
switch (c)
{
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'H':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
case 'g':
case 'h':
case 'i':
case 'j':
case 'k':
case 'l':
case 'm':
case 'n':
case 'o':
case 'p':
case 'q':
case 'r':
case 's':
case 't':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '+':
case '/':
return true;
default:
return false;
}
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/';
} }


} // namespace DistrhoBase64Helpers } // namespace DistrhoBase64Helpers
#endif #endif


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


static inline static inline
std::vector<uint8_t> d_getChunkFromBase64String(const char* const base64string) std::vector<uint8_t> d_getChunkFromBase64String(const char* const base64string)
@@ -213,6 +144,6 @@ std::vector<uint8_t> d_getChunkFromBase64String(const char* const base64string)
return ret; return ret;
} }


// -----------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


#endif // DISTRHO_BASE64_HPP_INCLUDED #endif // DISTRHO_BASE64_HPP_INCLUDED

+ 48
- 31
distrho/src/jackbridge/JackBridge.cpp View File

@@ -1,6 +1,6 @@
/* /*
* JackBridge for DPF * JackBridge for DPF
* Copyright (C) 2013-2022 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2024 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -60,10 +60,15 @@ typedef void* lib_t;
# undef HAVE_SDL2 # undef HAVE_SDL2
#endif #endif


#if defined(HAVE_RTAUDIO) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
#if defined(HAVE_RTAUDIO) && (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) > 0
// fix conflict between DGL and macOS names // fix conflict between DGL and macOS names
# define Point CorePoint # define Point CorePoint
# define Size CoreSize # define Size CoreSize
# ifdef __clang__
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdeprecated-declarations"
# pragma clang diagnostic ignored "-Wunused-but-set-variable"
# endif
# include "RtAudioBridge.hpp" # include "RtAudioBridge.hpp"
# ifdef RTAUDIO_API_TYPE # ifdef RTAUDIO_API_TYPE
# include "rtaudio/RtAudio.cpp" # include "rtaudio/RtAudio.cpp"
@@ -71,15 +76,18 @@ typedef void* lib_t;
# ifdef RTMIDI_API_TYPE # ifdef RTMIDI_API_TYPE
# include "rtmidi/RtMidi.cpp" # include "rtmidi/RtMidi.cpp"
# endif # endif
# ifdef __clang__
# pragma clang diagnostic pop
# endif
# undef Point # undef Point
# undef Size # undef Size
#endif #endif


#if defined(HAVE_SDL2) && DISTRHO_PLUGIN_NUM_INPUTS+DISTRHO_PLUGIN_NUM_OUTPUTS > 0
#if defined(HAVE_SDL2) && (DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS) > 0
# include "SDL2Bridge.hpp" # include "SDL2Bridge.hpp"
#endif #endif


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


extern "C" { extern "C" {


@@ -229,7 +237,7 @@ typedef void (JACKSYM_API *jacksym_set_thread_creator)(jacksym_thread_creator_t)


} // extern "C" } // extern "C"


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


struct JackBridge { struct JackBridge {
lib_t lib; lib_t lib;
@@ -632,7 +640,7 @@ static bool usingNativeBridge = false;
static bool usingRealJACK = true; static bool usingRealJACK = true;
static NativeBridge* nativeBridge = nullptr; static NativeBridge* nativeBridge = nullptr;


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


static JackBridge& getBridgeInstance() noexcept static JackBridge& getBridgeInstance() noexcept
{ {
@@ -642,7 +650,7 @@ static JackBridge& getBridgeInstance() noexcept


#endif // ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY)) #endif // ! (defined(JACKBRIDGE_DIRECT) || defined(JACKBRIDGE_DUMMY))


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


#if defined(__WINE__) && ! defined(JACKBRIDGE_DIRECT) #if defined(__WINE__) && ! defined(JACKBRIDGE_DIRECT)


@@ -861,7 +869,7 @@ struct WineBridge {


#endif // __WINE__ && ! JACKBRIDGE_DIRECT #endif // __WINE__ && ! JACKBRIDGE_DIRECT


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_is_ok() noexcept bool jackbridge_is_ok() noexcept
{ {
@@ -882,7 +890,7 @@ void jackbridge_init()
#endif #endif
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


void jackbridge_get_version(int* major_ptr, int* minor_ptr, int* micro_ptr, int* proto_ptr) void jackbridge_get_version(int* major_ptr, int* minor_ptr, int* micro_ptr, int* proto_ptr)
{ {
@@ -915,7 +923,7 @@ const char* jackbridge_get_version_string()
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


jack_client_t* jackbridge_client_open(const char* client_name, uint32_t options, jack_status_t* status) jack_client_t* jackbridge_client_open(const char* client_name, uint32_t options, jack_status_t* status)
{ {
@@ -1006,7 +1014,7 @@ bool jackbridge_client_close(jack_client_t* client)
return false; return false;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


int jackbridge_client_name_size() int jackbridge_client_name_size()
{ {
@@ -1034,7 +1042,7 @@ const char* jackbridge_get_client_name(jack_client_t* client)
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


char* jackbridge_client_get_uuid(jack_client_t* client) char* jackbridge_client_get_uuid(jack_client_t* client)
{ {
@@ -1075,7 +1083,7 @@ char* jackbridge_get_client_name_by_uuid(jack_client_t* client, const char* uuid
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_uuid_parse(const char* buf, jack_uuid_t* uuid) bool jackbridge_uuid_parse(const char* buf, jack_uuid_t* uuid)
{ {
@@ -1102,7 +1110,7 @@ void jackbridge_uuid_unparse(jack_uuid_t uuid, char buf[JACK_UUID_STRING_SIZE])
#endif #endif
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_activate(jack_client_t* client) bool jackbridge_activate(jack_client_t* client)
{ {
@@ -1145,7 +1153,7 @@ bool jackbridge_is_realtime(jack_client_t* client)
return false; return false;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback thread_init_callback, void* arg) bool jackbridge_set_thread_init_callback(jack_client_t* client, JackThreadInitCallback thread_init_callback, void* arg)
{ {
@@ -1423,7 +1431,7 @@ bool jackbridge_set_latency_callback(jack_client_t* client, JackLatencyCallback
return false; return false;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_set_freewheel(jack_client_t* client, bool onoff) bool jackbridge_set_freewheel(jack_client_t* client, bool onoff)
{ {
@@ -1452,7 +1460,7 @@ bool jackbridge_set_buffer_size(jack_client_t* client, jack_nframes_t nframes)
return false; return false;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client) jack_nframes_t jackbridge_get_sample_rate(jack_client_t* client)
{ {
@@ -1495,7 +1503,7 @@ float jackbridge_cpu_load(jack_client_t* client)
return 0.0f; return 0.0f;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* type, uint64_t flags, uint64_t buffer_size) jack_port_t* jackbridge_port_register(jack_client_t* client, const char* port_name, const char* type, uint64_t flags, uint64_t buffer_size)
{ {
@@ -1540,7 +1548,7 @@ void* jackbridge_port_get_buffer(jack_port_t* port, jack_nframes_t nframes)
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


const char* jackbridge_port_name(const jack_port_t* port) const char* jackbridge_port_name(const jack_port_t* port)
{ {
@@ -1672,7 +1680,7 @@ const char** jackbridge_port_get_all_connections(const jack_client_t* client, co
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_port_rename(jack_client_t* client, jack_port_t* port, const char* port_name) bool jackbridge_port_rename(jack_client_t* client, jack_port_t* port, const char* port_name)
{ {
@@ -1731,7 +1739,7 @@ int jackbridge_port_get_aliases(const jack_port_t* port, char* const aliases[2])
return 0; return 0;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_port_request_monitor(jack_port_t* port, bool onoff) bool jackbridge_port_request_monitor(jack_port_t* port, bool onoff)
{ {
@@ -1785,7 +1793,7 @@ bool jackbridge_port_monitoring_input(jack_port_t* port)
return false; return false;
} }


// -----------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port) bool jackbridge_connect(jack_client_t* client, const char* source_port, const char* destination_port)
{ {
@@ -1828,7 +1836,8 @@ bool jackbridge_port_disconnect(jack_client_t* client, jack_port_t* port)
return false; return false;
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


int jackbridge_port_name_size() int jackbridge_port_name_size()
{ {
@@ -1869,7 +1878,8 @@ uint32_t jackbridge_port_type_get_buffer_size(jack_client_t* client, const char*
return 0; return 0;
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


void jackbridge_port_get_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range) void jackbridge_port_get_latency_range(jack_port_t* port, uint32_t mode, jack_latency_range_t* range)
{ {
@@ -1914,7 +1924,8 @@ bool jackbridge_recompute_total_latencies(jack_client_t* client)
return false; return false;
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, uint64_t flags) const char** jackbridge_get_ports(jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, uint64_t flags)
{ {
@@ -1956,7 +1967,8 @@ jack_port_t* jackbridge_port_by_id(jack_client_t* client, jack_port_id_t port_id
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


void jackbridge_free(void* ptr) void jackbridge_free(void* ptr)
{ {
@@ -1973,7 +1985,8 @@ void jackbridge_free(void* ptr)
#endif #endif
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


uint32_t jackbridge_midi_get_event_count(void* port_buffer) uint32_t jackbridge_midi_get_event_count(void* port_buffer)
{ {
@@ -2043,7 +2056,8 @@ jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_
return nullptr; return nullptr;
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_release_timebase(jack_client_t* client) bool jackbridge_release_timebase(jack_client_t* client)
{ {
@@ -2192,7 +2206,8 @@ void jackbridge_transport_stop(jack_client_t* client)
#endif #endif
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


bool jackbridge_set_property(jack_client_t* client, jack_uuid_t subject, const char* key, const char* value, const char* type) bool jackbridge_set_property(jack_client_t* client, jack_uuid_t subject, const char* key, const char* value, const char* type)
{ {
@@ -2360,7 +2375,8 @@ void jackbridge_cycle_signal(jack_client_t* client, int status)
#endif #endif
} }


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------


#ifndef JACKBRIDGE_SKIP_NATIVE_UTILS #ifndef JACKBRIDGE_SKIP_NATIVE_UTILS


@@ -2460,4 +2476,5 @@ END_NAMESPACE_DISTRHO


#endif // JACKBRIDGE_SKIP_NATIVE_UTILS #endif // JACKBRIDGE_SKIP_NATIVE_UTILS


// -----------------------------------------------------------------------------

// --------------------------------------------------------------------------------------------------------------------

+ 8
- 10
examples/CairoUI/DemoWidgetBanner.hpp View File

@@ -1,7 +1,7 @@
/* /*
* DISTRHO Plugin Framework (DPF) * DISTRHO Plugin Framework (DPF)
* Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru> * Copyright (C) 2019-2021 Jean Pierre Cimalando <jp-dev@inbox.ru>
* Copyright (C) 2012-2023 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
* *
* Permission to use, copy, modify, and/or distribute this software for any purpose with * Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this * or without fee is hereby granted, provided that the above copyright notice and this
@@ -48,10 +48,8 @@ static constexpr const char banner[] =
" ***** * * " " ***** * * "
" "; " ";


enum {
rows = 23,
columns = 72,
};
static constexpr const int kNumRows = 23;
static constexpr const int kNumColumns = 72;


class DemoWidgetBanner : public CairoSubWidget class DemoWidgetBanner : public CairoSubWidget
{ {
@@ -71,19 +69,19 @@ protected:
int w = sz.getWidth(); int w = sz.getWidth();
int h = sz.getHeight(); int h = sz.getHeight();


const double diameter = (double)w / columns;
const double diameter = (double)w / kNumColumns;
const double radius = 0.5 * diameter; const double radius = 0.5 * diameter;
const double xoff = 0; const double xoff = 0;
const double yoff = 0.5 * (h - rows * diameter);
const double yoff = 0.5 * (h - kNumRows * diameter);


for (int r = 0; r < rows; ++r)
for (int r = 0; r < kNumRows; ++r)
{ {
for (int c = 0; c < columns; ++c)
for (int c = 0; c < kNumColumns; ++c)
{ {
double cx = xoff + radius + c * diameter; double cx = xoff + radius + c * diameter;
double cy = yoff + radius + r * diameter; double cy = yoff + radius + r * diameter;


char ch = banner[c + r * columns];
char ch = banner[c + r * kNumColumns];
if (ch != ' ') if (ch != ' ')
cairo_set_source_rgb(cr, 0.5, 0.9, 0.2); cairo_set_source_rgb(cr, 0.5, 0.9, 0.2);
else else


Loading…
Cancel
Save