pax_global_header 0000666 0000000 0000000 00000000064 15164025770 0014521 g ustar 00root root 0000000 0000000 52 comment=0230c0dabb79b7317aa492be74141454144204c4
smooth-0.9.11~git20260403.0230c0da/ 0000775 0000000 0000000 00000000000 15164025770 0015760 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/.gitattributes 0000664 0000000 0000000 00000000010 15164025770 0020642 0 ustar 00root root 0000000 0000000 * -text
smooth-0.9.11~git20260403.0230c0da/.github/ 0000775 0000000 0000000 00000000000 15164025770 0017320 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/.github/workflows/ 0000775 0000000 0000000 00000000000 15164025770 0021355 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/.github/workflows/codeql-analysis.yml 0000664 0000000 0000000 00000003525 15164025770 0025175 0 ustar 00root root 0000000 0000000 name: "Code scanning"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '0 4 * * 2'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
steps:
# Install dependencies.
- run: |
sudo apt update
sudo apt install -y libbz2-dev libcurl4-openssl-dev libfribidi-dev libgtk-3-dev libjpeg-dev libxml2-dev
- name: Checkout repository
uses: actions/checkout@v6
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
# âī¸ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
smooth-0.9.11~git20260403.0230c0da/.github/workflows/verify-build.yml 0000664 0000000 0000000 00000002544 15164025770 0024506 0 ustar 00root root 0000000 0000000 name: "Verify build"
on:
push:
pull_request:
schedule:
- cron: '0 6 * * 1'
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
cc: gcc
cxx: g++
- os: ubuntu-latest
cc: clang
cxx: clang++
- os: macos-latest
cc: clang
cxx: clang++
- os: windows-latest
cc: gcc
cxx: g++
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- name: Install dependencies
if: ${{ runner.os == 'Linux' }}
run: |
sudo apt update
sudo apt install -y libbz2-dev libcurl4-openssl-dev libfribidi-dev libgtk-3-dev libjpeg-dev libxml2-dev
- name: Checkout repository
uses: actions/checkout@v6
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
- name: Build
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
make -j$(nproc)
smooth-0.9.11~git20260403.0230c0da/.gitignore 0000664 0000000 0000000 00000000451 15164025770 0017750 0 ustar 00root root 0000000 0000000 # Ignore artifacts created during build.
BuildNumber
*.[oa]
*.so
*.so.*
*.dylib
*.dll
*.exe
*.pyc
bin/*
bin64/*
lib/*
lib64/*
libraries/v8/libraries.cc
libraries/v8/experimental-libraries.cc
msvc/**/.vs/*
msvc/**/Debug/*
msvc/**/Release/*
msvc/**/*.VC.*
msvc/**/*.vcxproj.user
smooth-0.9.11~git20260403.0230c0da/ChangeLog 0000664 0000000 0000000 00000001356 15164025770 0017537 0 ustar 00root root 0000000 0000000 ChangeLog for smooth
dd.mm.yy hh:mm - smooth alpha 0.9.11
- bitmaphaiku.cpp - fixed bitmap transparency issues
- filedlg_gtk.cpp - fixed GTK file dialog appearing in the background on X11 systems
- timerposix.cpp - fixed potential deadlocks when using POSIX timers with GLib/GTK
- fixed crash querying CPU info on systems without affinity setting support in libcpuid
- fixed compilation with Xcode 16.3 and later toolchains
- upgraded fribidi to version 1.0.16
- upgraded libcpuid to version 0.8.0
- upgraded libxml2 to version 2.15.1
- upgraded libcurl to version 8.11.0
- upgraded libiconv to version 1.19
- upgraded libpng to version 1.6.56
- upgraded libwebp to version 1.6.0
- upgraded zlib to version 1.3.2
- upgraded libjpeg to version 10
smooth-0.9.11~git20260403.0230c0da/Copying 0000664 0000000 0000000 00000021615 15164025770 0017320 0 ustar 00root root 0000000 0000000 The Artistic License 2.0
Copyright (c) 2000-2006, The Perl Foundation.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
This license establishes the terms under which a given free software
Package may be copied, modified, distributed, and/or redistributed.
The intent is that the Copyright Holder maintains some artistic
control over the development of that Package while still keeping the
Package available as open source and free software.
You are always permitted to make arrangements wholly outside of this
license directly with the Copyright Holder of a given Package. If the
terms of this license do not permit the full use that you propose to
make of the Package, you should contact the Copyright Holder and seek
a different licensing arrangement.
Definitions
"Copyright Holder" means the individual(s) or organization(s)
named in the copyright notice for the entire Package.
"Contributor" means any party that has contributed code or other
material to the Package, in accordance with the Copyright Holder's
procedures.
"You" and "your" means any person who would like to copy,
distribute, or modify the Package.
"Package" means the collection of files distributed by the
Copyright Holder, and derivatives of that collection and/or of
those files. A given Package may consist of either the Standard
Version, or a Modified Version.
"Distribute" means providing a copy of the Package or making it
accessible to anyone else, or in the case of a company or
organization, to others outside of your company or organization.
"Distributor Fee" means any fee that you charge for Distributing
this Package or providing support for this Package to another
party. It does not mean licensing fees.
"Standard Version" refers to the Package if it has not been
modified, or has been modified only in ways explicitly requested
by the Copyright Holder.
"Modified Version" means the Package, if it has been changed, and
such changes were not explicitly requested by the Copyright
Holder.
"Original License" means this Artistic License as Distributed with
the Standard Version of the Package, in its current version or as
it may be modified by The Perl Foundation in the future.
"Source" form means the source code, documentation source, and
configuration files for the Package.
"Compiled" form means the compiled bytecode, object code, binary,
or any other form resulting from mechanical transformation or
translation of the Source form.
Permission for Use and Modification Without Distribution
(1) You are permitted to use the Standard Version and create and use
Modified Versions for any purpose without restriction, provided that
you do not Distribute the Modified Version.
Permissions for Redistribution of the Standard Version
(2) You may Distribute verbatim copies of the Source form of the
Standard Version of this Package in any medium without restriction,
either gratis or for a Distributor Fee, provided that you duplicate
all of the original copyright notices and associated disclaimers. At
your discretion, such verbatim copies may or may not include a
Compiled form of the Package.
(3) You may apply any bug fixes, portability changes, and other
modifications made available from the Copyright Holder. The resulting
Package will still be considered the Standard Version, and as such
will be subject to the Original License.
Distribution of Modified Versions of the Package as Source
(4) You may Distribute your Modified Version as Source (either gratis
or for a Distributor Fee, and with or without a Compiled form of the
Modified Version) provided that you clearly document how it differs
from the Standard Version, including, but not limited to, documenting
any non-standard features, executables, or modules, and provided that
you do at least ONE of the following:
(a) make the Modified Version available to the Copyright Holder
of the Standard Version, under the Original License, so that the
Copyright Holder may include your modifications in the Standard
Version.
(b) ensure that installation of your Modified Version does not
prevent the user installing or running the Standard Version. In
addition, the Modified Version must bear a name that is different
from the name of the Standard Version.
(c) allow anyone who receives a copy of the Modified Version to
make the Source form of the Modified Version available to others
under
(i) the Original License or
(ii) a license that permits the licensee to freely copy,
modify and redistribute the Modified Version using the same
licensing terms that apply to the copy that the licensee
received, and requires that the Source form of the Modified
Version, and of any works derived from it, be made freely
available in that license fees are prohibited but Distributor
Fees are allowed.
Distribution of Compiled Forms of the Standard Version
or Modified Versions without the Source
(5) You may Distribute Compiled forms of the Standard Version without
the Source, provided that you include complete instructions on how to
get the Source of the Standard Version. Such instructions must be
valid at the time of your distribution. If these instructions, at any
time while you are carrying out such distribution, become invalid, you
must provide new instructions on demand or cease further distribution.
If you provide valid instructions or cease distribution within thirty
days after you become aware that the instructions are invalid, then
you do not forfeit any of your rights under this license.
(6) You may Distribute a Modified Version in Compiled form without
the Source, provided that you comply with Section 4 with respect to
the Source of the Modified Version.
Aggregating or Linking the Package
(7) You may aggregate the Package (either the Standard Version or
Modified Version) with other packages and Distribute the resulting
aggregation provided that you do not charge a licensing fee for the
Package. Distributor Fees are permitted, and licensing fees for other
components in the aggregation are permitted. The terms of this license
apply to the use and Distribution of the Standard or Modified Versions
as included in the aggregation.
(8) You are permitted to link Modified and Standard Versions with
other works, to embed the Package in a larger work of your own, or to
build stand-alone binary or bytecode versions of applications that
include the Package, and Distribute the result without restriction,
provided the result does not expose a direct interface to the Package.
Items That are Not Considered Part of a Modified Version
(9) Works (including, but not limited to, modules and scripts) that
merely extend or make use of the Package, do not, by themselves, cause
the Package to be a Modified Version. In addition, such works are not
considered parts of the Package itself, and are not subject to the
terms of this license.
General Provisions
(10) Any use, modification, and distribution of the Standard or
Modified Versions is governed by this Artistic License. By using,
modifying or distributing the Package, you accept this license. Do not
use, modify, or distribute the Package, if you do not accept this
license.
(11) If your Modified Version has been derived from a Modified
Version made by someone other than you, you are nevertheless required
to ensure that your Modified Version complies with the requirements of
this license.
(12) This license does not grant you the right to use any trademark,
service mark, tradename, or logo of the Copyright Holder.
(13) This license includes the non-exclusive, worldwide,
free-of-charge patent license to make, have made, use, offer to sell,
sell, import and otherwise transfer the Package with respect to any
patent claims licensable by the Copyright Holder that are necessarily
infringed by the Package. If you institute patent litigation
(including a cross-claim or counterclaim) against any party alleging
that the Package constitutes direct or contributory patent
infringement, then this Artistic License to you shall terminate on the
date that such litigation is filed.
(14) Disclaimer of Warranty:
THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. smooth-0.9.11~git20260403.0230c0da/Makefile 0000664 0000000 0000000 00000041612 15164025770 0017424 0 ustar 00root root 0000000 0000000 # Makefile for smooth v0.9
SMOOTH_PATH = .
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
### Object files ###
OBJECTS = classes/backends/backend.o
OBJECTS += classes/basic/object.o classes/basic/objecttype.o classes/basic/setup.o
OBJECTS += classes/errors/error.o classes/errors/success.o
OBJECTS += classes/errors/fs/endoffile.o classes/errors/fs/filenotfound.o
OBJECTS += classes/errors/misc/permissiondenied.o
OBJECTS += classes/files/directory.o classes/files/file.o
OBJECTS += classes/graphics/bitmap.o classes/graphics/color.o classes/graphics/font.o classes/graphics/surface.o
OBJECTS += classes/graphics/backends/bitmapbackend.o classes/graphics/backends/fontbackend.o classes/graphics/backends/surfacebackend.o
OBJECTS += classes/graphics/forms/rect.o
OBJECTS += classes/graphics/imageloader/imageloader.o classes/graphics/imageloader/jpeg.o classes/graphics/imageloader/pci.o classes/graphics/imageloader/png.o classes/graphics/imageloader/webp.o
OBJECTS += classes/graphics/modifiers/fontsize.o classes/graphics/modifiers/righttoleft.o
OBJECTS += classes/gui/application/application.o
OBJECTS += classes/gui/clipboard/clipboard.o
OBJECTS += classes/gui/clipboard/backends/clipboardbackend.o
OBJECTS += classes/gui/dialogs/colordlg.o classes/gui/dialogs/dialog.o classes/gui/dialogs/fontdlg.o classes/gui/dialogs/messagebox.o classes/gui/dialogs/splashscreen.o classes/gui/dialogs/tipodaydlg.o
OBJECTS += classes/gui/dialogs/directory/dirdlg.o
OBJECTS += classes/gui/dialogs/file/filedlg.o
OBJECTS += classes/gui/dialogs/icons/light.o
OBJECTS += classes/gui/widgets/layer.o classes/gui/widgets/widget.o
OBJECTS += classes/gui/widgets/basic/activearea.o classes/gui/widgets/basic/arrows.o classes/gui/widgets/basic/button.o classes/gui/widgets/basic/checkbox.o classes/gui/widgets/basic/client.o classes/gui/widgets/basic/divider.o classes/gui/widgets/basic/editbox.o classes/gui/widgets/basic/groupbox.o classes/gui/widgets/basic/hyperlink.o classes/gui/widgets/basic/image.o classes/gui/widgets/basic/multiedit.o classes/gui/widgets/basic/optionbox.o classes/gui/widgets/basic/progressbar.o classes/gui/widgets/basic/scrollbar.o classes/gui/widgets/basic/slider.o classes/gui/widgets/basic/statusbar.o classes/gui/widgets/basic/tabwidget.o classes/gui/widgets/basic/text.o classes/gui/widgets/basic/titlebar.o
OBJECTS += classes/gui/widgets/hotspot/hotspot.o classes/gui/widgets/hotspot/simplebutton.o
OBJECTS += classes/gui/widgets/multi/generic/container.o classes/gui/widgets/multi/generic/entry.o
OBJECTS += classes/gui/widgets/multi/image/imagebox.o classes/gui/widgets/multi/image/imageentry.o
OBJECTS += classes/gui/widgets/multi/list/combobox.o classes/gui/widgets/multi/list/list.o classes/gui/widgets/multi/list/listbox.o classes/gui/widgets/multi/list/listboxheader.o classes/gui/widgets/multi/list/listentry.o classes/gui/widgets/multi/list/listentryseparator.o
OBJECTS += classes/gui/widgets/multi/menu/menu.o classes/gui/widgets/multi/menu/menubar.o classes/gui/widgets/multi/menu/menubarentry.o classes/gui/widgets/multi/menu/menuentry.o classes/gui/widgets/multi/menu/micromenu.o classes/gui/widgets/multi/menu/popupmenu.o classes/gui/widgets/multi/menu/popupmenuentry.o classes/gui/widgets/multi/menu/popupmenuentrycheck.o classes/gui/widgets/multi/menu/popupmenuentryoption.o
OBJECTS += classes/gui/widgets/multi/tree/tree.o
OBJECTS += classes/gui/widgets/special/cursor.o classes/gui/widgets/special/dragcontrol.o classes/gui/widgets/special/droparea.o classes/gui/widgets/special/shortcut.o classes/gui/widgets/special/tooltip.o
OBJECTS += classes/gui/window/toolwindow.o classes/gui/window/window.o
OBJECTS += classes/gui/window/backends/windowbackend.o
OBJECTS += classes/i18n/language.o classes/i18n/number.o classes/i18n/section.o classes/i18n/translator.o classes/i18n/translator_internal.o
OBJECTS += classes/input/keyboard.o classes/input/pointer.o
OBJECTS += classes/input/backends/pointerbackend.o
OBJECTS += classes/io/driver.o classes/io/filter.o classes/io/instream.o classes/io/outstream.o classes/io/stream.o
OBJECTS += classes/io/drivers/driver_ansi.o classes/io/drivers/driver_https.o classes/io/drivers/driver_memory.o classes/io/drivers/driver_posix.o classes/io/drivers/driver_socket.o classes/io/drivers/driver_socks4.o classes/io/drivers/driver_socks5.o classes/io/drivers/driver_zero.o
OBJECTS += classes/io/filters/filter_bzip2.o classes/io/filters/filter_xor.o
OBJECTS += classes/misc/args.o classes/misc/array.o classes/misc/binary.o classes/misc/config.o classes/misc/datetime.o classes/misc/math.o classes/misc/memory.o classes/misc/number.o classes/misc/string.o classes/misc/string_case.o
OBJECTS += classes/misc/encoding/base64.o classes/misc/encoding/urlencode.o
OBJECTS += classes/misc/hash/crc16.o classes/misc/hash/crc32.o classes/misc/hash/crc64.o classes/misc/hash/md5.o classes/misc/hash/sha1.o
OBJECTS += classes/net/protocols/file.o classes/net/protocols/http.o classes/net/protocols/protocol.o
OBJECTS += classes/system/console.o classes/system/cpu.o classes/system/dynamicloader.o classes/system/event.o classes/system/screen.o classes/system/system.o classes/system/timer.o
OBJECTS += classes/system/backends/eventbackend.o classes/system/backends/screenbackend.o classes/system/backends/timerbackend.o
OBJECTS += classes/threads/access.o classes/threads/mutex.o classes/threads/rwlock.o classes/threads/semaphore.o classes/threads/thread.o
OBJECTS += classes/threads/backends/mutexbackend.o classes/threads/backends/semaphorebackend.o classes/threads/backends/threadbackend.o
OBJECTS += classes/xml/attribute.o classes/xml/document.o classes/xml/node.o
OBJECTS += classes/xml/xul/box.o classes/xml/xul/button.o classes/xml/xul/description.o classes/xml/xul/label.o classes/xml/xul/menubar.o classes/xml/xul/popupmenu.o classes/xml/xul/renderer.o classes/xml/xul/textbox.o classes/xml/xul/widget.o classes/xml/xul/window.o
OBJECTS += misc/codecs.o misc/init.o misc/pciio.o
ifeq ($(BUILD_WIN32),True)
OBJECTS += classes/backends/win32/backendwin32.o
OBJECTS += classes/graphics/imageloader/icon.o
OBJECTS += classes/gui/application/xulloader.o
OBJECTS += classes/gui/clipboard/backends/win32/clipboardwin32.o
OBJECTS += classes/gui/dialogs/directory/dirdlg_win32.o
OBJECTS += classes/gui/dialogs/file/filedlg_win32.o
OBJECTS += classes/gui/window/backends/gdi/droptarget.o classes/gui/window/backends/gdi/windowgdi.o
OBJECTS += classes/input/backends/win32/pointerwin32.o
OBJECTS += classes/io/drivers/driver_win32.o
OBJECTS += classes/system/backends/win32/eventwin32.o classes/system/backends/win32/screenwin32.o classes/system/backends/win32/timerwin32.o
OBJECTS += classes/threads/backends/win32/mutexwin32.o classes/threads/backends/win32/semaphorewin32.o classes/threads/backends/win32/threadwin32.o
ifeq ($(BUILD_GDIPLUS),True)
OBJECTS += classes/backends/gdiplus/backendgdiplus.o
OBJECTS += classes/graphics/backends/gdiplus/bitmapgdiplus.o classes/graphics/backends/gdiplus/fontgdiplus.o classes/graphics/backends/gdiplus/surfacegdiplus.o
else
OBJECTS += classes/graphics/backends/gdi/bitmapgdi.o classes/graphics/backends/gdi/fontgdi.o classes/graphics/backends/gdi/surfacegdi.o
endif
else ifeq ($(BUILD_OSX),True)
OBJECTS += classes/backends/cocoa/backendcocoa.o
OBJECTS += classes/graphics/backends/cocoa/bitmapcocoa.o classes/graphics/backends/cocoa/fontcocoa.o classes/graphics/backends/cocoa/surfacecocoa.o
OBJECTS += classes/gui/clipboard/backends/cocoa/clipboardcocoa.o
OBJECTS += classes/gui/dialogs/directory/dirdlg_cocoa.o
OBJECTS += classes/gui/dialogs/file/filedlg_cocoa.o
OBJECTS += classes/gui/widgets/multi/menu/menubar_cocoa.o
OBJECTS += classes/gui/window/backends/cocoa/windowcocoa.o
OBJECTS += classes/input/backends/cocoa/pointercocoa.o
OBJECTS += classes/system/backends/cocoa/eventcocoa.o classes/system/backends/cocoa/screencocoa.o classes/system/backends/cocoa/timercocoa.o
else ifeq ($(BUILD_HAIKU),True)
OBJECTS += classes/backends/haiku/backendhaiku.o
OBJECTS += classes/graphics/backends/haiku/bitmaphaiku.o classes/graphics/backends/haiku/fonthaiku.o classes/graphics/backends/haiku/surfacehaiku.o
OBJECTS += classes/gui/clipboard/backends/haiku/clipboardhaiku.o
OBJECTS += classes/gui/dialogs/directory/dirdlg_haiku.o
OBJECTS += classes/gui/dialogs/file/filedlg_haiku.o
OBJECTS += classes/gui/window/backends/haiku/windowhaiku.o
OBJECTS += classes/input/backends/haiku/pointerhaiku.o
OBJECTS += classes/system/backends/haiku/eventhaiku.o classes/system/backends/haiku/screenhaiku.o classes/system/backends/haiku/timerhaiku.o
else
OBJECTS += classes/gui/dialogs/directory/dirdlg_gtk.o
OBJECTS += classes/gui/dialogs/file/filedlg_gtk.o
endif
ifeq ($(BUILD_XLIB),True)
OBJECTS += classes/backends/xlib/backendxlib.o
OBJECTS += classes/graphics/backends/xlib/bitmapxlib.o
OBJECTS += classes/gui/clipboard/backends/xlib/clipboardxlib.o
OBJECTS += classes/gui/window/backends/xlib/windowxlib.o
OBJECTS += classes/input/backends/xlib/pointerxlib.o
OBJECTS += classes/system/backends/xlib/eventxlib.o classes/system/backends/xlib/screenxlib.o
ifeq ($(BUILD_CAIRO),True)
OBJECTS += classes/graphics/backends/cairo/fontcairo.o classes/graphics/backends/cairo/surfacecairo.o
else
OBJECTS += classes/graphics/backends/xlib/fontxlib.o classes/graphics/backends/xlib/surfacexlib.o
endif
endif
ifeq ($(BUILD_POSIXTIMER),True)
OBJECTS += classes/system/backends/posix/timerposix.o
else ifeq ($(BUILD_THREADSTIMER),True)
OBJECTS += classes/system/backends/threads/timerthreads.o
endif
ifeq ($(BUILD_POSIXTHREADS),True)
OBJECTS += classes/threads/backends/posix/mutexposix.o classes/threads/backends/posix/semaphoreposix.o
ifeq ($(BUILD_OSX),True)
OBJECTS += classes/threads/backends/cocoa/threadcocoa.o
else
OBJECTS += classes/threads/backends/posix/threadposix.o
endif
endif
### Output options ###
LIBS =
ifeq ($(USE_BUNDLED_LIBBZ2),True)
LIBS += $(LIBDIR)/libbz2.a
else
LIBS += -lbz2
endif
ifeq ($(USE_BUNDLED_LIBCPUID),True)
LIBS += $(LIBDIR)/libcpuid.a
else
LIBS += -lcpuid
endif
ifeq ($(USE_BUNDLED_LIBCURL),True)
LIBS += $(LIBDIR)/libcurl.a
ifeq ($(BUILD_WIN32),True)
LIBS += -lwldap32 -lcrypt32 -lbcrypt
else ifeq ($(BUILD_OSX),True)
LIBS += -framework Security -lldap
endif
else ifeq ($(BUILD_OSX),True)
LIBS += -lcurl
else
LIBS += $(shell pkg-config --libs libcurl)
endif
ifeq ($(USE_BUNDLED_LIBFRIBIDI),True)
LIBS += $(LIBDIR)/libfribidi.a
else
LIBS += -lfribidi
endif
ifeq ($(USE_BUNDLED_LIBICONV),True)
LIBS += $(LIBDIR)/libiconv.a
else ifeq ($(BUILD_OSX),True)
LIBS += -liconv
else ifeq ($(BUILD_HAIKU),True)
LIBS += -liconv
endif
ifeq ($(USE_BUNDLED_LIBJPEG),True)
LIBS += $(LIBDIR)/libjpeg.a
else
LIBS += -ljpeg
endif
ifeq ($(USE_BUNDLED_LIBPNG),True)
LIBS += $(LIBDIR)/libpng.a
else ifeq ($(BUILD_WIN32),True)
LIBS += -lpng
else ifeq ($(BUILD_OSX),True)
LIBS += -lpng
else ifeq ($(BUILD_HAIKU),True)
LIBS += -lpng
else
LIBS += $(shell pkg-config --libs libpng)
endif
ifeq ($(USE_BUNDLED_LIBWEBP),True)
LIBS += $(LIBDIR)/libwebp.a
else
LIBS += $(shell pkg-config --libs libwebp)
endif
ifeq ($(USE_BUNDLED_LIBXML2),True)
LIBS += $(LIBDIR)/libxml2.a
else
LIBS += -lxml2
endif
ifeq ($(USE_BUNDLED_ZLIB),True)
LIBS += $(LIBDIR)/libz.a
else
LIBS += -lz
endif
ifeq ($(BUILD_WIN32),True)
OBJECTS += resources/resources.o
ifneq ($(BUILD_GDIPLUS),True)
LIBS += -lmsimg32
else
LIBS += -lgdiplus
endif
LIBS += -lws2_32 -limm32 -lole32 -luuid
DLLNAME = $(BINDIR)/smooth$(SHARED)
LIBNAME = $(LIBDIR)/libsmooth.a
else ifeq ($(BUILD_OSX),True)
LIBS += -lpthread
DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED)
else ifeq ($(BUILD_HAIKU),True)
LIBS += -lbe -ltracker -lnetwork
DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED)
else
ifeq ($(BUILD_FREEBSD),True)
LIBS += -lrt
else ifeq ($(BUILD_LINUX),True)
LIBS += -lrt
else ifeq ($(BUILD_OPENBSD),True)
LIBS += -lXau -lXdmcp -lXxf86vm -lSM -lICE -lffi -ldrm -lpcre
endif
ifneq ($(BUILD_CAIRO),True)
LIBS += $(shell pkg-config --libs xft)
endif
LIBS += -lpthread
LIBS += $(shell pkg-config --libs gtk+-x11-3.0)
DLLNAME = $(LIBDIR)/libsmooth-$(VERSION)$(SHARED)
endif
### Linker options ###
REMOVE = rm
LINKER_OPTS = -L$(LIBDIR) -o $(DLLNAME)
REMOVE_OPTS = -f
ifeq ($(BUILD_WIN32),True)
LINKER_OPTS += --shared -mwindows -Wl,--dynamicbase,--nxcompat,--kill-at,--out-implib,$(LIBNAME)
else ifeq ($(BUILD_OSX),True)
LINKER_OPTS += -dynamiclib -framework Carbon -framework Cocoa -Wl,-dylib_install_name,libsmooth-$(VERSION).$(REVISION)$(SHARED)
else
LINKER_OPTS += --shared -Wl,-soname,libsmooth-$(VERSION)$(SHARED).$(REVISION)
ifeq ($(BUILD_FREEBSD),True)
LINKER_OPTS += -L/usr/local/lib
else ifeq ($(BUILD_OPENBSD),True)
LINKER_OPTS += -Wl,-rpath,/usr/local/lib -L/usr/local/lib -Wl,-rpath,/usr/X11R6/lib -L/usr/X11R6/lib
else ifeq ($(BUILD_NETBSD),True)
LINKER_OPTS += -Wl,-rpath,/usr/pkg/lib -L/usr/pkg/lib -Wl,-rpath,/usr/X11R7/lib -L/usr/X11R7/lib
endif
endif
### Install options ###
COPY = cp
LINK = ln
CHMOD = chmod
### Targets ###
.PHONY: all codesign folders objects lib programs libs install uninstall clean distclean doc doc-clean
all: lib programs
folders:
mkdir -p $(SMOOTH_PATH)/$(BINDIR) $(SMOOTH_PATH)/$(LIBDIR)
objects:
+ $(call makein,classes)
+ $(call makein,misc)
+ $(call makein,resources)
lib: folders $(DLLNAME)
programs: lib
+ $(call makein,tools)
+ $(call makein,samples)
libs:
+ $(call makein,libraries)
codesign: all
signtool sign -fd sha1 -tr http://timestamp.digicert.com -td sha1 $(BINDIR)/smooth*.dll $(BINDIR)/translator.exe
signtool sign -fd sha256 -tr http://timestamp.digicert.com -td sha256 -as $(BINDIR)/smooth*.dll $(BINDIR)/translator.exe
install: all
ifneq ($(BUILD_WIN32),True)
$(INSTALL) -d "$(DESTDIR)"$(libdir)
ifneq ($(BUILD_OSX),True)
$(INSTALL_DATA) $(DLLNAME) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED).$(REVISION)
$(LINK) -fs libsmooth-$(VERSION)$(SHARED).$(REVISION) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED)
ifeq ($(BUILD_V8),True)
$(INSTALL_DATA) $(LIBDIR)/libsmooth-js-$(VERSION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED).$(REVISION)
$(LINK) -fs libsmooth-js-$(VERSION)$(SHARED).$(REVISION) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED)
endif
ifneq ($(BUILD_SOLARIS),True)
ifneq ($(BUILD_HAIKU),True)
ifeq ("$(DESTDIR)","")
$(LDCONFIG) 2> /dev/null || true
endif
endif
endif
else
$(INSTALL_DATA) $(DLLNAME) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION).$(REVISION)$(SHARED)
$(LINK) -fs libsmooth-$(VERSION).$(REVISION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED)
ifeq ($(BUILD_V8),True)
$(INSTALL_DATA) $(LIBDIR)/libsmooth-js-$(VERSION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION).$(REVISION)$(SHARED)
$(LINK) -fs libsmooth-js-$(VERSION).$(REVISION)$(SHARED) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED)
endif
endif
$(INSTALL) -d "$(DESTDIR)"$(bindir)
$(INSTALL_PROGRAM) $(BINDIR)/translator "$(DESTDIR)"$(bindir)/smooth-translator
$(INSTALL) -d "$(DESTDIR)"$(includedir)
$(COPY) -r "$(SRCDIR)"/include/smooth "$(DESTDIR)"$(includedir)
$(CHMOD) -R a=rX,u=rwX "$(DESTDIR)"$(includedir)/smooth
ifeq ($(BUILD_V8),True)
$(COPY) -r "$(SRCDIR)"/include/smooth-js "$(DESTDIR)"$(includedir)
$(CHMOD) -R a=rX,u=rwX "$(DESTDIR)"$(includedir)/smooth-js
endif
$(INSTALL_DATA) "$(SRCDIR)"/include/smooth.h "$(DESTDIR)"$(includedir)
endif
uninstall:
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED).$(REVISION)
ifeq ($(BUILD_V8),True)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED).$(REVISION)
endif
ifneq ($(BUILD_SOLARIS),True)
ifneq ($(BUILD_HAIKU),True)
ifeq ("$(DESTDIR)","")
$(LDCONFIG) 2> /dev/null || true
endif
endif
endif
else
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION)$(SHARED)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-$(VERSION).$(REVISION)$(SHARED)
ifeq ($(BUILD_V8),True)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION)$(SHARED)
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(libdir)/libsmooth-js-$(VERSION).$(REVISION)$(SHARED)
endif
endif
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(bindir)/smooth-translator
$(REMOVE) $(REMOVE_OPTS) -r "$(DESTDIR)"$(includedir)/smooth
ifeq ($(BUILD_V8),True)
$(REMOVE) $(REMOVE_OPTS) -r "$(DESTDIR)"$(includedir)/smooth-js
endif
$(REMOVE) $(REMOVE_OPTS) "$(DESTDIR)"$(includedir)/smooth.h
endif
clean:
$(call cleanin,classes)
$(call cleanin,misc)
$(call cleanin,resources)
$(call cleanin,tools)
$(call cleanin,samples)
$(REMOVE) $(REMOVE_OPTS) $(DLLNAME) $(LIBNAME)
distclean: clean
$(call cleanin,libraries)
ifneq ("$(SRCDIR)","$(CURDIR)")
rmdir $(SMOOTH_PATH)/$(BINDIR) $(SMOOTH_PATH)/$(LIBDIR) || true
endif
doc: doc-clean
doxys
doc-clean:
rm -r -f doc/reference
$(OBJECTS): objects
$(DLLNAME): $(OBJECTS) | libs
$(LD) $(OBJECTS) $(LINKER_OPTS) $(LDFLAGS) $(LIBS)
ifeq ($(findstring release,$(config)),release)
-countbuild BuildNumber
endif
smooth-0.9.11~git20260403.0230c0da/Makefile-commands 0000664 0000000 0000000 00000007531 15164025770 0021225 0 ustar 00root root 0000000 0000000 ########## smooth commands makefile ##########
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
CCOPTS = -I"$(SRCDIR)"/$(SMOOTH_PATH)/include $(MYCCOPTS)
RC = windres
RCOPTS = -DSMOOTH_DLL -O coff
LDOPTS = -L"$(SRCDIR)"/$(SMOOTH_PATH)/$(LIBDIR) $(LIBS)
ifndef GLOBALDLL
CCOPTS += -fvisibility=hidden
ifeq ($(BUILD_WIN32),True)
LDOPTS += -lsmooth
else
LDOPTS += -lsmooth-$(VERSION)
endif
endif
ifeq ($(BUILD_WIN32),True)
CCOPTS += -DUNICODE -D_UNICODE
LDOPTS += -mwindows -Wl,--dynamicbase,--nxcompat
ifdef IMPORTLIB
ifdef GLOBALDLL
LDOPTS += -Wl,--out-implib,$(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB)
else
LDOPTS += -Wl,--out-implib,$(IMPORTLIB)
endif
endif
ifeq ($(BUILD_X86),True)
RCOPTS += --target=pe-i386
else ifeq ($(BUILD_X86_64),True)
RCOPTS += --target=pe-x86-64
else ifeq ($(BUILD_ARM64),True)
RC = aarch64-w64-mingw32-windres
endif
else
CCOPTS += -fPIC
ifneq ($(BUILD_SOLARIS),True)
ifneq ($(BUILD_HAIKU),True)
CCOPTS += -pthread
endif
endif
ifdef GLOBALDLL
ifeq ($(BUILD_OSX),True)
LDOPTS += -Wl,-dylib_install_name,lib$(GLOBALDLL)-$(VERSION).$(REVISION)$(SHARED)
else
LDOPTS += -Wl,-soname,lib$(GLOBALDLL)-$(VERSION)$(SHARED).$(REVISION)
endif
endif
ifeq ($(BUILD_OPENBSD),True)
LDOPTS += -L/usr/X11R6/lib -L/usr/local/lib
endif
endif
ifndef GLOBALLIB
ifndef GLOBALEXE
ifndef GLOBALDLL
ifndef LOCALEXE
ifndef LOCALDLL
CCOPTS += -DSMOOTH_DLL
endif
endif
endif
endif
endif
.SUFFIXES: .mm .rc
TARGETS =
ifdef GLOBALLIB
TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/$(GLOBALLIB)
endif
ifdef GLOBALEXE
TARGETS += $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALEXE)$(EXECUTABLE)
endif
ifdef GLOBALDLL
ifeq ($(BUILD_WIN32),True)
TARGETS += $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED)
TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB)
else
TARGETS += $(SMOOTH_PATH)/$(LIBDIR)/lib$(GLOBALDLL)-$(VERSION)$(SHARED)
endif
endif
ifdef LOCALEXE
TARGETS += $(LOCALEXE)$(EXECUTABLE)
endif
ifdef LOCALDLL
TARGETS += $(LOCALDLL)$(SHARED)
ifeq ($(BUILD_WIN32),True)
TARGETS += $(IMPORTLIB)
endif
endif
all: allcmds $(OBJECTS) $(TARGETS)
allcmds:
+ $(ALLCMD1)
+ $(ALLCMD2)
+ $(ALLCMD3)
+ $(ALLCMD4)
clean:
ifdef OBJECTS
rm -f $(OBJECTS)
endif
ifdef TARGETS
rm -f $(TARGETS)
endif
$(CLEANCMD1)
$(CLEANCMD2)
$(CLEANCMD3)
$(CLEANCMD4)
.c.o:
$(CC) $(CCOPTS) $(CFLAGS) -c $< -o $@
.cc.o:
$(CXX) $(CCOPTS) $(CXXFLAGS) -c $< -o $@
.cpp.o:
$(CXX) $(CCOPTS) $(CXXFLAGS) -c $< -o $@
.m.o:
$(OBJC) $(CCOPTS) $(OBJCFLAGS) -c $< -o $@
.mm.o:
$(OBJCXX) $(CCOPTS) $(OBJCXXFLAGS) -c $< -o $@
.rc.o:
$(RC) $(RCOPTS) $< -o $@
ifdef GLOBALLIB
$(SMOOTH_PATH)/$(LIBDIR)/$(GLOBALLIB): $(OBJECTS)
mkdir -p $(SMOOTH_PATH)/$(LIBDIR)
$(AR) rs $@ $(OBJECTS)
endif
ifdef GLOBALEXE
$(SMOOTH_PATH)/$(BINDIR)/$(GLOBALEXE)$(EXECUTABLE): $(OBJECTS)
mkdir -p $(SMOOTH_PATH)/$(BINDIR)
$(LD) -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
endif
ifdef GLOBALDLL
ifeq ($(BUILD_WIN32),True)
$(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED): $(OBJECTS)
mkdir -p $(SMOOTH_PATH)/$(BINDIR)
else
$(SMOOTH_PATH)/$(LIBDIR)/lib$(GLOBALDLL)-$(VERSION)$(SHARED): $(OBJECTS)
endif
mkdir -p $(SMOOTH_PATH)/$(LIBDIR)
ifneq ($(BUILD_OSX),True)
$(LD) --shared -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
else
$(LD) -dynamiclib -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
endif
ifeq ($(BUILD_WIN32),True)
$(SMOOTH_PATH)/$(LIBDIR)/$(IMPORTLIB): $(SMOOTH_PATH)/$(BINDIR)/$(GLOBALDLL)$(SHARED)
endif
endif
ifdef LOCALEXE
$(LOCALEXE)$(EXECUTABLE): $(OBJECTS)
$(LD) -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
endif
ifdef LOCALDLL
$(LOCALDLL)$(SHARED): $(OBJECTS)
ifneq ($(BUILD_OSX),True)
$(LD) --shared -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
else
$(LD) -dynamiclib -o $@ $(OBJECTS) $(LDOPTS) $(LDFLAGS) $(LDFLAGS_TOOLS)
endif
ifeq ($(BUILD_WIN32),True)
$(IMPORTLIB): $(LOCALDLL)$(SHARED)
endif
endif
smooth-0.9.11~git20260403.0230c0da/Makefile-options 0000664 0000000 0000000 00000027212 15164025770 0021115 0 ustar 00root root 0000000 0000000 ########## smooth options makefile ##########
VERSION = 0.9
REVISION = 0
# Find source folder and set vpath
SRCDIR = $(abspath $(dir $(firstword $(MAKEFILE_LIST))))
vpath %.c "$(SRCDIR)"
vpath %.cc "$(SRCDIR)"
vpath %.cpp "$(SRCDIR)"
vpath %.m "$(SRCDIR)"
vpath %.mm "$(SRCDIR)"
vpath %.js "$(SRCDIR)"
vpath %.py "$(SRCDIR)"
vpath %.rc "$(SRCDIR)"
# Define makein and cleanin macros
ifeq ("$(SRCDIR)","$(CURDIR)")
makein = cd $(1) && $(MAKE) $(2) && cd ..
cleanin = cd $(1) && $(MAKE) clean && cd ..
else
makein = mkdir -p $(1) && cd $(1) && $(MAKE) -f "$(SRCDIR)"/$(1)/Makefile $(2) && cd ..
cleanin = mkdir -p $(1) && cd $(1) && $(MAKE) -f "$(SRCDIR)"/$(1)/Makefile clean && cd .. && (rmdir $(1) || true)
endif
# Find architecture and system
UNAME = $(shell uname)
MACHINE = $(shell $(CC) -dumpmachine)
ifneq ($(findstring arm,$(MACHINE)),)
ifneq ($(BUILD_ARM),False)
BUILD_ARM = True
endif
else ifneq ($(findstring aarch64,$(MACHINE)),)
ifneq ($(BUILD_ARM64),False)
BUILD_ARM64 = True
endif
else ifneq ($(findstring mips,$(MACHINE)),)
ifneq ($(BUILD_MIPS),False)
BUILD_MIPS = True
endif
else ifneq ($(findstring powerpc64,$(MACHINE)),)
ifneq ($(BUILD_PPC64),False)
BUILD_PPC64 = True
endif
else ifneq ($(findstring powerpc,$(MACHINE)),)
ifneq ($(BUILD_PPC),False)
BUILD_PPC = True
endif
else ifneq ($(findstring riscv64,$(MACHINE)),)
ifneq ($(BUILD_RISCV64),False)
BUILD_RISCV64 = True
endif
else ifneq ($(findstring x86_64,$(MACHINE)),)
ifneq ($(BUILD_ARM64),True)
ifneq ($(BUILD_X86),True)
ifneq ($(BUILD_X86_64),False)
BUILD_X86_64 = True
endif
endif
endif
else ifneq ($(findstring amd64,$(MACHINE)),)
ifneq ($(BUILD_ARM64),True)
ifneq ($(BUILD_X86),True)
ifneq ($(BUILD_X86_64),False)
BUILD_X86_64 = True
endif
endif
endif
else ifneq ($(findstring i586,$(MACHINE))$(findstring i686,$(MACHINE)),)
ifneq ($(BUILD_ARM64),True)
ifneq ($(BUILD_X86),False)
ifneq ($(BUILD_X86_64),True)
BUILD_X86 = True
endif
endif
endif
endif
# Disable threads based timers
BUILD_THREADSTIMER = False
# Do not build V8 JavaScript library by default
BUILD_V8 = False
# Treat MSYS and MinGW the same
ifneq ($(findstring MSYS,$(UNAME)),)
UNAME = MINGW
endif
ifneq ($(findstring MINGW,$(UNAME)),)
# Set executable and shared object extensions
EXECUTABLE = .exe
SHARED = .dll
# Build using Win32 backends
BUILD_WIN32 = True
# Disable GDI+ backend by default
BUILD_GDIPLUS = False
else
# Set executable and shared object extensions
EXECUTABLE =
SHARED = .so
BUILD_UNIX = True
# Build using XLib backends
BUILD_XLIB = True
# Build using Cairo graphics backend
BUILD_CAIRO = True
# Build using POSIX threads
BUILD_POSIXTHREADS = True
# Build using POSIX timers
BUILD_POSIXTIMER = True
ifeq ($(UNAME),Linux)
BUILD_LINUX = True
else ifeq ($(UNAME),FreeBSD)
BUILD_FREEBSD = True
else ifeq ($(UNAME),OpenBSD)
BUILD_OPENBSD = True
# Enable threads based timers
BUILD_POSIXTIMER = False
BUILD_THREADSTIMER = True
else ifeq ($(UNAME),NetBSD)
BUILD_NETBSD = True
else ifeq ($(UNAME),SunOS)
BUILD_SOLARIS = True
else ifeq ($(UNAME),Haiku)
BUILD_HAIKU = True
# Disable POSIX timer backend
BUILD_POSIXTIMER = False
# Disable XLib and Cairo backends
BUILD_XLIB = False
BUILD_CAIRO = False
else ifeq ($(UNAME),GNU)
BUILD_GNU = True
# Enable threads based timers
BUILD_POSIXTIMER = False
BUILD_THREADSTIMER = True
else ifeq ($(UNAME),Darwin)
# Set shared object extension
SHARED = .dylib
BUILD_OSX = True
# Disable XLib and Cairo backends
BUILD_XLIB = False
BUILD_CAIRO = False
# Disable POSIX timers
BUILD_POSIXTIMER = False
endif
endif
# Set default commands
ifndef OBJC
OBJC = $(CC)
endif
ifndef OBJCXX
OBJCXX = $(CXX)
endif
ifeq ($(LD),ld)
LD = $(CXX)
endif
LDCONFIG = /sbin/ldconfig
INSTALL = install
ifeq ($(BUILD_SOLARIS),True)
INSTALL = ginstall
endif
INSTALL_PROGRAM = $(INSTALL)
INSTALL_DATA = $(INSTALL) -m 644
# Set output folders
BINDIR = bin
LIBDIR = lib
ifeq ($(BUILD_WIN32),True)
ifeq ($(BUILD_X86_64),True)
BINDIR = bin64
LIBDIR = lib64
endif
endif
# Set install folders
ifndef prefix
prefix = /usr/local
ifeq ($(BUILD_HAIKU),True)
prefix = /system/non-packaged
endif
endif
bindir = $(prefix)/bin
libdir = $(prefix)/lib
includedir = $(prefix)/include
datadir = $(prefix)/share
ifeq ($(BUILD_HAIKU),True)
includedir = $(prefix)/develop/headers
datadir = $(prefix)/data
endif
# Decide which libraries to use
ifeq ($(findstring bundledlibbz2,$(config)),bundledlibbz2)
USE_BUNDLED_LIBBZ2 = True
else ifeq ($(findstring systemlibbz2,$(config)),systemlibbz2)
USE_BUNDLED_LIBBZ2 = False
else
ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBBZ2 = True
endif
endif
ifeq ($(findstring bundledlibcpuid,$(config)),bundledlibcpuid)
USE_BUNDLED_LIBCPUID = True
else ifeq ($(findstring systemlibcpuid,$(config)),systemlibcpuid)
USE_BUNDLED_LIBCPUID = False
else
USE_BUNDLED_LIBCPUID = True
endif
ifeq ($(findstring bundledlibcurl,$(config)),bundledlibcurl)
USE_BUNDLED_LIBCURL = True
else ifeq ($(findstring systemlibcurl,$(config)),systemlibcurl)
USE_BUNDLED_LIBCURL = False
else
ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBCURL = True
endif
endif
ifeq ($(findstring bundledlibfribidi,$(config)),bundledlibfribidi)
USE_BUNDLED_LIBFRIBIDI = True
else ifeq ($(findstring systemlibfribidi,$(config)),systemlibfribidi)
USE_BUNDLED_LIBFRIBIDI = False
else
ifeq ($(BUILD_OSX),True)
USE_BUNDLED_LIBFRIBIDI = True
else ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBFRIBIDI = True
endif
endif
ifeq ($(findstring bundledlibiconv,$(config)),bundledlibiconv)
USE_BUNDLED_LIBICONV = True
else ifeq ($(findstring systemlibiconv,$(config)),systemlibiconv)
USE_BUNDLED_LIBICONV = False
else
ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBICONV = True
endif
endif
ifeq ($(findstring bundledlibjpeg,$(config)),bundledlibjpeg)
USE_BUNDLED_LIBJPEG = True
else ifeq ($(findstring systemlibjpeg,$(config)),systemlibjpeg)
USE_BUNDLED_LIBJPEG = False
else
ifeq ($(BUILD_OSX),True)
USE_BUNDLED_LIBJPEG = True
else ifeq ($(BUILD_SOLARIS),True)
USE_BUNDLED_LIBJPEG = True
else ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBJPEG = True
endif
endif
ifeq ($(findstring bundledlibpng,$(config)),bundledlibpng)
USE_BUNDLED_LIBPNG = True
else ifeq ($(findstring systemlibpng,$(config)),systemlibpng)
USE_BUNDLED_LIBPNG = False
else
ifeq ($(BUILD_OSX),True)
USE_BUNDLED_LIBPNG = True
else ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBPNG = True
endif
endif
ifeq ($(findstring bundledlibwebp,$(config)),bundledlibwebp)
USE_BUNDLED_LIBWEBP = True
else ifeq ($(findstring systemlibwebp,$(config)),systemlibwebp)
USE_BUNDLED_LIBWEBP = False
else
USE_BUNDLED_LIBWEBP = True
endif
ifeq ($(findstring bundledlibxml2,$(config)),bundledlibxml2)
USE_BUNDLED_LIBXML2 = True
else ifeq ($(findstring systemlibxml2,$(config)),systemlibxml2)
USE_BUNDLED_LIBXML2 = False
else
ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_LIBXML2 = True
endif
endif
ifeq ($(findstring bundledzlib,$(config)),bundledzlib)
USE_BUNDLED_ZLIB = True
else ifeq ($(findstring systemzlib,$(config)),systemzlib)
USE_BUNDLED_ZLIB = False
else
ifeq ($(BUILD_OSX),True)
USE_BUNDLED_ZLIB = True
else ifeq ($(BUILD_WIN32),True)
USE_BUNDLED_ZLIB = True
endif
endif
# Set release specific options
ifeq ($(findstring release,$(config)),release)
ifeq ($(BUILD_FREEBSD),True)
override CC = clang
override CXX = clang++
override OBJC = clang
override OBJCXX = clang++
override LD = clang++
else ifeq ($(BUILD_OSX),True)
override CC = gcc
override CXX = g++
override OBJC = gcc
override OBJCXX = g++
override LD = g++
endif
override CFLAGS = -pipe -g0 -Wall
override CXXFLAGS =
override OBJCFLAGS =
override OBJCXXFLAGS =
override LDFLAGS = -pipe
ifneq ($(BUILD_SOLARIS),True)
override CFLAGS += -Os
endif
ifneq ($(RTTI),True)
ifneq ($(BUILD_HAIKU),True)
override CXXFLAGS += -fno-rtti
override OBJCXXFLAGS += -fno-rtti
endif
endif
ifneq ($(EXCEPTION),True)
override CXXFLAGS += -fno-exceptions
override OBJCXXFLAGS += -fno-exceptions
endif
ifeq ($(BUILD_OSX),True)
# Find macOS and Xcode version
XCODEVERSION = $(shell xcodebuild -version | head -n1)
MACOSVERSION = $(MACOSX_DEPLOYMENT_TARGET)
ifeq ($(MACOSVERSION),)
MACOSVERSION = $(shell sw_vers | awk '$$1 == "ProductVersion:" { print $$2 }')
endif
XCODE_LE3 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -le 3 ]; then echo True; fi")
XCODE_LE9 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -le 9 ]; then echo True; fi")
XCODE_EQ12 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -eq 12 ]; then echo True; fi")
XCODE_GE13 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#\#* }; if [ \$${v%%.*} -ge 13 ]; then echo True; fi")
XCODE_N_GE2 = $(shell bash -c "v='$(XCODEVERSION)'; v=\$${v\#*.}; if [ \$${v%%.*} -ge 2 ]; then echo True; fi")
MACOS_GE11 = $(shell bash -c "v='$(MACOSVERSION)'; if [ \$${v%%.*} -ge 11 ]; then echo True; fi")
# Build universal binaries
ifneq ($(BUILD_X86_64),False)
BUILD_X86_64 = True
endif
ifeq ($(XCODE_LE9),True)
ifneq ($(BUILD_X86),False)
BUILD_X86 = True
endif
ifeq ($(XCODE_LE3),True)
ifneq ($(BUILD_PPC),False)
BUILD_PPC = True
endif
endif
else ifeq ($(XCODE_EQ12),True)
ifeq ($(XCODE_N_GE2),True)
ifeq ($(MACOS_GE11),True)
ifneq ($(BUILD_ARM64),False)
BUILD_ARM64 = True
endif
endif
endif
else ifeq ($(XCODE_GE13),True)
ifeq ($(MACOS_GE11),True)
ifneq ($(BUILD_ARM64),False)
BUILD_ARM64 = True
endif
endif
endif
# Set build flags
override LDFLAGS += -Wl,-x
ifeq ($(BUILD_X86),True)
override CFLAGS += -arch i386 -Xarch_i386 -march=prescott
override LDFLAGS += -arch i386
endif
ifeq ($(BUILD_X86_64),True)
ifeq ($(MACOS_GE11),True)
override CFLAGS += -arch x86_64 -Xarch_x86_64 -march=haswell
else
override CFLAGS += -arch x86_64 -Xarch_x86_64 -march=core2
endif
override LDFLAGS += -arch x86_64
endif
ifeq ($(BUILD_PPC),True)
override CFLAGS += -arch ppc -Xarch_ppc -mcpu=G4
override LDFLAGS += -arch ppc
endif
ifeq ($(BUILD_PPC64),True)
override CFLAGS += -arch ppc64 -Xarch_ppc64 -mcpu=G5
override LDFLAGS += -arch ppc64
endif
ifeq ($(BUILD_ARM64),True)
override CFLAGS += -arch arm64
override LDFLAGS += -arch arm64
endif
else
override LDFLAGS += -s
ifeq ($(BUILD_X86),True)
override CFLAGS += -m32
override LDFLAGS += -m32
else ifeq ($(BUILD_X86_64),True)
override CFLAGS += -m64
override LDFLAGS += -m64
endif
endif
override CXXFLAGS += $(CFLAGS)
override OBJCFLAGS += $(CFLAGS)
override OBJCXXFLAGS += $(CFLAGS)
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
LDFLAGS_TOOLS += -Wl,-rpath,.
endif
endif
endif
# Set debug specific options
ifeq ($(findstring debug,$(config)),debug)
override CFLAGS = -pipe -g -Wall -DDEBUG
override CXXFLAGS =
override OBJCFLAGS =
override OBJCXXFLAGS =
override LDFLAGS = -pipe
ifneq ($(RTTI),True)
ifneq ($(BUILD_HAIKU),True)
override CXXFLAGS += -fno-rtti
override OBJCXXFLAGS += -fno-rtti
endif
endif
ifneq ($(EXCEPTION),True)
override CXXFLAGS += -fno-exceptions
override OBJCXXFLAGS += -fno-exceptions
endif
override CXXFLAGS += $(CFLAGS)
override OBJCFLAGS += $(CFLAGS)
override OBJCXXFLAGS += $(CFLAGS)
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
override LDFLAGS_TOOLS += -Wl,-rpath,.
endif
endif
endif
# Flags needed for Windows ARM64 toolchain
ifeq ($(BUILD_WIN32),True)
ifeq ($(BUILD_ARM64),True)
override CFLAGS += -target aarch64-w64-mingw32
override LDFLAGS += -target aarch64-w64-mingw32
endif
endif
# Clear config variable
config =
smooth-0.9.11~git20260403.0230c0da/Readme.md 0000664 0000000 0000000 00000003461 15164025770 0017503 0 ustar 00root root 0000000 0000000 The smooth Class Library
====================================================================================================
[](https://github.com/enzo1982/smooth/actions?query=workflow%3A%22Verify+build%22+branch%3Amaster) [](https://github.com/enzo1982/smooth/commits/master) [](https://github.com/enzo1982/smooth/blob/master/Copying)
_smooth_ is an object oriented C++ class library for Windows, macOS, Linux and most Unix-like operating systems. It provides basic functionality and platform support for applications and libraries.
Features provided by _smooth_ include:
- user interface API with various widgets
- simple to use multithreading API
- file and network IO interface
- completely transparent Unicode and software internationalization support
- a libxml2 based XML parser
Installation
------------
The following packages must be installed in order to compile _smooth_:
- libbz2 / libbzip2 development package
- libcurl development package
- libfribidi development package
- libgtk+3.0 development package
- libjpeg development package
- libxml2 development package
After installing these prerequisites, run `make` followed by `sudo make install` to compile and install _smooth_.
License
-------
_smooth_ is Free Software and is made available under the terms of "The Artistic License, Version 2.0".
----------------------------------------------------------------------------------------------------
The official _smooth_ homepage: http://www.smooth-project.org/
robert.kausch@freac.org,
Robert Kausch
smooth-0.9.11~git20260403.0230c0da/ToDo.xml 0000664 0000000 0000000 00000202617 15164025770 0017357 0 ustar 00root root 0000000 0000000
ToDo
---------
- save the last ~100 conversion results
- avoid calls to MultiByteToWideChar and WideCharToMultiByte
ToDo
---------
- replace smooth::Client with smooth::Canvas and allow direct drawing operations
ToDo
---------
- protected inheritance from Array<>
- pseudo signal (is a function returning a signal)
- real signals stored in the Array
- Int Add(Int id) { return Array::Add(signalTYPE(), id); }
- Int Remove(Int id) { return Array::Remove(id); }
- Signal0<Void> &operator ()(Int id) { return Array::GetReference(id); }
- can be filled like this
MultiSignal<Signal0<Void>> onSignal;
onSignal.Add(argument);
onSignal.Remove(argument);
- can be called like this
object->onSignal(argument).Connect(...);
object->onSignal(argument).Emit();
- argument is an integer
ToDo
---------
- implement a keyboard interface (i.e. a method for Widgets to handle keyboard input)
Singleton
- key constants like Keyboard::RETURN replace Windows VK_* constants
- use multisignals to get key events
- multisignal index is value of key constant
- onKeyDown, onKeyUp
- replaces WM_KEY* messages
- alternatively use single signal with key code as argument
- function IsKeyDown
Singleton
- use a signal for character input
- replaces WM_CHAR messages
ToDo
---------
- implement a mouse interface (although probably used more seldom)
Singleton
- multisignals onButtonDown, onButtonUp
- replaces WM_*BUTTON* messages
- signal onMouseMove
- replaces WM_MOUSEMOVE message
ToDo
----------
Skizze für eine Layout-Engine für smooth:
Container erhalten einen Layout-Manager-Decorator, der sich um die Anordnung der Elemente kümmert.
Es gibt verschiedene, auswechselbare Layout-Manager mit unterschiedlichen Grundlayouts.
Für Container kann die X- und Y-Ausrichtung der Elemente angegeben werden (topleft, topmiddle, topright, middleleft, middle, middleright, bottomleft, bottommiddle, bottomright).
Elemente brauchen eine Y-Offset-Position, damit der Layout-Manager weiß, auf welcher Höhe sie ausgerichtet werden müssen, um Text auf der gleichen Ebene zu erhalten.
Beispiel: Die meisten Elemente haben Y-Offset 0, Text-Elemente haben Offset 3 und Button Elemente Offset -1.
Elemente können unabhängig vom Layout-Manager auch absolut positioniert werden.
Elemente können mehrere Felder eines Grid-Layouts einnehmen (rowspan, colspan).
Elemente können Breitenanpassung zulassen oder feste Breite definieren.
ExcAAHic7VfJbtswEO3ZQP6BN7eFVUjymuQUN057aNACzqEBdKGskUSYIgWSshMH/vcOSTmLe3N7iwKDw+WRYmYeH4dPiTJ5lFChmStWdRHF4zjJIM9DW3IqiigcRk9JLoUxKcdKmOSC8SRflVRpMCG5XZIlziZLUCy/3CMkeguJyfKxSiW/3O/PesmGwXbNRDZKmlWU1FRliXmYjEIso3jmzHlsTTyeWDOMQ2dmDjIaOcg4cpDx1EFwtjXT0EGmEweZDR1kdu4gWLqlw9h/KZz5T0Xj2H85mhx24Oxw5HGj0ONGU48bDz0Ol/O23fm03frU7z2a+c3bf8Vbv/04tPu3PtTRjNzJa2k9cNYLnv9825fLNdvtgORJP18pAkwA+UEfZWOChShsqx3RlZSmvHg91Tn2KamFgQdjI9KfTxNDUwzPZ+zFH9/wlBus4GAtMCAgTOhmPJjUwvf79xYY8hVZTtGx6GxVUm5AOK+Lg9tvqaAFqOAaVlJRI9WAZAjGk1OSpiIZA3IlpMpEIwo3suBQoV+BrG2kqgqU+fIqQO/NwR03T+fmQpOCpYZsQOlVyQB9AgNCG72FVamBp1TBEU9JxQxp0M3tDI48RTJ/U43IuEPqjo0dG09h442/eV4Ec02FcAL4O0DKZeQ+uGq0QsKZv7QQkwooIEUmbkGhM8lHI2sOuRkQrFQsyzi4qmJFiZ2+xwMOo962gFQaIysP8PUDzLcc7FNH9Y7qJwnvgbepoo0TUJeJ3Qc/8xyz2+CX1MwwKTAXoFZwLdePdHgLLOlnuZXrHBscV1HkOx6hSQmYPYCVccTZ0wLmcCoqe8S0BlwYc4s7DJmbbpcvOHgpX+ApArJrnvOVjuQdyU8h+RyYrhnwC3KNdKywZZPfZ+qX1Mr1gfIkHDg+Bkfj7ejQXQDzBqX31RLtYBB1FO0oegpF3z6mJsK+yxpB0zLpwwjfwwXZyOpYea1iE5pqyRtD6lapGT7DWpXtyNiR8Z+SghcuVlAqwDfYDXB7R9skQeNbi2WB56S2XQLKyma8Sm51TfFqX0luK1122hHxfxFxroDh7U1FTbW2r69dw6lNJIm0xMwB7/YWhNlkzqwedkp41tuf9T78AWMGOH0AAA==
Themes in smooth
-----------------------------
Der Theme-Programmierer schreibt Klassen, welche die Originalklassen ersetzen z.B.:
class ColorfulButton : public Button
{
public:
ColorfulButton(const Button &);
virtual Int Paint(Int);
};
Dabei können (sollten) die Paint- und Process-Funktionen überschrieben werden. Außerdem
muss ein Kopierkonstruktor für die Basisklasse vorhanden sein.
Dann wird in einer Initialisierungsfunktion deklariert, wie die Klasse eingesetzt werden
soll:
Object::DeclareReplacement(Button::classID, ColorfulButton::classID);
Die smooth-Klassenbibliothek ersetzt dann automatisch alle Buttons durch ColorfulButtons.
Diese Ersetzung geschiet bei der Registrierung eines Buttons bei einem Container.
Object::GetReplacementFor(object);
-->
Object *GetReplacementFor(Object *object)
{
if (replacementClassIDs.GetEntry(object->classID) != 0)
{
return CreateObjectByClassIDFrom(replacementClassIDs.GetEntry(object->classID), object);
}
return object;
}
Die Theme-Klassen werden in einer DLL-Datei zusammengefasst (oder direkt in eine EXE-Datei eingebunden),
welche dann über eine spezielle Funktion aktiviert wird.
Easily Customizable Menus
-------------------------------------------
Rechtsklick auf einen Menüeintrag öffnet ein Kontextmenü.
Funktionen: Umbenennen, Entfernen, Neuer Eintrag, Eigenschaften, Shortcut ändern
Im Eigenschaften Dialog kann unter anderem die Aktion definiert werden, die ausgeführt werden soll. Dazu werden im Programmcode Aktionen registriert (mit Application als Container). Möglicherweise sollte es vordefinierte Aktionen geben (z.B. ExitProgram).
Außerdem: Bild und Text eines Eintrags können verändert werden
Font("Times", 18, Font::Bold)
e.g. Font::Bold, Font::Italic
Note
--------
Implemented as an additional array specifying the order of elements in a list.
ToDo
---------
- part of class Widget
- set context menu using getContextMenu callback
- send a signal before opening menu
- open menu upon SM_RBUTTONDOWN
ToDo
---------
An idea:
#define foreach(type,var,array)
array.InitializeIndex(#var#);
for (type var;var=array.GetNth(array.GetIndexValue(#var#)),count<array.Length();array.IncrementIndex(#var#))
Array<String> strings;
foreach (String, s, strings)
{
}
ToDo
---------
- Template-Datei wird in Übersetzungsdatei angegeben
- Translator zeigt fehlende (rot), geänderte (orange) und übersetzte Einträge (schwarz)
TreeWidget
-------------------
Trees werden als spezielle ListEntries implementiert. Mit einem Button zum öffnen des Subtrees.
Dabei ist der Tree für die ListBox nur ein einziger Eintrag. Der Subtree wird ebenfalls wieder als ListBox implementiert (Child des TreeListEntries).
Die alte Tree-Implementierung wird damit überflüssig.
smooth-0.9.11~git20260403.0230c0da/classes/ 0000775 0000000 0000000 00000000000 15164025770 0017415 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/Makefile 0000664 0000000 0000000 00000000763 15164025770 0021063 0 ustar 00root root 0000000 0000000 ########## smooth directory $(MAKE)file ##########
# Change these variables to fit this location:
SMOOTH_PATH = ..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
FOLDERS = backends basic errors files graphics gui i18n input io misc net system threads xml
.PHONY: $(FOLDERS)
all: $(FOLDERS)
$(FOLDERS):
+ $(call makein,$@)
clean: $(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean)
$(foreach FOLDER,$(FOLDERS),$(FOLDER)##clean):
$(call cleanin,$(subst ##clean,,$@))
smooth-0.9.11~git20260403.0230c0da/classes/backends/ 0000775 0000000 0000000 00000000000 15164025770 0021167 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/Makefile 0000664 0000000 0000000 00000001214 15164025770 0022625 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../..
# Enter object files here:
OBJECTS = backend.o
# Enter addition commands for targets all and clean here:
ALLCMD1 = $(call makein,cocoa) && $(call makein,gdiplus)
ALLCMD2 = $(call makein,haiku) && $(call makein,win32)
ALLCMD3 = $(call makein,xlib)
CLEANCMD1 = $(call cleanin,cocoa) && $(call cleanin,gdiplus)
CLEANCMD2 = $(call cleanin,haiku) && $(call cleanin,win32)
CLEANCMD3 = $(call cleanin,xlib)
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/backend.cpp 0000664 0000000 0000000 00000004575 15164025770 0023275 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2011 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#if defined __WIN32__ && defined SMOOTH_STATIC
#include
#endif
S::Array *S::Backends::Backend::backends = NIL;
S::Array *S::Backends::Backend::backend_creators = NIL;
S::Int S::Backends::Backend::AddBackend(Backend *(*backend)())
{
if (backend == NIL) return Error();
if (backend_creators == NIL) backend_creators = new Array;
backend_creators->Add(backend);
return Success();
}
S::Int S::Backends::Backend::GetNOfBackends()
{
return backends->Length();
}
S::Backends::Backend *S::Backends::Backend::GetNthBackend(Int n)
{
return backends->GetNth(n);
}
S::Int S::Backends::Backend::InitBackends()
{
if (backends == NIL) backends = new Array;
if (backend_creators == NIL) backend_creators = new Array;
for (Int i = 0; i < backend_creators->Length(); i++)
{
backends->Add(backend_creators->GetNth(i)());
}
for (Int i = 0; i < backends->Length(); i++)
{
if (backends->GetNth(i)->Init() == Error())
{
/* Deinit already initialized backends and return.
*/
for (Int j = i - 1; j >= 0; j--) backends->GetNth(j)->Deinit();
return Error();
}
}
return Success();
}
S::Int S::Backends::Backend::DeinitBackends()
{
for (Int i = 0; i < backends->Length(); i++)
{
backends->GetNth(i)->Deinit();
delete backends->GetNth(i);
}
backends->RemoveAll();
delete backends;
delete backend_creators;
return Success();
}
S::Backends::Backend::Backend()
{
#if defined __WIN32__ && defined SMOOTH_STATIC
volatile Bool null = 0;
if (null) BackendWin32();
#endif
type = BACKEND_NONE;
}
S::Backends::Backend::~Backend()
{
}
S::Int S::Backends::Backend::Init()
{
return Success();
}
S::Int S::Backends::Backend::Deinit()
{
return Success();
}
S::Short S::Backends::Backend::GetBackendType() const
{
return type;
}
smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/ 0000775 0000000 0000000 00000000000 15164025770 0022253 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/Makefile 0000664 0000000 0000000 00000000647 15164025770 0023722 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_OSX),True)
OBJECTS += backendcocoa.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/cocoa/backendcocoa.mm 0000664 0000000 0000000 00000024713 15164025770 0025211 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2025 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
using namespace smooth;
using namespace smooth::GUI;
S::Backends::Backend *CreateBackendCocoa()
{
return new S::Backends::BackendCocoa();
}
S::Int backendCocoaTmp = S::Backends::Backend::AddBackend(&CreateBackendCocoa);
#if defined MAC_OS_X_VERSION_10_6 && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
@interface CocoaApplicationDelegate : NSObject { }
#else
@interface CocoaApplicationDelegate : NSObject { }
#endif
- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender;
- (void) application: (NSApplication *) sender openFiles: (NSArray *) fileNames;
- (DropArea *) findDropArea: (Widget *) container;
@end
@implementation CocoaApplicationDelegate
- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) sender
{
/* Send a dummy event to allow NSApp::run to exit.
*/
NSEvent *event = [NSEvent otherEventWithType: NSApplicationDefined
location: NSMakePoint(0, 0)
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: nil
subtype: 0
data1: 0
data2: 0];
[NSApp postEvent: event
atStart: YES];
[NSApp stop: self];
/* Request application to quit.
*/
System::EventCocoa::RequestApplicationQuit();
/* Application will terminate after all windows are closed.
*/
return NSTerminateCancel;
}
- (void) application: (NSApplication *) sender openFiles: (NSArray *) fileNames
{
/* Look for a window with a drop area.
*/
DropArea *dropArea = NIL;
for (Int n = 0; n < Window::GetNOfWindows(); n++)
{
Window *window = Window::GetNthWindow(n);
if (!window->IsVisible()) continue;
if ((dropArea = [self findDropArea: window]) != NIL) break;
}
/* Check whether a drop area has been found.
*/
if (dropArea == NIL)
{
[sender replyToOpenOrPrint: NSApplicationDelegateReplyFailure];
return;
}
/* Simulate arrival of the files via drag & drop.
*/
Array files;
for (UnsignedInt i = 0; i < [fileNames count]; i++)
{
String file;
file.ImportFrom("UTF-8", [[fileNames objectAtIndex: i] UTF8String]);
files.Add(file);
dropArea->onDropFile.Emit(file);
}
dropArea->onDropFiles.Emit(files);
[sender replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
}
- (DropArea *) findDropArea: (Widget *) container
{
for (Int n = 0; n < container->GetNOfObjects(); n++)
{
Widget *widget = container->GetNthObject(n);
if (widget->GetObjectType() == DropArea::classID && widget->IsActive()) return (DropArea *) widget;
DropArea *dropArea = [self findDropArea: widget];
if (dropArea != NIL) return dropArea;
}
return NIL;
}
@end
S::Backends::BackendCocoa::BackendCocoa()
{
type = BACKEND_COCOA;
pool = nil;
}
S::Backends::BackendCocoa::~BackendCocoa()
{
}
S::Int S::Backends::BackendCocoa::Init()
{
/* Init the Cocoa app.
*/
[NSApplication sharedApplication];
/* Create a garbage collection pool.
*/
pool = [[NSAutoreleasePool alloc] init];
/* Set application delegate.
*/
[NSApp setDelegate: [[[CocoaApplicationDelegate alloc] init] autorelease]];
/* Get default colors.
*/
UpdateColors();
/* Set default language if not set.
*/
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defaults objectForKey: @"AppleLanguages"];
NSString *language = [languages objectAtIndex: 0];
setenv("LANG", [language UTF8String], False);
return Success();
}
S::Int S::Backends::BackendCocoa::Deinit()
{
/* Release our garbage collection pool.
*/
[pool release];
return Success();
}
S::Void S::Backends::BackendCocoa::UpdateColors()
{
/* Create a dummy window to retrieve its background color.
*
* This does not work in macOS 10.10 to 10.13, so we check if it returned
* a meaningful color and assign a light gray default value otherwise.
*/
NSWindow *window = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, 0, 0)
styleMask: NSTitledWindowMask
backing: NSBackingStoreBuffered
defer: YES];
NSColor *windowBackground = [[window backgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
if ([windowBackground redComponent] == 0 &&
[windowBackground greenComponent] == 0 &&
[windowBackground blueComponent] == 0) windowBackground = [NSColor colorWithDeviceRed: 0.9 green: 0.9 blue: 0.9 alpha: 1.0];
[window release];
/* Query the other UI colors.
*/
NSColor *text = [[NSColor textColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *textBackground = [[NSColor textBackgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *controlText = [[NSColor controlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *disabledControlText = [[NSColor disabledControlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *selectedText = [[NSColor selectedTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *selectedTextBackground = [[NSColor selectedTextBackgroundColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *alternateSelectedControl = [[NSColor alternateSelectedControlColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
NSColor *alternateSelectedControlText = [[NSColor alternateSelectedControlTextColor] colorUsingColorSpaceName: NSDeviceRGBColorSpace];
if ([disabledControlText redComponent] == 0 &&
[disabledControlText greenComponent] == 0 &&
[disabledControlText blueComponent] == 0) disabledControlText = [NSColor colorWithDeviceRed: 0.5 green: 0.5 blue: 0.5 alpha: 1.0];
/* Query link color if selector exists.
*/
static SEL linkColorSelector = @selector(linkColor);
static Bool canQueryLinkColor = [[NSColor class] respondsToSelector: linkColorSelector];
NSColor *linkColor = nil;
if (canQueryLinkColor) linkColor = [((NSColor *(*)(id, SEL)) [[NSColor class] methodForSelector: linkColorSelector])([NSColor class], linkColorSelector) colorUsingColorSpaceName: NSDeviceRGBColorSpace];
/* Convert to smooth colors.
*/
Setup::BackgroundColor = GUI::Color([windowBackground redComponent] * 255, [windowBackground greenComponent] * 255, [windowBackground blueComponent] * 255);
Setup::LightGrayColor = GUI::Color(([windowBackground redComponent] + (1.0 - [windowBackground redComponent]) * 0.6) * 255, ([windowBackground greenComponent] + (1.0 - [windowBackground greenComponent]) * 0.6) * 255, ([windowBackground blueComponent] + (1.0 - [windowBackground blueComponent]) * 0.6) * 255);
Setup::ClientColor = GUI::Color([textBackground redComponent] * 255, [textBackground greenComponent] * 255, [textBackground blueComponent] * 255);
Setup::ClientTextColor = GUI::Color([text redComponent] * 255, [text greenComponent] * 255, [text blueComponent] * 255);
Setup::DividerLightColor = GUI::Color(([windowBackground redComponent] + (1.0 - [windowBackground redComponent]) * 0.6) * 255, ([windowBackground greenComponent] + (1.0 - [windowBackground greenComponent]) * 0.6) * 255, ([windowBackground blueComponent] + (1.0 - [windowBackground blueComponent]) * 0.6) * 255);
Setup::DividerDarkColor = GUI::Color([windowBackground redComponent] * 0.7 * 255, [windowBackground greenComponent] * 0.7 * 255, [windowBackground blueComponent] * 0.7 * 255);
Setup::TextColor = GUI::Color([controlText redComponent] * 255, [controlText greenComponent] * 255, [controlText blueComponent] * 255);
Setup::InactiveTextColor = GUI::Color([disabledControlText redComponent] * 255, [disabledControlText greenComponent] * 255, [disabledControlText blueComponent] * 255);
Setup::HighlightColor = GUI::Color([selectedTextBackground redComponent] * 255, [selectedTextBackground greenComponent] * 255, [selectedTextBackground blueComponent] * 255);
Setup::HighlightTextColor = GUI::Color([selectedText redComponent] * 255, [selectedText greenComponent] * 255, [selectedText blueComponent] * 255);
Setup::GradientStartColor = GUI::Color(([alternateSelectedControl redComponent] - [alternateSelectedControl redComponent] * 0.25) * 255, ([alternateSelectedControl greenComponent] - [alternateSelectedControl greenComponent] * 0.25) * 255, ([alternateSelectedControl blueComponent] - [alternateSelectedControl blueComponent] * 0.25) * 255);
Setup::GradientEndColor = GUI::Color(([alternateSelectedControl redComponent] + (1.0 - [alternateSelectedControl redComponent]) * 0.25) * 255, ([alternateSelectedControl greenComponent] + (1.0 - [alternateSelectedControl greenComponent]) * 0.25) * 255, ([alternateSelectedControl blueComponent] + (1.0 - [alternateSelectedControl blueComponent]) * 0.25) * 255);
Setup::GradientTextColor = GUI::Color([alternateSelectedControlText redComponent] * 255, [alternateSelectedControlText greenComponent] * 255, [alternateSelectedControlText blueComponent] * 255);
if (linkColor != nil)
{
Setup::LinkColor = GUI::Color([linkColor redComponent] * 255, [linkColor greenComponent] * 255, [linkColor blueComponent] * 255);
Setup::LinkHighlightColor = GUI::Color([linkColor redComponent] * 255, [linkColor greenComponent] * 255, [linkColor blueComponent] * 255);
}
if (Setup::InactiveTextColor == Setup::TextColor)
{
Setup::InactiveTextColor = Setup::InactiveTextColor.Average(Setup::BackgroundColor);
}
}
S::Bool S::Backends::BackendCocoa::IsOSXVersionAtLeast(Int majorVersion, Int minorVersion, Int microVersion)
{
static SInt32 osMajorVersion = 0;
static SInt32 osMinorVersion = 0;
static SInt32 osMicroVersion = 0;
if (osMajorVersion == 0)
{
Gestalt(gestaltSystemVersionMajor, &osMajorVersion);
Gestalt(gestaltSystemVersionMinor, &osMinorVersion);
Gestalt(gestaltSystemVersionBugFix, &osMicroVersion);
}
if ( osMajorVersion > majorVersion ||
(osMajorVersion == majorVersion && ( osMinorVersion > minorVersion ||
(osMinorVersion == minorVersion && osMicroVersion >= microVersion)))) return True;
return False;
}
smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/ 0000775 0000000 0000000 00000000000 15164025770 0022636 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/Makefile 0000664 0000000 0000000 00000000655 15164025770 0024304 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_GDIPLUS),True)
OBJECTS += backendgdiplus.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/gdiplus/backendgdiplus.cpp 0000775 0000000 0000000 00000002154 15164025770 0026326 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2011 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::Backends::Backend *CreateBackendGDIPlus()
{
return new S::Backends::BackendGDIPlus();
}
S::Int backendGDIPlusTmp = S::Backends::Backend::AddBackend(&CreateBackendGDIPlus);
S::Backends::BackendGDIPlus::BackendGDIPlus()
{
type = BACKEND_GDIPLUS;
}
S::Backends::BackendGDIPlus::~BackendGDIPlus()
{
}
S::Int S::Backends::BackendGDIPlus::Init()
{
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
/* Initialize GDI+.
*/
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
return Success();
}
S::Int S::Backends::BackendGDIPlus::Deinit()
{
Gdiplus::GdiplusShutdown(gdiplusToken);
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/ 0000775 0000000 0000000 00000000000 15164025770 0022270 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/Makefile 0000664 0000000 0000000 00000000651 15164025770 0023732 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_HAIKU),True)
OBJECTS += backendhaiku.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/haiku/backendhaiku.cpp 0000664 0000000 0000000 00000011117 15164025770 0025406 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
namespace smooth
{
class HaikuApplication : public BApplication
{
private:
static String GetAppSignature()
{
BResources resources(GUI::Application::GetCommand());
size_t size = 0;
const char *signature = (const char *) resources.LoadResource('MIMS', "BEOS:APP_SIG", &size);
if (signature) return signature;
return String("application/x-vnd.").Append(File(GUI::Application::GetCommand()).GetFileName());
}
public:
HaikuApplication() : BApplication(GetAppSignature())
{
}
};
};
S::Backends::Backend *CreateBackendHaiku()
{
return new S::Backends::BackendHaiku();
}
S::Int backenHaikuTmp = S::Backends::Backend::AddBackend(&CreateBackendHaiku);
S::Backends::BackendHaiku::BackendHaiku()
{
type = BACKEND_HAIKU;
}
S::Backends::BackendHaiku::~BackendHaiku()
{
}
S::Int S::Backends::BackendHaiku::Init()
{
/* Set locale to user default.
*/
setlocale(LC_ALL, "");
/* Get default colors.
*/
UpdateColors();
return Success();
}
S::Int S::Backends::BackendHaiku::Deinit()
{
return Success();
}
S::Void S::Backends::BackendHaiku::UpdateColors()
{
rgb_color panelBackground = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color panelText = ui_color(B_PANEL_TEXT_COLOR);
rgb_color documentBackground = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
rgb_color documentText = ui_color(B_DOCUMENT_TEXT_COLOR);
rgb_color windowTab = ui_color(B_WINDOW_TAB_COLOR);
rgb_color windowText = ui_color(B_WINDOW_TEXT_COLOR);
rgb_color tooltipBackground = ui_color(B_TOOL_TIP_BACKGROUND_COLOR);
rgb_color tooltipText = ui_color(B_TOOL_TIP_TEXT_COLOR);
rgb_color link = ui_color(B_LINK_TEXT_COLOR);
rgb_color linkHover = ui_color(B_LINK_HOVER_COLOR);
Setup::BackgroundColor = GUI::Color(panelBackground.red, panelBackground.green, panelBackground.blue);
Setup::LightGrayColor = GUI::Color(panelBackground.red + (255 - panelBackground.red) * 0.6, panelBackground.green + (255 - panelBackground.green) * 0.6, panelBackground.blue + (255 - panelBackground.blue) * 0.6);
Setup::ClientColor = GUI::Color(documentBackground.red, documentBackground.green, documentBackground.blue);
Setup::ClientTextColor = GUI::Color(documentText.red, documentText.green, documentText.blue);
Setup::DividerLightColor = GUI::Color(panelBackground.red + (255 - panelBackground.red) * 0.6, panelBackground.green + (255 - panelBackground.green) * 0.6, panelBackground.blue + (255 - panelBackground.blue) * 0.6);
Setup::DividerDarkColor = GUI::Color(panelBackground.red * 0.7, panelBackground.green * 0.7, panelBackground.blue * 0.7);
Setup::TextColor = GUI::Color(panelText.red, panelText.green, panelText.blue);
Setup::InactiveTextColor = GUI::Color(panelText.red + (255 - panelText.red) * 0.5, panelText.green + (255 - panelText.green) * 0.5, panelText.blue + (255 - panelText.blue) * 0.5);
Setup::HighlightColor = GUI::Color(windowTab.red + (255 - windowTab.red) * 0.5, windowTab.green + (255 - windowTab.green) * 0.5, windowTab.blue + (255 - windowTab.blue) * 0.5);
Setup::HighlightTextColor = GUI::Color(documentText.red, documentText.green, documentText.blue);
Setup::GradientStartColor = GUI::Color(windowTab.red, windowTab.green, windowTab.blue);
Setup::GradientEndColor = GUI::Color(windowTab.red + (255 - windowTab.red) * 0.6, windowTab.green + (255 - windowTab.green) * 0.6, windowTab.blue + (255 - windowTab.blue) * 0.6);
Setup::GradientTextColor = GUI::Color(windowText.red, windowText.green, windowText.blue);
Setup::TooltipColor = GUI::Color(tooltipBackground.red, tooltipBackground.green, tooltipBackground.blue);
Setup::TooltipTextColor = GUI::Color(tooltipText.red, tooltipText.green, tooltipText.blue);
Setup::LinkColor = GUI::Color(link.red, link.green, link.blue);
Setup::LinkHighlightColor = GUI::Color(linkHover.red, linkHover.green, linkHover.blue);
}
BApplication *S::Backends::BackendHaiku::GetApplication()
{
static HaikuApplication app;
return be_app;
}
smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/ 0000775 0000000 0000000 00000000000 15164025770 0022131 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/Makefile 0000664 0000000 0000000 00000001105 15164025770 0023566 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Change these variables to fit your project:
ifeq ($(USE_BUNDLED_LIBICONV),True)
MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support/libiconv
endif
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_WIN32),True)
OBJECTS += backendwin32.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/win32/backendwin32.cpp 0000664 0000000 0000000 00000032232 15164025770 0025111 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2023 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#define MAX_EXT_PATH 32768
size_t (*iconv)(iconv_t, char **, size_t *, char **, size_t *) = NIL;
iconv_t (*iconv_open)(const char *, const char *) = NIL;
int (*iconv_close)(iconv_t) = NIL;
int (*iconvctl)(iconv_t, int, void *) = NIL;
HINSTANCE iconvDLL = NIL;
HINSTANCE hDllInstance = NIL;
S::Bool S::LoadIconvDLL()
{
iconvDLL = LoadLibrary(GUI::Application::GetApplicationDirectory().Append("iconv"));
iconv = (size_t (*)(iconv_t, char **, size_t *, char **, size_t *)) GetProcAddress(iconvDLL, "libiconv");
iconv_open = (iconv_t (*)(const char *, const char *)) GetProcAddress(iconvDLL, "libiconv_open");
iconv_close = (int (*)(iconv_t)) GetProcAddress(iconvDLL, "libiconv_close");
iconvctl = (int (*)(iconv_t, int, void *)) GetProcAddress(iconvDLL, "libiconvctl");
if (iconv == NIL ||
iconv_open == NIL ||
iconv_close == NIL ||
iconvctl == NIL) { FreeIconvDLL(); return False; }
return True;
}
S::Void S::FreeIconvDLL()
{
FreeLibrary(iconvDLL);
iconv = NIL;
iconv_open = NIL;
iconv_close = NIL;
iconvctl = NIL;
}
#ifndef SMOOTH_STATIC
extern "C"
{
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
hDllInstance = hInst;
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}
}
#endif
static HMODULE user32dll = NIL;
typedef BOOL (WINAPI* SETPROCESSDPIAWARE)();
static SETPROCESSDPIAWARE ex_SetProcessDPIAware = NIL;
S::Backends::Backend *CreateBackendWin32()
{
return new S::Backends::BackendWin32();
}
S::Int backendWin32Tmp = S::Backends::Backend::AddBackend(&CreateBackendWin32);
S::Backends::BackendWin32::BackendWin32()
{
type = BACKEND_WIN32;
}
S::Backends::BackendWin32::~BackendWin32()
{
}
S::Int S::Backends::BackendWin32::Init()
{
/* Init COM library.
*/
OleInitialize(NIL);
/* Init Windows sockets.
*/
WORD wVersionRequested = MAKEWORD(2,2);
WSADATA wsaData;
WSAStartup(wVersionRequested, &wsaData);
/* Declare the process DPI aware.
*/
user32dll = LoadLibrary(L"user32.dll");
ex_SetProcessDPIAware = (SETPROCESSDPIAWARE) GetProcAddress(user32dll, "SetProcessDPIAware");
if (ex_SetProcessDPIAware != NIL) ex_SetProcessDPIAware();
/* Get default colors.
*/
UpdateColors();
/* Get mouse hover time and tolerance.
*/
SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &Setup::HoverTime, 0);
SystemParametersInfo(SPI_GETMOUSEHOVERWIDTH, 0, &Setup::HoverWidth, 0);
SystemParametersInfo(SPI_GETMOUSEHOVERHEIGHT, 0, &Setup::HoverHeight, 0);
return Success();
}
S::Int S::Backends::BackendWin32::Deinit()
{
/* Free dynamically loaded user32 library.
*/
FreeLibrary(user32dll);
/* Cleanup Windows sockets.
*/
WSACleanup();
/* Uninit COM library.
*/
OleUninitialize();
return Success();
}
S::Void S::Backends::BackendWin32::UpdateColors()
{
/* Query dark mode and accent color on Windows 10.
*/
Bool darkModeEnabled = False;
GUI::Color colorizationColor(-1);
GUI::Color accentColor(-1);
Bool accentColorPrevalence = False;
HKEY key;
if (RegOpenKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &key) == ERROR_SUCCESS)
{
DWORD value = 1;
DWORD size = sizeof(value);
if (RegQueryValueEx(key, L"AppsUseLightTheme", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) darkModeEnabled = !value;
RegCloseKey(key);
}
if (RegOpenKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\DWM", &key) == ERROR_SUCCESS)
{
DWORD value = 0;
DWORD size = sizeof(value);
if (RegQueryValueEx(key, L"ColorizationColor", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) colorizationColor = GUI::Color((value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF);
if (RegQueryValueEx(key, L"AccentColor", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) accentColor = GUI::Color(value & 0xFF, (value >> 8) & 0xFF, (value >> 16) & 0xFF);
if (RegQueryValueEx(key, L"ColorPrevalence", 0, NULL, (BYTE *) &value, &size) == ERROR_SUCCESS) accentColorPrevalence = value;
RegCloseKey(key);
}
/* Set theme colors.
*/
if (darkModeEnabled)
{
Setup::BackgroundColor = GUI::Color(64, 64, 70);
Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6);
Setup::ClientColor = GUI::Color(32, 32, 35);
Setup::ClientTextColor = GUI::Color(255, 255, 255);
Setup::DividerLightColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6);
Setup::DividerDarkColor = GetSysColor(COLOR_3DSHADOW);
Setup::TextColor = GUI::Color(245, 245, 245);
Setup::InactiveTextColor = GUI::Color(160, 160, 160);
Setup::LinkColor = GUI::Color(100, 160, 225);
Setup::LinkHighlightColor = GUI::Color(100, 160, 225);
}
else
{
Setup::BackgroundColor = GetSysColor(COLOR_3DFACE);
Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6);
Setup::ClientColor = GetSysColor(COLOR_WINDOW);
Setup::ClientTextColor = GetSysColor(COLOR_WINDOWTEXT);
Setup::DividerLightColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6);
Setup::DividerDarkColor = GetSysColor(COLOR_3DSHADOW);
Setup::TextColor = GetSysColor(COLOR_BTNTEXT);
Setup::InactiveTextColor = GetSysColor(COLOR_GRAYTEXT);
Setup::LinkColor = GetSysColor(COLOR_HOTLIGHT);
Setup::LinkHighlightColor = GetSysColor(COLOR_HOTLIGHT);
}
/* Set accent colors.
*/
if (accentColor != GUI::Color(-1))
{
Setup::HighlightColor = accentColor.Grayscale().GetRed() < 245 ? accentColor : GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.15, accentColor.GetGreen() - accentColor.GetGreen() * 0.15, accentColor.GetBlue() - accentColor.GetBlue() * 0.15);
Setup::HighlightTextColor = Setup::HighlightColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255);
if (darkModeEnabled)
{
Setup::GradientStartColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.45, accentColor.GetGreen() - accentColor.GetGreen() * 0.45, accentColor.GetBlue() - accentColor.GetBlue() * 0.45);
Setup::GradientEndColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.30, accentColor.GetGreen() - accentColor.GetGreen() * 0.30, accentColor.GetBlue() - accentColor.GetBlue() * 0.30);
Setup::GradientTextColor = GUI::Color(245, 245, 245);
}
else
{
Setup::GradientStartColor = GUI::Color(accentColor.GetRed() - accentColor.GetRed() * 0.15, accentColor.GetGreen() - accentColor.GetGreen() * 0.15, accentColor.GetBlue() - accentColor.GetBlue() * 0.15);
Setup::GradientEndColor = GUI::Color(accentColor.GetRed() + (255 - accentColor.GetRed()) * 0.25, accentColor.GetGreen() + (255 - accentColor.GetGreen()) * 0.25, accentColor.GetBlue() + (255 - accentColor.GetBlue()) * 0.25);
Setup::GradientTextColor = Setup::GradientStartColor.Average(Setup::GradientEndColor).Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255);
}
if (accentColorPrevalence)
{
Setup::TitlebarStartColor = accentColor;
Setup::TitlebarEndColor = Setup::TitlebarStartColor;
Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255);
}
else
{
Setup::TitlebarStartColor = Setup::GradientStartColor;
Setup::TitlebarEndColor = Setup::GradientEndColor;
Setup::TitlebarTextColor = Setup::GradientTextColor;
}
Setup::InactiveTitlebarStartColor = Setup::TitlebarStartColor.Grayscale();
Setup::InactiveTitlebarEndColor = Setup::TitlebarEndColor.Grayscale();
Setup::InactiveTitlebarTextColor = Setup::TitlebarTextColor.Grayscale();
}
else if (colorizationColor != GUI::Color(-1))
{
Setup::HighlightColor = colorizationColor.Grayscale().GetRed() < 245 ? colorizationColor : GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.15, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.15, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.15);
Setup::HighlightTextColor = Setup::HighlightColor.Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255);
Setup::GradientStartColor = GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.15, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.15, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.15);
Setup::GradientEndColor = GUI::Color(colorizationColor.GetRed() + (255 - colorizationColor.GetRed()) * 0.25, colorizationColor.GetGreen() + (255 - colorizationColor.GetGreen()) * 0.25, colorizationColor.GetBlue() + (255 - colorizationColor.GetBlue()) * 0.25);
Setup::GradientTextColor = Setup::GradientStartColor.Average(Setup::GradientEndColor).Grayscale().GetRed() > 190 ? GUI::Color(0) : GUI::Color(255, 255, 255);
if (Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2))
{
Setup::TitlebarStartColor = colorizationColor.Grayscale().GetRed() < 250 ? colorizationColor : GUI::Color(colorizationColor.GetRed() - colorizationColor.GetRed() * 0.02, colorizationColor.GetGreen() - colorizationColor.GetGreen() * 0.02, colorizationColor.GetBlue() - colorizationColor.GetBlue() * 0.02);
Setup::TitlebarEndColor = Setup::TitlebarStartColor;
Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() < 120 ? GUI::Color(245, 245, 245) : GUI::Color(0);
Setup::InactiveTitlebarStartColor = GUI::Color(235, 235, 235);
Setup::InactiveTitlebarEndColor = GUI::Color(235, 235, 235);
Setup::InactiveTitlebarTextColor = GUI::Color(0);
}
else
{
Setup::TitlebarStartColor = Setup::GradientStartColor;
Setup::TitlebarEndColor = Setup::GradientEndColor;
Setup::TitlebarTextColor = Setup::TitlebarStartColor.Grayscale().GetRed() < 120 ? GUI::Color(245, 245, 245) : GUI::Color(0);
Setup::InactiveTitlebarStartColor = Setup::TitlebarStartColor.Grayscale();
Setup::InactiveTitlebarEndColor = Setup::TitlebarEndColor.Grayscale();
Setup::InactiveTitlebarTextColor = Setup::TitlebarTextColor.Grayscale();
}
}
else
{
Setup::HighlightColor = GetSysColor(COLOR_HIGHLIGHT);
Setup::HighlightTextColor = GetSysColor(COLOR_HIGHLIGHTTEXT);
Setup::GradientStartColor = GetSysColor(COLOR_ACTIVECAPTION);
Setup::GradientEndColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
Setup::GradientTextColor = GetSysColor(COLOR_CAPTIONTEXT);
Setup::TitlebarStartColor = GetSysColor(COLOR_ACTIVECAPTION);
Setup::TitlebarEndColor = GetSysColor(COLOR_GRADIENTACTIVECAPTION);
Setup::TitlebarTextColor = GetSysColor(COLOR_CAPTIONTEXT);
Setup::InactiveTitlebarStartColor = GetSysColor(COLOR_INACTIVECAPTION);
Setup::InactiveTitlebarEndColor = GetSysColor(COLOR_GRADIENTINACTIVECAPTION);
Setup::InactiveTitlebarTextColor = GetSysColor(COLOR_INACTIVECAPTIONTEXT);
}
/* Set tooltip and link colors.
*/
Setup::TooltipColor = GetSysColor(COLOR_INFOBK);
Setup::TooltipTextColor = GetSysColor(COLOR_INFOTEXT);
}
S::Bool S::Backends::BackendWin32::IsWindowsVersionAtLeast(UnsignedInt platformId, UnsignedInt majorVersion, UnsignedInt minorVersion)
{
static OSVERSIONINFO versionInfo = { 0 };
if (versionInfo.dwOSVersionInfoSize == 0)
{
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&versionInfo);
}
if (versionInfo.dwPlatformId == platformId && ( versionInfo.dwMajorVersion > majorVersion ||
(versionInfo.dwMajorVersion == majorVersion && versionInfo.dwMinorVersion >= minorVersion))) return True;
return False;
}
S::String S::Backends::BackendWin32::GetFullPathName(const String &shortPath)
{
static const String extendedPathPrefix = "\\\\?\\";
if (shortPath.StartsWith(extendedPathPrefix)) return shortPath;
wchar_t buffer[MAX_EXT_PATH] = { 0 };
if (GetLongPathName(Directory::MakeExtendedPath(shortPath), buffer, MAX_EXT_PATH) == 0) return shortPath;
return Directory::StripExtendedPathPrefix(buffer);
}
smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/ 0000775 0000000 0000000 00000000000 15164025770 0022125 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/Makefile 0000664 0000000 0000000 00000001233 15164025770 0023564 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Change these variables to fit your project:
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
ifneq ($(BUILD_HAIKU),True)
MYCCOPTS += $(shell pkg-config --cflags x11)
MYCCOPTS += $(shell pkg-config --cflags gtk+-3.0)
endif
endif
endif
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_XLIB),True)
OBJECTS += backendxlib.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/backends/xlib/backendxlib.cpp 0000664 0000000 0000000 00000030612 15164025770 0025101 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2025 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace X11;
#ifndef GTK_STATE_FLAG_LINK
# define GTK_STATE_FLAG_LINK GtkStateFlags(1 << 9)
#endif
static void toggleTimerInterrupts(bool allowed)
{
sigset_t ss;
sigemptyset(&ss);
sigaddset(&ss, SIGALRM);
pthread_sigmask(allowed ? SIG_UNBLOCK : SIG_BLOCK, &ss, NIL);
}
static GdkRGBA get_gtk_color(GType type, const gchar *className, GtkStateFlags stateFlags, bool background)
{
/* Create dummy widget of requested type.
*/
GtkWidget *widget = NIL;
if (type == GTK_TYPE_WINDOW) widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
else if (type == GTK_TYPE_TOOLTIP) widget = gtk_window_new(GTK_WINDOW_POPUP);
else if (type == GTK_TYPE_BUTTON) widget = gtk_button_new();
else if (type == GTK_TYPE_TEXT_VIEW) widget = gtk_text_view_new();
else if (type == GTK_TYPE_LINK_BUTTON) widget = gtk_link_button_new("");
if (widget == NIL) return { 0, 0, 0, 0 };
/* Get GtkStyleContext to query color.
*/
GtkStyleContext *style = gtk_widget_get_style_context(widget);
gtk_style_context_add_class(style, className);
/* Query color from style context.
*/
GdkRGBA color;
if (background) gtk_style_context_get_background_color(style, stateFlags, &color);
else gtk_style_context_get_color(style, stateFlags, &color);
g_object_ref_sink(widget);
g_object_unref(widget);
return color;
}
static S::GUI::Color get_kde_color(const S::String &category, const S::String &color)
{
S::String spec = S::Backends::BackendXLib::QueryKDESettings(S::String("Colors:").Append(category), color);
const S::Array &values = spec.Explode(",");
if (values.Length() != 3) return S::GUI::Color();
return S::GUI::Color(values.GetNth(0).ToInt(), values.GetNth(1).ToInt(), values.GetNth(2).ToInt());
}
S::Backends::Backend *CreateBackendXLib()
{
return new S::Backends::BackendXLib();
}
S::Int backendXLibTmp = S::Backends::Backend::AddBackend(&CreateBackendXLib);
Display *S::Backends::BackendXLib::display = NIL;
XIM S::Backends::BackendXLib::im = NIL;
S::Backends::BackendXLib::BackendXLib()
{
type = BACKEND_XLIB;
}
S::Backends::BackendXLib::~BackendXLib()
{
}
S::Int S::Backends::BackendXLib::Init()
{
XInitThreads();
/* Open display.
*/
const char *displayId = getenv("DISPLAY");
if (displayId != NIL)
{
display = XOpenDisplay(NIL);
if (display == NIL)
{
fprintf(stderr, "Error: Unable to open display at %s.\n", displayId);
return Error();
}
/* Init the GTK with SIGALRM signals disabled to make
* threads created by gtk_init inherit this SIGMASK.
*/
toggleTimerInterrupts(false);
gtk_init(NULL, NULL);
/* Get default colors.
*/
UpdateColors();
/* Set locale and open input method.
*/
setlocale(LC_ALL, "");
XSetLocaleModifiers("");
im = XOpenIM(display, NIL, NIL, NIL);
}
return Success();
}
S::Int S::Backends::BackendXLib::Deinit()
{
if (im != NIL) XCloseIM(im);
if (display != NIL) XCloseDisplay(display);
toggleTimerInterrupts(true);
return Success();
}
S::Void S::Backends::BackendXLib::UpdateColors()
{
/* Check desktop environment.
*/
String desktop = getenv("XDG_CURRENT_DESKTOP");
const Array &IDs = desktop.Explode(":");
foreach (const String &ID, IDs)
{
if (ID == "KDE" && UpdateColorsKDE()) return;
}
UpdateColorsGnome();
}
S::Bool S::Backends::BackendXLib::UpdateColorsGnome()
{
/* Query UI colors defined in GTK theme.
*/
GdkRGBA backgroundColor = get_gtk_color(GTK_TYPE_WINDOW, GTK_STYLE_CLASS_BACKGROUND, GTK_STATE_FLAG_NORMAL, true);
GdkRGBA textColor = get_gtk_color(GTK_TYPE_BUTTON, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false);
if (gdk_rgba_equal(&backgroundColor, &textColor)) return False;
GdkRGBA clientColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, true);
GdkRGBA clientTextColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false);
GdkRGBA highlightColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), true);
GdkRGBA highlightTextColor = get_gtk_color(GTK_TYPE_TEXT_VIEW, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED), false);
GdkRGBA tooltipColor = get_gtk_color(GTK_TYPE_TOOLTIP, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, true);
GdkRGBA tooltipTextColor = get_gtk_color(GTK_TYPE_TOOLTIP, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_NORMAL, false);
GdkRGBA linkColor = get_gtk_color(GTK_TYPE_LINK_BUTTON, GTK_STYLE_CLASS_VIEW, GTK_STATE_FLAG_LINK, false);
GdkRGBA linkHighlightColor = get_gtk_color(GTK_TYPE_LINK_BUTTON, GTK_STYLE_CLASS_VIEW, GtkStateFlags(GTK_STATE_FLAG_LINK | GTK_STATE_FLAG_PRELIGHT), false);
/* Convert to smooth colors.
*/
Setup::BackgroundColor = GUI::Color(255 * backgroundColor.red, 255 * backgroundColor.green, 255 * backgroundColor.blue);
Setup::LightGrayColor = GUI::Color(255 * (backgroundColor.red + (1.0 - backgroundColor.red) * 0.6), 255 * (backgroundColor.green + (1.0 - backgroundColor.green) * 0.6), 255 * (backgroundColor.blue + (1.0 - backgroundColor.blue) * 0.6));
Setup::ClientColor = GUI::Color(255 * clientColor.red, 255 * clientColor.green, 255 * clientColor.blue);
Setup::ClientTextColor = GUI::Color(255 * clientTextColor.red, 255 * clientTextColor.green, 255 * clientTextColor.blue);
Setup::DividerLightColor = GUI::Color(255 * (backgroundColor.red + (1.0 - backgroundColor.red) * 0.6), 255 * (backgroundColor.green + (1.0 - backgroundColor.green) * 0.6), 255 * (backgroundColor.blue + (1.0 - backgroundColor.blue) * 0.6));
Setup::DividerDarkColor = GUI::Color(255 * backgroundColor.red * 0.7, 255 * backgroundColor.green * 0.7, 255 * backgroundColor.blue * 0.7);
Setup::TextColor = GUI::Color(255 * textColor.red, 255 * textColor.green, 255 * textColor.blue);
Setup::InactiveTextColor = Setup::TextColor.Average(Setup::BackgroundColor);
Setup::HighlightColor = GUI::Color(255 * highlightColor.red, 255 * highlightColor.green, 255 * highlightColor.blue);
Setup::HighlightTextColor = GUI::Color(255 * highlightTextColor.red, 255 * highlightTextColor.green, 255 * highlightTextColor.blue);
Setup::GradientStartColor = GUI::Color(255 * (highlightColor.red - highlightColor.red * 0.15), 255 * (highlightColor.green - highlightColor.green * 0.15), 255 * (highlightColor.blue - highlightColor.blue * 0.15));
Setup::GradientEndColor = GUI::Color(255 * (highlightColor.red + (1.0 - highlightColor.red) * 0.15), 255 * (highlightColor.green + (1.0 - highlightColor.green) * 0.15), 255 * (highlightColor.blue + (1.0 - highlightColor.blue) * 0.15));
Setup::GradientTextColor = GUI::Color(255 * highlightTextColor.red, 255 * highlightTextColor.green, 255 * highlightTextColor.blue);
Setup::TooltipColor = GUI::Color(255 * tooltipColor.red, 255 * tooltipColor.green, 255 * tooltipColor.blue);
Setup::TooltipTextColor = GUI::Color(255 * tooltipTextColor.red, 255 * tooltipTextColor.green, 255 * tooltipTextColor.blue);
if (GUI::Color(255 * linkColor.red, 255 * linkColor.green, 255 * linkColor.blue) != Setup::TextColor)
{
Setup::LinkColor = GUI::Color(255 * linkColor.red, 255 * linkColor.green, 255 * linkColor.blue);
Setup::LinkHighlightColor = GUI::Color(255 * linkHighlightColor.red, 255 * linkHighlightColor.green, 255 * linkHighlightColor.blue);
}
return True;
}
S::Bool S::Backends::BackendXLib::UpdateColorsKDE()
{
GUI::Color backgroundColor = get_kde_color("Window", "BackgroundNormal");
GUI::Color textColor = get_kde_color("Window", "ForegroundNormal");
if (backgroundColor == textColor) return False;
Setup::BackgroundColor = backgroundColor;
Setup::TextColor = textColor;
Setup::InactiveTextColor = get_kde_color("Window", "ForegroundInactive");
if (Setup::BackgroundColor.Grayscale() < Setup::TextColor.Grayscale())
{
GUI::Color backgroundAlternate = get_kde_color("Window", "BackgroundAlternate");
if (backgroundAlternate.Grayscale() > Setup::BackgroundColor.Grayscale()) Setup::BackgroundColor = backgroundAlternate;
}
Setup::LightGrayColor = GUI::Color(Setup::BackgroundColor.GetRed() + (255 - Setup::BackgroundColor.GetRed()) * 0.6, Setup::BackgroundColor.GetGreen() + (255 - Setup::BackgroundColor.GetGreen()) * 0.6, Setup::BackgroundColor.GetBlue() + (255 - Setup::BackgroundColor.GetBlue()) * 0.6);
Setup::ClientColor = get_kde_color("View", "BackgroundNormal");
Setup::ClientTextColor = get_kde_color("View", "ForegroundNormal");
Setup::DividerLightColor = Setup::LightGrayColor;
Setup::DividerDarkColor = GUI::Color(Setup::BackgroundColor.GetRed() * 0.7, Setup::BackgroundColor.GetGreen() * 0.7, Setup::BackgroundColor.GetBlue() * 0.7);
Setup::HighlightColor = get_kde_color("Selection", "BackgroundNormal");
Setup::HighlightTextColor = get_kde_color("Selection", "ForegroundNormal");
Setup::GradientStartColor = GUI::Color(Setup::HighlightColor.GetRed() * 0.75, Setup::HighlightColor.GetGreen() * 0.75, Setup::HighlightColor.GetBlue() * 0.75);
Setup::GradientEndColor = GUI::Color(Setup::HighlightColor.GetRed() + (255 - Setup::HighlightColor.GetRed()) * 0.15, Setup::HighlightColor.GetGreen() + (255 - Setup::HighlightColor.GetGreen()) * 0.15, Setup::HighlightColor.GetBlue() + (255 - Setup::HighlightColor.GetBlue()) * 0.15);
Setup::GradientTextColor = Setup::HighlightTextColor;
Setup::TooltipColor = get_kde_color("Tooltip", "BackgroundNormal");
Setup::TooltipTextColor = get_kde_color("Tooltip", "ForegroundNormal");
Setup::LinkColor = get_kde_color("Window", "ForegroundLink");
Setup::LinkHighlightColor = get_kde_color("Window", "ForegroundActive");
return True;
}
Display *S::Backends::BackendXLib::GetDisplay()
{
return display;
}
XIM S::Backends::BackendXLib::GetIM()
{
return im;
}
S::String S::Backends::BackendXLib::FindExecutable(const String &executable)
{
/* Search the path for executable.
*/
String path = getenv("PATH");
const Array &paths = path.Explode(":");
foreach (const String &path, paths)
{
/* Check for executable in this path.
*/
File file(String(path).Append("/").Append(executable));
if (file.Exists()) return file;
}
return NIL;
}
S::String S::Backends::BackendXLib::QueryGSettings(const String &schema, const String &key)
{
static String gsettings = FindExecutable("gsettings");
if (gsettings == NIL) return NIL;
/* Execute gsettings to query value.
*/
FILE *pstdin = popen(String(gsettings).Append(" get ").Append(schema).Append(" ").Append(key), "r");
if (pstdin != NIL)
{
char value[256];
if (fgets(value, 256, pstdin) != NIL)
{
pclose(pstdin);
return value;
}
pclose(pstdin);
}
return NIL;
}
S::String S::Backends::BackendXLib::QueryKDESettings(const String &category, const String &key)
{
File kdeConfig("kdeglobals", System::System::GetApplicationDataDirectory());
if (!kdeConfig.Exists()) return NIL;
IO::InStream in(IO::STREAM_FILE, kdeConfig, IO::IS_READ);
/* Find category header.
*/
while (in.GetPos() < in.Size())
{
String line = in.InputLine();
if (line == String("[").Append(category).Append("]")) break;
}
/* Find key.
*/
while (in.GetPos() < in.Size())
{
String line = in.InputLine();
if ( line.StartsWith("[")) break;
if (!line.StartsWith(key.Append("="))) continue;
return line.Tail(line.Length() - line.Find("=") - 1);
}
return NIL;
}
S::String S::Backends::BackendXLib::QueryXfConf(const String &channel, const String &property)
{
static String xfconfquery = FindExecutable("xfconf-query");
if (xfconfquery == NIL) return NIL;
/* Execute xfconf-query to query value.
*/
FILE *pstdin = popen(String(xfconfquery).Append(" -c ").Append(channel).Append(" -p ").Append(property), "r");
if (pstdin != NIL)
{
char value[256];
if (fgets(value, 256, pstdin) != NIL)
{
pclose(pstdin);
return value;
}
pclose(pstdin);
}
return NIL;
}
smooth-0.9.11~git20260403.0230c0da/classes/basic/ 0000775 0000000 0000000 00000000000 15164025770 0020476 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/basic/Makefile 0000664 0000000 0000000 00000000470 15164025770 0022137 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../..
# Enter object files here:
OBJECTS = object.o objecttype.o setup.o
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/basic/object.cpp 0000664 0000000 0000000 00000007752 15164025770 0022463 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2018 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
const S::Short S::Object::classID = S::Object::RequestClassID();
S::Short S::Object::nextClassID = 0;
S::Int S::Object::nextObjectHandle = 0;
S::Array S::Object::objects;
S::Array S::Object::deletable;
S::System::Timer *S::Object::cleanupTimer = NIL;
S::Object::Object() : type(this)
{
/* Enable R/W locking for object lists.
*/
if (objects.Length() == 0)
{
objects.EnableLocking();
deletable.EnableLocking();
}
type = classID;
handle = RequestObjectHandle();
name = NIL;
lockingEnabled = False;
isDeletable = False;
isObjectInUse = 0;
flags = 0;
objects.Add(this, handle);
/* Create periodical cleanup timer if we
* just created the first object.
*/
if (objects.Length() == 1)
{
cleanupTimer = new System::Timer();
cleanupTimer->onInterval.Connect(&Object::ObjectCleanup);
cleanupTimer->Start(1000);
}
}
S::Object::~Object()
{
/* Try to remove ourself from the object list
* as DeleteObject might not have been called.
*/
if (!isDeletable) objects.Remove(handle);
/* Free periodical cleanup timer if the timer
* itself is the only remaining object.
*/
if (objects.Length() == 1)
{
cleanupTimer->Stop();
DeleteObject(cleanupTimer);
}
/* Delete name string if it was created.
*/
if (name != NIL) delete name;
}
S::Int S::Object::EnableLocking(Bool enable)
{
lockingEnabled = enable;
return Success();
}
S::Int S::Object::GetNOfObjects()
{
return objects.Length();
}
S::Object *S::Object::GetNthObject(Int n)
{
return objects.GetNth(n);
}
S::Object *S::Object::GetObject(Int objectHandle, Short objectType)
{
Object *object = objects.Get(objectHandle);
if (object == NIL) return NIL;
if (object->GetObjectType() == objectType) return object;
else return NIL;
}
S::Object *S::Object::GetObject(const String &objectName)
{
for (Int i = 0; i < GetNOfObjects(); i++)
{
Object *object = GetNthObject(i);
if (object->name != NIL && *(object->name) == objectName) return object;
}
return NIL;
}
S::Int S::Object::SetName(const String &nName)
{
if (GetObject(nName) != NIL) return Error();
if (name == NIL) name = new String();
*name = nName;
return Success();
}
const S::String &S::Object::GetName() const
{
static String prefix = "Object::";
if (name == NIL) name = new String(String(prefix).Append(String::FromInt(handle)));
return *name;
}
S::Short S::Object::RequestClassID()
{
return nextClassID++;
}
S::Int S::Object::RequestObjectHandle()
{
if (initializing) return nextObjectHandle++;
else return Threads::Access::Increment(nextObjectHandle) - 1;
}
S::Int S::Object::DeleteObject(Object *object)
{
if (object == NIL || objects.Get(object->handle) == NIL) return Error();
/* Notify object that it will be deleted soon.
*/
object->EnqueueForDeletion();
object->isDeletable = True;
if (!object->IsObjectInUse())
{
/* Delete object immediately if
* it is not currently in use.
*/
objects.Remove(object->handle);
delete object;
}
else
{
/* Remove object from object list and add
* it to the list of objects to delete.
*/
objects.Remove(object->handle);
deletable.Add(object, object->handle);
}
return Success();
}
S::Void S::Object::ObjectCleanup()
{
/* Loop through all deletable objects...
*/
for (Int i = 0; i < deletable.Length(); i++)
{
Object *object = deletable.GetNth(i);
if (object->IsObjectInUse()) continue;
deletable.RemoveNth(i--);
delete object;
}
}
smooth-0.9.11~git20260403.0230c0da/classes/basic/objecttype.cpp 0000664 0000000 0000000 00000001526 15164025770 0023356 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2010 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
S::ObjectType::ObjectType(Object *iObject)
{
object = iObject;
type = Object::classID;
}
S::ObjectType::ObjectType(const ObjectType &objectType)
{
object = objectType.object;
type = objectType.type;
}
S::Bool S::ObjectType::operator ==(Short objType) const
{
return (type == objType) ? True : object->IsTypeCompatible(objType);
}
smooth-0.9.11~git20260403.0230c0da/classes/basic/setup.cpp 0000664 0000000 0000000 00000004370 15164025770 0022346 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2019 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
/* Init color constant with default values.
*/
S::GUI::Color S::Setup::BackgroundColor(240, 240, 240);
S::GUI::Color S::Setup::ClientColor(255, 255, 255);
S::GUI::Color S::Setup::ClientTextColor(0, 0, 0);
S::GUI::Color S::Setup::LightGrayColor(248, 248, 248);
S::GUI::Color S::Setup::DividerLightColor(237, 236, 232);
S::GUI::Color S::Setup::DividerDarkColor(128, 128, 128);
S::GUI::Color S::Setup::TextColor(0, 0, 0);
S::GUI::Color S::Setup::InactiveTextColor(128, 128, 128);
S::GUI::Color S::Setup::HighlightColor(55, 115, 215);
S::GUI::Color S::Setup::HighlightTextColor(255, 255, 255);
S::GUI::Color S::Setup::GradientStartColor(10, 36, 106);
S::GUI::Color S::Setup::GradientEndColor(166, 202, 240);
S::GUI::Color S::Setup::GradientTextColor(255, 255, 255);
S::GUI::Color S::Setup::TitlebarStartColor(10, 36, 106);
S::GUI::Color S::Setup::TitlebarEndColor(166, 202, 240);
S::GUI::Color S::Setup::TitlebarTextColor(255, 255, 255);
S::GUI::Color S::Setup::InactiveTitlebarStartColor(128, 128, 128);
S::GUI::Color S::Setup::InactiveTitlebarEndColor(192, 192, 192);
S::GUI::Color S::Setup::InactiveTitlebarTextColor(212, 208, 200);
S::GUI::Color S::Setup::TooltipColor(255, 255, 225);
S::GUI::Color S::Setup::TooltipTextColor(0, 0, 0);
S::GUI::Color S::Setup::LinkColor(0, 0, 225);
S::GUI::Color S::Setup::LinkHighlightColor(0, 128, 225);
#ifdef __WIN32__
S::Bool S::Setup::useIconv = S::False;
#else
S::Bool S::Setup::useIconv = S::True;
#endif
S::Float S::Setup::FontSize = 1.00;
S::Bool S::Setup::rightToLeft = S::False;
S::Int S::Setup::HoverTime = 400;
S::Int S::Setup::HoverWidth = 4;
S::Int S::Setup::HoverHeight = 4;
S::Setup::Setup()
{
}
S::Setup::Setup(const Setup &)
{
}
S::Setup::Setup(const Setup *)
{
}
smooth-0.9.11~git20260403.0230c0da/classes/errors/ 0000775 0000000 0000000 00000000000 15164025770 0020731 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/errors/Makefile 0000664 0000000 0000000 00000000745 15164025770 0022377 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../..
# Enter object files here:
OBJECTS = error.o success.o
# Enter addition commands for targets all and clean here:
ALLCMD1 = $(call makein,fs)
ALLCMD2 = $(call makein,misc)
CLEANCMD1 = $(call cleanin,fs)
CLEANCMD2 = $(call cleanin,misc)
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/errors/error.cpp 0000775 0000000 0000000 00000001446 15164025770 0022576 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2009 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::String S::Errors::Error::ToString() const
{
return "Unknown error";
}
S::Bool S::Errors::Error::operator ==(const Error &error) const
{
if (code == error.code) return True;
else return False;
}
S::Bool S::Errors::Error::operator !=(const Error &error) const
{
return !(*this == error);
}
smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/ 0000775 0000000 0000000 00000000000 15164025770 0021341 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/Makefile 0000664 0000000 0000000 00000000470 15164025770 0023002 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
# Enter object files here:
OBJECTS = endoffile.o filenotfound.o
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/endoffile.cpp 0000775 0000000 0000000 00000001175 15164025770 0024007 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2009 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::Errors::EndOfFile::EndOfFile()
{
code = -100;
}
S::String S::Errors::EndOfFile::ToString() const
{
return "End of file";
}
smooth-0.9.11~git20260403.0230c0da/classes/errors/fs/filenotfound.cpp 0000775 0000000 0000000 00000001214 15164025770 0024542 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2009 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::Errors::FileNotFound::FileNotFound()
{
code = -101;
}
S::String S::Errors::FileNotFound::ToString() const
{
return "File not found";
}
smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/ 0000775 0000000 0000000 00000000000 15164025770 0021664 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/Makefile 0000664 0000000 0000000 00000000460 15164025770 0023324 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
# Enter object files here:
OBJECTS = permissiondenied.o
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/errors/misc/permissiondenied.cpp 0000775 0000000 0000000 00000001237 15164025770 0025737 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2009 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::Errors::PermissionDenied::PermissionDenied()
{
code = -2;
}
S::String S::Errors::PermissionDenied::ToString() const
{
return "Permission denied";
}
smooth-0.9.11~git20260403.0230c0da/classes/errors/success.cpp 0000775 0000000 0000000 00000001105 15164025770 0023105 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2009 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::String S::Errors::Success::ToString() const
{
return "Operation successful";
}
smooth-0.9.11~git20260403.0230c0da/classes/files/ 0000775 0000000 0000000 00000000000 15164025770 0020517 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/files/Makefile 0000664 0000000 0000000 00000000455 15164025770 0022163 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../..
# Enter object files here:
OBJECTS = directory.o file.o
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/files/directory.cpp 0000664 0000000 0000000 00000026264 15164025770 0023241 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2022 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/* Define to get 64 bit stat call.
*/
#ifndef __WIN32__
# define _FILE_OFFSET_BITS 64
#endif
#include
#ifdef __WIN32__
# include
# include
#else
# include
# include
# include
# include
# include
# ifndef PATH_MAX
# define PATH_MAX 32768
# endif
# ifndef GLOB_ONLYDIR
# define GLOB_ONLYDIR 0
# endif
#endif
static const S::String &kDelimiter = S::Directory::GetDirectoryDelimiter();
static const S::String kSlash = "/";
static const S::String kBackslash = "\\";
static const S::String kUncPrefix = "\\\\";
static const S::String kDot = ".";
static const S::String kDots = "..";
static const S::String kTilde = "~";
static const S::String kDotElement = S::String(kDelimiter).Append(kDot).Append(kDelimiter);
static const S::String kDotsElement = S::String(kDelimiter).Append(kDots).Append(kDelimiter);
char *S::Directory::directoryDelimiter = NIL;
S::Directory::Directory()
{
}
S::Directory::Directory(const String &iDirName, const String &iDirPath)
{
dirName = iDirName;
dirPath = iDirPath;
#ifdef __WIN32__
if (dirName.Contains(kSlash)) dirName.Replace(kSlash, kDelimiter);
if (dirPath.Contains(kSlash)) dirPath.Replace(kSlash, kDelimiter);
#else
if (dirName.Contains(kBackslash)) dirName.Replace(kBackslash, kDelimiter);
if (dirPath.Contains(kBackslash)) dirPath.Replace(kBackslash, kDelimiter);
#endif
if (dirName != NIL && dirPath == NIL)
{
#ifdef __WIN32__
if (dirName.StartsWith(kDelimiter) && !dirName.StartsWith(kUncPrefix)) dirName = String(Directory::GetActiveDirectory()).Head(2).Append(dirName);
#endif
#ifdef __WIN32__
if (dirName[1] == ':' || dirName.StartsWith(kUncPrefix))
#else
if (dirName.StartsWith(kDelimiter) || dirName.StartsWith(kTilde))
#endif
{
dirPath = dirName;
dirName = NIL;
}
else
{
dirPath = String(Directory::GetActiveDirectory()).Append(kDelimiter).Append(dirName);
dirName = NIL;
}
}
if (dirName == NIL)
{
if (dirPath.EndsWith(kDelimiter)) dirPath[dirPath.Length() - 1] = 0;
Int lastBS = dirPath.FindLast(kDelimiter);
if (lastBS >= 0)
{
dirName = dirPath.Tail(dirPath.Length() - lastBS - 1);
dirPath[lastBS] = 0;
}
}
/* Replace ./ elements.
*/
if (!dirPath.EndsWith(kDelimiter)) dirPath.Append(kDelimiter);
if (dirPath.Contains(kDotElement)) dirPath.Replace(kDotElement, kDelimiter);
if (dirPath.StartsWith(String(kDot).Append(kDelimiter))) dirPath = String(Directory::GetActiveDirectory()).Append(dirPath.Tail(dirPath.Length() - 2));
/* Replace ../ elements.
*/
while (dirPath.Contains(kDotsElement))
{
Int upPos = dirPath.Find(kDotsElement);
Int prePos = dirPath.Head(upPos).FindLast(kDelimiter);
dirPath.Replace(dirPath.SubString(prePos, upPos - prePos + 3), String());
}
if (dirPath.EndsWith(kDelimiter)) dirPath[dirPath.Length() - 1] = 0;
}
S::Directory::Directory(const Directory &iDirectory)
{
*this = iDirectory;
}
S::Directory::~Directory()
{
}
S::Directory &S::Directory::operator =(const Directory &nDirectory)
{
if (&nDirectory == this) return *this;
dirName = nDirectory.dirName;
dirPath = nDirectory.dirPath;
return *this;
}
S::Directory::operator S::String() const
{
if (dirName == NIL) return dirPath;
return String(dirPath).Append(kDelimiter).Append(dirName);
}
const S::String &S::Directory::GetDirectoryName() const
{
return dirName;
}
const S::String &S::Directory::GetDirectoryPath() const
{
return dirPath;
}
const S::Array &S::Directory::GetFiles() const
{
return GetFilesByPattern("*");
}
const S::Array &S::Directory::GetDirectories() const
{
return GetDirectoriesByPattern("*");
}
const S::Array &S::Directory::GetFilesByPattern(const String &pattern) const
{
files.RemoveAll();
#ifdef __WIN32__
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append(kBackslash).Append(pattern), &findData);
Bool success = (handle != INVALID_HANDLE_VALUE);
while (success)
{
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) files.Add(File(findData.cFileName, *this));
success = FindNextFile(handle, &findData);
}
FindClose(handle);
#else
String path = String(*this).Replace("*", "\\*").Replace("?", "\\?").
Replace("[", "\\[").Replace("]", "\\]");
glob_t fileData = { 0 };
if (glob(path.Append(kSlash).Append(pattern).ConvertTo("UTF-8"), GLOB_MARK, NIL, &fileData) == 0)
{
String::InputFormat inputFormat("UTF-8");
for (size_t i = 0; i < fileData.gl_pathc; i++)
{
if (!String(fileData.gl_pathv[i]).EndsWith(kSlash)) files.Add(File(fileData.gl_pathv[i]));
}
globfree(&fileData);
}
#endif
return files;
}
const S::Array &S::Directory::GetDirectoriesByPattern(const String &pattern) const
{
directories.RemoveAll();
#ifdef __WIN32__
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append(kBackslash).Append(pattern), &findData);
Bool success = (handle != INVALID_HANDLE_VALUE);
while (success)
{
if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && String(findData.cFileName) != kDot && String(findData.cFileName) != kDots) directories.Add(Directory(findData.cFileName, *this));
success = FindNextFile(handle, &findData);
}
FindClose(handle);
#else
String path = String(*this).Replace("*", "\\*").Replace("?", "\\?").
Replace("[", "\\[").Replace("]", "\\]");
glob_t fileData = { 0 };
if (glob(path.Append(kSlash).Append(pattern).ConvertTo("UTF-8"), GLOB_MARK | GLOB_ONLYDIR, NIL, &fileData) == 0)
{
String::InputFormat inputFormat("UTF-8");
for (size_t i = 0; i < fileData.gl_pathc; i++)
{
if (String(fileData.gl_pathv[i]).EndsWith(kSlash)) directories.Add(Directory(fileData.gl_pathv[i]));
}
globfree(&fileData);
}
#endif
return directories;
}
S::DateTime S::Directory::GetCreateTime() const
{
DateTime dateTime;
if (!Exists()) return dateTime;
#ifdef __WIN32__
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(MakeExtendedPath(*this), &findData);
FindClose(handle);
SYSTEMTIME time;
FileTimeToSystemTime(&findData.ftCreationTime, &time);
dateTime.SetYMD(time.wYear, time.wMonth, time.wDay);
dateTime.SetHMS(time.wHour, time.wMinute, time.wSecond);
#endif
return dateTime;
}
S::Bool S::Directory::Exists() const
{
#ifdef __WIN32__
/* Check if root directory of a drive
*/
if (dirPath[dirPath.Length() - 1] == ':' && dirName == NIL)
{
DWORD drives = GetLogicalDrives();
if ((drives >> (dirPath.ToUpper()[0] - 'A')) & 1) return True;
else return False;
}
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(MakeExtendedPath(*this), &findData);
if (handle == INVALID_HANDLE_VALUE) return False;
FindClose(handle);
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return False;
#else
struct stat info;
if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return False;
if (!S_ISDIR(info.st_mode)) return False;
#endif
return True;
}
S::Int S::Directory::Create()
{
if (Exists()) return Success();
Bool result = False;
String directory = *this;
for (Int i = 1; i <= directory.Length(); i++)
{
if (directory[i] == '\\' || directory[i] == '/' || directory[i] == 0)
{
String path = directory.Head(i);
#ifdef __WIN32__
result = CreateDirectory(MakeExtendedPath(path), NIL);
#else
if (mkdir(path.ConvertTo("UTF-8"), 0777) == 0) result = True;
else result = False;
#endif
}
}
if (result == False) return Error();
else return Success();
}
S::Int S::Directory::Copy(const Directory &destination)
{
return Error();
}
S::Int S::Directory::Move(const Directory &destination)
{
if (!Exists()) return Error();
#ifdef __WIN32__
Bool result = MoveFile(MakeExtendedPath(*this), MakeExtendedPath(destination));
#else
Bool result = (rename(String(*this).ConvertTo("UTF-8"), String(destination).ConvertTo("UTF-8")) == 0);
#endif
if (result == False) return Error();
else return Success();
}
S::Int S::Directory::Delete()
{
#ifdef __WIN32__
Bool result = RemoveDirectory(MakeExtendedPath(*this));
#else
Bool result = (rmdir(String(*this).ConvertTo("UTF-8")) == 0);
#endif
if (result == False) return Error();
else return Success();
}
S::Int S::Directory::Empty()
{
#ifdef __WIN32__
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(MakeExtendedPath(*this).Append("\\*"), &findData);
if (handle == INVALID_HANDLE_VALUE) return Error();
do
{
if (String(findData.cFileName) == kDot || String(findData.cFileName) == kDots) continue;
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
Directory dir(findData.cFileName, *this);
dir.Empty();
dir.Delete();
}
else
{
File(findData.cFileName, *this).Delete();
}
}
while (FindNextFile(handle, &findData));
FindClose(handle);
#endif
return Success();
}
const char *S::Directory::GetDirectoryDelimiter()
{
if (directoryDelimiter == NIL)
{
#ifdef __WIN32__
directoryDelimiter = (char *) "\\";
#else
directoryDelimiter = (char *) "/";
#endif
}
return directoryDelimiter;
}
const char *S::Directory::GetUnicodePathPrefix(const String &path)
{
#ifdef __WIN32__
static const char *unicodePathPrefix = "\\\\?\\";
if (path.StartsWith(kUncPrefix)) return "";
return unicodePathPrefix;
#endif
return "";
}
S::String S::Directory::MakeExtendedPath(const String &path)
{
#ifdef __WIN32__
static const String extendedPathPrefix = "\\\\?\\";
static const String uncPathPrefix = "\\\\?\\UNC\\";
if (!path.StartsWith(extendedPathPrefix))
{
if (path.StartsWith(kUncPrefix)) return String(uncPathPrefix).Append(path.Tail(path.Length() - 2));
return String(extendedPathPrefix).Append(path);
}
#endif
return path;
}
S::String S::Directory::StripExtendedPathPrefix(const String &path)
{
#ifdef __WIN32__
static const String extendedPathPrefix = "\\\\?\\";
static const String uncPathPrefix = "\\\\?\\UNC\\";
if (path.StartsWith(extendedPathPrefix))
{
if (path.StartsWith(uncPathPrefix)) return String(kUncPrefix).Append(path.Tail(path.Length() - uncPathPrefix.Length()));
return path.Tail(path.Length() - extendedPathPrefix.Length());
}
#endif
return path;
}
S::Directory S::Directory::GetActiveDirectory()
{
#ifdef __WIN32__
Buffer buffer(32768 + 1);
GetCurrentDirectory(buffer.Size(), buffer);
String dir = (wchar_t *) buffer;
#else
Buffer buffer(PATH_MAX + 1);
String dir;
if (getcwd(buffer, buffer.Size()) != NIL) dir = buffer;
#endif
return Directory(NIL, dir);
}
S::Int S::Directory::SetActiveDirectory(const Directory &directory)
{
#ifdef __WIN32__
Bool result = SetCurrentDirectory(MakeExtendedPath(directory).Append(kBackslash));
#else
Bool result = (chdir(String(directory).ConvertTo("UTF-8")) == 0);
#endif
if (result == False) return Error();
else return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/files/file.cpp 0000664 0000000 0000000 00000025436 15164025770 0022154 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2022 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
/* Define to get 64 bit stat call.
*/
#ifndef __WIN32__
# define _FILE_OFFSET_BITS 64
#endif
#include
#include
#include
#ifdef __WIN32__
# include
#else
# include
# include
# include
# include
#endif
namespace smooth
{
#ifdef __WIN32__
typedef FILETIME FileTime;
DateTime FileTimeToDateTime(const FileTime &fileTime)
{
SYSTEMTIME utc, time;
FileTimeToSystemTime(&fileTime, &utc);
SystemTimeToTzSpecificLocalTime(NIL, &utc, &time);
DateTime dateTime;
dateTime.SetYMD(time.wYear, time.wMonth, time.wDay);
dateTime.SetHMS(time.wHour, time.wMinute, time.wSecond);
return dateTime;
}
FileTime DateTimeToFileTime(const DateTime &dateTime)
{
SYSTEMTIME time, utc;
memset(&time, 0, sizeof(time));
time.wYear = dateTime.GetYear();
time.wMonth = dateTime.GetMonth();
time.wDay = dateTime.GetDay();
time.wHour = dateTime.GetHour();
time.wMinute = dateTime.GetMinute();
time.wSecond = dateTime.GetSecond();
FileTime fileTime;
TzSpecificLocalTimeToSystemTime(NIL, &time, &utc);
SystemTimeToFileTime(&utc, &fileTime);
return fileTime;
}
Bool GetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime)
{
if (!file.Exists()) return False;
HANDLE handle = CreateFile(Directory::MakeExtendedPath(file), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL);
::GetFileTime(handle, cTime, aTime, wTime);
CloseHandle(handle);
return True;
}
Bool SetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime)
{
if (!file.Exists()) return False;
HANDLE handle = CreateFile(Directory::MakeExtendedPath(file), GENERIC_WRITE, 0, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL);
::SetFileTime(handle, cTime, aTime, wTime);
CloseHandle(handle);
return True;
}
#else
typedef time_t FileTime;
DateTime FileTimeToDateTime(const FileTime &fileTime)
{
tm time;
localtime_r(&fileTime, &time);
DateTime dateTime;
dateTime.SetYMD(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday);
dateTime.SetHMS(time.tm_hour, time.tm_min, time.tm_sec);
return dateTime;
}
FileTime DateTimeToFileTime(const DateTime &dateTime)
{
tm time;
memset(&time, 0, sizeof(time));
time.tm_year = dateTime.GetYear() - 1900;
time.tm_mon = dateTime.GetMonth() - 1;
time.tm_mday = dateTime.GetDay();
time.tm_hour = dateTime.GetHour();
time.tm_min = dateTime.GetMinute();
time.tm_sec = dateTime.GetSecond();
time.tm_isdst = -1;
return mktime(&time);
}
Bool GetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime)
{
if (!file.Exists()) return False;
struct stat info;
if (stat(String(file).ConvertTo("UTF-8"), &info) != 0) return False;
if (cTime != NIL) *cTime = info.st_mtime;
if (aTime != NIL) *aTime = info.st_atime;
if (wTime != NIL) *wTime = info.st_mtime;
return True;
}
Bool SetFileTime(const File &file, FileTime *cTime, FileTime *aTime, FileTime *wTime)
{
if (!file.Exists()) return False;
struct stat info;
struct utimbuf times;
if (stat(String(file).ConvertTo("UTF-8"), &info) != 0) return False;
times.actime = info.st_atime;
times.modtime = info.st_mtime;
if (cTime != NIL) times.modtime = *cTime;
if (aTime != NIL) times.actime = *aTime;
if (wTime != NIL) times.modtime = *wTime;
if (utime(String(file).ConvertTo("UTF-8"), ×) != 0) return False;
return True;
}
#endif
};
static const S::String &kDelimiter = S::Directory::GetDirectoryDelimiter();
static const S::String kSlash = "/";
static const S::String kBackslash = "\\";
static const S::String kUncPrefix = "\\\\";
static const S::String kDot = ".";
static const S::String kDots = "..";
static const S::String kTilde = "~";
static const S::String kDotElement = S::String(kDelimiter).Append(kDot).Append(kDelimiter);
static const S::String kDotsElement = S::String(kDelimiter).Append(kDots).Append(kDelimiter);
S::File::File()
{
}
S::File::File(const String &iFileName, const String &iFilePath)
{
fileName = iFileName;
filePath = iFilePath;
#ifdef __WIN32__
if (fileName.Contains(kSlash)) fileName.Replace(kSlash, kDelimiter);
if (filePath.Contains(kSlash)) filePath.Replace(kSlash, kDelimiter);
#else
if (fileName.Contains(kBackslash)) fileName.Replace(kBackslash, kDelimiter);
if (filePath.Contains(kBackslash)) filePath.Replace(kBackslash, kDelimiter);
#endif
if (fileName != NIL && filePath == NIL)
{
#ifdef __WIN32__
if (fileName.StartsWith(kDelimiter) && !fileName.StartsWith(kUncPrefix)) fileName = String(Directory::GetActiveDirectory()).Head(2).Append(fileName);
#endif
#ifdef __WIN32__
if (fileName[1] == ':' || fileName.StartsWith(kUncPrefix))
#else
if (fileName.StartsWith(kDelimiter) || fileName.StartsWith(kTilde))
#endif
{
filePath = fileName;
fileName = NIL;
}
else
{
filePath = String(Directory::GetActiveDirectory()).Append(kDelimiter).Append(fileName);
fileName = NIL;
}
}
if (fileName == NIL)
{
Int lastBS = filePath.FindLast(kDelimiter);
fileName = filePath.Tail(filePath.Length() - lastBS - 1);
filePath[lastBS >= 0 ? lastBS : 0] = 0;
}
/* Replace ./ elements.
*/
if (!filePath.EndsWith(kDelimiter)) filePath.Append(kDelimiter);
if (filePath.Contains(kDotElement)) filePath.Replace(kDotElement, kDelimiter);
if (filePath.StartsWith(String(kDot).Append(kDelimiter))) filePath = String(Directory::GetActiveDirectory()).Append(filePath.Tail(filePath.Length() - 2));
/* Replace ../ elements.
*/
while (filePath.Contains(kDotsElement))
{
Int upPos = filePath.Find(kDotsElement);
Int prePos = filePath.Head(upPos).FindLast(kDelimiter);
filePath.Replace(filePath.SubString(prePos, upPos - prePos + 3), String());
}
if (filePath.EndsWith(kDelimiter)) filePath[filePath.Length() - 1] = 0;
}
S::File::File(const File &iFile)
{
fileName = iFile.fileName;
filePath = iFile.filePath;
}
S::File::~File()
{
}
S::File::operator S::String() const
{
return String(filePath).Append(kDelimiter).Append(fileName);
}
const S::String &S::File::GetFileName() const
{
return fileName;
}
const S::String &S::File::GetFilePath() const
{
return filePath;
}
S::Int64 S::File::GetFileSize() const
{
if (!Exists()) return -1;
#ifdef __WIN32__
HANDLE handle = CreateFile(Directory::MakeExtendedPath(*this), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NIL);
DWORD sizeLow = 0;
DWORD sizeHigh = 0;
sizeLow = ::GetFileSize(handle, &sizeHigh);
CloseHandle(handle);
return (Int64(sizeHigh) << 32) + sizeLow;
#else
struct stat info;
if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return 0;
return info.st_size;
#endif
}
S::DateTime S::File::GetCreationTime() const
{
FileTime fileTime;
if (!GetFileTime(*this, &fileTime, NIL, NIL)) return DateTime();
return FileTimeToDateTime(fileTime);
}
S::DateTime S::File::GetAccessTime() const
{
FileTime fileTime;
if (!GetFileTime(*this, NIL, &fileTime, NIL)) return DateTime();
return FileTimeToDateTime(fileTime);
}
S::DateTime S::File::GetWriteTime() const
{
FileTime fileTime;
if (!GetFileTime(*this, NIL, NIL, &fileTime)) return DateTime();
return FileTimeToDateTime(fileTime);
}
S::Bool S::File::SetAccessTime(const DateTime &dateTime)
{
FileTime fileTime = DateTimeToFileTime(dateTime);
return SetFileTime(*this, NIL, &fileTime, NIL);
}
S::Bool S::File::SetWriteTime(const DateTime &dateTime)
{
FileTime fileTime = DateTimeToFileTime(dateTime);
return SetFileTime(*this, NIL, NIL, &fileTime);
}
S::Bool S::File::Exists() const
{
#ifdef __WIN32__
WIN32_FIND_DATA findData;
HANDLE handle = FindFirstFile(Directory::MakeExtendedPath(*this), &findData);
if (handle == INVALID_HANDLE_VALUE) return False;
FindClose(handle);
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return False;
#else
struct stat info;
if (stat(String(*this).ConvertTo("UTF-8"), &info) != 0) return False;
if (!S_ISREG(info.st_mode)) return False;
#endif
return True;
}
S::Int S::File::Create()
{
if (Exists()) return Error();
#ifdef __WIN32__
HANDLE handle = CreateFile(Directory::MakeExtendedPath(*this), GENERIC_READ, FILE_SHARE_READ, NIL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NIL);
if (handle == INVALID_HANDLE_VALUE) return Error();
CloseHandle(handle);
#endif
return Success();
}
S::Int S::File::Copy(const File &destination)
{
if (!Exists()) return Error();
#ifdef __WIN32__
Bool result = CopyFile(Directory::MakeExtendedPath(*this), Directory::MakeExtendedPath(destination), True);
#else
Bool result = False;
FILE *source = fopen(String(*this).ConvertTo("UTF-8"), "rb");
FILE *dest = fopen(String(destination).ConvertTo("UTF-8"), "wb");
if (source != NIL && dest != NIL)
{
Int bytesLeft = GetFileSize();
Int chunkSize = 32768;
UnsignedByte *buffer = new UnsignedByte [chunkSize];
while (bytesLeft)
{
chunkSize = Math::Min(chunkSize, bytesLeft);
if (fread(buffer, chunkSize, 1, source) == 1) fwrite(buffer, chunkSize, 1, dest);
else break;
bytesLeft -= chunkSize;
}
delete [] buffer;
if (!bytesLeft) result = True;
}
if (source != NIL) fclose(source);
if (dest != NIL) fclose(dest);
#endif
if (result == False) return Error();
else return Success();
}
S::Int S::File::Move(const File &destination)
{
if (!Exists()) return Error();
#ifdef __WIN32__
String fileName = Directory::MakeExtendedPath(*this);
UnsignedInt fileAttributes = GetFileAttributes(fileName);
SetFileAttributes(fileName, fileAttributes & ~FILE_ATTRIBUTE_READONLY);
Bool result = MoveFile(fileName, Directory::MakeExtendedPath(destination));
SetFileAttributes(fileName, fileAttributes);
#else
Bool result = (rename(String(*this).ConvertTo("UTF-8"), String(destination).ConvertTo("UTF-8")) == 0);
#endif
if (result == False) return Error();
else return Success();
}
S::Int S::File::Delete()
{
if (!Exists()) return Error();
#ifdef __WIN32__
String fileName = Directory::MakeExtendedPath(*this);
SetFileAttributes(fileName, GetFileAttributes(fileName) & ~FILE_ATTRIBUTE_READONLY);
Bool result = DeleteFile(fileName);
#else
Bool result = (remove(String(*this).ConvertTo("UTF-8")) == 0);
#endif
if (result == False) return Error();
else return Success();
}
S::Int S::File::Truncate()
{
if (!Exists()) return Error();
if (Delete() == Error()) return Error();
return Create();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/ 0000775 0000000 0000000 00000000000 15164025770 0021215 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/Makefile 0000664 0000000 0000000 00000001235 15164025770 0022656 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../..
# Enter object files here:
OBJECTS = bitmap.o color.o font.o surface.o
# Enter addition commands for targets all and clean here:
ALLCMD1 = $(call makein,backends)
ALLCMD2 = $(call makein,forms)
ALLCMD3 = $(call makein,imageloader)
ALLCMD4 = $(call makein,modifiers)
CLEANCMD1 = $(call cleanin,backends)
CLEANCMD2 = $(call cleanin,forms)
CLEANCMD3 = $(call cleanin,imageloader)
CLEANCMD4 = $(call cleanin,modifiers)
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/ 0000775 0000000 0000000 00000000000 15164025770 0022767 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/Makefile 0000664 0000000 0000000 00000001341 15164025770 0024426 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../..
# Enter object files here:
OBJECTS = bitmapbackend.o fontbackend.o surfacebackend.o
# Enter addition commands for targets all and clean here:
ALLCMD1 = $(call makein,cairo) && $(call makein,cocoa)
ALLCMD2 = $(call makein,gdi) && $(call makein,gdiplus)
ALLCMD3 = $(call makein,haiku) && $(call makein,xlib)
CLEANCMD1 = $(call cleanin,cairo) && $(call cleanin,cocoa)
CLEANCMD2 = $(call cleanin,gdi) && $(call cleanin,gdiplus)
CLEANCMD3 = $(call cleanin,haiku) && $(call cleanin,xlib)
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/bitmapbackend.cpp 0000775 0000000 0000000 00000021371 15164025770 0026266 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#if defined __WIN32__ && defined SMOOTH_STATIC
#include
#endif
S::GUI::BitmapBackend *CreateBitmapBackend_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapBackend(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapBackend_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapBackend(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapBackend_cI(const int nil)
{
return new S::GUI::BitmapBackend(nil);
}
S::GUI::BitmapBackend *CreateBitmapBackend_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapBackend(iBitmap);
}
S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_pV)(S::Void *) = &CreateBitmapBackend_pV;
S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_crSI)(const S::GUI::Size &, S::Int) = &CreateBitmapBackend_crSI;
S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_cI)(const int) = &CreateBitmapBackend_cI;
S::GUI::BitmapBackend *(*S::GUI::BitmapBackend::backend_creator_crB)(const S::GUI::BitmapBackend &) = &CreateBitmapBackend_crB;
S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(Void *))
{
if (backend == NIL) return Error();
backend_creator_pV = backend;
return Success();
}
S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const Size &, Int))
{
if (backend == NIL) return Error();
backend_creator_crSI = backend;
return Success();
}
S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const int))
{
if (backend == NIL) return Error();
backend_creator_cI = backend;
return Success();
}
S::Int S::GUI::BitmapBackend::SetBackend(BitmapBackend *(*backend)(const BitmapBackend &))
{
if (backend == NIL) return Error();
backend_creator_crB = backend;
return Success();
}
S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(Void *iBitmap)
{
return backend_creator_pV(iBitmap);
}
S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const Size &iSize, Int iDepth)
{
return backend_creator_crSI(iSize, iDepth);
}
S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const int nil)
{
return backend_creator_cI(nil);
}
S::GUI::BitmapBackend *S::GUI::BitmapBackend::CreateBackendInstance(const BitmapBackend &iBitmap)
{
return backend_creator_crB(iBitmap);
}
S::GUI::BitmapBackend::BitmapBackend(Void *iBitmap)
{
#if defined __WIN32__ && defined SMOOTH_STATIC
volatile Bool null = 0;
if (null) BitmapGDI();
#endif
type = BITMAP_NONE;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
S::GUI::BitmapBackend::BitmapBackend(const Size &iSize, Int iDepth)
{
type = BITMAP_NONE;
size = iSize;
depth = iDepth;
bytes = NIL;
bpp = 0;
align = 0;
}
S::GUI::BitmapBackend::BitmapBackend(const int nil)
{
type = BITMAP_NONE;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
S::GUI::BitmapBackend::BitmapBackend(const BitmapBackend &iBitmap)
{
type = BITMAP_NONE;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
S::GUI::BitmapBackend::~BitmapBackend()
{
}
S::Short S::GUI::BitmapBackend::GetBitmapType() const
{
return type;
}
const S::GUI::Size &S::GUI::BitmapBackend::GetSize() const
{
return size;
}
S::Byte S::GUI::BitmapBackend::GetDepth() const
{
return depth;
}
S::UnsignedByte *S::GUI::BitmapBackend::GetBytes() const
{
return (UnsignedByte *) bytes;
}
S::Byte S::GUI::BitmapBackend::GetBitsPerPixel() const
{
return bpp;
}
S::Byte S::GUI::BitmapBackend::GetLineAlignment() const
{
return align;
}
S::Bool S::GUI::BitmapBackend::CreateBitmap(const Size &nSize, Int nDepth)
{
return False;
}
S::Bool S::GUI::BitmapBackend::DeleteBitmap()
{
return True;
}
S::Bool S::GUI::BitmapBackend::SetSystemBitmap(Void *nBitmap)
{
return False;
}
S::Void *S::GUI::BitmapBackend::GetSystemBitmap() const
{
return NIL;
}
S::Int S::GUI::BitmapBackend::GrayscaleBitmap()
{
Point point;
for (point.y = 0; point.y < size.cy; point.y++)
{
for (point.x = 0; point.x < size.cx; point.x++)
{
Color pixel = GetPixel(point);
Int gray = (pixel.GetRed() + pixel.GetGreen() + pixel.GetBlue()) / 3;
if (depth == 32) SetPixel(point, Color(gray | (gray << 8) | (gray << 16) | (pixel.GetAlpha() << 24), Color::RGBA));
else SetPixel(point, Color(gray, gray, gray));
}
}
return Success();
}
S::Int S::GUI::BitmapBackend::InvertColors()
{
Point point;
for (point.y = 0; point.y < size.cy; point.y++)
{
for (point.x = 0; point.x < size.cx; point.x++)
{
Color pixel = GetPixel(point);
Int red = 255 - pixel.GetRed();
Int green = 255 - pixel.GetGreen();
Int blue = 255 - pixel.GetBlue();
if (depth == 32) SetPixel(point, Color(red | (green << 8) | (blue << 16) | (pixel.GetAlpha() << 24), Color::RGBA));
else SetPixel(point, Color(red, green, blue));
}
}
return Success();
}
S::Int S::GUI::BitmapBackend::ReplaceColor(const Color &iColor1, const Color &iColor2)
{
Color color1 = iColor1.ConvertTo(Color::RGB);
Color color2 = iColor2.ConvertTo(Color::RGB);
Point point;
for (point.y = 0; point.y < size.cy; point.y++)
{
for (point.x = 0; point.x < size.cx; point.x++)
{
Color pixel = GetPixel(point);
if (pixel.ConvertTo(Color::RGB) != color1) continue;
if (depth == 32) SetPixel(point, Color(Long(color2) | (pixel.GetAlpha() << 24), Color::RGBA));
else SetPixel(point, color2);
}
}
return Success();
}
S::Int S::GUI::BitmapBackend::SetBackgroundColor(const Color &iColor)
{
if (depth != 32) return Success();
Color color = iColor.ConvertTo(Color::RGB);
Point point;
for (point.y = 0; point.y < size.cy; point.y++)
{
for (point.x = 0; point.x < size.cx; point.x++)
{
Color pixel = GetPixel(point);
if (pixel.GetAlpha() != 255)
{
Color result = Color((pixel.GetRed() * pixel.GetAlpha() + color.GetRed() * (255 - pixel.GetAlpha())) / 255,
(pixel.GetGreen() * pixel.GetAlpha() + color.GetGreen() * (255 - pixel.GetAlpha())) / 255,
(pixel.GetBlue() * pixel.GetAlpha() + color.GetBlue() * (255 - pixel.GetAlpha())) / 255);
SetPixel(point, 255 << 24 | result);
}
}
}
return Success();
}
S::GUI::Bitmap S::GUI::BitmapBackend::Scale(const Size &newSize) const
{
Bitmap bitmap(newSize, depth);
Point srcPoint;
Point destPoint;
Float scaleFactorX = Float(size.cx) / Float(newSize.cx);
Float scaleFactorY = Float(size.cy) / Float(newSize.cy);
for (destPoint.y = 0; destPoint.y < newSize.cy; destPoint.y++)
{
for (destPoint.x = 0; destPoint.x < newSize.cx; destPoint.x++)
{
Float red = 0, green = 0, blue = 0, alpha = 0;
for (srcPoint.x = Int(Float(destPoint.x) * scaleFactorX); srcPoint.x < Int(Float(destPoint.x + 1) * scaleFactorX + 0.9999); srcPoint.x++)
{
for (srcPoint.y = Int(Float(destPoint.y) * scaleFactorY); srcPoint.y < Int(Float(destPoint.y + 1) * scaleFactorY + 0.9999); srcPoint.y++)
{
Int color = GetPixel(srcPoint);
Float weightX = (1.0 - Math::Max(0.0, Float(destPoint.x) * scaleFactorX - Float(srcPoint.x)) - Math::Max(0.0, Float(srcPoint.x + 1) - Float(destPoint.x + 1) * scaleFactorX)) / scaleFactorX;
Float weightY = (1.0 - Math::Max(0.0, Float(destPoint.y) * scaleFactorY - Float(srcPoint.y)) - Math::Max(0.0, Float(srcPoint.y + 1) - Float(destPoint.y + 1) * scaleFactorY)) / scaleFactorY;
red += Float( color & 255) * weightX * weightY;
green += Float((color >> 8) & 255) * weightX * weightY;
blue += Float((color >> 16) & 255) * weightX * weightY;
if (depth == 32) alpha += Float((color >> 24) & 255) * weightX * weightY;
}
}
bitmap.SetPixel(destPoint, Color(Int(red) | (Int(green) << 8) | (Int(blue) << 16) | (Int(alpha) << 24), Color::RGBA));
}
}
return bitmap;
}
S::Bool S::GUI::BitmapBackend::SetPixel(const Point &iPoint, const Color &color)
{
return False;
}
S::GUI::Color S::GUI::BitmapBackend::GetPixel(const Point &iPoint) const
{
return 0;
}
S::GUI::BitmapBackend &S::GUI::BitmapBackend::operator =(const int nil)
{
SetSystemBitmap(NIL);
return *this;
}
S::GUI::BitmapBackend &S::GUI::BitmapBackend::operator =(const BitmapBackend &newBitmap)
{
return *this;
}
S::Bool S::GUI::BitmapBackend::operator ==(const int nil) const
{
return True;
}
S::Bool S::GUI::BitmapBackend::operator !=(const int nil) const
{
return False;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/ 0000775 0000000 0000000 00000000000 15164025770 0024064 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/Makefile 0000664 0000000 0000000 00000001462 15164025770 0025527 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Change these variables to fit your project:
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
ifneq ($(BUILD_HAIKU),True)
MYCCOPTS += $(shell pkg-config --cflags pangocairo)
MYCCOPTS += $(shell pkg-config --cflags gdk-3.0)
endif
endif
else
ifeq ($(USE_BUNDLED_LIBFRIBIDI),True)
MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC
endif
endif
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_CAIRO),True)
OBJECTS += fontcairo.o surfacecairo.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/fontcairo.cpp 0000775 0000000 0000000 00000006175 15164025770 0026570 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2022 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
using namespace X11;
#include
#include
#include
S::GUI::FontBackend *CreateFontCairo(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontCairo(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontCairoTmp = S::GUI::FontBackend::SetBackend(&CreateFontCairo);
S::Int addFontCairoInitTmp = S::AddInitFunction(&S::GUI::FontCairo::Initialize);
S::Int S::GUI::FontCairo::Initialize()
{
Font::Default = "Helvetica";
Setup::FontSize = 1.0;
String font = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "font-name");
Float scaleFactor = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "text-scaling-factor").ToFloat();
if (font != NIL)
{
Font::Default = font.SubString(1, font.FindLast(" ") - 1);
Setup::FontSize = font.SubString(font.FindLast(" ") + 1, font.Length() - font.FindLast(" ") - 2).ToFloat() / Font::DefaultSize;
}
if (scaleFactor != 0) Setup::FontSize *= scaleFactor;
return Success();
}
S::GUI::FontCairo::FontCairo(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_CAIRO;
}
S::GUI::FontCairo::~FontCairo()
{
}
S::GUI::Size S::GUI::FontCairo::GetTextSize(const String &iText) const
{
if (iText == NIL) return Size();
String text = iText;
Int textLength = text.Length();
/* Set up Cairo font and calculate text size.
*/
Float dpi = Surface().GetSurfaceDPI();
cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 0, 0);
cairo_t *context = cairo_create(surface);
PangoLayout *layout = pango_cairo_create_layout(context);
PangoFontDescription *desc = pango_font_description_from_string(String(fontName)
.Append(" ")
.Append(fontStyle & Font::Italic ? "Italic " : "")
.Append(fontWeight >= Font::Bold ? "Bold " : "")
.Append(String::FromInt(Math::Round(fontSize * dpi / 96.0))));
if (textLength > 0) pango_layout_set_text(layout, text.ConvertTo("UTF-8"), -1);
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
int x = 0;
int y = 0;
pango_layout_get_pixel_size(layout, &x, &y);
g_object_unref(layout);
cairo_destroy(context);
cairo_surface_destroy(surface);
return Size(x, y - 2);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cairo/surfacecairo.cpp 0000775 0000000 0000000 00000053715 15164025770 0027254 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2022 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace X11;
#include
#include
#include
#include
#include
#include
#if (CAIRO_VERSION_MAJOR == 0 ) || \
(CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR <= 8 ) || \
(CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR == 9 && CAIRO_VERSION_MICRO <= 1)
# define CAIRO_OPERATOR_DIFFERENCE CAIRO_OPERATOR_XOR
#endif
S::GUI::SurfaceBackend *CreateSurfaceCairo(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceCairo(iSurface, maxSize);
}
S::Int surfaceCairoTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceCairo);
S::Short S::GUI::SurfaceCairo::surfaceDPI = -1;
S::GUI::SurfaceCairo::SurfaceCairo(Void *iWindow, const Size &maxSize)
{
type = SURFACE_CAIRO;
window = (X11::Window) iWindow;
paintBitmap = NIL;
display = Backends::BackendXLib::GetDisplay();
if (display != NIL) visual = XDefaultVisual(display, XDefaultScreen(display));
else visual = NIL;
context = NIL;
surface = NIL;
paintSurfaceCairo = NIL;
paintContextCairo = NIL;
if (window != NIL)
{
size = maxSize;
if (maxSize == Size())
{
size.cx = XDisplayWidth(display, XDefaultScreen(display)) + 2;
size.cy = XDisplayHeight(display, XDefaultScreen(display)) + 2;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, window, &windowAttributes);
paintBitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth);
paintSurfaceCairo = cairo_xlib_surface_create(display, paintBitmap, visual, size.cx, size.cy);
paintContextCairo = cairo_create(paintSurfaceCairo);
paintRects.Add(Rect(Point(0, 0), size));
cairo_set_antialias(paintContextCairo, CAIRO_ANTIALIAS_NONE);
allocSize = size;
}
}
S::GUI::SurfaceCairo::~SurfaceCairo()
{
if (window != NIL)
{
cairo_destroy(paintContextCairo);
cairo_surface_destroy(paintSurfaceCairo);
XFreePixmap(display, paintBitmap);
}
}
S::Int S::GUI::SurfaceCairo::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (window != NIL && !painting)
{
cairo_destroy(paintContextCairo);
cairo_surface_destroy(paintSurfaceCairo);
XFreePixmap(display, paintBitmap);
paintRects.RemoveAll();
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, window, &windowAttributes);
paintBitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth);
paintSurfaceCairo = cairo_xlib_surface_create(display, paintBitmap, visual, size.cx, size.cy);
paintContextCairo = cairo_create(paintSurfaceCairo);
paintRects.Add(Rect(Point(0, 0), size));
cairo_set_antialias(paintContextCairo, CAIRO_ANTIALIAS_NONE);
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceCairo::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceCairo::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (window != NIL)
{
GC gc = XCreateGC(display, window, 0, NIL);
XCopyArea(display, paintBitmap, window, gc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), pRect.left, pRect.top);
XFreeGC(display, gc);
}
return Success();
}
S::Int S::GUI::SurfaceCairo::StartPaint(const Rect &iPRect)
{
if (window == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
cairo_save(paintContextCairo);
cairo_rectangle(paintContextCairo, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight());
cairo_clip(paintContextCairo);
paintRects.Add(pRect);
painting++;
return Success();
}
S::Int S::GUI::SurfaceCairo::EndPaint()
{
if (!painting) return Error();
painting--;
if (painting == 0) PaintRect(paintRects.GetLast());
paintRects.RemoveNth(paintRects.Length() - 1);
cairo_restore(paintContextCairo);
return Success();
}
S::Void *S::GUI::SurfaceCairo::GetSystemSurface() const
{
return (Void *) window;
}
S::Short S::GUI::SurfaceCairo::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
Float dpi = 96.0;
if (display != NIL)
{
/* Load gdk_screen_get_monitor_scale_factor dynamically.
*/
System::DynamicLoader gdk("gdk-3");
gint (*ex_gdk_screen_get_monitor_scale_factor)(GdkScreen *, gint) = (gint (*)(GdkScreen *, gint)) gdk.GetFunctionAddress("gdk_screen_get_monitor_scale_factor");
/* Get GDK scale factor.
*/
Float scale = 1.0;
if (ex_gdk_screen_get_monitor_scale_factor != NIL) scale = ex_gdk_screen_get_monitor_scale_factor(gdk_screen_get_default(), 0);
else scale = (Int64) Number::FromIntString(getenv("GDK_SCALE"));
/* Alternatively, query the scale factor from the KDE configuration.
*/
if (scale <= 1.0) scale = Backends::BackendXLib::QueryKDESettings("KScreen", "ScaleFactor").ToFloat();
/* Alternatively, query custom DPI setting via XfConf.
*/
if (scale <= 1.0) scale = Backends::BackendXLib::QueryXfConf("xsettings", "/Xft/DPI").ToInt() / dpi;
/* Update DPI value if a scale factor has been determined.
*/
if (scale > 0) dpi *= scale;
}
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Void S::GUI::SurfaceCairo::CreateCairoContext()
{
if (context != NIL || surface != NIL) return;
surface = cairo_xlib_surface_create(display, window, visual, size.cx, size.cy);
context = cairo_create(surface);
cairo_set_antialias(context, CAIRO_ANTIALIAS_NONE);
}
S::Void S::GUI::SurfaceCairo::DestroyCairoContext()
{
if (context == NIL || surface == NIL) return;
cairo_destroy(context);
cairo_surface_destroy(surface);
context = NIL;
surface = NIL;
}
S::Int S::GUI::SurfaceCairo::SetPixel(const Point &iPoint, const Color &color)
{
if (window == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
if (!painting)
{
CreateCairoContext();
cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
cairo_rectangle(context, point.x, point.y, 1.0, 1.0);
cairo_fill(context);
DestroyCairoContext();
}
cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
cairo_rectangle(paintContextCairo, point.x, point.y, 1.0, 1.0);
cairo_fill(paintContextCairo);
return Success();
}
S::Int S::GUI::SurfaceCairo::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (window == NIL) return Success();
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
/* Draw non-straight lines manually to work around bugs in XWayland.
*/
if (pos1.x != pos2.x && pos1.y != pos2.y)
{
Int steps = Math::Max(Math::Abs(pos2.x - pos1.x), Math::Abs(pos2.y - pos1.y));
Float xAdvance = steps ? Float(pos2.x - pos1.x) / steps : 0;
Float yAdvance = steps ? Float(pos2.y - pos1.y) / steps : 0;
if (!painting)
{
CreateCairoContext();
cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
for (Int i = 0; i < steps; i++) cairo_rectangle(context, pos1.x + i * xAdvance, pos1.y + i * yAdvance, 1.0, 1.0);
cairo_fill(context);
DestroyCairoContext();
}
cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
for (Int i = 0; i < steps; i++) cairo_rectangle(paintContextCairo, pos1.x + i * xAdvance, pos1.y + i * yAdvance, 1.0, 1.0);
cairo_fill(paintContextCairo);
}
else
{
if (!painting)
{
CreateCairoContext();
cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
cairo_set_line_width(context, 1.0);
cairo_move_to(context, pos1.x + 0.01, pos1.y + 0.01);
cairo_line_to(context, pos2.x + 0.01, pos2.y + 0.01);
cairo_stroke(context);
DestroyCairoContext();
}
cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
cairo_set_line_width(paintContextCairo, 1.0);
cairo_move_to(paintContextCairo, pos1.x + 0.01, pos1.y + 0.01);
cairo_line_to(paintContextCairo, pos2.x + 0.01, pos2.y + 0.01);
cairo_stroke(paintContextCairo);
}
return Success();
}
S::Int S::GUI::SurfaceCairo::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
if (!painting)
{
CreateCairoContext();
cairo_set_source_rgb(context, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
}
cairo_set_source_rgb(paintContextCairo, color.GetRed() / 255.0, color.GetGreen() / 255.0, color.GetBlue() / 255.0);
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
if (!painting)
{
cairo_move_to(context, rect.left + ellipse.cx, rect.top);
cairo_line_to(context, rect.right - ellipse.cx, rect.top);
cairo_curve_to(context, rect.right, rect.top, rect.right, rect.top, rect.right, rect.top + ellipse.cy);
cairo_line_to(context, rect.right, rect.bottom - ellipse.cy);
cairo_curve_to(context, rect.right, rect.bottom, rect.right, rect.bottom, rect.right - ellipse.cx, rect.bottom);
cairo_line_to(context, rect.left + ellipse.cx, rect.bottom);
cairo_curve_to(context, rect.left, rect.bottom, rect.left, rect.bottom, rect.left, rect.bottom - ellipse.cy);
cairo_line_to(context, rect.left, rect.top + ellipse.cy);
cairo_curve_to(context, rect.left, rect.top, rect.left, rect.top, rect.left + ellipse.cx, rect.top);
cairo_fill(context);
}
cairo_move_to(paintContextCairo, rect.left + ellipse.cx, rect.top);
cairo_line_to(paintContextCairo, rect.right - ellipse.cx, rect.top);
cairo_curve_to(paintContextCairo, rect.right, rect.top, rect.right, rect.top, rect.right, rect.top + ellipse.cy);
cairo_line_to(paintContextCairo, rect.right, rect.bottom - ellipse.cy);
cairo_curve_to(paintContextCairo, rect.right, rect.bottom, rect.right, rect.bottom, rect.right - ellipse.cx, rect.bottom);
cairo_line_to(paintContextCairo, rect.left + ellipse.cx, rect.bottom);
cairo_curve_to(paintContextCairo, rect.left, rect.bottom, rect.left, rect.bottom, rect.left, rect.bottom - ellipse.cy);
cairo_line_to(paintContextCairo, rect.left, rect.top + ellipse.cy);
cairo_curve_to(paintContextCairo, rect.left, rect.top, rect.left, rect.top, rect.left + ellipse.cx, rect.top);
cairo_fill(paintContextCairo);
}
else
{
if (!painting)
{
cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(context);
}
cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(paintContextCairo);
}
}
else if (style == Rect::Outlined)
{
if (!painting)
{
cairo_set_line_width(context, 1.0);
cairo_rectangle(context, rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1);
cairo_stroke(context);
}
cairo_set_line_width(paintContextCairo, 1.0);
cairo_rectangle(paintContextCairo, rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1);
cairo_stroke(paintContextCairo);
}
else if (style & Rect::Inverted)
{
if (cairo_version() >= CAIRO_VERSION_ENCODE(1,9,2))
{
if (!painting)
{
cairo_set_operator(context, CAIRO_OPERATOR_DIFFERENCE);
cairo_set_source_rgb(context, 1.0, 1.0, 1.0);
cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(context);
cairo_set_operator(context, CAIRO_OPERATOR_OVER);
}
cairo_set_operator(paintContextCairo, CAIRO_OPERATOR_DIFFERENCE);
cairo_set_source_rgb(paintContextCairo, 1.0, 1.0, 1.0);
cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(paintContextCairo);
cairo_set_operator(paintContextCairo, CAIRO_OPERATOR_OVER);
}
else
{
Bitmap area(rect.GetSize());
BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize()));
area.InvertColors();
BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect);
}
}
else if (style & Rect::Dotted)
{
if (!painting)
{
for (Int x = rect.left + 1; x < rect.right; x += 2) cairo_rectangle(context, x, rect.top, 1.0, 1.0);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) cairo_rectangle(context, rect.right - 1, y, 1.0, 1.0);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) cairo_rectangle(context, x, rect.bottom - 1, 1.0, 1.0);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) cairo_rectangle(context, rect.left, y, 1.0, 1.0);
cairo_fill(context);
}
for (Int x = rect.left + 1; x < rect.right; x += 2) cairo_rectangle(paintContextCairo, x, rect.top, 1.0, 1.0);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) cairo_rectangle(paintContextCairo, rect.right - 1, y, 1.0, 1.0);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) cairo_rectangle(paintContextCairo, x, rect.bottom - 1, 1.0, 1.0);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) cairo_rectangle(paintContextCairo, rect.left, y, 1.0, 1.0);
cairo_fill(paintContextCairo);
}
if (!painting) DestroyCairoContext();
return Success();
}
S::Int S::GUI::SurfaceCairo::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow)
{
if (window == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow);
Font font = iFont;
Rect rect = iRect;
Int lineHeight = 0;
/* Set up Cairo font.
*/
Rect tRect = rightToLeft.TranslateRect(rect);
PangoLayout *layout = NIL;
PangoFontDescription *desc = pango_font_description_from_string(String(font.GetName())
.Append(" ")
.Append(font.GetStyle() & Font::Italic ? "Italic " : "")
.Append(font.GetWeight() >= Font::Bold ? "Bold " : "")
.Append(String::FromInt(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 96.0))));
if (!painting)
{
CreateCairoContext();
cairo_save(context);
cairo_rectangle(context, tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight() + 1);
cairo_clip(context);
cairo_set_source_rgb(context, font.GetColor().GetRed() / 255.0, font.GetColor().GetGreen() / 255.0, font.GetColor().GetBlue() / 255.0);
layout = pango_cairo_create_layout(context);
pango_layout_set_font_description(layout, desc);
}
cairo_save(paintContextCairo);
cairo_rectangle(paintContextCairo, tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight() + 1);
cairo_clip(paintContextCairo);
cairo_set_source_rgb(paintContextCairo, font.GetColor().GetRed() / 255.0, font.GetColor().GetGreen() / 255.0, font.GetColor().GetBlue() / 255.0);
PangoLayout *paintLayout = pango_cairo_create_layout(paintContextCairo);
pango_layout_set_font_description(paintLayout, desc);
pango_font_description_free(desc);
/* Draw text line by line.
*/
const Array &lines = string.Explode("\n");
if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3;
foreach (const String &line, lines)
{
Int lineLength = line.Length();
if (lineLength == 0) { rect.top += lineHeight; continue; }
Rect tRect = rightToLeft.TranslateRect(rect);
tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left;
Int utf8Length = (line != NIL ? strlen(line.ConvertTo("UTF-8")) : 0);
PangoAttrList *attributes = pango_attr_list_new();
PangoAttribute *underline = pango_attr_underline_new(font.GetStyle() & Font::Underline ? PANGO_UNDERLINE_SINGLE : PANGO_UNDERLINE_NONE);
PangoAttribute *strikethrough = pango_attr_strikethrough_new(font.GetStyle() & Font::StrikeOut ? True : False);
underline->end_index = utf8Length;
strikethrough->end_index = utf8Length;
pango_attr_list_insert(attributes, underline);
pango_attr_list_insert(attributes, strikethrough);
if (!painting)
{
pango_layout_set_attributes(layout, attributes);
pango_layout_set_text(layout, String(line).Append(" ").ConvertTo("UTF-8"), -1);
cairo_move_to(context, tRect.left, tRect.top);
pango_cairo_show_layout(context, layout);
}
pango_layout_set_attributes(paintLayout, attributes);
pango_layout_set_text(paintLayout, String(line).Append(" ").ConvertTo("UTF-8"), -1);
cairo_move_to(paintContextCairo, tRect.left, tRect.top);
pango_cairo_show_layout(paintContextCairo, paintLayout);
pango_attr_list_unref(attributes);
rect.top += lineHeight;
}
if (!painting)
{
g_object_unref(layout);
cairo_restore(context);
DestroyCairoContext();
}
g_object_unref(paintLayout);
cairo_restore(paintContextCairo);
return Success();
}
S::Int S::GUI::SurfaceCairo::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
/* Setup colors.
*/
Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1;
Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2;
/* Setup Cairo objects and draw gradient.
*/
cairo_pattern_t *pattern = cairo_pattern_create_linear(0, 0, style == OR_HORZ ? rect.GetWidth() : 0,
style == OR_VERT ? rect.GetHeight() : 0);
cairo_pattern_add_color_stop_rgb(pattern, 0, c1.GetRed() / 255.0, c1.GetGreen() / 255.0, c1.GetBlue() / 255.0);
cairo_pattern_add_color_stop_rgb(pattern, 1, c2.GetRed() / 255.0, c2.GetGreen() / 255.0, c2.GetBlue() / 255.0);
if (!painting)
{
CreateCairoContext();
cairo_set_source(context, pattern);
cairo_rectangle(context, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(context);
DestroyCairoContext();
}
cairo_set_source(paintContextCairo, pattern);
cairo_rectangle(paintContextCairo, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
cairo_fill(paintContextCairo);
cairo_pattern_destroy(pattern);
return Success();
}
S::Int S::GUI::SurfaceCairo::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
Bitmap premultipliedBitmap = bitmap;
PremultiplyAlpha(premultipliedBitmap);
Size srcSize = premultipliedBitmap.GetSize();
cairo_format_t srcFormat = premultipliedBitmap.GetDepth() == 32 ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
cairo_surface_t *srcSurface = cairo_image_surface_create_for_data(premultipliedBitmap.GetBytes(), srcFormat, srcSize.cx, srcSize.cy, srcSize.cx * 4);
if (!painting)
{
CreateCairoContext();
cairo_rectangle(context, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
cairo_clip(context);
cairo_translate(context, destRect.left, destRect.top);
cairo_scale(context, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight());
cairo_set_source_surface(context, srcSurface, -srcRect.left, -srcRect.top);
cairo_paint(context);
DestroyCairoContext();
}
cairo_save(paintContextCairo);
cairo_rectangle(paintContextCairo, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
cairo_clip(paintContextCairo);
cairo_translate(paintContextCairo, destRect.left, destRect.top);
cairo_scale(paintContextCairo, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight());
cairo_set_source_surface(paintContextCairo, srcSurface, -srcRect.left, -srcRect.top);
cairo_paint(paintContextCairo);
cairo_restore(paintContextCairo);
cairo_surface_destroy(srcSurface);
return Success();
}
S::Int S::GUI::SurfaceCairo::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
cairo_surface_t *bitmapSurface = cairo_image_surface_create_for_data(bitmap.GetBytes(), CAIRO_FORMAT_RGB24, bitmap.GetSize().cx, bitmap.GetSize().cy, bitmap.GetSize().cx * 4);
cairo_t *bitmapContext = cairo_create(bitmapSurface);
cairo_rectangle(bitmapContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
cairo_clip(bitmapContext);
cairo_translate(bitmapContext, destRect.left, destRect.top);
cairo_scale(bitmapContext, (float) destRect.GetWidth() / srcRect.GetWidth(), (float) destRect.GetHeight() / srcRect.GetHeight());
cairo_set_source_surface(bitmapContext, surface, -srcRect.left, -srcRect.top);
cairo_paint(bitmapContext);
cairo_destroy(bitmapContext);
cairo_surface_destroy(bitmapSurface);
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/ 0000775 0000000 0000000 00000000000 15164025770 0024053 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/Makefile 0000664 0000000 0000000 00000000704 15164025770 0025514 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_OSX),True)
OBJECTS += bitmapcocoa.o fontcocoa.o surfacecocoa.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/bitmapcocoa.mm 0000664 0000000 0000000 00000014463 15164025770 0026677 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
S::GUI::BitmapBackend *CreateBitmapCocoa_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapCocoa(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapCocoa_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapCocoa(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapCocoa_cI(const int null)
{
return new S::GUI::BitmapCocoa(null);
}
S::GUI::BitmapBackend *CreateBitmapCocoa_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapCocoa((const S::GUI::BitmapCocoa &) iBitmap);
}
S::Int bitmapCocoaTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_pV);
S::Int bitmapCocoaTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_crSI);
S::Int bitmapCocoaTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_cI);
S::Int bitmapCocoaTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapCocoa_crB);
S::GUI::BitmapCocoa::BitmapCocoa(Void *iBitmap)
{
Initialize();
SetSystemBitmap(iBitmap);
}
S::GUI::BitmapCocoa::BitmapCocoa(const Size &iSize, Int iDepth)
{
Initialize();
CreateBitmap(iSize, iDepth);
}
S::GUI::BitmapCocoa::BitmapCocoa(const int null)
{
Initialize();
SetSystemBitmap(NIL);
}
S::GUI::BitmapCocoa::BitmapCocoa(const BitmapCocoa &iBitmap)
{
Initialize();
SetSystemBitmap((Void *) iBitmap.bitmap);
depth = iBitmap.depth;
}
S::GUI::BitmapCocoa::~BitmapCocoa()
{
DeleteBitmap();
}
S::Void S::GUI::BitmapCocoa::Initialize()
{
type = BITMAP_COCOA;
bitmap = nil;
image = nil;
}
S::Bool S::GUI::BitmapCocoa::CreateBitmap(const Size &nSize, Int nDepth)
{
DeleteBitmap();
if (nDepth == -1) nDepth = [[NSScreen deepestScreen] depth];
if (nDepth != 24 && nDepth != 32) nDepth = 24;
bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: nil
pixelsWide: nSize.cx
pixelsHigh: nSize.cy
bitsPerSample: 8
samplesPerPixel: nDepth == 32 ? 4 : 3
hasAlpha: nDepth == 32
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bitmapFormat: 0
bytesPerRow: 4 * nSize.cx
bitsPerPixel: 32];
if (bitmap == nil) return False;
bytes = [bitmap bitmapData];
size = nSize;
depth = nDepth;
bpp = 32;
align = 4;
return True;
}
S::Bool S::GUI::BitmapCocoa::DeleteBitmap()
{
if (bitmap != nil)
{
if (image != nil)
{
[image release];
image = nil;
}
[bitmap release];
bitmap = nil;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
return True;
}
S::GUI::Bitmap S::GUI::BitmapCocoa::Scale(const Size &newSize) const
{
Bitmap result(newSize, depth);
NSImage *image = (NSImage *) result.GetSystemBitmap();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: (NSBitmapImageRep *) [[image representations] objectAtIndex: 0]];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: context];
[bitmap drawInRect: NSMakeRect(0, 0, newSize.cx, newSize.cy)];
[image recache];
[NSGraphicsContext restoreGraphicsState];
[pool release];
return result;
}
S::Bool S::GUI::BitmapCocoa::SetSystemBitmap(Void *nBitmap)
{
if (nBitmap == GetSystemBitmap()) return True;
if (nBitmap == NIL)
{
DeleteBitmap();
}
else
{
CreateBitmap(Size([(NSBitmapImageRep *) nBitmap pixelsWide], [(NSBitmapImageRep *) nBitmap pixelsHigh]), 8 * [(NSBitmapImageRep *) nBitmap samplesPerPixel]);
/* Copy source bitmap to destination.
*/
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: bitmap];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: context];
[(NSBitmapImageRep *) nBitmap drawInRect: NSMakeRect(0, 0, size.cx, size.cy)];
[NSGraphicsContext restoreGraphicsState];
[pool release];
}
return True;
}
S::Void *S::GUI::BitmapCocoa::GetSystemBitmap() const
{
if (image == nil && bitmap != nil)
{
image = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)];
[image addRepresentation: bitmap];
[image setFlipped: YES];
}
return (Void *) image;
}
S::Bool S::GUI::BitmapCocoa::SetPixel(const Point &point, const Color &iColor)
{
if (bytes == NIL) return False;
if (point.y >= size.cy || point.x >= size.cx) return False;
Color color = iColor.ConvertTo(Color::RGBA);
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = point.y * (size.cx * 4) + point.x * 4;
switch (depth)
{
case 24:
data[offset + 2] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 0] = color & 255;
return True;
case 32:
data[offset + 2] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 0] = color & 255;
data[offset + 3] = (color >> 24) & 255;
return True;
}
return False;
}
S::GUI::Color S::GUI::BitmapCocoa::GetPixel(const Point &point) const
{
if (bytes == NIL) return 0;
if (point.y >= size.cy || point.x >= size.cx) return 0;
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = point.y * (size.cx * 4) + point.x * 4;
switch (depth)
{
case 24:
return Color( data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset + 0], Color::RGB);
case 32:
return Color(data[offset + 3] << 24 | data[offset + 2] << 16 | data[offset + 1] << 8 | data[offset + 0], Color::RGBA);
}
return 0;
}
S::GUI::BitmapBackend &S::GUI::BitmapCocoa::operator =(const BitmapBackend &newBitmap)
{
if (&newBitmap == this) return *this;
SetSystemBitmap((Void *) ((BitmapCocoa &) newBitmap).bitmap);
return *this;
}
S::Bool S::GUI::BitmapCocoa::operator ==(const int null) const
{
if (bitmap == NIL) return True;
else return False;
}
S::Bool S::GUI::BitmapCocoa::operator !=(const int null) const
{
if (bitmap == NIL) return False;
else return True;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/fontcocoa.mm 0000664 0000000 0000000 00000007376 15164025770 0026376 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
S::GUI::FontBackend *CreateFontCocoa(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontCocoa(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontCocoaTmp = S::GUI::FontBackend::SetBackend(&CreateFontCocoa);
S::Int addFontCocoaInitTmp = S::AddInitFunction(&S::GUI::FontCocoa::Initialize);
S::Int S::GUI::FontCocoa::Initialize()
{
/* The default font size on macOS is 13pt. However, apps like Finder and other Apple
* software use various font sizes between 11 and 13pt depending on the kind of label.
*
* smooth apps look too bulky with the default 13pt font size, so we apply a scale
* factor to reduce the standard size to 12pt.
*/
Float fontSize = [NSFont systemFontSize] / 13.0 * 12.0;
Font::Default.ImportFrom("UTF-8", [[[NSFont systemFontOfSize: fontSize] familyName] UTF8String]);
Setup::FontSize = fontSize / 96.0 * 72.0 / Font::DefaultSize;
return Success();
}
S::GUI::FontCocoa::FontCocoa(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_COCOA;
}
S::GUI::FontCocoa::~FontCocoa()
{
}
S::GUI::Size S::GUI::FontCocoa::GetTextSize(const String &text) const
{
if (text == NIL) return Size();
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSFont *font = GetNativeFont(Font(fontName, fontSize, fontWeight, fontStyle));
NSDictionary *attributes = [NSDictionary dictionaryWithObject: font
forKey: NSFontAttributeName];
NSAttributedString *string = [[[NSAttributedString alloc] initWithString: [NSString stringWithUTF8String: text.ConvertTo("UTF-8")]
attributes: attributes] autorelease];
NSSize size = [string size];
[pool release];
return Size(size.width, size.height - 2);
}
NSFont *S::GUI::FontCocoa::GetNativeFont(const Font &font)
{
static SEL monoSpacedDigitSystemFontSelector = @selector(monospacedDigitSystemFontOfSize:weight:);
static Bool queryMonospacedDigitFont = [[NSFont class] respondsToSelector: monoSpacedDigitSystemFontSelector];
/* Get font object.
*/
Float dpi = Surface().GetSurfaceDPI();
NSFont *nativeFont = nil;
if (queryMonospacedDigitFont && font.GetName() == Font::Default)
{
/* Get font with monospaced digits if available.
*/
nativeFont = ((NSFont *(*)(id, SEL, CGFloat, CGFloat)) [[NSFont class] methodForSelector: monoSpacedDigitSystemFontSelector])([NSFont class], monoSpacedDigitSystemFontSelector, font.GetSize() * dpi / 72.0, 0.0);
}
else
{
/* Otherwise use standard system font.
*/
nativeFont = [[NSFontManager sharedFontManager] fontWithFamily: [NSString stringWithUTF8String: font.GetName().ConvertTo("UTF-8")]
traits: 0
weight: 5
size: font.GetSize() * dpi / 72.0];
}
/* Set font traits.
*/
if (font.GetWeight() >= Font::Bold) nativeFont = [[NSFontManager sharedFontManager] convertFont: nativeFont toHaveTrait: NSBoldFontMask];
if (font.GetStyle() & Font::Italic) nativeFont = [[NSFontManager sharedFontManager] convertFont: nativeFont toHaveTrait: NSItalicFontMask];
return nativeFont;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/cocoa/surfacecocoa.mm 0000664 0000000 0000000 00000037201 15164025770 0027046 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2023 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
S::GUI::SurfaceBackend *CreateSurfaceCocoa(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceCocoa(iSurface, maxSize);
}
S::Int surfaceCocoaTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceCocoa);
namespace smooth
{
namespace GUI
{
static NSColor *NSColorForColor(const Color &color)
{
return [NSColor colorWithCalibratedRed: color.GetRed() / 255.0
green: color.GetGreen() / 255.0
blue: color.GetBlue() / 255.0
alpha: 1.0];
}
}
}
S::Short S::GUI::SurfaceCocoa::surfaceDPI = -1;
S::GUI::SurfaceCocoa::SurfaceCocoa(Void *iWindow, const Size &maxSize)
{
type = SURFACE_COCOA;
window = (NSWindow *) iWindow;
paintImage = nil;
paintBitmap = nil;
paintPending = False;
lockCount = 0;
if (window != NIL)
{
size = maxSize;
if (maxSize == Size())
{
NSScreen *screen = [NSScreen mainScreen];
NSRect frame = [screen visibleFrame];
size.cx = frame.size.width;
size.cy = frame.size.height;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
paintImage = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)];
paintBitmap = [[[window contentView] bitmapImageRepForCachingDisplayInRect: NSMakeRect(0, 0, size.cx, size.cy)] retain];
[paintImage addRepresentation: paintBitmap];
paintRects.Add(Rect(Point(0, 0), size));
[NSBezierPath setDefaultLineWidth: 0.0];
allocSize = size;
}
}
S::GUI::SurfaceCocoa::~SurfaceCocoa()
{
if (window != NIL)
{
[paintBitmap release];
[paintImage release];
}
}
S::Int S::GUI::SurfaceCocoa::Lock()
{
SurfaceBackend::Lock();
if (++lockCount > 1 || window == NIL) return Success();
/* Draw pending areas when this is the main thread.
*/
if (paintPending && [NSThread isMainThread]) PaintRect(paintPendingRect);
/* Otherwise spin while waiting for painting to occur.
*/
while (paintPending)
{
lockCount--;
SurfaceBackend::Release();
Application::Lock::ResumeLock(Application::Lock::SuspendLock());
SurfaceBackend::Lock();
lockCount++;
}
/* Create autorelease pool.
*/
pool = [[NSAutoreleasePool alloc] init];
return Success();
}
S::Int S::GUI::SurfaceCocoa::Release()
{
if (--lockCount == 0 && window != NIL) [pool release];
SurfaceBackend::Release();
return Success();
}
S::Int S::GUI::SurfaceCocoa::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (window != NIL && !painting)
{
paintRects.RemoveAll();
[paintBitmap release];
[paintImage release];
paintImage = [[NSImage alloc] initWithSize: NSMakeSize(size.cx, size.cy)];
paintBitmap = [[[window contentView] bitmapImageRepForCachingDisplayInRect: NSMakeRect(0, 0, size.cx, size.cy)] retain];
[paintImage addRepresentation: paintBitmap];
paintRects.Add(Rect(Point(0, 0), size));
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceCocoa::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceCocoa::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (window == NIL || ![window isVisible]) return Success();
NSView *contentView = [window contentView];
NSRect rect = NSMakeRect(pRect.left, pRect.top, pRect.right - pRect.left, pRect.bottom - pRect.top);
if ([NSThread isMainThread])
{
if ([NSView focusView] == contentView)
{
/* Draw cached image if focussed.
*/
[paintImage drawInRect: rect
fromRect: rect
operation: NSCompositeCopy
fraction: 1.0];
}
else if (!Backends::BackendCocoa::IsOSXVersionAtLeast(10, 7, 0))
{
/* Lock content view and draw on older OS X versions.
*/
[contentView lockFocus];
[paintImage drawInRect: rect
fromRect: rect
operation: NSCompositeCopy
fraction: 1.0];
[window flushWindow];
[contentView unlockFocus];
}
else
{
/* Otherwise call displayRect: if not focussed.
*/
[contentView displayRect: rect];
}
paintPending = False;
}
else
{
/* Call displayRect: on main thread if in another one.
*/
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: [contentView methodSignatureForSelector: @selector(displayRect:)]];
[invocation setTarget: contentView];
[invocation setSelector: @selector(displayRect:)];
[invocation setArgument: &rect
atIndex: 2];
[invocation retainArguments];
[invocation performSelectorOnMainThread: @selector(invoke) withObject: nil waitUntilDone: NO];
paintPending = True;
paintPendingRect = pRect;
}
return Success();
}
S::Int S::GUI::SurfaceCocoa::StartPaint(const Rect &iPRect)
{
if (window == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
[NSGraphicsContext saveGraphicsState];
if (painting == 0) [NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithBitmapImageRep: paintBitmap]];
NSRectClip(NSMakeRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight()));
paintRects.Add(pRect);
painting++;
return Success();
}
S::Int S::GUI::SurfaceCocoa::EndPaint()
{
if (!painting) return Error();
painting--;
Rect paintRect = paintRects.GetLast();
paintRects.RemoveNth(paintRects.Length() - 1);
[NSGraphicsContext restoreGraphicsState];
if (painting == 0) PaintRect(paintRect);
return Success();
}
S::Void *S::GUI::SurfaceCocoa::GetSystemSurface() const
{
return (Void *) window;
}
S::Short S::GUI::SurfaceCocoa::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
Float dpi = 96.0;
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Float S::GUI::SurfaceCocoa::GetScaleFactor() const
{
/* Get screen information.
*/
static SEL scaleFactorSelector = @selector(backingScaleFactor);
static Bool canQueryScaleFactor = [[NSScreen mainScreen] respondsToSelector: scaleFactorSelector];
if (!canQueryScaleFactor || window == NIL || [window screen] == nil) return 1.0;
NSScreen *screen = [window screen];
return ((CGFloat (*)(id, SEL)) [screen methodForSelector: scaleFactorSelector])(screen, scaleFactorSelector);
}
S::Int S::GUI::SurfaceCocoa::SetPixel(const Point &iPoint, const Color &color)
{
if (window == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
Bool endPaint = painting ? False : StartPaint(Rect(point, Size(1, 1))) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[NSColorForColor(color) set];
NSRectFill(NSMakeRect(point.x, point.y, 1, 1));
if (endPaint) EndPaint();
return Success();
}
S::Int S::GUI::SurfaceCocoa::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (window == NIL) return Success();
/* Convert coordinates.
*/
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
NSPoint point1 = NSMakePoint(pos1.x + 0.5, pos1.y + 0.5);
NSPoint point2 = NSMakePoint(pos2.x + 0.5, pos2.y + 0.5);
/* Adjust to Windows GDI behavior for diagonal lines.
*/
Float scaleFactor = GetScaleFactor();
if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y) && scaleFactor == 1.0)
{
if (pos1.x < pos2.x && pos1.y < pos2.y) { point2.x--; point2.y--; }
if (pos1.x > pos2.x && pos1.y < pos2.y) { point2.x++; point2.y--; }
}
/* Adjust to Windows GDI behaviour for horizontal and vertical lines.
*/
if (point1.x < point2.x) { point1.x -= 0.5; point2.x -= 0.5; }
if (point1.x > point2.x) { point1.x += 0.5; point2.x += 0.5; }
if (point1.y < point2.y) { point1.y -= 0.5; point2.y -= 0.5; }
if (point1.y > point2.y) { point1.y += 0.5; point2.y += 0.5; }
Rect rect;
rect.left = Math::Min(point1.x, point2.x);
rect.top = Math::Min(point1.y, point2.y);
rect.right = Math::Max(point1.x, point2.x) + 1;
rect.bottom = Math::Max(point1.y, point2.y) + 1;
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[NSColorForColor(color) set];
NSBezierPath *path = [NSBezierPath bezierPath];
[path setLineWidth: 1.0];
[path moveToPoint: point1];
[path lineToPoint: point2];
[path stroke];
if (endPaint) EndPaint();
return Success();
}
S::Int S::GUI::SurfaceCocoa::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
/* ToDo: Implement drawing of rounded boxes.
*/
}
else
{
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[NSColorForColor(color) set];
NSRectFill(NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight()));
if (endPaint) EndPaint();
}
}
else if (style == Rect::Outlined)
{
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[NSColorForColor(color) set];
NSFrameRect(NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight()));
if (endPaint) EndPaint();
}
else if (style & Rect::Inverted)
{
Float scaleFactor = GetScaleFactor();
Bitmap area(rect.GetSize() * scaleFactor);
BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize()));
area.InvertColors();
BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect);
}
else if (style & Rect::Dotted)
{
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
[NSColorForColor(color) set];
NSBezierPath *path = [NSBezierPath bezierPathWithRect: NSMakeRect(rect.left + 0.5, rect.top + 0.5, rect.GetWidth() - 1, rect.GetHeight() - 1)];
CGFloat pattern[2] = { 1.0, 1.0 };
[path setLineDash: pattern count: 2 phase: 1];
[path setLineWidth: 1.0];
[path stroke];
if (endPaint) EndPaint();
}
return Success();
}
S::Int S::GUI::SurfaceCocoa::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow)
{
if (window == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow);
NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjectsAndKeys: FontCocoa::GetNativeFont(font), NSFontAttributeName,
NSColorForColor(font.GetColor()), NSForegroundColorAttributeName, nil];
if (font.GetStyle() & Font::Underline) [attributes setObject: [NSNumber numberWithInt: NSUnderlineStyleSingle] forKey: NSUnderlineStyleAttributeName];
if (font.GetStyle() & Font::StrikeOut) [attributes setObject: [NSNumber numberWithInt: NSUnderlineStyleSingle] forKey: NSStrikethroughStyleAttributeName];
Rect rect = iRect;
Int lineHeight = font.GetScaledTextSizeY() + 3;
const Array &lines = string.Explode("\n");
/* Draw to window.
*/
Rect tRect = rightToLeft.TranslateRect(rect);
NSAffineTransform *transform = [NSAffineTransform transform];
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: YES];
[NSGraphicsContext saveGraphicsState];
NSRectClip(NSMakeRect(tRect.left, tRect.top, tRect.GetWidth(), tRect.GetHeight()));
[transform scaleXBy: 1.0 yBy: -1.0];
[transform concat];
foreach (const String &line, lines)
{
tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left;
tRect.top += lineHeight;
if (line != NIL)
{
NSString *string = [NSString stringWithUTF8String: line.ConvertTo("UTF-8")];
[string drawAtPoint: NSMakePoint(tRect.left, -1.0 * (tRect.top - 1))
withAttributes: attributes];
}
}
[NSGraphicsContext restoreGraphicsState];
if (endPaint) EndPaint();
[attributes release];
return Success();
}
S::Int S::GUI::SurfaceCocoa::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
Bool endPaint = painting ? False : StartPaint(rect) == Success();
[[NSGraphicsContext currentContext] setShouldAntialias: NO];
NSGradient *gradient = [[NSGradient alloc] initWithStartingColor: NSColorForColor(color1)
endingColor: NSColorForColor(color2)];
[gradient drawInRect: NSMakeRect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight())
angle: (style == OR_HORZ ? (rightToLeft.GetRightToLeft() ? 180 : 0.0) : 270)];
[gradient release];
if (endPaint) EndPaint();
return Success();
}
S::Int S::GUI::SurfaceCocoa::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
Bitmap premultipliedBitmap = bitmap;
PremultiplyAlpha(premultipliedBitmap);
NSImage *image = (NSImage *) premultipliedBitmap.GetSystemBitmap();
Bool endPaint = painting ? False : StartPaint(destRect) == Success();
[image drawInRect: NSMakeRect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight())
fromRect: NSMakeRect(srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight())
operation: NSCompositeSourceOver
fraction: 1.0];
if (endPaint) EndPaint();
return Success();
}
S::Int S::GUI::SurfaceCocoa::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Create context for destination bitmap.
*/
NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithBitmapImageRep: (NSBitmapImageRep *) [[(NSImage *) bitmap.GetSystemBitmap() representations] objectAtIndex: 0]];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext: context];
/* Transform to adjust for flipped destination context.
*/
NSAffineTransform *transform = [NSAffineTransform transform];
[transform scaleXBy: 1.0 yBy: -1.0];
[transform translateXBy: 0.0 yBy: -1.0 * destRect.GetHeight()];
[transform set];
/* Copy drawing cache contents to destination context.
*/
[paintImage drawInRect: NSMakeRect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight())
fromRect: NSMakeRect(srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight())
operation: NSCompositeCopy
fraction: 1.0];
[(NSImage *) bitmap.GetSystemBitmap() recache];
[NSGraphicsContext restoreGraphicsState];
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/fontbackend.cpp 0000775 0000000 0000000 00000012241 15164025770 0025754 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2019 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#if defined __WIN32__ && defined SMOOTH_STATIC
#include
#endif
/* Cache computed text extents as this is very slow on Haiku.
*/
namespace smooth
{
class ExtentsCacheEntry
{
private:
UnsignedInt32 crc32;
GUI::Size extents;
public:
ExtentsCacheEntry(const String &text,
const String &fontName,
Int fontSize,
Int fontWeight,
Int fontStyle) { crc32 = String(text).Append(fontName)
.Append(String::FromInt(fontSize << 16 |
fontWeight << 4 |
fontStyle)).ComputeCRC32(); }
UnsignedInt32 GetCRC32() const { return crc32; }
const GUI::Size &GetExtents() const { return extents; }
Void SetExtents(const GUI::Size &nExtents) { extents = nExtents; }
};
static Array extentsCache;
};
S::Int addFontBackendInitTmp = S::AddInitFunction(&S::GUI::FontBackend::Initialize);
S::Int addFontBackendFreeTmp = S::AddFreeFunction(&S::GUI::FontBackend::Free);
S::GUI::FontBackend *CreateFontBackend(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::GUI::FontBackend *(*S::GUI::FontBackend::backend_creator)(const String &, Short, Short, Short, const Color &) = &CreateFontBackend;
S::Int S::GUI::FontBackend::SetBackend(FontBackend *(*backend)(const String &, Short, Short, Short, const Color &))
{
if (backend == NIL) return Error();
backend_creator = backend;
return Success();
}
S::GUI::FontBackend *S::GUI::FontBackend::CreateBackendInstance(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor)
{
return backend_creator(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::GUI::FontBackend::FontBackend(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor)
{
#if defined __WIN32__ && defined SMOOTH_STATIC
volatile Bool null = 0;
if (null) FontGDI();
#endif
type = FONT_NONE;
fontName = iFontName;
fontSize = iFontSize;
fontColor = iFontColor;
fontWeight = iFontWeight;
fontStyle = iFontStyle;
}
S::GUI::FontBackend::~FontBackend()
{
}
S::Int S::GUI::FontBackend::Initialize()
{
extentsCache.EnableLocking();
return Success();
}
S::Int S::GUI::FontBackend::Free()
{
foreach (ExtentsCacheEntry *entry, extentsCache) delete entry;
extentsCache.RemoveAll();
return Success();
}
S::Short S::GUI::FontBackend::GetFontType() const
{
return type;
}
S::Int S::GUI::FontBackend::GetTextSizeX(const String &text, Bool scaled) const
{
if (text == NIL) return 0;
Int length = text.Length();
Int offset = 0;
Int sizex = 0;
for (Int i = 0; i <= length; i++)
{
if (i < length && text[i] != '\n') continue;
sizex = (Int) Math::Max(sizex, GetTextSize(text.SubString(offset, i - offset), scaled).cx);
offset = i + 1;
}
return sizex;
}
S::Int S::GUI::FontBackend::GetTextSizeY(const String &text, Bool scaled) const
{
if (text == NIL) return 0;
Int length = text.Length();
Int lines = 1;
for (Int i = 0; i < length; i++)
{
if (text[i] == '\n') lines++;
}
/* Line height is always the same regardless of the actual text,
* so we use a default text here and multiply by the numer of lines.
*/
static String string = "abcdefghijklmnopqrstuvwxyz";
return (lines * (GetTextSize(string, scaled).cy - 1)) + (lines - 1) * 3;
}
S::GUI::Size S::GUI::FontBackend::GetTextSize(const String &text, Bool scaled) const
{
if (text == NIL) return Size();
/* Check for existing cache entry.
*/
ExtentsCacheEntry entry(text, fontName, fontSize, fontWeight, fontStyle);
Float dpi = Surface().GetSurfaceDPI();
Int crc = entry.GetCRC32();
if (ExtentsCacheEntry *cacheEntry = extentsCache.Get(crc))
{
if (scaled || Math::Abs(dpi - 96.0) < 0.1) return cacheEntry->GetExtents();
else return cacheEntry->GetExtents() * 96.0 / dpi;
}
/* Compute scaled text size.
*/
Size size = GetTextSize(text);
entry.SetExtents(size);
/* Save at most 2048 cache entries.
*/
if (extentsCache.Length() >= 2048)
{
for (Int i = 0; i < 1024; i++)
{
delete extentsCache.GetFirst();
extentsCache.RemoveNth(0);
}
}
extentsCache.Add(new ExtentsCacheEntry(entry), crc);
/* Return computed text size.
*/
if (scaled || Math::Abs(dpi - 96.0) < 0.1) return size;
else return size * 96.0 / dpi;
}
S::GUI::Size S::GUI::FontBackend::GetTextSize(const String &text) const
{
return Size();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/ 0000775 0000000 0000000 00000000000 15164025770 0023532 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/Makefile 0000664 0000000 0000000 00000001216 15164025770 0025172 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Change these variables to fit your project:
ifeq ($(USE_BUNDLED_LIBFRIBIDI),True)
MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC
endif
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_WIN32),True)
ifneq ($(BUILD_GDIPLUS),True)
OBJECTS += bitmapgdi.o fontgdi.o surfacegdi.o
endif
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/bitmapgdi.cpp 0000775 0000000 0000000 00000013527 15164025770 0026211 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::GUI::BitmapBackend *CreateBitmapGDI_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapGDI(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapGDI_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapGDI(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapGDI_cI(const int nil)
{
return new S::GUI::BitmapGDI(nil);
}
S::GUI::BitmapBackend *CreateBitmapGDI_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapGDI((const S::GUI::BitmapGDI &) iBitmap);
}
S::Int bitmapGDITmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_pV);
S::Int bitmapGDITmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_crSI);
S::Int bitmapGDITmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_cI);
S::Int bitmapGDITmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDI_crB);
S::GUI::BitmapGDI::BitmapGDI(Void *iBitmap)
{
type = BITMAP_GDI;
bitmap = NIL;
SetSystemBitmap(iBitmap);
}
S::GUI::BitmapGDI::BitmapGDI(const Size &iSize, Int iDepth)
{
type = BITMAP_GDI;
bitmap = NIL;
CreateBitmap(iSize, iDepth);
}
S::GUI::BitmapGDI::BitmapGDI(const int nil)
{
type = BITMAP_GDI;
bitmap = NIL;
SetSystemBitmap(NIL);
}
S::GUI::BitmapGDI::BitmapGDI(const BitmapGDI &iBitmap)
{
type = BITMAP_GDI;
bitmap = NIL;
SetSystemBitmap(iBitmap.bitmap);
}
S::GUI::BitmapGDI::~BitmapGDI()
{
DeleteBitmap();
}
S::Bool S::GUI::BitmapGDI::CreateBitmap(const Size &nSize, Int nDepth)
{
DeleteBitmap();
if (nDepth == -1) nDepth = 24;
if (nDepth != 24 && nDepth != 32) nDepth = 24;
UnsignedByte *buffer = new UnsignedByte [sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)];
BITMAPINFO *bmpInfo = (BITMAPINFO *) buffer;
bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo->bmiHeader.biWidth = nSize.cx;
bmpInfo->bmiHeader.biHeight = nSize.cy;
bmpInfo->bmiHeader.biPlanes = 1;
bmpInfo->bmiHeader.biBitCount = nDepth;
bmpInfo->bmiHeader.biCompression = BI_RGB;
bmpInfo->bmiHeader.biSizeImage = 0;
bmpInfo->bmiHeader.biXPelsPerMeter = 0;
bmpInfo->bmiHeader.biYPelsPerMeter = 0;
bmpInfo->bmiHeader.biClrUsed = 0;
bmpInfo->bmiHeader.biClrImportant = 0;
bmpInfo->bmiColors[0].rgbBlue = 0;
bmpInfo->bmiColors[0].rgbGreen = 0;
bmpInfo->bmiColors[0].rgbRed = 0;
bmpInfo->bmiColors[0].rgbReserved = 0;
bitmap = CreateDIBSection(NIL, bmpInfo, DIB_RGB_COLORS, (Void **) &bytes, NIL, 0);
delete [] buffer;
if (bitmap == NIL) return False;
size = nSize;
depth = nDepth;
bpp = depth;
align = 4;
return True;
}
S::Bool S::GUI::BitmapGDI::DeleteBitmap()
{
if (bitmap != NIL)
{
::DeleteObject(bitmap);
bitmap = NIL;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
return True;
}
S::Bool S::GUI::BitmapGDI::SetSystemBitmap(Void *nBitmap)
{
if (nBitmap == GetSystemBitmap()) return True;
if (nBitmap == NIL)
{
DeleteBitmap();
}
else
{
BITMAP bmp;
GetObject(nBitmap, sizeof(bmp), &bmp);
CreateBitmap(Size(bmp.bmWidth, bmp.bmHeight), bmp.bmBitsPixel);
HDC dc1 = CreateCompatibleDC(NIL);
HDC dc2 = CreateCompatibleDC(NIL);
HBITMAP backup1 = (HBITMAP) SelectObject(dc1, nBitmap);
HBITMAP backup2 = (HBITMAP) SelectObject(dc2, bitmap);
BitBlt(dc2, 0, 0, size.cx, size.cy, dc1, 0, 0, SRCCOPY);
(HBITMAP) SelectObject(dc1, backup1);
bitmap = (HBITMAP) SelectObject(dc2, backup2);
DeleteDC(dc1);
DeleteDC(dc2);
}
return True;
}
S::Void *S::GUI::BitmapGDI::GetSystemBitmap() const
{
return (Void *) bitmap;
}
S::Bool S::GUI::BitmapGDI::SetPixel(const Point &point, const Color &iColor)
{
if (bytes == NIL) return False;
if (point.y >= size.cy || point.x >= size.cx) return False;
Color color = iColor.ConvertTo(Color::RGBA);
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = 0;
switch (depth)
{
case 24:
offset = (size.cy - point.y - 1) * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3;
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
return True;
case 32:
offset = (size.cy - point.y - 1) * ( size.cx * 4) + point.x * 4;
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
data[offset + 3] = (color >> 24) & 255;
return True;
}
return False;
}
S::GUI::Color S::GUI::BitmapGDI::GetPixel(const Point &point) const
{
if (bytes == NIL) return 0;
if (point.y >= size.cy || point.x >= size.cx) return 0;
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = 0;
switch (depth)
{
case 24:
offset = (size.cy - point.y - 1) * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3;
return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB);
case 32:
offset = (size.cy - point.y - 1) * ( size.cx * 4) + point.x * 4;
return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA);
}
return 0;
}
S::GUI::BitmapBackend &S::GUI::BitmapGDI::operator =(const BitmapBackend &newBitmap)
{
if (&newBitmap == this) return *this;
SetSystemBitmap(((BitmapGDI &) newBitmap).bitmap);
return *this;
}
S::Bool S::GUI::BitmapGDI::operator ==(const int nil) const
{
if (bitmap == NIL) return True;
else return False;
}
S::Bool S::GUI::BitmapGDI::operator !=(const int nil) const
{
if (bitmap == NIL) return False;
else return True;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/fontgdi.cpp 0000775 0000000 0000000 00000005602 15164025770 0025676 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
S::GUI::FontBackend *CreateFontGDI(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontGDI(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontGDITmp = S::GUI::FontBackend::SetBackend(&CreateFontGDI);
S::Int addFontGDIInitTmp = S::AddInitFunction(&S::GUI::FontGDI::Initialize);
S::Int S::GUI::FontGDI::Initialize()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
Font::Default = ncm.lfMessageFont.lfFaceName;
Setup::FontSize = Float(-ncm.lfMessageFont.lfHeight) / 96.0 * 72.0 / Font::DefaultSize;
return Success();
}
S::GUI::FontGDI::FontGDI(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_GDI;
}
S::GUI::FontGDI::~FontGDI()
{
}
S::GUI::Size S::GUI::FontGDI::GetTextSize(const String &text) const
{
if (text == NIL) return Size();
Int textLength = text.Length();
/* Fall back to Tahoma when trying to measure Hebrew on pre Windows 8 using Segoe UI.
*/
String fontName = this->fontName;
if (fontName == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2))
{
for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x05FF) { fontName = "Tahoma"; break; }
}
/* Check for right to left characters in text.
*/
Bool rtlCharacters = False;
for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x08FF) { rtlCharacters = True; break; }
/* Set up Windows font and calculate text size.
*/
Float dpi = Surface().GetSurfaceDPI();
HDC dc = CreateCompatibleDC(NIL);
HFONT hFont = CreateFont(-Math::Round(fontSize * dpi / 72.0), 0, 0, 0, fontWeight, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, FF_ROMAN, fontName);
HFONT hOldFont = (HFONT) SelectObject(dc, hFont);
RECT tRect;
DrawTextEx(dc, text, -1, &tRect, DT_EXPANDTABS | DT_NOPREFIX | DT_LEFT | (rtlCharacters ? DT_RTLREADING : 0) | DT_CALCRECT, NIL);
SelectObject(dc, hOldFont);
::DeleteObject(hFont);
DeleteDC(dc);
return Size(tRect.right - tRect.left, tRect.bottom - tRect.top);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdi/surfacegdi.cpp 0000775 0000000 0000000 00000043241 15164025770 0026361 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2021 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
S::GUI::SurfaceBackend *CreateSurfaceGDI(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceGDI(iSurface, maxSize);
}
S::Int surfaceGDITmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceGDI);
S::Short S::GUI::SurfaceGDI::surfaceDPI = -1;
S::GUI::SurfaceGDI::SurfaceGDI(Void *iWindow, const Size &maxSize)
{
type = SURFACE_GDI;
window = (HWND) iWindow;
paintBitmap = NIL;
paintContext = NIL;
if (window != NIL)
{
HDC gdi_dc = GetWindowDC(window);
size = maxSize;
if (maxSize == Size())
{
size.cx = GetDeviceCaps(gdi_dc, HORZRES) + 2;
size.cy = GetDeviceCaps(gdi_dc, VERTRES) + 2;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
paintContext = CreateCompatibleDC(gdi_dc);
HBITMAP bitmap = CreateCompatibleBitmap(gdi_dc, size.cx, size.cy);
paintBitmap = (HBITMAP) SelectObject(paintContext, bitmap);
paintRects.Add(Rect(Point(0, 0), size));
ReleaseDC(window, gdi_dc);
allocSize = size;
}
}
S::GUI::SurfaceGDI::~SurfaceGDI()
{
if (window != NIL)
{
HBITMAP bitmap = (HBITMAP) SelectObject(paintContext, paintBitmap);
DeleteDC(paintContext);
::DeleteObject(bitmap);
}
}
S::Int S::GUI::SurfaceGDI::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (window != NIL && !painting)
{
HBITMAP bitmap = (HBITMAP) SelectObject(paintContext, paintBitmap);
::DeleteObject(bitmap);
paintRects.RemoveAll();
HDC gdi_dc = GetWindowDC(window);
bitmap = CreateCompatibleBitmap(gdi_dc, size.cx, size.cy);
paintBitmap = (HBITMAP) SelectObject(paintContext, bitmap);
paintRects.Add(Rect(Point(0, 0), size));
ReleaseDC(window, gdi_dc);
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceGDI::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceGDI::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (window != NIL)
{
HDC gdi_dc = GetWindowDC(window);
BitBlt(gdi_dc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), paintContext, pRect.left, pRect.top, SRCCOPY);
ReleaseDC(window, gdi_dc);
}
return Success();
}
S::Int S::GUI::SurfaceGDI::StartPaint(const Rect &iPRect)
{
if (window == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
HRGN region = CreateRectRgn(pRect.left, pRect.top, pRect.right, pRect.bottom);
SaveDC(paintContext);
SelectClipRgn(paintContext, region);
::DeleteObject(region);
paintRects.Add(pRect);
painting++;
return Success();
}
S::Int S::GUI::SurfaceGDI::EndPaint()
{
if (!painting) return Error();
painting--;
if (painting == 0) PaintRect(paintRects.GetLast());
paintRects.RemoveNth(paintRects.Length() - 1);
RestoreDC(paintContext, -1);
return Success();
}
S::Void *S::GUI::SurfaceGDI::GetSystemSurface() const
{
return (Void *) window;
}
S::Short S::GUI::SurfaceGDI::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
Float dpi = 96.0;
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Int S::GUI::SurfaceGDI::SetPixel(const Point &iPoint, const Color &color)
{
if (window == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
::SetPixel(gdi_dc, point.x, point.y, color);
ReleaseDC(window, gdi_dc);
}
::SetPixel(paintContext, point.x, point.y, color);
return Success();
}
S::Int S::GUI::SurfaceGDI::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (window == NIL) return Success();
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
HPEN hPen = CreatePen(PS_SOLID, 1, color);
HPEN hOldPen = NIL;
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
hOldPen = (HPEN) SelectObject(gdi_dc, hPen);
MoveToEx(gdi_dc, pos1.x, pos1.y, NIL);
LineTo(gdi_dc, pos2.x, pos2.y);
hPen = (HPEN) SelectObject(gdi_dc, hOldPen);
ReleaseDC(window, gdi_dc);
}
hOldPen = (HPEN) SelectObject(paintContext, hPen);
MoveToEx(paintContext, pos1.x, pos1.y, NIL);
LineTo(paintContext, pos2.x, pos2.y);
hPen = (HPEN) SelectObject(paintContext, hOldPen);
::DeleteObject(hPen);
return Success();
}
S::Int S::GUI::SurfaceGDI::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
HDC gdi_dc = painting ? NIL : GetWindowDC(window);
HBRUSH brush = CreateSolidBrush(color);
RECT wRect = { rect.left, rect.top, rect.right, rect.bottom };
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
HPEN pen = CreatePen(PS_SOLID, 0, color);
if (!painting)
{
HBRUSH previousBrush = (HBRUSH) SelectObject(gdi_dc, brush);
HPEN previousPen = (HPEN) SelectObject(gdi_dc, pen);
RoundRect(gdi_dc, rect.left, rect.top, rect.right, rect.bottom, ellipse.cx, ellipse.cy);
brush = (HBRUSH) SelectObject(gdi_dc, previousBrush);
pen = (HPEN) SelectObject(gdi_dc, previousPen);
}
HBRUSH previousBrush = (HBRUSH) SelectObject(paintContext, brush);
HPEN previousPen = (HPEN) SelectObject(paintContext, pen);
RoundRect(paintContext, rect.left, rect.top, rect.right, rect.bottom, ellipse.cx, ellipse.cy);
brush = (HBRUSH) SelectObject(paintContext, previousBrush);
pen = (HPEN) SelectObject(paintContext, previousPen);
::DeleteObject(pen);
}
else
{
if (!painting) FillRect(gdi_dc, &wRect, brush);
FillRect(paintContext, &wRect, brush);
}
}
else if (style == Rect::Outlined)
{
if (!painting) FrameRect(gdi_dc, &wRect, brush);
FrameRect(paintContext, &wRect, brush);
}
else if (style & Rect::Inverted)
{
if (!painting) InvertRect(gdi_dc, &wRect);
InvertRect(paintContext, &wRect);
}
else if (style & Rect::Dotted)
{
if (!painting)
{
for (Int x = rect.left + 1; x < rect.right; x += 2) ::SetPixel(gdi_dc, x, rect.top, color);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) ::SetPixel(gdi_dc, rect.right - 1, y, color);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) ::SetPixel(gdi_dc, x, rect.bottom - 1, color);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) ::SetPixel(gdi_dc, rect.left, y, color);
}
for (Int x = rect.left + 1; x < rect.right; x += 2) ::SetPixel(paintContext, x, rect.top, color);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) ::SetPixel(paintContext, rect.right - 1, y, color);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) ::SetPixel(paintContext, x, rect.bottom - 1, color);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) ::SetPixel(paintContext, rect.left, y, color);
}
::DeleteObject(brush);
if (!painting) ReleaseDC(window, gdi_dc);
return Success();
}
S::Int S::GUI::SurfaceGDI::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow)
{
if (window == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow);
Int stringLength = string.Length();
Font font = iFont;
Rect rect = iRect;
Int lineHeight = 0;
/* Fall back to Tahoma when trying to draw Hebrew on pre Windows 8 using Segoe UI.
*/
if (font.GetName() == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2))
{
for (Int i = 0; i < stringLength; i++) if (string[i] >= 0x0590 && string[i] <= 0x05FF) { font.SetName("Tahoma"); break; }
}
/* Set up Windows font.
*/
HDC gdi_dc = painting ? NIL : GetWindowDC(window);
HFONT hfont = CreateFont(-Math::Round(font.GetSize() * fontSize.TranslateY(96) / 72.0), 0, 0, 0, font.GetWeight(), font.GetStyle() & Font::Italic, font.GetStyle() & Font::Underline, font.GetStyle() & Font::StrikeOut, ANSI_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, FF_ROMAN, font.GetName());
HFONT holdfont = NIL;
HFONT holdfont2 = NIL;
if (!painting)
{
SetBkMode(gdi_dc, TRANSPARENT);
SetTextColor(gdi_dc, font.GetColor());
holdfont = (HFONT) SelectObject(gdi_dc, hfont);
}
SetBkMode(paintContext, TRANSPARENT);
SetTextColor(paintContext, font.GetColor());
holdfont2 = (HFONT) SelectObject(paintContext, hfont);
/* Draw text line by line.
*/
const Array &lines = string.Explode("\n");
if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3;
foreach (const String &line, lines)
{
Int lineLength = line.Length();
/* Check for right to left characters in text.
*/
Bool rtlCharacters = False;
for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; }
/* Draw text, reordering if necessary.
*/
Rect tRect = rightToLeft.TranslateRect(rect);
RECT wRect = { tRect.left, tRect.top, tRect.right, tRect.bottom };
if (rtlCharacters && Setup::useIconv)
{
String visualLine;
/* Reorder the string with fribidi, then get
* the glyph indices using GetCharacterPlacement
* and display using the glyph indices.
* This does not work with Kanji.
*/
FriBidiChar *visual = new FriBidiChar [lineLength + 1];
FriBidiParType type = (rightToLeft.GetRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR);
fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), lineLength, &type, visual, NIL, NIL, NIL);
visual[lineLength] = 0;
visualLine.ImportFrom("UCS-4LE", (char *) visual);
delete [] visual;
GCP_RESULTS results;
wchar_t *glyphs = new wchar_t [lineLength + 1];
ZeroMemory(&results, sizeof(results));
results.lStructSize = sizeof(results);
results.lpGlyphs = glyphs;
results.nGlyphs = lineLength + 1;
ZeroMemory(glyphs, 2 * (lineLength + 1));
if (!painting)
{
if (rightToLeft.GetRightToLeft()) SetTextAlign(gdi_dc, TA_RIGHT);
else SetTextAlign(gdi_dc, TA_LEFT);
}
if (rightToLeft.GetRightToLeft()) SetTextAlign(paintContext, TA_RIGHT);
else SetTextAlign(paintContext, TA_LEFT);
GetCharacterPlacement(paintContext, visualLine, lineLength, 0, &results, 0);
if (rightToLeft.GetRightToLeft()) wRect.left -= 10;
else wRect.right += 10;
if (!painting) ExtTextOut(gdi_dc, (rightToLeft.GetRightToLeft() ? wRect.right : wRect.left), wRect.top, ETO_CLIPPED | ETO_GLYPH_INDEX, &wRect, results.lpGlyphs, results.nGlyphs, NIL);
ExtTextOut(paintContext, (rightToLeft.GetRightToLeft() ? wRect.right : wRect.left), wRect.top, ETO_CLIPPED | ETO_GLYPH_INDEX, &wRect, results.lpGlyphs, results.nGlyphs, NIL);
delete [] glyphs;
}
else
{
/* Let Windows do any reordering and ligating.
* Works with Kanji, but RTL is only supported
* on XP and later versions of Windows and even
* later versions get the base direction wrong.
*/
if (!painting)
{
SetTextAlign(gdi_dc, TA_LEFT);
DrawTextEx(gdi_dc, line, -1, &wRect, DT_EXPANDTABS | DT_NOPREFIX | (rightToLeft.GetRightToLeft() ? DT_RIGHT : DT_LEFT) | (rtlCharacters ? DT_RTLREADING : 0), NIL);
}
SetTextAlign(paintContext, TA_LEFT);
DrawTextEx(paintContext, line, -1, &wRect, DT_EXPANDTABS | DT_NOPREFIX | (rightToLeft.GetRightToLeft() ? DT_RIGHT : DT_LEFT) | (rtlCharacters ? DT_RTLREADING : 0), NIL);
}
rect.top += lineHeight;
}
if (!painting)
{
SelectObject(gdi_dc, holdfont);
ReleaseDC(window, gdi_dc);
}
SelectObject(paintContext, holdfont2);
::DeleteObject(hfont);
return Success();
}
S::Int S::GUI::SurfaceGDI::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
/* Setup colors.
*/
Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1;
Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2;
/* Setup GDI structures and draw gradient.
*/
GRADIENT_RECT rects[1] = { { 0, 1 } };
TRIVERTEX vertices[2] = { { rect.left, rect.top, COLOR16(c1.GetRed() << 8), COLOR16(c1.GetGreen() << 8), COLOR16(c1.GetBlue() << 8), 0 },
{ rect.right, rect.bottom, COLOR16(c2.GetRed() << 8), COLOR16(c2.GetGreen() << 8), COLOR16(c2.GetBlue() << 8), 0 } };
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
if (style == OR_HORZ) GdiGradientFill(gdi_dc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_H);
else GdiGradientFill(gdi_dc, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);
ReleaseDC(window, gdi_dc);
}
if (style == OR_HORZ) GdiGradientFill(paintContext, vertices, 2, rects, 1, GRADIENT_FILL_RECT_H);
else GdiGradientFill(paintContext, vertices, 2, rects, 1, GRADIENT_FILL_RECT_V);
return Success();
}
S::Int S::GUI::SurfaceGDI::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
HDC gdi_dc = painting ? NIL : GetWindowDC(window);
HDC cdc = CreateCompatibleDC(paintContext);
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
Bitmap premultipliedBitmap = bitmap;
PremultiplyAlpha(premultipliedBitmap);
if (destRect.GetSize() == srcRect.GetSize())
{
HBITMAP backup = (HBITMAP) SelectObject(cdc, premultipliedBitmap.GetSystemBitmap());
if (!painting)
{
if (bitmap.GetDepth() == 32) AlphaBlend(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), blend);
else BitBlt(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, SRCCOPY);
}
if (bitmap.GetDepth() == 32) AlphaBlend(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), blend);
else BitBlt(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, srcRect.left, srcRect.top, SRCCOPY);
SelectObject(cdc, backup);
}
else
{
Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth());
Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight());
Size srcSize = premultipliedBitmap.GetSize();
const Bitmap &srcBitmap = premultipliedBitmap.Scale(Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY));
HBITMAP backup = (HBITMAP) SelectObject(cdc, srcBitmap.GetSystemBitmap());
if (!painting)
{
if (bitmap.GetDepth() == 32) AlphaBlend(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.GetWidth()) / scaleFactorX, Float(srcRect.GetHeight()) / scaleFactorY, blend);
else BitBlt(gdi_dc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, SRCCOPY);
}
if (bitmap.GetDepth() == 32) AlphaBlend(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.GetWidth()) / scaleFactorX, Float(srcRect.GetHeight()) / scaleFactorY, blend);
else BitBlt(paintContext, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), cdc, Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, SRCCOPY);
SelectObject(cdc, backup);
}
DeleteDC(cdc);
if (!painting) ReleaseDC(window, gdi_dc);
return Success();
}
S::Int S::GUI::SurfaceGDI::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
HDC cdc = CreateCompatibleDC(paintContext);
HBITMAP backup = (HBITMAP) SelectObject(cdc, bitmap.GetSystemBitmap());
if (destRect.GetSize() == srcRect.GetSize())
{
BitBlt(cdc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), paintContext, srcRect.left, srcRect.top, SRCCOPY);
}
else
{
SetStretchBltMode(cdc, HALFTONE);
StretchBlt(cdc, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), paintContext, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), SRCCOPY);
}
SelectObject(cdc, backup);
DeleteDC(cdc);
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/ 0000775 0000000 0000000 00000000000 15164025770 0024436 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/Makefile 0000664 0000000 0000000 00000000716 15164025770 0026102 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_GDIPLUS),True)
OBJECTS += bitmapgdiplus.o fontgdiplus.o surfacegdiplus.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/bitmapgdiplus.cpp 0000775 0000000 0000000 00000012665 15164025770 0030023 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
S::GUI::BitmapBackend *CreateBitmapGDIPlus_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapGDIPlus(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapGDIPlus_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapGDIPlus(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapGDIPlus_cI(const int nil)
{
return new S::GUI::BitmapGDIPlus(nil);
}
S::GUI::BitmapBackend *CreateBitmapGDIPlus_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapGDIPlus((const S::GUI::BitmapGDIPlus &) iBitmap);
}
S::Int bitmapGDIPlusTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_pV);
S::Int bitmapGDIPlusTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_crSI);
S::Int bitmapGDIPlusTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_cI);
S::Int bitmapGDIPlusTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapGDIPlus_crB);
S::GUI::BitmapGDIPlus::BitmapGDIPlus(Void *iBitmap)
{
type = BITMAP_GDIPLUS;
bitmap = NIL;
hBitmap = NIL;
SetSystemBitmap(iBitmap);
}
S::GUI::BitmapGDIPlus::BitmapGDIPlus(const Size &iSize, Int iDepth)
{
type = BITMAP_GDIPLUS;
bitmap = NIL;
hBitmap = NIL;
CreateBitmap(iSize, iDepth);
}
S::GUI::BitmapGDIPlus::BitmapGDIPlus(const int nil)
{
type = BITMAP_GDIPLUS;
bitmap = NIL;
hBitmap = NIL;
SetSystemBitmap(NIL);
}
S::GUI::BitmapGDIPlus::BitmapGDIPlus(const BitmapGDIPlus &iBitmap)
{
type = BITMAP_GDIPLUS;
bitmap = NIL;
hBitmap = NIL;
if (iBitmap != NIL)
{
CreateBitmap(iBitmap.GetSize(), iBitmap.GetDepth());
memcpy(bytes, iBitmap.GetBytes(), (bpp / 8) * size.cx * size.cy);
}
}
S::GUI::BitmapGDIPlus::~BitmapGDIPlus()
{
DeleteBitmap();
}
S::Bool S::GUI::BitmapGDIPlus::CreateBitmap(const Size &nSize, Int nDepth)
{
DeleteBitmap();
if (nDepth == -1) nDepth = 32;
if (nDepth != 32) nDepth = 32;
bytes = new UnsignedByte [(nDepth / 8) * nSize.cx * nSize.cy];
bitmap = new Gdiplus::Bitmap(nSize.cx, nSize.cy, nSize.cx * (nDepth / 8), PixelFormat32bppARGB, (BYTE *) bytes);
if (bitmap == NIL) return False;
size = nSize;
depth = nDepth;
bpp = depth;
align = 4;
return True;
}
S::Bool S::GUI::BitmapGDIPlus::DeleteBitmap()
{
if (bitmap != NIL)
{
delete bitmap;
if (hBitmap != NIL) ::DeleteObject(hBitmap);
bitmap = NIL;
hBitmap = NIL;
size = Size(0, 0);
depth = 0;
delete [] (UnsignedByte *) bytes;
bytes = NIL;
bpp = 0;
align = 0;
}
return True;
}
S::Bool S::GUI::BitmapGDIPlus::SetSystemBitmap(Void *nBitmap)
{
if (nBitmap == GetSystemBitmap()) return True;
if (nBitmap == NIL)
{
DeleteBitmap();
}
else
{
Gdiplus::Bitmap *gdipBitmap = (Gdiplus::Bitmap *) nBitmap;
CreateBitmap(Size(gdipBitmap->GetWidth(), gdipBitmap->GetHeight()), 32);
Gdiplus::Graphics graphics(bitmap);
graphics.DrawImage(gdipBitmap, 0, 0, gdipBitmap->GetWidth(), gdipBitmap->GetHeight());
}
return True;
}
S::Void *S::GUI::BitmapGDIPlus::GetSystemBitmap() const
{
return (Void *) bitmap;
}
S::Bool S::GUI::BitmapGDIPlus::SetPixel(const Point &point, const Color &iColor)
{
if (bytes == NIL) return False;
if (point.y >= size.cy || point.x >= size.cx) return False;
Color color = iColor.ConvertTo(Color::RGBA);
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = 0;
switch (depth)
{
case 24:
offset = point.y * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3;
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
return True;
case 32:
offset = point.y * ( size.cx * 4) + point.x * 4;
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
data[offset + 3] = (color >> 24) & 255;
return True;
}
return False;
}
S::GUI::Color S::GUI::BitmapGDIPlus::GetPixel(const Point &point) const
{
if (bytes == NIL) return 0;
if (point.y >= size.cy || point.x >= size.cx) return 0;
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = 0;
switch (depth)
{
case 24:
offset = point.y * (((4 - ((size.cx * 3) & 3)) & 3) + size.cx * 3) + point.x * 3;
return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB);
case 32:
offset = point.y * ( size.cx * 4) + point.x * 4;
return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA);
}
return 0;
}
S::GUI::BitmapBackend &S::GUI::BitmapGDIPlus::operator =(const BitmapBackend &newBitmap)
{
if (&newBitmap == this) return *this;
DeleteBitmap();
if (newBitmap != NIL)
{
CreateBitmap(newBitmap.GetSize(), newBitmap.GetDepth());
memcpy(bytes, newBitmap.GetBytes(), (bpp / 8) * size.cx * size.cy);
}
return *this;
}
S::Bool S::GUI::BitmapGDIPlus::operator ==(const int nil) const
{
if (bitmap == NIL) return True;
else return False;
}
S::Bool S::GUI::BitmapGDIPlus::operator !=(const int nil) const
{
if (bitmap == NIL) return False;
else return True;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/fontgdiplus.cpp 0000775 0000000 0000000 00000005405 15164025770 0027507 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
S::GUI::FontBackend *CreateFontGDIPlus(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontGDIPlus(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontGDIPlusTmp = S::GUI::FontBackend::SetBackend(&CreateFontGDIPlus);
S::Int addFontGDIPlusInitTmp = S::AddInitFunction(&S::GUI::FontGDIPlus::Initialize);
S::Int S::GUI::FontGDIPlus::Initialize()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(ncm);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
Font::Default = ncm.lfMessageFont.lfFaceName;
Setup::FontSize = Float(-ncm.lfMessageFont.lfHeight) / 96.0 * 72.0 / Font::DefaultSize;
return Success();
}
S::GUI::FontGDIPlus::FontGDIPlus(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_GDIPLUS;
}
S::GUI::FontGDIPlus::~FontGDIPlus()
{
}
S::GUI::Size S::GUI::FontGDIPlus::GetTextSize(const String &text) const
{
if (text == NIL) return Size();
Int textLength = text.Length();
/* Fall back to Tahoma when trying to measure Hebrew on pre Windows 8 using Segoe UI.
*/
String fontName = this->fontName;
if (fontName == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2))
{
for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x05FF) { fontName = "Tahoma"; break; }
}
/* Set up GDI+ font and calculate text size.
*/
Float dpi = Surface().GetSurfaceDPI();
Gdiplus::Graphics gdip_context((HWND) NIL);
Gdiplus::Font gdip_font(fontName, fontSize * dpi / 96.0, fontWeight >= Font::Bold ? Gdiplus::FontStyleBold : Gdiplus::FontStyleRegular);
Gdiplus::StringFormat gdip_format(Gdiplus::StringFormatFlagsNoWrap | Gdiplus::StringFormatFlagsMeasureTrailingSpaces);
Gdiplus::RectF gdip_rect;
gdip_format.SetAlignment(Gdiplus::StringAlignmentNear);
gdip_context.MeasureString(text, -1, &gdip_font, Gdiplus::PointF(0.0, 0.0), &gdip_format, &gdip_rect);
return Size(gdip_rect.Width, gdip_rect.Height - 2);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/gdiplus/surfacegdiplus.cpp 0000775 0000000 0000000 00000035601 15164025770 0030172 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
S::GUI::SurfaceBackend *CreateSurfaceGDIPlus(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceGDIPlus(iSurface, maxSize);
}
S::Int surfaceGDIPlusTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceGDIPlus);
S::Short S::GUI::SurfaceGDIPlus::surfaceDPI = -1;
S::GUI::SurfaceGDIPlus::SurfaceGDIPlus(Void *iWindow, const Size &maxSize)
{
type = SURFACE_GDIPLUS;
window = (HWND) iWindow;
paintBitmap = NIL;
paintContext = NIL;
if (window != NIL)
{
HDC gdi_dc = GetWindowDC(window);
size = maxSize;
if (maxSize == Size())
{
size.cx = GetDeviceCaps(gdi_dc, HORZRES) + 2;
size.cy = GetDeviceCaps(gdi_dc, VERTRES) + 2;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc);
paintBitmap = new Gdiplus::Bitmap(size.cx, size.cy, graphics);
paintContext = new Gdiplus::Graphics(paintBitmap);
paintRects.Add(Rect(Point(0, 0), size));
delete graphics;
ReleaseDC(window, gdi_dc);
allocSize = size;
}
}
S::GUI::SurfaceGDIPlus::~SurfaceGDIPlus()
{
if (window != NIL)
{
delete paintContext;
delete paintBitmap;
}
}
S::Int S::GUI::SurfaceGDIPlus::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (window != NIL && !painting)
{
delete paintContext;
delete paintBitmap;
paintRects.RemoveAll();
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc);
paintBitmap = new Gdiplus::Bitmap(size.cx, size.cy, graphics);
paintContext = new Gdiplus::Graphics(paintBitmap);
paintRects.Add(Rect(Point(0, 0), size));
delete graphics;
ReleaseDC(window, gdi_dc);
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceGDIPlus::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceGDIPlus::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (window != NIL)
{
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *graphics = new Gdiplus::Graphics(gdi_dc);
Gdiplus::RectF srcRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight());
Gdiplus::RectF destRect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight());
graphics->DrawImage(paintBitmap, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
delete graphics;
ReleaseDC(window, gdi_dc);
}
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::StartPaint(const Rect &iPRect)
{
if (window == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
paintStates.Add(paintContext->Save());
paintRects.Add(pRect);
paintContext->SetClip(Gdiplus::Rect(pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight()));
painting++;
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::EndPaint()
{
if (!painting) return Error();
painting--;
if (painting == 0) PaintRect(paintRects.GetLast());
paintContext->Restore(paintStates.GetLast());
paintRects.RemoveNth(paintRects.Length() - 1);
paintStates.RemoveNth(paintStates.Length() - 1);
return Success();
}
S::Void *S::GUI::SurfaceGDIPlus::GetSystemSurface() const
{
return (Void *) window;
}
S::Short S::GUI::SurfaceGDIPlus::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
Float dpi = 96.0;
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Int S::GUI::SurfaceGDIPlus::SetPixel(const Point &iPoint, const Color &color)
{
if (window == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
Gdiplus::Bitmap bitmap(1, 1);
bitmap.SetPixel(0, 0, Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue()));
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc);
pGraphics->DrawImage(&bitmap, point.x, point.y);
delete pGraphics;
ReleaseDC(window, gdi_dc);
}
paintContext->DrawImage(&bitmap, point.x, point.y);
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (window == NIL) return Success();
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
/* Adjust to Windows GDI behavior for diagonal lines.
*/
if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y))
{
if (pos1.x < pos2.x) pos2.x--;
else if (pos1.x > pos2.x) pos2.x++;
if (pos1.y < pos2.y) pos2.y--;
else if (pos1.y > pos2.y) pos2.y++;
}
/* Adjust to Windows GDI behaviour for horizontal and vertical lines.
*/
if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--;
if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--;
if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--;
if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--;
if (pos1 == pos2) return SetPixel(rightToLeft.TranslatePoint(pos1), color);
Gdiplus::Pen pen(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue()));
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc);
pGraphics->DrawLine(&pen, pos1.x, pos1.y, pos2.x, pos2.y);
delete pGraphics;
ReleaseDC(window, gdi_dc);
}
paintContext->DrawLine(&pen, pos1.x, pos1.y, pos2.x, pos2.y);
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
Gdiplus::SolidBrush gdip_brush(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue()));
Gdiplus::Pen gdip_pen(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue()));
Gdiplus::Rect gdip_rect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
HDC gdi_dc = NIL;
Gdiplus::Graphics *pGraphics = NIL;
if (!painting)
{
gdi_dc = GetWindowDC(window);
pGraphics = new Gdiplus::Graphics(gdi_dc);
}
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
/* ToDo: Allow drawing of rounded rects.
*/
}
else
{
if (!painting) pGraphics->FillRectangle(&gdip_brush, gdip_rect);
paintContext->FillRectangle(&gdip_brush, gdip_rect);
}
}
else if (style == Rect::Outlined)
{
gdip_rect.Width--;
gdip_rect.Height--;
if (!painting) pGraphics->DrawRectangle(&gdip_pen, gdip_rect);
paintContext->DrawRectangle(&gdip_pen, gdip_rect);
}
else if (style & Rect::Inverted)
{
Bitmap area(rect.GetSize());
BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize()));
area.InvertColors();
BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect);
}
else if (style & Rect::Dotted)
{
if (!painting)
{
for (Int x = rect.left + 1; x < rect.right; x += 2) pGraphics->DrawLine(&gdip_pen, x, rect.top, x, rect.top - 1);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) pGraphics->DrawLine(&gdip_pen, rect.right - 1, y, rect.right, y);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) pGraphics->DrawLine(&gdip_pen, x, rect.bottom - 1, x, rect.bottom);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) pGraphics->DrawLine(&gdip_pen, rect.left, y, rect.left - 1, y);
}
for (Int x = rect.left + 1; x < rect.right; x += 2) paintContext->DrawLine(&gdip_pen, x, rect.top, x, rect.top - 1);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) paintContext->DrawLine(&gdip_pen, rect.right - 1, y, rect.right, y);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) paintContext->DrawLine(&gdip_pen, x, rect.bottom - 1, x, rect.bottom);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) paintContext->DrawLine(&gdip_pen, rect.left, y, rect.left - 1, y);
}
if (!painting)
{
delete pGraphics;
ReleaseDC(window, gdi_dc);
}
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow)
{
if (window == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, iFont, shadow);
Int stringLength = string.Length();
Font font = iFont;
Rect rect = iRect;
Int lineHeight = 0;
Color color = font.GetColor();
/* Fall back to Tahoma when trying to draw Hebrew on pre Windows 8 using Segoe UI.
*/
if (font.GetName() == "Segoe UI" && !Backends::BackendWin32::IsWindowsVersionAtLeast(VER_PLATFORM_WIN32_NT, 6, 2))
{
for (Int i = 0; i < stringLength; i++) if (string[i] >= 0x0590 && string[i] <= 0x05FF) { font.SetName("Tahoma"); break; }
}
/* Set up GDI+ font.
*/
Gdiplus::Font gdip_font(font.GetName(), fontSize.TranslateY(font.GetSize()), (font.GetWeight() >= Font::Bold ? Gdiplus::FontStyleBold : Gdiplus::FontStyleRegular) |
(font.GetStyle() & Font::Italic ? Gdiplus::FontStyleItalic : Gdiplus::FontStyleRegular) |
(font.GetStyle() & Font::Underline ? Gdiplus::FontStyleUnderline : Gdiplus::FontStyleRegular) |
(font.GetStyle() & Font::StrikeOut ? Gdiplus::FontStyleStrikeout : Gdiplus::FontStyleRegular));
Gdiplus::SolidBrush gdip_brush(Gdiplus::Color(color.GetRed(), color.GetGreen(), color.GetBlue()));
Gdiplus::StringFormat gdip_format(Gdiplus::StringFormatFlagsNoWrap);
HDC gdi_dc = NIL;
Gdiplus::Graphics *pGraphics = NIL;
if (!painting)
{
gdi_dc = GetWindowDC(window);
pGraphics = new Gdiplus::Graphics(gdi_dc);
}
/* Draw text line by line.
*/
const Array &lines = string.Explode("\n");
if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3;
foreach (const String &line, lines)
{
Int lineLength = line.Length();
/* Check for right to left characters in text.
*/
Bool rtlCharacters = False;
for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; }
Rect tRect = rightToLeft.TranslateRect(rect);
Gdiplus::RectF gdip_rect(tRect.left, tRect.top, tRect.GetWidth() + 2, tRect.GetHeight());
if (rtlCharacters) gdip_format.SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap | Gdiplus::StringFormatFlagsDirectionRightToLeft);
else gdip_format.SetFormatFlags(Gdiplus::StringFormatFlagsNoWrap);
if ((!rtlCharacters && rightToLeft.GetRightToLeft()) ||
( rtlCharacters && !rightToLeft.GetRightToLeft())) gdip_format.SetAlignment(Gdiplus::StringAlignmentFar);
else gdip_format.SetAlignment(Gdiplus::StringAlignmentNear);
if (!painting) pGraphics->DrawString(line, -1, &gdip_font, gdip_rect, &gdip_format, &gdip_brush);
paintContext->DrawString(line, -1, &gdip_font, gdip_rect, &gdip_format, &gdip_brush);
rect.top += lineHeight;
}
if (!painting)
{
delete pGraphics;
ReleaseDC(window, gdi_dc);
}
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
/* Setup colors.
*/
Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1;
Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2;
/* Setup GDI+ objects and draw gradient.
*/
Gdiplus::LinearGradientBrush gdip_brush(Gdiplus::Point(rect.left, rect.top),
Gdiplus::Point(rect.left + (style == OR_HORZ ? rect.GetWidth() : 0),
rect.top + (style == OR_VERT ? rect.GetHeight() : 0)),
Gdiplus::Color(c1.GetRed(), c1.GetGreen(), c1.GetBlue()),
Gdiplus::Color(c2.GetRed(), c2.GetGreen(), c2.GetBlue()));
Gdiplus::Rect gdip_rect(rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *pGraphics = new Gdiplus::Graphics(gdi_dc);
pGraphics->FillRectangle(&gdip_brush, gdip_rect);
delete pGraphics;
ReleaseDC(window, gdi_dc);
}
paintContext->FillRectangle(&gdip_brush, gdip_rect);
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
Gdiplus::Bitmap *gdip_bitmap = (Gdiplus::Bitmap *) bitmap.GetSystemBitmap();
if (!painting)
{
HDC gdi_dc = GetWindowDC(window);
Gdiplus::Graphics *screen = new Gdiplus::Graphics(gdi_dc);
screen->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
screen->DrawImage(gdip_bitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL);
delete screen;
ReleaseDC(window, gdi_dc);
}
paintContext->SetCompositingMode(Gdiplus::CompositingModeSourceOver);
paintContext->DrawImage(gdip_bitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL);
return Success();
}
S::Int S::GUI::SurfaceGDIPlus::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
Gdiplus::Bitmap *gdip_bitmap = (Gdiplus::Bitmap *) bitmap.GetSystemBitmap();
Gdiplus::Graphics gdip_graphics(gdip_bitmap);
gdip_graphics.DrawImage(paintBitmap, Gdiplus::Rect(destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight()), srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), Gdiplus::UnitPixel, NIL, NIL, NIL);
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/ 0000775 0000000 0000000 00000000000 15164025770 0024070 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/Makefile 0000664 0000000 0000000 00000000706 15164025770 0025533 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_HAIKU),True)
OBJECTS += bitmaphaiku.o fonthaiku.o surfacehaiku.o
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/bitmaphaiku.cpp 0000664 0000000 0000000 00000011614 15164025770 0027075 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2024 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
S::GUI::BitmapBackend *CreateBitmapHaiku_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapHaiku(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapHaiku_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapHaiku(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapHaiku_cI(const int nil)
{
return new S::GUI::BitmapHaiku(nil);
}
S::GUI::BitmapBackend *CreateBitmapHaiku_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapHaiku((const S::GUI::BitmapHaiku &) iBitmap);
}
S::Int bitmapHaikuTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_pV);
S::Int bitmapHaikuTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_crSI);
S::Int bitmapHaikuTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_cI);
S::Int bitmapHaikuTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapHaiku_crB);
S::GUI::BitmapHaiku::BitmapHaiku(Void *iBitmap)
{
type = BITMAP_HAIKU;
bitmap = NIL;
SetSystemBitmap(iBitmap);
}
S::GUI::BitmapHaiku::BitmapHaiku(const Size &iSize, Int iDepth)
{
type = BITMAP_HAIKU;
bitmap = NIL;
CreateBitmap(iSize, iDepth);
}
S::GUI::BitmapHaiku::BitmapHaiku(const int nil)
{
type = BITMAP_HAIKU;
bitmap = NIL;
SetSystemBitmap(NIL);
}
S::GUI::BitmapHaiku::BitmapHaiku(const BitmapHaiku &iBitmap)
{
type = BITMAP_HAIKU;
bitmap = NIL;
SetSystemBitmap((Void *) iBitmap.bitmap);
}
S::GUI::BitmapHaiku::~BitmapHaiku()
{
DeleteBitmap();
}
S::Bool S::GUI::BitmapHaiku::CreateBitmap(const Size &nSize, Int nDepth)
{
DeleteBitmap();
if (nDepth == -1) nDepth = 24;
if (nDepth != 24 && nDepth != 32) nDepth = 24;
bitmap = new BBitmap(BRect(0, 0, nSize.cx - 1, nSize.cy - 1), nDepth == 32 ? B_RGBA32 : B_RGB32, true);
if (bitmap == NIL) return False;
bytes = bitmap->Bits();
size = nSize;
depth = nDepth;
bpp = 32;
align = 4;
return True;
}
S::Bool S::GUI::BitmapHaiku::DeleteBitmap()
{
if (bitmap != NIL)
{
delete bitmap;
bitmap = NIL;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
return True;
}
S::Bool S::GUI::BitmapHaiku::SetSystemBitmap(Void *nBitmap)
{
if (nBitmap == GetSystemBitmap()) return True;
if (nBitmap == NIL)
{
DeleteBitmap();
}
else
{
BBitmap *haikuBitmap = (BBitmap *) nBitmap;
BRect bounds = haikuBitmap->Bounds();
CreateBitmap(Size(bounds.right + 1, bounds.bottom + 1), haikuBitmap->ColorSpace() == B_RGBA32 ? 32 : 24);
BView *view = new BView(bounds, NULL, B_FOLLOW_ALL_SIDES, 0);
bitmap->AddChild(view);
bitmap->Lock();
view->DrawBitmap(haikuBitmap, BPoint(0, 0));
bitmap->Unlock();
bitmap->RemoveChild(view);
delete view;
}
return True;
}
S::Void *S::GUI::BitmapHaiku::GetSystemBitmap() const
{
return (Void *) bitmap;
}
S::Bool S::GUI::BitmapHaiku::SetPixel(const Point &point, const Color &iColor)
{
if (bytes == NIL) return False;
if (point.y >= size.cy || point.x >= size.cx) return False;
Color color = iColor.ConvertTo(Color::RGBA);
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = point.y * (size.cx * 4) + point.x * 4;
switch (depth)
{
case 24:
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
return True;
case 32:
data[offset + 0] = (color >> 16) & 255;
data[offset + 1] = (color >> 8) & 255;
data[offset + 2] = color & 255;
data[offset + 3] = (color >> 24) & 255;
return True;
}
return False;
}
S::GUI::Color S::GUI::BitmapHaiku::GetPixel(const Point &point) const
{
if (bytes == NIL) return 0;
if (point.y >= size.cy || point.x >= size.cx) return 0;
UnsignedByte *data = ((UnsignedByte *) bytes);
Int offset = point.y * (size.cx * 4) + point.x * 4;
switch (depth)
{
case 24:
return Color( data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGB);
case 32:
return Color(data[offset + 3] << 24 | data[offset + 0] << 16 | data[offset + 1] << 8 | data[offset + 2], Color::RGBA);
}
return 0;
}
S::GUI::BitmapBackend &S::GUI::BitmapHaiku::operator =(const BitmapBackend &newBitmap)
{
if (&newBitmap == this) return *this;
SetSystemBitmap((Void *) ((BitmapHaiku &) newBitmap).bitmap);
return *this;
}
S::Bool S::GUI::BitmapHaiku::operator ==(const int nil) const
{
if (bitmap == NIL) return True;
else return False;
}
S::Bool S::GUI::BitmapHaiku::operator !=(const int nil) const
{
if (bitmap == NIL) return False;
else return True;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/fonthaiku.cpp 0000664 0000000 0000000 00000003760 15164025770 0026572 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
S::GUI::FontBackend *CreateFontHaiku(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontHaiku(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontHaikuTmp = S::GUI::FontBackend::SetBackend(&CreateFontHaiku);
S::Int addFontHaikuInitTmp = S::AddInitFunction(&S::GUI::FontHaiku::Initialize);
S::Int S::GUI::FontHaiku::Initialize()
{
font_family family;
be_plain_font->GetFamilyAndStyle(&family, NIL);
Font::Default = family;
Setup::FontSize = be_plain_font->Size() / 96.0 * 72.0 / Font::DefaultSize;
return Success();
}
S::GUI::FontHaiku::FontHaiku(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_HAIKU;
}
S::GUI::FontHaiku::~FontHaiku()
{
}
S::GUI::Size S::GUI::FontHaiku::GetTextSize(const String &text) const
{
if (text == NIL) return Size();
Float dpi = Surface().GetSurfaceDPI();
BFont font;
font_height height;
font.SetFamilyAndStyle(fontName, NULL);
font.SetFace((fontStyle & Font::Italic ? B_ITALIC_FACE : 0) |
(fontWeight >= Font::Bold ? B_BOLD_FACE : 0));
font.SetSize(Math::Round(fontSize * dpi / 72.0));
font.GetHeight(&height);
return Size(font.StringWidth(text.ConvertTo("UTF-8")), Math::Ceil(height.ascent + height.descent));
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/haiku/surfacehaiku.cpp 0000664 0000000 0000000 00000033754 15164025770 0027262 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
S::GUI::SurfaceBackend *CreateSurfaceHaiku(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceHaiku(iSurface, maxSize);
}
S::Int surfaceHaikuTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceHaiku);
S::Short S::GUI::SurfaceHaiku::surfaceDPI = -1;
S::GUI::SurfaceHaiku::SurfaceHaiku(Void *iView, const Size &maxSize)
{
type = SURFACE_HAIKU;
view = (BView *) iView;
bitmap = NIL;
bitmapView = NIL;
if (view != NIL)
{
size = maxSize;
BScreen screen;
BRect frame = screen.Frame();
if (maxSize == Size())
{
size.cx = 1 + frame.right + 2;
size.cy = 1 + frame.bottom + 2;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
bitmap = new BBitmap(BRect(0, 0, size.cx, size.cy), screen.ColorSpace(), true);
bitmapView = new BView(bitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
bitmap->AddChild(bitmapView);
paintRects.Add(Rect(Point(0, 0), size));
allocSize = size;
}
}
S::GUI::SurfaceHaiku::~SurfaceHaiku()
{
if (view != NIL)
{
bitmap->RemoveChild(bitmapView);
delete bitmapView;
delete bitmap;
}
}
S::Int S::GUI::SurfaceHaiku::Lock()
{
SurfaceBackend::Lock();
if (view != NIL && !painting)
{
BWindow *window = view->Window();
while (window->LockWithTimeout(0) != B_OK)
{
SurfaceBackend::Release();
Application::Lock::ResumeLock(Application::Lock::SuspendLock());
SurfaceBackend::Lock();
}
bitmap->Lock();
}
return Success();
}
S::Int S::GUI::SurfaceHaiku::Release()
{
if (view != NIL && !painting)
{
BWindow *window = view->Window();
bitmap->Unlock();
window->Unlock();
}
return SurfaceBackend::Release();
}
S::Int S::GUI::SurfaceHaiku::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (view != NIL && !painting)
{
bitmap->Unlock();
bitmap->RemoveChild(bitmapView);
delete bitmapView;
delete bitmap;
paintRects.RemoveAll();
bitmap = new BBitmap(BRect(0, 0, size.cx, size.cy), B_RGB32, true);
bitmapView = new BView(bitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
bitmap->AddChild(bitmapView);
bitmap->Lock();
paintRects.Add(Rect(Point(0, 0), size));
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceHaiku::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceHaiku::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (view != NIL)
{
bitmapView->Sync();
view->SetDrawingMode(B_OP_COPY);
view->DrawBitmapAsync(bitmap, BRect(pRect.left, pRect.top, pRect.right, pRect.bottom), BRect(pRect.left, pRect.top, pRect.right, pRect.bottom));
}
return Success();
}
S::Int S::GUI::SurfaceHaiku::StartPaint(const Rect &iPRect)
{
if (view == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
BRegion clippingRegion(BRect(pRect.left, pRect.top, pRect.right, pRect.bottom));
bitmapView->PushState();
bitmapView->ConstrainClippingRegion(&clippingRegion);
paintRects.Add(pRect);
painting++;
return Success();
}
S::Int S::GUI::SurfaceHaiku::EndPaint()
{
if (!painting) return Error();
painting--;
if (painting == 0) PaintRect(paintRects.GetLast());
paintRects.RemoveNth(paintRects.Length() - 1);
bitmapView->PopState();
return Success();
}
S::Void *S::GUI::SurfaceHaiku::GetSystemSurface() const
{
return (Void *) view;
}
S::Short S::GUI::SurfaceHaiku::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
Float dpi = 96.0;
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Int S::GUI::SurfaceHaiku::SetPixel(const Point &iPoint, const Color &color)
{
if (view == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
if (!painting)
{
view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
view->FillRect(BRect(point.x, point.y, point.x, point.y));
}
bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
bitmapView->FillRect(BRect(point.x, point.y, point.x, point.y));
return Success();
}
S::Int S::GUI::SurfaceHaiku::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (view == NIL) return Success();
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
/* Adjust to Windows GDI behavior for diagonal lines.
*/
if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y))
{
if (pos1.x < pos2.x) pos2.x--;
else if (pos1.x > pos2.x) pos2.x++;
if (pos1.y < pos2.y) pos2.y--;
else if (pos1.y > pos2.y) pos2.y++;
}
/* Adjust to Windows GDI behaviour for horizontal and vertical lines.
*/
if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--;
if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--;
if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--;
if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--;
if (!painting)
{
view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
view->MovePenTo(BPoint(pos1.x, pos1.y));
view->StrokeLine(BPoint(pos2.x, pos2.y));
}
bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
bitmapView->MovePenTo(BPoint(pos1.x, pos1.y));
bitmapView->StrokeLine(BPoint(pos2.x, pos2.y));
return Success();
}
S::Int S::GUI::SurfaceHaiku::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (view == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect) - Size(1, 1);
if (!painting) view->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
bitmapView->SetHighColor(color.GetRed(), color.GetGreen(), color.GetBlue());
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
if (!painting) view->FillRoundRect(BRect(rect.left, rect.top, rect.right, rect.bottom), ellipse.cx, ellipse.cy);
bitmapView->FillRoundRect(BRect(rect.left, rect.top, rect.right, rect.bottom), ellipse.cx, ellipse.cy);
}
else
{
if (!painting) view->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
bitmapView->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
}
}
else if (style == Rect::Outlined)
{
if (!painting) view->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
bitmapView->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
}
else if (style & Rect::Inverted)
{
if (!painting) view->InvertRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
bitmapView->InvertRect(BRect(rect.left, rect.top, rect.right, rect.bottom));
}
else if (style & Rect::Dotted)
{
pattern pattern = {{ 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }};
if (!painting) view->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom), pattern);
bitmapView->StrokeRect(BRect(rect.left, rect.top, rect.right, rect.bottom), pattern);
}
return Success();
}
S::Int S::GUI::SurfaceHaiku::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow)
{
if (view == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow);
Rect rect = iRect;
Int lineHeight = 0;
/* Set up Haiku font.
*/
BFont viewFont;
font_height height;
viewFont.SetFamilyAndStyle(font.GetName(), NULL);
viewFont.SetFace((font.GetStyle() & Font::Italic ? B_ITALIC_FACE : 0) |
(font.GetStyle() & Font::Underline ? B_UNDERSCORE_FACE : 0) |
(font.GetStyle() & Font::StrikeOut ? B_STRIKEOUT_FACE : 0) |
(font.GetWeight() >= Font::Bold ? B_BOLD_FACE : 0));
viewFont.SetSize(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 72.0));
Rect tRect = rightToLeft.TranslateRect(rect);
BRegion clippingRegion(BRect(tRect.left, tRect.top, tRect.right, tRect.bottom));
if (!painting)
{
view->PushState();
view->SetFont(&viewFont);
view->SetDrawingMode(B_OP_OVER);
view->SetHighColor(font.GetColor().GetRed(), font.GetColor().GetGreen(), font.GetColor().GetBlue());
view->ConstrainClippingRegion(&clippingRegion);
}
bitmapView->PushState();
bitmapView->SetFont(&viewFont);
bitmapView->GetFontHeight(&height);
bitmapView->SetDrawingMode(B_OP_OVER);
bitmapView->SetHighColor(font.GetColor().GetRed(), font.GetColor().GetGreen(), font.GetColor().GetBlue());
bitmapView->ConstrainClippingRegion(&clippingRegion);
/* Draw text line by line.
*/
const Array &lines = string.Explode("\n");
if (lines.Length() > 1) lineHeight = font.GetScaledTextSizeY() + 3;
foreach (const String &line, lines)
{
Rect tRect = rightToLeft.TranslateRect(rect);
tRect.left = rightToLeft.GetRightToLeft() ? tRect.right - font.GetScaledTextSizeX(line) : tRect.left;
if (!painting) view->DrawString(line.ConvertTo("UTF-8"), BPoint(tRect.left, tRect.top + height.ascent));
bitmapView->DrawString(line.ConvertTo("UTF-8"), BPoint(tRect.left, tRect.top + height.ascent));
rect.top += lineHeight;
}
if (!painting) view->PopState();
bitmapView->PopState();
return Success();
}
S::Int S::GUI::SurfaceHaiku::Gradient(const Rect &iRect, const Color &color1, const Color &color2, Int style)
{
if (view == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect) - Size(1, 1);
/* Setup colors.
*/
Color c1 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color2 : color1;
Color c2 = (style == OR_HORZ && rightToLeft.GetRightToLeft()) ? color1 : color2;
/* Setup graphics objects and draw gradient.
*/
BGradient *gradient = new BGradientLinear(0, 0, style == OR_HORZ ? rect.GetWidth() : 0,
style == OR_VERT ? rect.GetHeight() : 0);
gradient->AddColorStop(BGradient::ColorStop(c1.GetRed(), c1.GetGreen(), c1.GetBlue(), 255, 0), 0);
gradient->AddColorStop(BGradient::ColorStop(c2.GetRed(), c2.GetGreen(), c2.GetBlue(), 255, 255), 1);
if (!painting) view->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom), *gradient);
bitmapView->FillRect(BRect(rect.left, rect.top, rect.right, rect.bottom), *gradient);
delete gradient;
return Success();
}
S::Int S::GUI::SurfaceHaiku::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (view == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
drawing_mode drawingMode = bitmap.GetDepth() == 32 ? B_OP_ALPHA : B_OP_COPY;
if (!painting) view->SetDrawingMode(drawingMode);
bitmapView->SetDrawingMode(drawingMode);
if (destRect.GetSize() == srcRect.GetSize())
{
if (!painting) view->DrawBitmap((BBitmap *) bitmap.GetSystemBitmap(), BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR);
bitmapView->DrawBitmap((BBitmap *) bitmap.GetSystemBitmap(), BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR);
}
else
{
/* Quality of Haiku's biliniear filter is not good enough and there are no other options.
* Use our own weighted average scaling until there are better alternatives offered by Haiku.
*/
Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth());
Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight());
Size srcSize = bitmap.GetSize();
const Bitmap &scaledBitmap = bitmap.Scale(Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY));
if (!painting) view->DrawBitmap((BBitmap *) scaledBitmap.GetSystemBitmap(), BRect(Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.right) / scaleFactorX, Float(srcRect.bottom) / scaleFactorY), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR);
bitmapView->DrawBitmap((BBitmap *) scaledBitmap.GetSystemBitmap(), BRect(Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, Float(srcRect.right) / scaleFactorX, Float(srcRect.bottom) / scaleFactorY), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR);
}
return Success();
}
S::Int S::GUI::SurfaceHaiku::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (view == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
BBitmap *destBitmap = (BBitmap *) bitmap.GetSystemBitmap();
BView *destView = new BView(destBitmap->Bounds(), NULL, B_FOLLOW_ALL_SIDES, 0);
destBitmap->AddChild(destView);
destBitmap->Lock();
bitmapView->Sync();
destView->DrawBitmap(this->bitmap, BRect(srcRect.left, srcRect.top, srcRect.right, srcRect.bottom), BRect(destRect.left, destRect.top, destRect.right, destRect.bottom), B_FILTER_BITMAP_BILINEAR);
destBitmap->Unlock();
destBitmap->RemoveChild(destView);
delete destView;
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/surfacebackend.cpp 0000775 0000000 0000000 00000021673 15164025770 0026447 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2021 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#if defined __WIN32__ && defined SMOOTH_STATIC
#include
#endif
S::GUI::SurfaceBackend *CreateSurfaceBackend(S::Void *iSurface, const S::GUI::Size &maxSize)
{
return new S::GUI::SurfaceBackend(iSurface, maxSize);
}
S::GUI::SurfaceBackend *(*S::GUI::SurfaceBackend::backend_creator)(S::Void *, const S::GUI::Size &) = &CreateSurfaceBackend;
S::Int S::GUI::SurfaceBackend::SetBackend(SurfaceBackend *(*backend)(Void *, const Size &))
{
if (backend == NIL) return Error();
backend_creator = backend;
return Success();
}
S::GUI::SurfaceBackend *S::GUI::SurfaceBackend::CreateBackendInstance(Void *iSurface, const Size &maxSize)
{
return backend_creator(iSurface, maxSize);
}
S::GUI::SurfaceBackend::SurfaceBackend(Void *iSurface, const Size &maxSize)
{
#if defined __WIN32__ && defined SMOOTH_STATIC
volatile Bool null = 0;
if (null) SurfaceGDI();
#endif
type = SURFACE_NONE;
size.cx = 0;
size.cy = 0;
paintRect.left = -1;
paintRect.top = -1;
paintRect.right = -1;
paintRect.bottom = -1;
painting = 0;
}
S::GUI::SurfaceBackend::~SurfaceBackend()
{
}
S::Int S::GUI::SurfaceBackend::Lock()
{
return Application::Lock::Acquire();
}
S::Int S::GUI::SurfaceBackend::Release()
{
return Application::Lock::Release();
}
S::Short S::GUI::SurfaceBackend::GetSurfaceType() const
{
return type;
}
S::Int S::GUI::SurfaceBackend::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
return Success();
}
const S::GUI::Size &S::GUI::SurfaceBackend::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceBackend::SetRightToLeft(Bool nRightToLeft)
{
rightToLeft.SetRightToLeft(nRightToLeft);
return Success();
}
S::Int S::GUI::SurfaceBackend::PaintRect(const Rect &pRect)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::StartPaint(const Rect &pRect)
{
painting++;
return Success();
}
S::Int S::GUI::SurfaceBackend::EndPaint()
{
painting--;
return Success();
}
S::Void *S::GUI::SurfaceBackend::GetSystemSurface() const
{
return NIL;
}
S::Short S::GUI::SurfaceBackend::GetSurfaceDPI() const
{
return 96;
}
S::Int S::GUI::SurfaceBackend::SetPixel(const Point &point, const Color &color)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::Line(const Point &pos1, const Point &pos2, const Color &color)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::Frame(const Rect &iRect, Short style)
{
Rect rect = rightToLeft.TranslateRect(iRect);
Point p1 = Point(rect.left, rect.top);
Point p2 = Point(rect.right - 1, rect.top);
Point p3 = Point(rect.left, rect.bottom - 1);
Point p4 = Point(rect.right - 1, rect.bottom - 1);
Long color1 = 0;
Long color2 = 0;
switch (style)
{
case FRAME_UP:
color1 = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255));
color2 = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0));
break;
case FRAME_DOWN:
color1 = Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0));
color2 = Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255));
break;
}
Bool preRTL = rightToLeft.GetRightToLeft();
rightToLeft.SetRightToLeft(False);
StartPaint(rect);
Line(p1, p2, color1);
Line(p1, p3, color1);
Line(p2, p4, color2);
Line(p3, p4, color2);
SetPixel(p4, color2);
EndPaint();
rightToLeft.SetRightToLeft(preRTL);
return Success();
}
S::Int S::GUI::SurfaceBackend::Box(const Rect &rect, const Color &color, Int style, const Size &ellipse)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::SetText(const String &string, const Rect &iRect, const Font &iFont, Bool shadow)
{
if (shadow)
{
Rect rect = iRect + Point(2, 2);
Font font = iFont;
Int fontColor = font.GetColor();
font.SetColor(Color((Int) ((Float) Setup::BackgroundColor.GetRed() / 3 * 2), (Int) ((Float) Setup::BackgroundColor.GetGreen() / 3 * 2), (Int) ((Float) Setup::BackgroundColor.GetBlue() / 3 * 2)));
SetText(string, rect, font, False);
rect = rect - Point(2, 2);
font.SetColor(fontColor);
SetText(string, rect, font, False);
}
return Success();
}
S::Int S::GUI::SurfaceBackend::Gradient(const Rect &rect, const Color &color1, const Color &color2, Int style)
{
Float red1 = color1.GetRed();
Float green1 = color1.GetGreen();
Float blue1 = color1.GetBlue();
Float red2 = color2.GetRed();
Float green2 = color2.GetGreen();
Float blue2 = color2.GetBlue();
Int xmax = rect.GetWidth();
Int ymax = rect.GetHeight();
Bitmap bmp(Size(xmax, ymax));
switch (style)
{
case OR_HORZ:
{
Float biasr = (red2 - red1) / xmax;
Float biasg = (green2 - green1) / xmax;
Float biasb = (blue2 - blue1) / xmax;
if (rightToLeft.GetRightToLeft())
{
for (Int x = xmax - 1; x >= 0; x--)
{
red1 = red1 + biasr;
green1 = green1 + biasg;
blue1 = blue1 + biasb;
for (Int y = 0; y < ymax; y++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1));
}
}
else
{
for (Int x = 0; x < xmax; x++)
{
red1 = red1 + biasr;
green1 = green1 + biasg;
blue1 = blue1 + biasb;
for (Int y = 0; y < ymax; y++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1));
}
}
}
break;
case OR_VERT:
{
Float biasr = (red2 - red1) / ymax;
Float biasg = (green2 - green1) / ymax;
Float biasb = (blue2 - blue1) / ymax;
for (Int y = 0; y < ymax; y++)
{
red1 = red1 + biasr;
green1 = green1 + biasg;
blue1 = blue1 + biasb;
for (Int x = 0; x < xmax; x++) bmp.SetPixel(Point(x, y), Color((Int) red1, (Int) green1, (Int) blue1));
}
}
break;
}
BlitFromBitmap(bmp, Rect(Point(0, 0), rect.GetSize()), rect);
return Success();
}
S::Int S::GUI::SurfaceBackend::Bar(const Point &iP1, const Point &iP2, Int orientation)
{
Point p1 = rightToLeft.TranslatePoint(iP1);
Point p2 = rightToLeft.TranslatePoint(iP2);
if (rightToLeft.GetRightToLeft())
{
if (orientation == OR_HORZ) { p1 = rightToLeft.TranslatePoint(iP2); p2 = rightToLeft.TranslatePoint(iP1); }
if (orientation == OR_VERT) { p1 -= Point(2, 0); p2 -= Point(2, 0); }
}
Bool preRTL = rightToLeft.GetRightToLeft();
rightToLeft.SetRightToLeft(False);
if (orientation == OR_HORZ)
{
Line(p1, p2, Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)));
p1.y++;
p2.y++;
Line(p1, p2, Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)));
}
else if (orientation == OR_VERT)
{
p2.y++;
Line(p1, p2, Color(Math::Max(Setup::BackgroundColor.GetRed() - 64, 0), Math::Max(Setup::BackgroundColor.GetGreen() - 64, 0), Math::Max(Setup::BackgroundColor.GetBlue() - 64, 0)));
p1.x++;
p2.x++;
Line(p1, p2, Color(Math::Min(Setup::BackgroundColor.GetRed() + 64, 255), Math::Min(Setup::BackgroundColor.GetGreen() + 64, 255), Math::Min(Setup::BackgroundColor.GetBlue() + 64, 255)));
}
rightToLeft.SetRightToLeft(preRTL);
return Success();
}
S::Int S::GUI::SurfaceBackend::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &destRect)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::BlitToBitmap(const Rect &srcRect, Bitmap &bitmap, const Rect &destRect)
{
return Success();
}
S::Int S::GUI::SurfaceBackend::PremultiplyAlpha(Bitmap &bitmap)
{
if (bitmap.GetDepth() != 32) return Success();
Point point;
Size size = bitmap.GetSize();
for (point.y = 0; point.y < size.cy; point.y++)
{
for (point.x = 0; point.x < size.cx; point.x++)
{
Color pixel = bitmap.GetPixel(point);
if (pixel.GetAlpha() != 255) bitmap.SetPixel(point, Color( pixel.GetRed() * pixel.GetAlpha() / 255 |
(pixel.GetGreen() * pixel.GetAlpha() / 255) << 8 |
(pixel.GetBlue() * pixel.GetAlpha() / 255) << 16 |
pixel.GetAlpha() << 24, Color::RGBA));
}
}
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/ 0000775 0000000 0000000 00000000000 15164025770 0023725 5 ustar 00root root 0000000 0000000 smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/Makefile 0000664 0000000 0000000 00000001577 15164025770 0025377 0 ustar 00root root 0000000 0000000 ########## smooth directory makefile ##########
# Change these variables to fit this location:
SMOOTH_PATH = ../../../..
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-options
# Change these variables to fit your project:
ifneq ($(BUILD_WIN32),True)
ifneq ($(BUILD_OSX),True)
ifneq ($(BUILD_HAIKU),True)
MYCCOPTS += $(shell pkg-config --cflags x11)
ifneq ($(BUILD_CAIRO),True)
MYCCOPTS += $(shell pkg-config --cflags xft)
endif
endif
endif
endif
ifeq ($(USE_BUNDLED_LIBFRIBIDI),True)
MYCCOPTS += -I"$(SRCDIR)"/$(SMOOTH_PATH)/include/support -DFRIBIDI_LIB_STATIC
endif
# Enter object files here:
OBJECTS =
ifeq ($(BUILD_XLIB),True)
OBJECTS += bitmapxlib.o
ifneq ($(BUILD_CAIRO),True)
OBJECTS += fontxlib.o surfacexlib.o
endif
endif
## Do not change anything below this line. ##
include $(dir $(firstword $(MAKEFILE_LIST)))/$(SMOOTH_PATH)/Makefile-commands
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/bitmapxlib.cpp 0000775 0000000 0000000 00000013126 15164025770 0026572 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
using namespace X11;
S::GUI::BitmapBackend *CreateBitmapXLib_pV(S::Void *iBitmap)
{
return new S::GUI::BitmapXLib(iBitmap);
}
S::GUI::BitmapBackend *CreateBitmapXLib_crSI(const S::GUI::Size &iSize, S::Int iDepth)
{
return new S::GUI::BitmapXLib(iSize, iDepth);
}
S::GUI::BitmapBackend *CreateBitmapXLib_cI(const int nil)
{
return new S::GUI::BitmapXLib(nil);
}
S::GUI::BitmapBackend *CreateBitmapXLib_crB(const S::GUI::BitmapBackend &iBitmap)
{
return new S::GUI::BitmapXLib((const S::GUI::BitmapXLib &) iBitmap);
}
S::Int bitmapXLibTmp_pV = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_pV);
S::Int bitmapXLibTmp_crSI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_crSI);
S::Int bitmapXLibTmp_cI = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_cI);
S::Int bitmapXLibTmp_crB = S::GUI::BitmapBackend::SetBackend(&CreateBitmapXLib_crB);
S::GUI::BitmapXLib::BitmapXLib(Void *iBitmap)
{
Initialize();
SetSystemBitmap(iBitmap);
}
S::GUI::BitmapXLib::BitmapXLib(const Size &iSize, Int iDepth)
{
Initialize();
CreateBitmap(iSize, iDepth);
}
S::GUI::BitmapXLib::BitmapXLib(const int nil)
{
Initialize();
SetSystemBitmap(NIL);
}
S::GUI::BitmapXLib::BitmapXLib(const BitmapXLib &iBitmap)
{
Initialize();
SetSystemBitmap((Void *) iBitmap.bitmap);
}
S::GUI::BitmapXLib::~BitmapXLib()
{
DeleteBitmap();
}
S::Void S::GUI::BitmapXLib::Initialize()
{
type = BITMAP_XLIB;
bitmap = NIL;
display = Backends::BackendXLib::GetDisplay();
}
S::Bool S::GUI::BitmapXLib::CreateBitmap(const Size &nSize, Int nDepth)
{
if (display == NIL) return False;
DeleteBitmap();
if (nDepth == -1) nDepth = XDefaultDepth(display, XDefaultScreen(display));
if (nDepth != 24 && nDepth != 32) nDepth = 24;
/* Find best fit for pixel format.
*/
int count = 0;
int index = 0;
XPixmapFormatValues *formats = XListPixmapFormats(display, &count);
for (Int i = 0; i < count; i++)
{
if (Math::Abs(formats[i].depth - nDepth) < Math::Abs(formats[index].depth - nDepth)) index = i;
if (formats[i].depth == nDepth) break;
}
/* Allocate and create image.
*/
bytes = new UnsignedByte [nSize.cy * nSize.cx * (formats[index].bits_per_pixel / 8) + nSize.cy * (((nSize.cx * formats[index].bits_per_pixel) % formats[index].scanline_pad) / 8)];
bitmap = XCreateImage(display, XDefaultVisual(display, XDefaultScreen(display)), formats[index].depth, ZPixmap, 0, (char *) bytes, nSize.cx, nSize.cy, formats[index].scanline_pad, 0);
if (bitmap == NIL) { delete [] (UnsignedByte *) bytes; XFree(formats); return False; }
size = nSize;
depth = formats[index].depth;
bpp = formats[index].bits_per_pixel;
align = formats[index].scanline_pad / 8;
XFree(formats);
return True;
}
S::Bool S::GUI::BitmapXLib::DeleteBitmap()
{
if (bitmap != NIL)
{
delete [] bitmap->data;
bitmap->data = NIL;
XDestroyImage(bitmap);
bitmap = NIL;
size = Size(0, 0);
depth = 0;
bytes = NIL;
bpp = 0;
align = 0;
}
return True;
}
S::Bool S::GUI::BitmapXLib::SetSystemBitmap(Void *nBitmap)
{
if (nBitmap == GetSystemBitmap()) return True;
if (nBitmap == NIL)
{
DeleteBitmap();
}
else
{
XImage *image = (XImage *) nBitmap;
CreateBitmap(Size(image->width, image->height), image->depth);
memcpy(bitmap->data, image->data, size_t(image->height) * size_t(image->bytes_per_line));
}
return True;
}
S::Void *S::GUI::BitmapXLib::GetSystemBitmap() const
{
return (Void *) bitmap;
}
S::Bool S::GUI::BitmapXLib::SetPixel(const Point &iPoint, const Color &iColor)
{
if (bitmap == NIL) return Error();
Color color = iColor.ConvertTo(Color::RGBA);
if (depth == 16) XPutPixel(bitmap, iPoint.x, iPoint.y, ((color.GetRed() >> 3) << 11) | ((color.GetGreen() >> 2) << 5) | (color.GetBlue() >> 3));
else if (depth == 24) XPutPixel(bitmap, iPoint.x, iPoint.y, ( color.GetRed() << 16) | ( color.GetGreen() << 8) | (color.GetBlue() ));
else if (depth == 32) XPutPixel(bitmap, iPoint.x, iPoint.y, (color.GetAlpha() << 24) | ( color.GetRed() << 16) | ( color.GetGreen() << 8) | (color.GetBlue() ));
return True;
}
S::GUI::Color S::GUI::BitmapXLib::GetPixel(const Point &iPoint) const
{
if (bitmap == NIL) return Color();
Long value = XGetPixel(bitmap, iPoint.x, iPoint.y);
if (depth == 16) return Color(((value >> 11) & 31) << 3, ((value >> 5) & 63) << 2, (value & 31) << 3, Color::RGB);
else if (depth == 24) return Color( (value >> 16) & 255, (value >> 8) & 255, value & 255 , Color::RGB);
else if (depth == 32) return ((value >> 24) & 255) << 24 | Color( (value >> 16) & 255, (value >> 8) & 255, value & 255 , Color::RGBA);
return Color();
}
S::GUI::BitmapBackend &S::GUI::BitmapXLib::operator =(const BitmapBackend &newBitmap)
{
if (&newBitmap == this) return *this;
SetSystemBitmap((Void *) ((BitmapXLib &) newBitmap).bitmap);
return *this;
}
S::Bool S::GUI::BitmapXLib::operator ==(const int nil) const
{
if (bitmap == NIL) return True;
else return False;
}
S::Bool S::GUI::BitmapXLib::operator !=(const int nil) const
{
if (bitmap == NIL) return False;
else return True;
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/fontxlib.cpp 0000664 0000000 0000000 00000006633 15164025770 0026266 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2022 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
using namespace X11;
#include
S::GUI::FontBackend *CreateFontXLib(const S::String &iFontName, S::Short iFontSize, S::Short iFontWeight, S::Short iFontStyle, const S::GUI::Color &iFontColor)
{
return new S::GUI::FontXLib(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor);
}
S::Int fontXLibTmp = S::GUI::FontBackend::SetBackend(&CreateFontXLib);
S::Int addFontXLibInitTmp = S::AddInitFunction(&S::GUI::FontXLib::Initialize);
S::Int S::GUI::FontXLib::Initialize()
{
Font::Default = "Helvetica";
Setup::FontSize = 1.0;
String font = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "font-name");
Float scaleFactor = Backends::BackendXLib::QueryGSettings("org.gnome.desktop.interface", "text-scaling-factor").ToFloat();
if (font != NIL)
{
Font::Default = font.SubString(1, font.FindLast(" ") - 1);
Setup::FontSize = font.SubString(font.FindLast(" ") + 1, font.Length() - font.FindLast(" ") - 2).ToFloat() / Font::DefaultSize;
}
if (scaleFactor != 0) Setup::FontSize *= scaleFactor;
return Success();
}
S::GUI::FontXLib::FontXLib(const String &iFontName, Short iFontSize, Short iFontWeight, Short iFontStyle, const Color &iFontColor) : FontBackend(iFontName, iFontSize, iFontWeight, iFontStyle, iFontColor)
{
type = FONT_XLIB;
}
S::GUI::FontXLib::~FontXLib()
{
}
S::GUI::Size S::GUI::FontXLib::GetTextSize(const String &iText) const
{
if (iText == NIL) return Size();
Display *display = Backends::BackendXLib::GetDisplay();
if (display == NIL) return Size();
String text = iText;
Int textLength = text.Length();
Float dpi = Surface().GetSurfaceDPI();
Bool rtlCharacters = False;
for (Int i = 0; i < textLength; i++) if (text[i] >= 0x0590 && text[i] <= 0x08FF) { rtlCharacters = True; break; }
if (rtlCharacters && Setup::useIconv)
{
/* Reorder the string with fribidi.
*/
FriBidiChar *visual = new FriBidiChar [textLength + 1];
FriBidiParType type = FRIBIDI_PAR_RTL;
fribidi_log2vis((FriBidiChar *) text.ConvertTo("UCS-4LE"), textLength, &type, visual, NIL, NIL, NIL);
visual[textLength] = 0;
text.ImportFrom("UCS-4LE", (char *) visual);
delete [] visual;
}
/* Get text extents.
*/
XftFont *font = XftFontOpenName(display, XDefaultScreen(display), String(fontName).Append("-").Append(String::FromInt(Math::Round(fontSize * dpi / 96.0))).Append(":").Append(fontWeight >= Font::Bold ? "bold" : "medium").Append(fontStyle & Font::Italic ? ":italic" : ""));
XGlyphInfo extents = { 0 };
XftTextExtents16(display, font, (XftChar16 *) text.ConvertTo("UCS2"), textLength, &extents);
XftFontClose(display, font);
int lines = 1;
for (Int i = 0; i < textLength; i++) if (text[i] == '\n') lines++;
return Size(extents.width - 2, (font->ascent + 2) * lines);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/backends/xlib/surfacexlib.cpp 0000775 0000000 0000000 00000040423 15164025770 0026746 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2020 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace X11;
S::GUI::SurfaceBackend *CreateSurfaceXLib(S::Void *iSurface, const S::GUI::Size &)
{
return new S::GUI::SurfaceXLib(iSurface);
}
S::Int surfaceXLibTmp = S::GUI::SurfaceBackend::SetBackend(&CreateSurfaceXLib);
S::Short S::GUI::SurfaceXLib::surfaceDPI = -1;
S::GUI::SurfaceXLib::SurfaceXLib(Void *iWindow, const Size &maxSize)
{
type = SURFACE_XLIB;
window = (X11::Window) iWindow;
bitmap = NIL;
gc = NIL;
display = Backends::BackendXLib::GetDisplay();
if (window != NIL)
{
size = maxSize;
if (maxSize == Size())
{
size.cx = XDisplayWidth(display, XDefaultScreen(display)) + 2;
size.cy = XDisplayHeight(display, XDefaultScreen(display)) + 2;
}
fontSize.SetFontSize(GetSurfaceDPI());
rightToLeft.SetSurfaceSize(size);
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, window, &windowAttributes);
bitmap = XCreatePixmap(display, window, size.cx, size.cy, windowAttributes.depth);
gc = XCreateGC(display, bitmap, 0, NIL);
paintRects.Add(Rect(Point(0, 0), size));
allocSize = size;
}
}
S::GUI::SurfaceXLib::~SurfaceXLib()
{
if (bitmap != NIL)
{
XFreeGC(display, gc);
XFreePixmap(display, bitmap);
}
}
S::Int S::GUI::SurfaceXLib::SetSize(const Size &nSize)
{
size = nSize;
rightToLeft.SetSurfaceSize(size);
if (allocSize.cx >= nSize.cx && allocSize.cy >= nSize.cy) return Success();
if (window != NIL && !painting)
{
XFreeGC(display, gc);
XFreePixmap(display, bitmap);
paintRects.RemoveAll();
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, window, &windowAttributes);
bitmap = XCreatePixmap(display, DefaultRootWindow(display), size.cx, size.cy, windowAttributes.depth);
gc = XCreateGC(display, bitmap, 0, NIL);
paintRects.Add(Rect(Point(0, 0), size));
}
allocSize = nSize;
return Success();
}
const S::GUI::Size &S::GUI::SurfaceXLib::GetSize() const
{
return size;
}
S::Int S::GUI::SurfaceXLib::PaintRect(const Rect &pRect)
{
if (painting) return Error();
if (window != NIL)
{
XCopyArea(display, bitmap, window, gc, pRect.left, pRect.top, pRect.GetWidth(), pRect.GetHeight(), pRect.left, pRect.top);
}
return Success();
}
S::Int S::GUI::SurfaceXLib::StartPaint(const Rect &iPRect)
{
if (window == NIL) return Success();
Rect pRect = Rect::OverlapRect(rightToLeft.TranslateRect(iPRect), paintRects.GetLast());
XRectangle clipRect;
clipRect.x = pRect.left;
clipRect.y = pRect.top;
clipRect.width = pRect.GetWidth();
clipRect.height = pRect.GetHeight();
XSetClipRectangles(display, gc, 0, 0, &clipRect, 1, Unsorted);
paintRects.Add(pRect);
painting++;
return Success();
}
S::Int S::GUI::SurfaceXLib::EndPaint()
{
if (!painting) return Error();
painting--;
if (painting == 0)
{
PaintRect(paintRects.GetLast());
XSetClipMask(display, gc, None);
}
else
{
const Rect &paintRect = paintRects.GetNth(paintRects.Length() - 2);
XRectangle clipRect;
clipRect.x = paintRect.left;
clipRect.y = paintRect.top;
clipRect.width = paintRect.GetWidth();
clipRect.height = paintRect.GetHeight();
XSetClipRectangles(display, gc, 0, 0, &clipRect, 1, Unsorted);
}
paintRects.RemoveNth(paintRects.Length() - 1);
return Success();
}
S::Void *S::GUI::SurfaceXLib::GetSystemSurface() const
{
return (Void *) window;
}
S::Short S::GUI::SurfaceXLib::GetSurfaceDPI() const
{
if (Application::GetScaleFactor() != 0) surfaceDPI = Math::Round(96.0 * Application::GetScaleFactor());
if (surfaceDPI != -1) return surfaceDPI;
/* Evaluate GDK_SCALE setting.
*/
Float dpi = 96.0;
Int scale = (Int64) Number::FromIntString(getenv("GDK_SCALE"));
if (scale > 0) dpi *= scale;
surfaceDPI = Math::Round(dpi * Setup::FontSize);
return surfaceDPI;
}
S::Int S::GUI::SurfaceXLib::SetPixel(const Point &iPoint, const Color &color)
{
if (window == NIL) return Success();
Point point = rightToLeft.TranslatePoint(iPoint);
XGCValues gcValues;
gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed());
XChangeGC(display, gc, GCForeground, &gcValues);
if (!painting) XDrawPoint(display, window, gc, point.x, point.y);
XDrawPoint(display, bitmap, gc, point.x, point.y);
return Success();
}
S::Int S::GUI::SurfaceXLib::Line(const Point &iPos1, const Point &iPos2, const Color &color)
{
if (window == NIL) return Success();
Point pos1 = rightToLeft.TranslatePoint(iPos1);
Point pos2 = rightToLeft.TranslatePoint(iPos2);
/* Adjust to Windows GDI behavior for diagonal lines.
*/
if (Math::Abs(pos2.x - pos1.x) == Math::Abs(pos2.y - pos1.y))
{
if (pos1.x < pos2.x) pos2.x--;
else if (pos1.x > pos2.x) pos2.x++;
if (pos1.y < pos2.y) pos2.y--;
else if (pos1.y > pos2.y) pos2.y++;
}
/* Adjust to Windows GDI behaviour for horizontal and vertical lines.
*/
if (pos1.x == pos2.x && pos1.y < pos2.y) pos2.y--;
if (pos1.x == pos2.x && pos1.y > pos2.y) pos1.y--;
if (pos1.y == pos2.y && pos1.x < pos2.x) pos2.x--;
if (pos1.y == pos2.y && pos1.x > pos2.x) pos1.x--;
XGCValues gcValues;
gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed());
XChangeGC(display, gc, GCForeground, &gcValues);
if (!painting) XDrawLine(display, window, gc, pos1.x, pos1.y, pos2.x, pos2.y);
XDrawLine(display, bitmap, gc, pos1.x, pos1.y, pos2.x, pos2.y);
return Success();
}
S::Int S::GUI::SurfaceXLib::Box(const Rect &iRect, const Color &color, Int style, const Size &ellipse)
{
if (window == NIL) return Success();
Rect rect = rightToLeft.TranslateRect(iRect);
XGCValues gcValues;
gcValues.foreground = Color(color.GetBlue(), color.GetGreen(), color.GetRed());
XChangeGC(display, gc, GCForeground, &gcValues);
if (style & Rect::Filled)
{
if (style & Rect::Rounded)
{
/* ToDo: Allow drawing of rounded rects.
*/
}
else
{
if (!painting) XFillRectangle(display, window, gc, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
XFillRectangle(display, bitmap, gc, rect.left, rect.top, rect.GetWidth(), rect.GetHeight());
}
}
else if (style == Rect::Outlined)
{
if (!painting) XDrawRectangle(display, window, gc, rect.left, rect.top, rect.GetWidth() - 1, rect.GetHeight() - 1);
XDrawRectangle(display, bitmap, gc, rect.left, rect.top, rect.GetWidth() - 1, rect.GetHeight() - 1);
}
else if (style & Rect::Inverted)
{
Bitmap area(rect.GetSize());
BlitToBitmap(iRect, area, Rect(Point(0, 0), area.GetSize()));
area.InvertColors();
BlitFromBitmap(area, Rect(Point(0, 0), area.GetSize()), iRect);
}
else if (style & Rect::Dotted)
{
if (!painting)
{
for (Int x = rect.left + 1; x < rect.right; x += 2) XDrawPoint(display, window, gc, x, rect.top);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) XDrawPoint(display, window, gc, rect.right - 1, y);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) XDrawPoint(display, window, gc, x, rect.bottom - 1);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) XDrawPoint(display, window, gc, rect.left, y);
}
for (Int x = rect.left + 1; x < rect.right; x += 2) XDrawPoint(display, bitmap, gc, x, rect.top);
for (Int y = rect.top - (rect.GetWidth() ) % 2 + 2; y < rect.bottom; y += 2) XDrawPoint(display, bitmap, gc, rect.right - 1, y);
for (Int x = rect.right - (rect.GetWidth() + rect.GetHeight()) % 2 - 2; x >= rect.left; x -= 2) XDrawPoint(display, bitmap, gc, x, rect.bottom - 1);
for (Int y = rect.bottom - ( rect.GetHeight()) % 2 - 1; y >= rect.top; y -= 2) XDrawPoint(display, bitmap, gc, rect.left, y);
}
return Success();
}
S::Int S::GUI::SurfaceXLib::SetText(const String &string, const Rect &iRect, const Font &font, Bool shadow)
{
if (window == NIL) return Success();
if (string == NIL) return Error();
if (shadow) return SurfaceBackend::SetText(string, iRect, font, shadow);
Rect rect = iRect;
Int lineHeight = font.GetScaledTextSizeY() + 3;
XftFont *xfont = XftFontOpenName(display, XDefaultScreen(display), String(font.GetName()).Append("-").Append(String::FromInt(Math::Round(font.GetSize() * fontSize.TranslateY(96) / 96.0))).Append(":").Append(font.GetWeight() >= Font::Bold ? "bold" : "medium").Append(font.GetStyle() & Font::Italic ? ":italic" : ""));
XftDraw *wdraw = XftDrawCreate(display, window, XDefaultVisual(display, XDefaultScreen(display)), XDefaultColormap(display, XDefaultScreen(display)));
XftDraw *bdraw = XftDrawCreate(display, bitmap, XDefaultVisual(display, XDefaultScreen(display)), XDefaultColormap(display, XDefaultScreen(display)));
/* Allocate text color.
*/
XRenderColor xrcolor;
XftColor xftcolor;
xrcolor.red = font.GetColor().GetRed() * 256;
xrcolor.green = font.GetColor().GetGreen() * 256;
xrcolor.blue = font.GetColor().GetBlue() * 256;
xrcolor.alpha = 0xffff;
XftColorAllocValue(display, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display)), &xrcolor, &xftcolor);
/* Set clipping area.
*/
const Rect &pRect = paintRects.GetLast();
XRectangle clipRect;
clipRect.x = pRect.left;
clipRect.y = pRect.top;
clipRect.width = pRect.GetWidth();
clipRect.height = pRect.GetHeight();
XftDrawSetClipRectangles(wdraw, 0, 0, &clipRect, 1);
XftDrawSetClipRectangles(bdraw, 0, 0, &clipRect, 1);
/* Draw text line by line.
*/
const Array &lines = string.Explode("\n");
foreach (String line, lines)
{
Int lineLength = line.Length();
/* Check for right to left characters in text.
*/
Bool rtlCharacters = False;
for (Int i = 0; i < lineLength; i++) if (line[i] >= 0x0590 && line[i] <= 0x08FF) { rtlCharacters = True; break; }
/* Draw text, reordering if necessary.
*/
Rect tRect = rightToLeft.TranslateRect(rect);
if (rtlCharacters && Setup::useIconv)
{
/* Reorder the string with fribidi.
*/
FriBidiChar *visual = new FriBidiChar [lineLength + 1];
FriBidiParType type = (rightToLeft.GetRightToLeft() ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR);
fribidi_log2vis((FriBidiChar *) line.ConvertTo("UCS-4LE"), lineLength, &type, visual, NIL, NIL, NIL);
visual[lineLength] = 0;
line.ImportFrom("UCS-4LE", (char *) visual);
delete [] visual;
}
if (!painting) XftDrawString16(wdraw, &xftcolor, xfont, tRect.left, tRect.top + lineHeight - 4, (XftChar16 *) line.ConvertTo("UCS2"), lineLength);
XftDrawString16(bdraw, &xftcolor, xfont, tRect.left, tRect.top + lineHeight - 4, (XftChar16 *) line.ConvertTo("UCS2"), lineLength);
rect.top += lineHeight;
}
/* Clean up everything.
*/
XftColorFree(display, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display)), &xftcolor);
XftDrawDestroy(wdraw);
XftDrawDestroy(bdraw);
XftFontClose(display, xfont);
return Success();
}
S::Int S::GUI::SurfaceXLib::BlitFromBitmap(const Bitmap &bitmap, const Rect &srcRect, const Rect &iDestRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect destRect = rightToLeft.TranslateRect(iDestRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Convert format if depths do not match.
*/
XWindowAttributes windowAttributes;
XGetWindowAttributes(display, window, &windowAttributes);
Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth());
Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight());
const Bitmap *srcBitmap = &bitmap;
Size srcSize = bitmap.GetSize();
Size destSize = Size(Float(srcSize.cx) / scaleFactorX, Float(srcSize.cy) / scaleFactorY);
if (bitmap.GetDepth() == 32 || bitmap.GetDepth() != windowAttributes.depth)
{
const Bitmap &bitmap = srcBitmap->Scale(destSize);
Bitmap *copy = new Bitmap(destSize, windowAttributes.depth);
XImage *bkgr = XGetImage(display, this->bitmap, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight(), AllPlanes, ZPixmap);
Point point;
for (point.y = 0; point.y < destSize.cy; point.y++)
{
for (point.x = 0; point.x < destSize.cx; point.x++)
{
Color color = bitmap.GetPixel(point);
Int alpha = color.GetAlpha();
if (alpha != 255)
{
Long background = XGetPixel(bkgr, point.x, point.y);
color = ((color.GetRed() * alpha + ((background >> 16) & 255) * (255 - alpha)) / 255) |
((color.GetGreen() * alpha + ((background >> 8) & 255) * (255 - alpha)) / 255) << 8 |
((color.GetBlue() * alpha + ( background & 255) * (255 - alpha)) / 255) << 16;
}
copy->SetPixel(point, color);
}
}
XDestroyImage(bkgr);
srcBitmap = copy;
}
/* Copy the image.
*/
if (destRect.GetSize() == srcRect.GetSize())
{
if (!painting) XPutImage(display, window, gc, (XImage *) srcBitmap->GetSystemBitmap(), srcRect.left, srcRect.top, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
XPutImage(display, this->bitmap, gc, (XImage *) srcBitmap->GetSystemBitmap(), srcRect.left, srcRect.top, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
}
else
{
const Bitmap &bitmap = srcBitmap->Scale(destSize);
if (!painting) XPutImage(display, window, gc, (XImage *) bitmap.GetSystemBitmap(), Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
XPutImage(display, this->bitmap, gc, (XImage *) bitmap.GetSystemBitmap(), Float(srcRect.left) / scaleFactorX, Float(srcRect.top) / scaleFactorY, destRect.left, destRect.top, destRect.GetWidth(), destRect.GetHeight());
}
/* Delete copy if we created one earlier.
*/
if (bitmap.GetDepth() != windowAttributes.depth) delete srcBitmap;
return Success();
}
S::Int S::GUI::SurfaceXLib::BlitToBitmap(const Rect &iSrcRect, Bitmap &bitmap, const Rect &destRect)
{
if (window == NIL) return Success();
if (bitmap == NIL) return Error();
Rect srcRect = rightToLeft.TranslateRect(iSrcRect);
if (srcRect.GetWidth() == 0 || srcRect.GetHeight() == 0 ||
destRect.GetWidth() == 0 || destRect.GetHeight() == 0) return Success();
/* Copy the image.
*/
XImage *image = XGetImage(display, this->bitmap, srcRect.left, srcRect.top, srcRect.GetWidth(), srcRect.GetHeight(), AllPlanes, ZPixmap);
Point point;
Float scaleFactorX = Float(srcRect.GetWidth()) / Float(destRect.GetWidth());
Float scaleFactorY = Float(srcRect.GetHeight()) / Float(destRect.GetHeight());
for (point.y = 0; point.y < destRect.GetHeight(); point.y++)
{
for (point.x = 0; point.x < destRect.GetWidth(); point.x++)
{
Float red = 0, green = 0, blue = 0;
for (Int srcX = Math::Floor(Float(point.x) * scaleFactorX); srcX < Math::Ceil(Float(point.x + 1) * scaleFactorX); srcX++)
{
for (Int srcY = Math::Floor(Float(point.y) * scaleFactorY); srcY < Math::Ceil(Float(point.y + 1) * scaleFactorY); srcY++)
{
Long value = XGetPixel(image, srcX, srcY);
Float weightX = (1.0 - Math::Max(0.0, Float(point.x) * scaleFactorX - Float(srcX)) - Math::Max(0.0, Float(srcX + 1) - Float(point.x + 1) * scaleFactorX)) / scaleFactorX;
Float weightY = (1.0 - Math::Max(0.0, Float(point.y) * scaleFactorY - Float(srcY)) - Math::Max(0.0, Float(srcY + 1) - Float(point.y + 1) * scaleFactorY)) / scaleFactorY;
red += Float((value >> 16) & 255) * weightX * weightY;
green += Float((value >> 8) & 255) * weightX * weightY;
blue += Float( value & 255) * weightX * weightY;
}
}
bitmap.SetPixel(point, Color(red, green, blue));
}
}
XDestroyImage(image);
return Success();
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/bitmap.cpp 0000664 0000000 0000000 00000010524 15164025770 0023177 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2019 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
#include
S::GUI::Bitmap::Bitmap(const int nil)
{
backend = BitmapBackend::CreateBackendInstance(nil);
}
S::GUI::Bitmap::Bitmap(const Size &iSize, Int iDepth)
{
backend = BitmapBackend::CreateBackendInstance(iSize, iDepth);
}
S::GUI::Bitmap::Bitmap(const Bitmap &iBitmap)
{
backend = BitmapBackend::CreateBackendInstance(*(iBitmap.backend));
}
S::GUI::Bitmap::Bitmap(Void *iBitmap)
{
backend = BitmapBackend::CreateBackendInstance(iBitmap);
}
S::GUI::Bitmap::~Bitmap()
{
delete backend;
}
S::Short S::GUI::Bitmap::GetBitmapType() const
{
return backend->GetBitmapType();
}
const S::GUI::Size &S::GUI::Bitmap::GetSize() const
{
return backend->GetSize();
}
S::Byte S::GUI::Bitmap::GetDepth() const
{
return backend->GetDepth();
}
S::UnsignedByte *S::GUI::Bitmap::GetBytes() const
{
return backend->GetBytes();
}
S::Byte S::GUI::Bitmap::GetBitsPerPixel() const
{
return backend->GetBitsPerPixel();
}
S::Byte S::GUI::Bitmap::GetLineAlignment() const
{
return backend->GetLineAlignment();
}
S::Bool S::GUI::Bitmap::CreateBitmap(const Size &nSize, Int nDepth)
{
return backend->CreateBitmap(nSize, nDepth);
}
S::Bool S::GUI::Bitmap::DeleteBitmap()
{
return backend->DeleteBitmap();
}
S::Bool S::GUI::Bitmap::SetSystemBitmap(Void *nBitmap)
{
return backend->SetSystemBitmap(nBitmap);
}
S::Void *S::GUI::Bitmap::GetSystemBitmap() const
{
return backend->GetSystemBitmap();
}
S::Int S::GUI::Bitmap::GrayscaleBitmap()
{
return backend->GrayscaleBitmap();
}
S::Int S::GUI::Bitmap::InvertColors()
{
return backend->InvertColors();
}
S::Int S::GUI::Bitmap::ReplaceColor(const Color &color1, const Color &color2)
{
return backend->ReplaceColor(color1, color2);
}
S::Int S::GUI::Bitmap::SetBackgroundColor(const Color &color)
{
return backend->SetBackgroundColor(color);
}
S::GUI::Bitmap S::GUI::Bitmap::Scale(const Size &newSize) const
{
if (GetSize() == Size() || GetSize() == newSize) return *this;
return backend->Scale(newSize);
}
S::Int S::GUI::Bitmap::BlitFromSurface(Surface *surface, const Rect &srcRect, const Rect &destRect)
{
if (surface == NIL) return Error();
return surface->BlitToBitmap(srcRect, *this, destRect);
}
S::Int S::GUI::Bitmap::BlitToSurface(const Rect &srcRect, Surface *surface, const Rect &destRect) const
{
if (surface == NIL) return Error();
return surface->BlitFromBitmap(*this, srcRect, destRect);
}
S::Bool S::GUI::Bitmap::SetPixel(const Point &point, const Color &color)
{
return backend->SetPixel(point, color);
}
S::GUI::Color S::GUI::Bitmap::GetPixel(const Point &point) const
{
return backend->GetPixel(point);
}
S::GUI::Bitmap &S::GUI::Bitmap::operator =(Void *iBitmap)
{
*backend = iBitmap;
return *this;
}
S::GUI::Bitmap &S::GUI::Bitmap::operator =(const int nil)
{
*backend = nil;
return *this;
}
S::GUI::Bitmap &S::GUI::Bitmap::operator =(const Bitmap &newBitmap)
{
*backend = *(newBitmap.backend);
return *this;
}
S::Bool S::GUI::Bitmap::operator ==(const int nil) const
{
return (*backend == nil);
}
S::Bool S::GUI::Bitmap::operator !=(const int nil) const
{
return (*backend != nil);
}
S::Bool S::GUI::Bitmap::operator ==(const Bitmap &bitmap) const
{
if (*this == NIL && bitmap == NIL) return True;
if (*this == NIL || bitmap == NIL) return False;
if (GetSize() != bitmap.GetSize() ||
GetDepth() != bitmap.GetDepth() ||
GetBitsPerPixel() != bitmap.GetBitsPerPixel() ||
GetLineAlignment() != bitmap.GetLineAlignment()) return False;
Size size = GetSize();
Int bpp = GetBitsPerPixel();
Int align = GetLineAlignment();
Int bpl = ((align - ((size.cx * (bpp / 8)) % align)) % align) + size.cx * (bpp / 8);
Int bytes = bpl * size.cy;
if (memcmp(GetBytes(), bitmap.GetBytes(), bytes) != 0) return False;
return True;
}
S::Bool S::GUI::Bitmap::operator !=(const Bitmap &bitmap) const
{
return !(*this == bitmap);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/color.cpp 0000775 0000000 0000000 00000016331 15164025770 0023046 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2014 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include
#include
S::GUI::Color S::GUI::Color::ConvertTo(ColorSpace cs) const
{
double p1 = 0;
double p2 = 0;
double p3 = 0;
double p4 = 0;
double r;
double g;
double b;
double h;
double s;
double v;
double min;
double max;
switch (colorSpace)
{
case RGB:
switch (cs)
{
case RGB:
return *this;
case RGBA:
return Color(255 << 24 | color, RGBA);
case HSV:
r = GetRed();
g = GetGreen();
b = GetBlue();
max = Math::Max(Math::Max(r, g), b);
min = Math::Min(Math::Min(r, g), b);
v = max;
if (max != 0) s = (max - min) / max;
else s = 0;
h = 0;
if (s != 0)
{
double delta = max - min;
if (r == max) h = (g - b) / delta;
else if (g == max) h = 2 + (b - r) / delta;
else if (b == max) h = 4 + (r - g) / delta;
h *= 60;
if (h < 0) h += 360;
}
p1 = h / 360 * 255;
p2 = s * 255;
p3 = v;
p1 = Math::Round(p1);
p2 = Math::Round(p2);
return Color((int) p1, (int) p2, (int) p3, HSV);
case YUV:
p1 = (GetRed() + GetGreen() + GetBlue()) / 3;
p2 = GetBlue();
p3 = GetRed();
p1 = Math::Round(p1);
return Color((int) p1, (int) p2, (int) p3, YUV);
case CMY:
p1 = 255 - GetRed();
p2 = 255 - GetGreen();
p3 = 255 - GetBlue();
return Color((int) p1, (int) p2, (int) p3, CMY);
case CMYK:
r = GetRed();
g = GetGreen();
b = GetBlue();
p4 = 255 - Math::Max(Math::Max(r, g), b);
p1 = 255 - r - p4;
p2 = 255 - g - p4;
p3 = 255 - b - p4;
return Color(((Int) p1) | ((Int) p2) << 8 | ((Int) p3) << 16 | ((Int) p4) << 24, CMYK);
case GRAY:
return Color((GetRed() + GetGreen() + GetBlue()) / 3, GRAY);
default:
break;
}
break;
case RGBA:
switch (cs)
{
case RGB:
return Color(GetRed(), GetGreen(), GetBlue(), RGB);
case RGBA:
return *this;
case HSV:
return ConvertTo(RGB).ConvertTo(HSV);
case YUV:
return ConvertTo(RGB).ConvertTo(YUV);
case CMY:
return ConvertTo(RGB).ConvertTo(CMY);
case CMYK:
return ConvertTo(RGB).ConvertTo(CMYK);
case GRAY:
return ConvertTo(RGB).ConvertTo(GRAY);
default:
break;
}
break;
case HSV:
switch (cs)
{
case RGB:
h = ((double) GetRed()) / 255 * 360;
s = ((double) GetGreen()) / 255;
v = GetBlue();
if (s == 0)
{
p1 = v;
p2 = v;
p3 = v;
}
else
{
while (h < 0) h += 360;
while (h >= 360) h -= 360;
h /= 60;
double f = h - (int) h;
double p = v * (1 - s );
double q = v * (1 - (s * f ));
double t = v * (1 - (s * (1 - f)));
switch ((int) h)
{
case 0:
p1 = v;
p2 = t;
p3 = p;
break;
case 1:
p1 = q;
p2 = v;
p3 = p;
break;
case 2:
p1 = p;
p2 = v;
p3 = t;
break;
case 3:
p1 = p;
p2 = q;
p3 = v;
break;
case 4:
p1 = t;
p2 = p;
p3 = v;
break;
case 5:
p1 = v;
p2 = p;
p3 = q;
break;
default:
break;
}
}
p1 = Math::Round(p1);
p2 = Math::Round(p2);
p3 = Math::Round(p3);
return Color((int) p1, (int) p2, (int) p3, RGB);
case RGBA:
return ConvertTo(RGB).ConvertTo(RGBA);
case HSV:
return *this;
case YUV:
return ConvertTo(RGB).ConvertTo(YUV);
case CMY:
return ConvertTo(RGB).ConvertTo(CMY);
case CMYK:
return ConvertTo(RGB).ConvertTo(CMYK);
case GRAY:
return ConvertTo(RGB).ConvertTo(GRAY);
default:
break;
}
break;
case YUV:
switch (cs)
{
case RGB:
p1 = GetBlue();
p3 = GetGreen();
p2 = 3 * GetRed() - p1 - p3;
if (p2 < 0) p2 = 0;
return Color((int) p1, (int) p2, (int) p3, RGB);
case RGBA:
return ConvertTo(RGB).ConvertTo(RGBA);
case HSV:
return ConvertTo(RGB).ConvertTo(HSV);
case YUV:
return *this;
case CMY:
return ConvertTo(RGB).ConvertTo(CMY);
case CMYK:
return ConvertTo(RGB).ConvertTo(CMYK);
case GRAY:
return ConvertTo(RGB).ConvertTo(GRAY);
default:
break;
}
break;
case CMY:
switch (cs)
{
case RGB:
p1 = 255 - GetRed();
p2 = 255 - GetGreen();
p3 = 255 - GetBlue();
return Color((int) p1, (int) p2, (int) p3, RGB);
case RGBA:
return ConvertTo(RGB).ConvertTo(RGBA);
case HSV:
return ConvertTo(RGB).ConvertTo(HSV);
case YUV:
return ConvertTo(RGB).ConvertTo(YUV);
case CMY:
return *this;
case CMYK:
return ConvertTo(RGB).ConvertTo(CMYK);
case GRAY:
return ConvertTo(RGB).ConvertTo(GRAY);
default:
break;
}
break;
case CMYK:
switch (cs)
{
case RGB:
p4 = GetAlpha();
p1 = 255 - GetRed() - p4;
p2 = 255 - GetGreen() - p4;
p3 = 255 - GetBlue() - p4;
return Color((int) p1, (int) p2, (int) p3, RGB);
case RGBA:
return ConvertTo(RGB).ConvertTo(RGBA);
case HSV:
return ConvertTo(RGB).ConvertTo(HSV);
case YUV:
return ConvertTo(RGB).ConvertTo(YUV);
case CMY:
return ConvertTo(RGB).ConvertTo(CMY);
case CMYK:
return *this;
case GRAY:
return ConvertTo(RGB).ConvertTo(GRAY);
default:
break;
}
break;
case GRAY:
switch (cs)
{
case RGB:
return Color(color, color, color, RGB);
case RGBA:
return ConvertTo(RGB).ConvertTo(RGBA);
case HSV:
return ConvertTo(RGB).ConvertTo(HSV);
case YUV:
return ConvertTo(RGB).ConvertTo(YUV);
case CMY:
return ConvertTo(RGB).ConvertTo(CMY);
case CMYK:
return ConvertTo(RGB).ConvertTo(CMYK);
case GRAY:
return *this;
default:
break;
}
break;
default:
break;
}
return *this;
}
S::GUI::Color S::GUI::Color::Downsample(Int bpcc) const
{
if (bpcc == 8) return *this;
int first = GetRed();
int second = GetGreen();
int third = GetBlue();
first >>= (8 - bpcc);
second >>= (8 - bpcc);
third >>= (8 - bpcc);
return Color((Long) (first + Math::Pow(2, bpcc) * second + Math::Pow(4, bpcc) * third), colorSpace);
}
S::GUI::Color S::GUI::Color::Upsample(Int bpcc) const
{
if (bpcc == 8) return *this;
int first = color & (int) (Math::Pow(2, bpcc) - 1);
int second = (color >> bpcc ) & (int) (Math::Pow(2, bpcc) - 1);
int third = (color >> (2 * bpcc)) & (int) (Math::Pow(2, bpcc) - 1);
first = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) first);
second = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) second);
third = (int) (255 / (Math::Pow(2, bpcc) - 1) * (double) third);
return Color(first, second, third, colorSpace);
}
smooth-0.9.11~git20260403.0230c0da/classes/graphics/font.cpp 0000664 0000000 0000000 00000007533 15164025770 0022677 0 ustar 00root root 0000000 0000000 /* The smooth Class Library
* Copyright (C) 1998-2011 Robert Kausch
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of "The Artistic License, Version 2.0".
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
#include