summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsubhransu mohanty <sub.mohanty@samsung.com>2017-11-27 11:46:27 +0900
committersubhransu mohanty <sub.mohanty@samsung.com>2018-04-12 13:51:51 +0900
commit584d0c64904201d1a463fc2d020ca928d8e6dd57 (patch)
treeec9b63725489d1542d53992f57c00ac2d3f2219e
parente4fbab8b4716a801053119f5470caee587043bb2 (diff)
ussg: added a new ssg library
-rw-r--r--ssg/example/lottie1.json0
-rw-r--r--ssg/example/main.cpp29
-rw-r--r--ssg/example/meson.build7
-rw-r--r--ssg/include/ftraster_p.h32
-rw-r--r--ssg/include/meson.build8
-rw-r--r--ssg/include/sgcontext.h76
-rw-r--r--ssg/include/sgdebug.h143
-rw-r--r--ssg/include/sgelapsedtimer.h20
-rw-r--r--ssg/include/sgfontdatabase.h33
-rw-r--r--ssg/include/sgglobal.h201
-rw-r--r--ssg/include/sggradient.h77
-rw-r--r--ssg/include/sgjson.h9
-rw-r--r--ssg/include/sgmatrix.h79
-rw-r--r--ssg/include/sgnode.h227
-rw-r--r--ssg/include/sgnodeupdater_p.h30
-rw-r--r--ssg/include/sgnodevisitor_p.h28
-rw-r--r--ssg/include/sgpath.h60
-rw-r--r--ssg/include/sgpoint.h58
-rw-r--r--ssg/include/sgrect.h111
-rw-r--r--ssg/include/sgrectnode.h15
-rw-r--r--ssg/include/sgregion.h74
-rw-r--r--ssg/include/sgrenderer.h62
-rw-r--r--ssg/include/sgrle.h44
-rw-r--r--ssg/include/sgshapenode.h31
-rw-r--r--ssg/include/ssg6
-rw-r--r--ssg/include/ssg.h9
-rw-r--r--ssg/meson.build31
-rw-r--r--ssg/meson_options.txt9
-rw-r--r--ssg/src/animation/meson.build0
-rw-r--r--ssg/src/animation/sgkeyframe.h120
-rw-r--r--ssg/src/ftraster/ftraster.cpp295
-rw-r--r--ssg/src/ftraster/meson.build11
-rw-r--r--ssg/src/ftraster/sw_ft_math.cpp528
-rw-r--r--ssg/src/ftraster/sw_ft_math.h438
-rw-r--r--ssg/src/ftraster/sw_ft_raster.cpp1674
-rw-r--r--ssg/src/ftraster/sw_ft_raster.h607
-rw-r--r--ssg/src/ftraster/sw_ft_raster2.cpp1710
-rw-r--r--ssg/src/ftraster/sw_ft_stroker.cpp2292
-rw-r--r--ssg/src/ftraster/sw_ft_stroker.h325
-rw-r--r--ssg/src/ftraster/sw_ft_types.h160
-rw-r--r--ssg/src/lottie/animation/content/meson.build0
-rw-r--r--ssg/src/lottie/animation/keyframe/meson.build0
-rw-r--r--ssg/src/lottie/animation/meson.build8
-rw-r--r--ssg/src/lottie/jsontest.cpp501
-rw-r--r--ssg/src/lottie/lottiecomposition.cpp163
-rw-r--r--ssg/src/lottie/lottiecomposition.h255
-rw-r--r--ssg/src/lottie/lottiedrawable.cpp181
-rw-r--r--ssg/src/lottie/lottiedrawable.h36
-rw-r--r--ssg/src/lottie/meson.build21
-rw-r--r--ssg/src/lottie/model/animatable/meson.build0
-rw-r--r--ssg/src/lottie/model/content/meson.build0
-rw-r--r--ssg/src/lottie/model/layer/meson.build0
-rw-r--r--ssg/src/lottie/model/meson.build8
-rw-r--r--ssg/src/lottie/rapidjson/allocators.h271
-rw-r--r--ssg/src/lottie/rapidjson/cursorstreamwrapper.h78
-rw-r--r--ssg/src/lottie/rapidjson/document.h2672
-rw-r--r--ssg/src/lottie/rapidjson/encodedstream.h299
-rw-r--r--ssg/src/lottie/rapidjson/encodings.h716
-rw-r--r--ssg/src/lottie/rapidjson/error/en.h74
-rw-r--r--ssg/src/lottie/rapidjson/error/error.h161
-rw-r--r--ssg/src/lottie/rapidjson/filereadstream.h99
-rw-r--r--ssg/src/lottie/rapidjson/filewritestream.h104
-rw-r--r--ssg/src/lottie/rapidjson/fwd.h151
-rw-r--r--ssg/src/lottie/rapidjson/internal/biginteger.h290
-rw-r--r--ssg/src/lottie/rapidjson/internal/diyfp.h258
-rw-r--r--ssg/src/lottie/rapidjson/internal/dtoa.h245
-rw-r--r--ssg/src/lottie/rapidjson/internal/ieee754.h78
-rw-r--r--ssg/src/lottie/rapidjson/internal/itoa.h304
-rw-r--r--ssg/src/lottie/rapidjson/internal/meta.h181
-rw-r--r--ssg/src/lottie/rapidjson/internal/pow10.h55
-rw-r--r--ssg/src/lottie/rapidjson/internal/regex.h734
-rw-r--r--ssg/src/lottie/rapidjson/internal/stack.h231
-rw-r--r--ssg/src/lottie/rapidjson/internal/strfunc.h69
-rw-r--r--ssg/src/lottie/rapidjson/internal/strtod.h269
-rw-r--r--ssg/src/lottie/rapidjson/internal/swap.h46
-rw-r--r--ssg/src/lottie/rapidjson/istreamwrapper.h115
-rw-r--r--ssg/src/lottie/rapidjson/memorybuffer.h70
-rw-r--r--ssg/src/lottie/rapidjson/memorystream.h71
-rw-r--r--ssg/src/lottie/rapidjson/meson.build8
-rw-r--r--ssg/src/lottie/rapidjson/msinttypes/inttypes.h316
-rw-r--r--ssg/src/lottie/rapidjson/msinttypes/stdint.h300
-rw-r--r--ssg/src/lottie/rapidjson/ostreamwrapper.h81
-rw-r--r--ssg/src/lottie/rapidjson/pointer.h1358
-rw-r--r--ssg/src/lottie/rapidjson/prettywriter.h277
-rw-r--r--ssg/src/lottie/rapidjson/rapidjson.h630
-rw-r--r--ssg/src/lottie/rapidjson/reader.h2221
-rw-r--r--ssg/src/lottie/rapidjson/schema.h2017
-rw-r--r--ssg/src/lottie/rapidjson/stream.h223
-rw-r--r--ssg/src/lottie/rapidjson/stringbuffer.h121
-rw-r--r--ssg/src/lottie/rapidjson/writer.h711
-rw-r--r--ssg/src/meson.build28
-rw-r--r--ssg/src/scenegraph/backend/meson.build7
-rw-r--r--ssg/src/scenegraph/backend/software/meson.build10
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwaredrawable.cpp135
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwaredrawable.h68
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarenodeupdater.cpp134
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarenodeupdater.h76
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarerectnode.cpp0
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarerectnode.h12
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarerenderer.cpp207
-rw-r--r--ssg/src/scenegraph/backend/software/sgsoftwarerenderer.h50
-rw-r--r--ssg/src/scenegraph/core/meson.build11
-rw-r--r--ssg/src/scenegraph/core/sgcontext.cpp1
-rw-r--r--ssg/src/scenegraph/core/sgnode.cpp383
-rw-r--r--ssg/src/scenegraph/core/sgnodeupdater.cpp98
-rw-r--r--ssg/src/scenegraph/core/sgrectnode.cpp0
-rw-r--r--ssg/src/scenegraph/core/sgrenderer.cpp192
-rw-r--r--ssg/src/scenegraph/meson.build12
-rw-r--r--ssg/src/text/meson.build8
-rw-r--r--ssg/src/text/sgfontdatabase.cpp53
-rw-r--r--ssg/src/util/meson.build14
-rw-r--r--ssg/src/util/sgdebug.cpp701
-rw-r--r--ssg/src/util/sgelapsedtimer.cpp29
-rw-r--r--ssg/src/util/sgmatrix.cpp776
-rw-r--r--ssg/src/util/sgpath.cpp138
-rw-r--r--ssg/src/util/sgrect.cpp0
-rw-r--r--ssg/src/util/sgregion.cpp2359
-rw-r--r--ssg/src/util/sgrle.cpp438
-rw-r--r--ssg/src/util/sgrle.cppm441
-rw-r--r--ssg/test/meson.build20
-rw-r--r--ssg/test/ssgtestsuite.cpp8
-rw-r--r--ssg/test/testftraster.cpp30
-rw-r--r--ssg/test/testsgregion.cpp120
123 files changed, 33305 insertions, 0 deletions
diff --git a/ssg/example/lottie1.json b/ssg/example/lottie1.json
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/ssg/example/lottie1.json
diff --git a/ssg/example/main.cpp b/ssg/example/main.cpp
new file mode 100644
index 0000000000..938f4dba0c
--- /dev/null
+++ b/ssg/example/main.cpp
@@ -0,0 +1,29 @@
1#include<iostream>
2using namespace std;
3#include"sgregion.h"
4#include"sgmatrix.h"
5#include"sgpath.h"
6#include"ftraster_p.h"
7#include"sgelapsedtimer.h"
8#include"sgdebug.h"
9#include "sgjson.h"
10#include<iostream>
11#include<fstream>
12#include<sstream>
13
14
15int main()
16{
17 initialize(GuaranteedLogger(), "/tmp/", "ssglog", 1);
18 set_log_level(LogLevel::INFO);
19 //SGJson json;
20 std::ifstream file;
21 file.open("/home/subhransu/openSourceEfl/ssgrepo/ssg/build/example/LightBulb.json");
22 std::stringstream buffer;
23 buffer << file.rdbuf();
24 //std::cout <<"file size = "<< buffer.str().size()<<std::endl;
25 //std::cout << buffer.str().data();
26 SGJson json(buffer.str().data());
27 file.close();
28 return 0;
29}
diff --git a/ssg/example/meson.build b/ssg/example/meson.build
new file mode 100644
index 0000000000..1fa5a60750
--- /dev/null
+++ b/ssg/example/meson.build
@@ -0,0 +1,7 @@
1
2demo_sources = [ 'main.cpp']
3
4executable('ssg_demo',
5 demo_sources,
6 include_directories : inc,
7 link_with : ssglib)
diff --git a/ssg/include/ftraster_p.h b/ssg/include/ftraster_p.h
new file mode 100644
index 0000000000..595e991c19
--- /dev/null
+++ b/ssg/include/ftraster_p.h
@@ -0,0 +1,32 @@
1#ifndef FTRASTER_P_H
2#define FTRASTER_P_H
3#include"sgrle.h"
4#include<future>
5
6struct FTOutline;
7class SGPath;
8
9struct FTRasterPrivate;
10class FTRaster
11{
12public:
13 ~FTRaster();
14 static FTRaster &instance()
15 {
16 static FTRaster Singleton;
17 return Singleton;
18 }
19 FTRaster(const FTRaster &other) = delete;
20 FTRaster(FTRaster&&) = delete;
21 FTRaster& operator=(FTRaster const&) = delete;
22 FTRaster& operator=(FTRaster &&) = delete;
23
24 static FTOutline *toFTOutline(const SGPath &path);
25 static void deleteFTOutline(FTOutline *);
26 std::future<SGRle> generateFillInfo(const FTOutline *);
27 std::future<SGRle> generateStrokeInfo(const FTOutline *, CapStyle cap, JoinStyle join, double width);
28private:
29 FTRaster();
30 FTRasterPrivate *d;
31};
32#endif // FTRASTER_P_H
diff --git a/ssg/include/meson.build b/ssg/include/meson.build
new file mode 100644
index 0000000000..568d597167
--- /dev/null
+++ b/ssg/include/meson.build
@@ -0,0 +1,8 @@
1install_headers([
2 'ssg',
3 'ssg.h',
4 'sgglobal.h',
5 'sgregion.h',
6 'sgnode.h',
7 'sgmatrix.h'],
8 subdir: 'ssg')
diff --git a/ssg/include/sgcontext.h b/ssg/include/sgcontext.h
new file mode 100644
index 0000000000..61fcb74bee
--- /dev/null
+++ b/ssg/include/sgcontext.h
@@ -0,0 +1,76 @@
1#ifndef SGCONTEXT_H
2#define SGCONTEXT_H
3
4#include"sgglobal.h"
5
6class SGRectangleNode;
7class SGImageNode;
8class SGGlyphNode;
9class SGLayer;
10class SGRenderContext;
11
12class SG_EXPORT SGContext
13{
14
15public:
16 enum AntialiasingMethod {
17 UndecidedAntialiasing,
18 VertexAntialiasing,
19 MsaaAntialiasing
20 };
21
22 explicit SGContext();
23 virtual ~SGContext();
24
25 virtual void renderContextInitialized(SGRenderContext *renderContext);
26 virtual void renderContextInvalidated(SGRenderContext *renderContext);
27 virtual SGRenderContext *createRenderContext() = 0;
28
29 virtual SGRectangleNode *createRectangleNode() = 0;
30 virtual SGImageNode *createImageNode() = 0;
31 virtual SGGlyphNode *createGlyphNode(SGRenderContext *rc) = 0;
32 virtual SGLayer *createLayer(SGRenderContext *renderContext) = 0;
33
34 static SGContext *createDefaultContext();
35 //static SGRenderLoop *createWindowManager();
36
37 static void setBackend(const char *backend);
38 static const char *backend();
39};
40
41class SG_EXPORT SGRenderContext
42{
43public:
44 enum CreateTextureFlags {
45 CreateTexture_Alpha = 0x1,
46 CreateTexture_Atlas = 0x2,
47 CreateTexture_Mipmap = 0x4
48 };
49
50 SGRenderContext(SGContext *context);
51 virtual ~SGRenderContext();
52
53 SGContext *sceneGraphContext() const { return m_sg; }
54 virtual bool isValid() const { return true; }
55
56 virtual void initialize(void *context);
57 virtual void invalidate();
58 virtual void renderNextFrame(SGRenderer *renderer, uint fboId) = 0;
59 virtual void endSync();
60
61 virtual SGTexture *createTexture() const = 0;
62 virtual SGRenderer *createRenderer() = 0;
63
64 virtual void setAttachToGraphicsContext(bool attach) { Q_UNUSED(attach); }
65
66 virtual int maxTextureSize() const = 0;
67
68 void registerFontengineForCleanup(QFontEngine *engine);
69
70protected:
71 // Hold m_sg with QPointer in the rare case it gets deleted before us.
72 SGContext *m_sg;
73};
74
75
76#endif // SGCONTEXT_H
diff --git a/ssg/include/sgdebug.h b/ssg/include/sgdebug.h
new file mode 100644
index 0000000000..d922398187
--- /dev/null
+++ b/ssg/include/sgdebug.h
@@ -0,0 +1,143 @@
1#ifndef SGDEBUG_H
2#define SGDEBUG_H
3#include <cstdint>
4#include <memory>
5#include <string>
6#include <iosfwd>
7#include <type_traits>
8
9
10
11 enum class LogLevel : uint8_t { INFO, WARN, CRIT, OFF };
12
13
14class SGDebug
15{
16public:
17 SGDebug();
18 SGDebug& debug() {return *this;}
19 SGDebug(LogLevel level, char const * file, char const * function, uint32_t line);
20 ~SGDebug();
21
22 SGDebug(SGDebug &&) = default;
23 SGDebug& operator=(SGDebug &&) = default;
24
25 void stringify(std::ostream & os);
26
27 SGDebug& operator<<(char arg);
28 SGDebug& operator<<(int32_t arg);
29 SGDebug& operator<<(uint32_t arg);
30 //SGDebug& operator<<(int64_t arg);
31 //SGDebug& operator<<(uint64_t arg);
32
33 SGDebug& operator<<(long arg);
34 SGDebug& operator<<(unsigned long arg);
35 SGDebug& operator<<(double arg);
36 SGDebug& operator<<(std::string const & arg);
37
38 template < size_t N >
39 SGDebug& operator<<(const char (&arg)[N]) {
40 encode(string_literal_t(arg));
41 return *this;
42 }
43
44 template < typename Arg >
45 typename std::enable_if < std::is_same < Arg, char const * >::value, SGDebug& >::type
46 operator<<(Arg const & arg) {
47 encode(arg);
48 return *this;
49 }
50
51 template < typename Arg >
52 typename std::enable_if < std::is_same < Arg, char * >::value, SGDebug& >::type
53 operator<<(Arg const & arg) {
54 encode(arg);
55 return *this;
56 }
57
58 struct string_literal_t {
59 explicit string_literal_t(char const * s) : m_s(s) {}
60 char const * m_s;
61 };
62
63private:
64 char * buffer();
65
66 template < typename Arg >
67 void encode(Arg arg);
68
69 template < typename Arg >
70 void encode(Arg arg, uint8_t type_id);
71
72 void encode(char * arg);
73 void encode(char const * arg);
74 void encode(string_literal_t arg);
75 void encode_c_string(char const * arg, size_t length);
76 void resize_buffer_if_needed(size_t additional_bytes);
77 void stringify(std::ostream & os, char * start, char const * const end);
78
79private:
80 size_t m_bytes_used;
81 size_t m_buffer_size;
82 std::unique_ptr < char [] > m_heap_buffer;
83 bool m_logAll;
84 char m_stack_buffer[256 - sizeof(bool) - 2 * sizeof(size_t) - sizeof(decltype(m_heap_buffer)) - 8 /* Reserved */];
85};
86
87struct SGDebugServer
88{
89 /*
90 * Ideally this should have been operator+=
91 * Could not get that to compile, so here we are...
92 */
93 bool operator==(SGDebug &);
94};
95
96void set_log_level(LogLevel level);
97
98bool is_logged(LogLevel level);
99
100
101/*
102 * Non guaranteed logging. Uses a ring buffer to hold log lines.
103 * When the ring gets full, the previous log line in the slot will be dropped.
104 * Does not block producer even if the ring buffer is full.
105 * ring_buffer_size_mb - LogLines are pushed into a mpsc ring buffer whose size
106 * is determined by this parameter. Since each LogLine is 256 bytes,
107 * ring_buffer_size = ring_buffer_size_mb * 1024 * 1024 / 256
108 */
109struct NonGuaranteedLogger
110{
111 NonGuaranteedLogger(uint32_t ring_buffer_size_mb_) : ring_buffer_size_mb(ring_buffer_size_mb_) {}
112 uint32_t ring_buffer_size_mb;
113};
114
115/*
116 * Provides a guarantee log lines will not be dropped.
117 */
118struct GuaranteedLogger
119{
120};
121
122/*
123 * Ensure initialize() is called prior to any log statements.
124 * log_directory - where to create the logs. For example - "/tmp/"
125 * log_file_name - root of the file name. For example - "nanolog"
126 * This will create log files of the form -
127 * /tmp/nanolog.1.txt
128 * /tmp/nanolog.2.txt
129 * etc.
130 * log_file_roll_size_mb - mega bytes after which we roll to next log file.
131 */
132void initialize(GuaranteedLogger gl, std::string const & log_directory,
133 std::string const & log_file_name, uint32_t log_file_roll_size_mb);
134void initialize(NonGuaranteedLogger ngl, std::string const & log_directory,
135 std::string const & log_file_name, uint32_t log_file_roll_size_mb);
136
137
138#define SGDEBUG_LOG(LEVEL) SGDebugServer() == SGDebug(LEVEL, __FILE__, __func__, __LINE__).debug()
139#define sgDebug is_logged(LogLevel::INFO) && SGDEBUG_LOG(LogLevel::INFO)
140#define sgWarning is_logged(LogLevel::INFO) && SGDEBUG_LOG(LogLevel::WARN)
141#define sgCritical is_logged(LogLevel::INFO) && SGDEBUG_LOG(LogLevel::CRIT)
142
143#endif // SGDEBUG_H
diff --git a/ssg/include/sgelapsedtimer.h b/ssg/include/sgelapsedtimer.h
new file mode 100644
index 0000000000..6e78b869c2
--- /dev/null
+++ b/ssg/include/sgelapsedtimer.h
@@ -0,0 +1,20 @@
1#ifndef SGELAPSEDTIMER_H
2#define SGELAPSEDTIMER_H
3
4#include "sgglobal.h"
5#include<chrono>
6
7class SG_EXPORT SGElapsedTimer
8{
9public:
10 SGElapsedTimer():m_valid(false){}
11 double elapsed() const;
12 bool hasExpired(double millsec);
13 void start();
14 double restart();
15 inline bool isValid() const {return m_valid;}
16private:
17 std::chrono::high_resolution_clock::time_point clock;
18 bool m_valid;
19};
20#endif // SGELAPSEDTIMER_H
diff --git a/ssg/include/sgfontdatabase.h b/ssg/include/sgfontdatabase.h
new file mode 100644
index 0000000000..83573a6363
--- /dev/null
+++ b/ssg/include/sgfontdatabase.h
@@ -0,0 +1,33 @@
1#ifndef SGFONTDATABASE_H
2#define SGFONTDATABASE_H
3
4#include"sgglobal.h"
5
6class SGFontDatabasePrivate;
7class SG_EXPORT SGFontDatabase
8{
9public:
10 enum HintMode{
11 Default,
12 None,
13 Auto,
14 Full
15 };
16 ~SGFontDatabase();
17 static SGFontDatabase &instance()
18 {
19 static SGFontDatabase Singleton;
20 return Singleton;
21 }
22 SGFontDatabase(const SGFontDatabase &other) = delete;
23 SGFontDatabase(SGFontDatabase&&) = delete;
24 SGFontDatabase& operator=(SGFontDatabase const&) = delete;
25 SGFontDatabase& operator=(SGFontDatabase &&) = delete;
26 void print() const;
27private:
28 SGFontDatabase();
29 friend class SGFontDatabasePrivate;
30 SGFontDatabasePrivate *d;
31};
32
33#endif // SGFONTDATABASE_H
diff --git a/ssg/include/sgglobal.h b/ssg/include/sgglobal.h
new file mode 100644
index 0000000000..bec0d0f651
--- /dev/null
+++ b/ssg/include/sgglobal.h
@@ -0,0 +1,201 @@
1#ifndef SGGLOBAL_H
2#define SGGLOBAL_H
3
4#include<iostream>
5#include <cmath>
6#include<cstdint>
7#include<type_traits>
8#include<utility>
9
10typedef uint32_t uint;
11typedef uint16_t ushort;
12typedef uint8_t uchar;
13
14
15#define SG_VISIBILITY_AVAILABLE
16
17# ifdef SG_OS_WIN
18# define SG_EXPORT __declspec(dllexport)
19# define SG_IMPORT __declspec(dllimport)
20# elif defined(SG_VISIBILITY_AVAILABLE)
21# define SG_EXPORT __attribute__((visibility("default")))
22# define SG_EXPORT __attribute__((visibility("default")))
23# endif
24
25#define SG_UNUSED __attribute__((__unused__))
26#define SG_REQUIRED_RESULT __attribute__ ((__warn_unused_result__))
27
28#define SG_CONSTEXPR constexpr
29#define SG_NOTHROW noexcept
30
31#include"sgdebug.h"
32
33class RefCount
34{
35public:
36 inline RefCount(){}
37 inline RefCount(int i):atomic(i){}
38 inline bool ref() {
39 int count = atomic;
40 if (count == 0) // !isSharable
41 return false;
42 if (count != -1) // !isStatic
43 atomic++;
44 return true;
45 }
46 inline bool deref() {
47 int count = atomic;
48 if (count == 0) // !isSharable
49 return false;
50 if (count == -1) // isStatic
51 return true;
52 return --atomic;
53 }
54 bool isShared() const
55 {
56 int count = atomic;
57 return (count != 1) && (count != 0);
58 }
59 bool isStatic() const
60 {
61 // Persistent object, never deleted
62 return atomic == -1;
63 }
64 inline int count()const{return atomic;}
65 void setOwned() { atomic = 1; }
66 void setUnsharable() { atomic = 0; }
67private:
68 int atomic;
69};
70
71template <typename T>
72SG_CONSTEXPR inline const T &sgMin(const T &a, const T &b) { return (a < b) ? a : b; }
73template <typename T>
74SG_CONSTEXPR inline const T &sgMax(const T &a, const T &b) { return (a < b) ? b : a; }
75
76static inline bool sgCompare(double p1, double p2)
77{
78 return (std::abs(p1 - p2) * 1000000000000. <= sgMin(std::abs(p1), std::abs(p2)));
79}
80
81static inline bool sgCompare(float p1, float p2)
82{
83 return (std::abs(p1 - p2) * 100000.f <= sgMin(std::abs(p1), std::abs(p2)));
84}
85
86static inline bool sgIsNull(double d)
87{
88 return std::abs(d) <= 0.000000000001;
89}
90
91static inline bool sgIsNull(float f)
92{
93 return std::abs(f) <= 0.00001f;
94}
95
96class sgFlagHelper
97{
98 int i;
99public:
100 constexpr inline sgFlagHelper(int ai) noexcept : i(ai) {}
101 constexpr inline operator int() const noexcept { return i; }
102
103 constexpr inline sgFlagHelper(uint ai) noexcept : i(int(ai)) {}
104 constexpr inline sgFlagHelper(short ai) noexcept : i(int(ai)) {}
105 constexpr inline sgFlagHelper(ushort ai) noexcept : i(int(uint(ai))) {}
106 constexpr inline operator uint() const noexcept { return uint(i); }
107};
108
109template<typename Enum>
110class sgFlag
111{
112public:
113 static_assert((sizeof(Enum) <= sizeof(int)),
114 "sgFlag only supports int as storage so bigger type will overflow");
115 static_assert((std::is_enum<Enum>::value), "sgFlag is only usable on enumeration types.");
116
117 typedef typename std::conditional<
118 std::is_unsigned<typename std::underlying_type<Enum>::type>::value,
119 unsigned int,
120 signed int
121 >::type Int;
122
123 typedef Enum enum_type;
124 // compiler-generated copy/move ctor/assignment operators are fine!
125
126 constexpr inline sgFlag(Enum f) noexcept : i(Int(f)) {}
127 constexpr inline sgFlag() noexcept : i(0) {}
128 constexpr inline sgFlag(sgFlagHelper f) noexcept : i(f) {}
129
130 inline sgFlag &operator&=(int mask) noexcept { i &= mask; return *this; }
131 inline sgFlag &operator&=(uint mask) noexcept { i &= mask; return *this; }
132 inline sgFlag &operator&=(Enum mask) noexcept { i &= Int(mask); return *this; }
133 inline sgFlag &operator|=(sgFlag f) noexcept { i |= f.i; return *this; }
134 inline sgFlag &operator|=(Enum f) noexcept { i |= Int(f); return *this; }
135 inline sgFlag &operator^=(sgFlag f) noexcept { i ^= f.i; return *this; }
136 inline sgFlag &operator^=(Enum f) noexcept { i ^= Int(f); return *this; }
137
138 constexpr inline operator Int() const noexcept { return i; }
139
140 constexpr inline sgFlag operator|(sgFlag f) const { return sgFlag(sgFlagHelper(i | f.i)); }
141 constexpr inline sgFlag operator|(Enum f) const noexcept { return sgFlag(sgFlagHelper(i | Int(f))); }
142 constexpr inline sgFlag operator^(sgFlag f) const noexcept { return sgFlag(sgFlagHelper(i ^ f.i)); }
143 constexpr inline sgFlag operator^(Enum f) const noexcept { return sgFlag(sgFlagHelper(i ^ Int(f))); }
144 constexpr inline sgFlag operator&(int mask) const noexcept { return sgFlag(sgFlagHelper(i & mask)); }
145 constexpr inline sgFlag operator&(uint mask) const noexcept { return sgFlag(sgFlagHelper(i & mask)); }
146 constexpr inline sgFlag operator&(Enum f) const noexcept { return sgFlag(sgFlagHelper(i & Int(f))); }
147 constexpr inline sgFlag operator~() const noexcept { return sgFlag(sgFlagHelper(~i)); }
148
149 constexpr inline bool operator!() const noexcept { return !i; }
150
151 constexpr inline bool testFlag(Enum f) const noexcept { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); }
152 inline sgFlag &setFlag(Enum f, bool on = true) noexcept
153 {
154 return on ? (*this |= f) : (*this &= ~f);
155 }
156
157 Int i;
158};
159
160
161class SG_EXPORT SGColor
162{
163 inline SGColor() noexcept {a = r = g = b = 0;}
164 inline SGColor(int red, int green, int blue, int alpha = 255) noexcept { r = red; g = green; b = blue; a = alpha; }
165 inline int red() const noexcept {return r;}
166 inline int green() const noexcept{return g;}
167 inline int blue() const noexcept{return b;}
168 inline int alpha() const noexcept{return a;}
169 inline void setRed(int red) noexcept {r = red;}
170 inline void setGreen(int green)noexcept {g = green;}
171 inline void setBlue(int blue)noexcept {b = blue;}
172 inline void setAlpha(int alpha)noexcept {a = alpha;}
173
174public:
175 ushort a;
176 ushort r;
177 ushort g;
178 ushort b;
179};
180
181enum class FillRule {
182 OddEven,
183 Winding
184};
185
186enum class JoinStyle {
187 Miter,
188 Bevel,
189 Round
190};
191enum class CapStyle {
192 Flat,
193 Square,
194 Round
195};
196enum StrokeStyle {
197 SolidLine,
198 DashLine
199};
200
201#endif //SGGLOBAL_H
diff --git a/ssg/include/sggradient.h b/ssg/include/sggradient.h
new file mode 100644
index 0000000000..baff3af347
--- /dev/null
+++ b/ssg/include/sggradient.h
@@ -0,0 +1,77 @@
1#ifndef SGGRADIENT_H
2#define SGGRADIENT_H
3
4#include "sgglobal.h"
5#include<vector>
6
7class SGGradientStop
8{
9 SGGradientStop(double pos, const SGColor &color):m_pos(pos), m_color(color){}
10 inline double position(){return m_pos;}
11 inline double color(){return m_color;}
12public:
13 double m_pos;
14 SGColor m_color;
15};
16
17typedef std::vector<SGGradientStop> SGGradientStops;
18
19class SGGradient
20{
21public:
22 enum class SpreadMode {
23 Pad,
24 Repeat,
25 Reflect
26 };
27 SpreadMode spread() const;
28 void setSpread(SpreadMode mode);
29private:
30 SpreadMode m_spread;
31 SGGradientStops m_stops;
32};
33
34class SGLinearGradient : public SGGradient
35{
36 public:
37 double x1() const;
38 void setX1(double v);
39 double y1() const;
40 void setY1(double v);
41 double x2() const;
42 void setX2(double v);
43 double y2() const;
44 void setY2(double v);
45private:
46 double m_X1, m_Y1;
47 double m_X2, m_Y2;
48};
49
50class SGRadialGradient : public SGGradient
51{
52 public:
53 double centerX() const;
54 void setCenterX(double v);
55
56 double centerY() const;
57 void setCenterY(double v);
58
59 double centerRadius() const;
60 void setCenterRadius(double v);
61
62 double focalX() const;
63 void setFocalX(double v);
64
65 double focalY() const;
66 void setFocalY(double v);
67
68 double focalRadius() const;
69 void setFocalRadius(double v);
70private:
71 double m_centerX, m_centerY;
72 double m_focalX, m_focalY;
73 double m_centerRadius = 0;
74 double m_focalRadius = 0;
75};
76
77#endif // SGGRADIENT_H
diff --git a/ssg/include/sgjson.h b/ssg/include/sgjson.h
new file mode 100644
index 0000000000..c242c770a0
--- /dev/null
+++ b/ssg/include/sgjson.h
@@ -0,0 +1,9 @@
1#ifndef SGJSON_H
2#define SGJSON_H
3class SGJson
4{
5public:
6 SGJson(){}
7 SGJson(const char *data);
8};
9#endif // SGJSON_H
diff --git a/ssg/include/sgmatrix.h b/ssg/include/sgmatrix.h
new file mode 100644
index 0000000000..25ab0cf35f
--- /dev/null
+++ b/ssg/include/sgmatrix.h
@@ -0,0 +1,79 @@
1#ifndef SGMATRIX_H
2#define SGMATRIX_H
3#include"sgpoint.h"
4#include "sgregion.h"
5#include "sgglobal.h"
6
7struct SGMatrixData;
8class SG_EXPORT SGMatrix
9{
10public:
11 enum class Axis {
12 X,
13 Y,
14 Z
15 };
16 enum class MatrixType {
17 None = 0x00,
18 Translate = 0x01,
19 Scale = 0x02,
20 Rotate = 0x04,
21 Shear = 0x08,
22 Project = 0x10
23 };
24
25 SGMatrix();
26 ~SGMatrix();
27 SGMatrix(const SGMatrix &matrix);
28 SGMatrix(SGMatrix &&other);
29 SGMatrix &operator=(const SGMatrix &);
30 SGMatrix &operator=(SGMatrix &&other);
31
32 bool isAffine() const;
33 bool isIdentity() const;
34 bool isInvertible() const;
35 bool isScaling() const;
36 bool isRotating() const;
37 bool isTranslating() const;
38 MatrixType type() const;
39 inline float determinant() const;
40
41 SGMatrix &translate(float dx, float dy);
42 SGMatrix &scale(float sx, float sy);
43 SGMatrix &shear(float sh, float sv);
44 SGMatrix &rotate(float a, Axis axis);
45 SGMatrix &rotateRadians(float a, Axis axis);
46
47 SGPointF map(const SGPointF &p) const;
48 inline SGPointF map(float x, float y) const;
49 SGRect map(const SGRect &r) const;
50 SGRegion map(const SGRegion &r) const;
51
52 SG_REQUIRED_RESULT SGMatrix inverted(bool *invertible = nullptr) const;
53 SG_REQUIRED_RESULT SGMatrix adjoint() const;
54
55 SGMatrix operator*(const SGMatrix &o) const;
56 SGMatrix &operator*=(const SGMatrix &);
57 SGMatrix &operator*=(float mul);
58 SGMatrix &operator/=(float div);
59 bool operator==(const SGMatrix &) const;
60 bool operator!=(const SGMatrix &) const;
61 friend std::ostream& operator<<(std::ostream& os, const SGMatrix& o);
62private:
63 explicit SGMatrix(bool init);
64 explicit SGMatrix(float m11, float m12, float m13,
65 float m21, float m22, float m23,
66 float m31, float m32, float m33);
67 SGMatrix copy() const;
68 void detach();
69 void cleanUp(SGMatrixData *x);
70
71 SGMatrixData *d;
72};
73
74inline SGPointF SGMatrix::map(float x, float y) const
75{
76 return map(SGPointF(x, y));
77}
78
79#endif // SGMATRIX_H
diff --git a/ssg/include/sgnode.h b/ssg/include/sgnode.h
new file mode 100644
index 0000000000..dca24d20a3
--- /dev/null
+++ b/ssg/include/sgnode.h
@@ -0,0 +1,227 @@
1#ifndef SGNODE_H
2#define SGNODE_H
3
4#include<sgglobal.h>
5#include<sgregion.h>
6#include<sgmatrix.h>
7#include<vector>
8
9class SGGeometry;
10class SGRect;
11class SGRenderer;
12class SGNodeVisitor;
13class SG_EXPORT SGNode
14{
15public:
16 enum class NodeType {
17 Basic,
18 Geometry,
19 Transform,
20 Clip,
21 Opacity,
22 Root,
23 };
24
25 enum class Flag {
26 // Lower 16 bites reserved for general node
27 OwnedByParent = 0x0001,
28 UsePreprocess = 0x0002,
29 // 0x00ff0000 bits reserved for node subclasses
30 OwnsGeometry = 0x00010000,
31 IsVisitableNode = 0x01000000
32 };
33 typedef sgFlag<Flag> NodeFlag;
34 enum class DirtyState {
35 SubtreeBlocked = 0x0080,
36 Matrix = 0x0100,
37 NodeAdded = 0x0400,
38 NodeRemoved = 0x0800,
39 Geometry = 0x1000,
40 Material = 0x2000,
41 Opacity = 0x4000,
42 ForceUpdate = 0x8000,
43 UsePreprocess = 0x0002,
44 PropagationMask = Matrix
45 | NodeAdded
46 | Opacity
47 | ForceUpdate
48
49 };
50 typedef sgFlag<DirtyState> DirtyFlag;
51 SGNode();
52 virtual ~SGNode();
53
54 SGNode *parent() const { return m_parent; }
55
56 void removeChildNode(SGNode *node);
57 void removeAllChildNodes();
58 void prependChildNode(SGNode *node);
59 void appendChildNode(SGNode *node);
60 void insertChildNodeBefore(SGNode *node, SGNode *before);
61 void insertChildNodeAfter(SGNode *node, SGNode *after);
62 void reparentChildNodesTo(SGNode *newParent);
63
64 int childCount() const;
65 SGNode *childAtIndex(int i) const;
66 SGNode *firstChild() const { return m_firstChild; }
67 SGNode *lastChild() const { return m_lastChild; }
68 SGNode *nextSibling() const { return m_nextSibling; }
69 SGNode* previousSibling() const { return m_previousSibling; }
70
71 inline NodeType type() const { return m_type; }
72
73 void markDirty(DirtyFlag flags);
74
75 virtual bool isSubtreeBlocked() const;
76
77 NodeFlag flags() const { return m_nodeFlags; }
78 void setFlag(NodeFlag, bool = true);
79 void setFlags(NodeFlag, bool = true);
80
81 virtual void preprocess() { }
82 virtual void accept(SGNodeVisitor *){}
83protected:
84 SGNode(NodeType type);
85private:
86 friend class SGRootNode;
87 friend class SGRenderer;
88
89 void init();
90 void destroy();
91
92 SGNode *m_parent;
93 NodeType m_type;
94 SGNode *m_firstChild;
95 SGNode *m_lastChild;
96 SGNode *m_nextSibling;
97 SGNode *m_previousSibling;
98 int m_subtreeRenderableCount;
99
100 NodeFlag m_nodeFlags;
101};
102
103class SGClipNode;
104
105class SG_EXPORT SGBasicGeometryNode : public SGNode
106{
107public:
108 ~SGBasicGeometryNode();
109
110 void setGeometry(SGGeometry *geometry);
111 const SGGeometry *geometry() const { return m_geometry; }
112 SGGeometry *geometry() { return m_geometry; }
113
114 const SGMatrix *matrix() const { return m_matrix; }
115 const SGClipNode *clipList() const { return m_clip_list; }
116
117 void setRendererMatrix(const SGMatrix *m) { m_matrix = m; }
118 void setRendererClipList(const SGClipNode *c) { m_clip_list = c; }
119
120protected:
121 SGBasicGeometryNode(NodeType type);
122
123private:
124 friend class SGNodeUpdater;
125
126 SGGeometry *m_geometry;
127
128 int m_reserved_start_index;
129 int m_reserved_end_index;
130
131 const SGMatrix *m_matrix;
132 const SGClipNode *m_clip_list;
133};
134
135class SG_EXPORT SGGeometryNode : public SGBasicGeometryNode
136{
137public:
138 SGGeometryNode();
139 ~SGGeometryNode();
140
141 void setRenderOrder(int order);
142 int renderOrder() const { return m_render_order; }
143
144 void setInheritedOpacity(double opacity);
145 double inheritedOpacity() const { return m_opacity; }
146 void accept(SGNodeVisitor *visitor) override;
147private:
148 friend class SGNodeUpdater;
149
150 int m_render_order;
151
152 double m_opacity;
153};
154
155class SG_EXPORT SGClipNode : public SGBasicGeometryNode
156{
157public:
158 SGClipNode();
159 ~SGClipNode();
160
161 void setIsRectangular(bool rectHint);
162 bool isRectangular() const { return m_is_rectangular; }
163
164 void setClipRect(const SGRect &);
165 SGRect clipRect() const { return m_clip_rect; }
166 void accept(SGNodeVisitor *visitor) override;
167private:
168 bool m_is_rectangular;
169
170 SGRect m_clip_rect;
171};
172
173class SG_EXPORT SGTransformNode : public SGNode
174{
175public:
176 SGTransformNode();
177 ~SGTransformNode();
178
179 void setMatrix(const SGMatrix &matrix);
180 const SGMatrix &matrix() const { return m_matrix; }
181
182 void setCombinedMatrix(const SGMatrix &matrix);
183 const SGMatrix &combinedMatrix() const { return m_combined_matrix; }
184 void accept(SGNodeVisitor *visitor) override;
185private:
186 SGMatrix m_matrix;
187 SGMatrix m_combined_matrix;
188};
189
190class SG_EXPORT SGRootNode : public SGNode
191{
192public:
193 SGRootNode();
194 ~SGRootNode();
195 void accept(SGNodeVisitor *visitor) override;
196private:
197 void notifyNodeChange(SGNode *node, DirtyFlag flags);
198
199 friend class SGNode;
200 friend class SGGeometryNode;
201 friend class SGRenderer;
202
203 std::vector<SGRenderer *> m_renderers;
204};
205
206
207class SG_EXPORT SGOpacityNode : public SGNode
208{
209public:
210 SGOpacityNode();
211 ~SGOpacityNode();
212
213 void setOpacity(double opacity);
214 double opacity() const { return m_opacity; }
215
216 void setCombinedOpacity(double opacity);
217 double combinedOpacity() const { return m_combined_opacity; }
218
219 bool isSubtreeBlocked() const override;
220 void accept(SGNodeVisitor *visitor) override;
221private:
222 double m_opacity;
223 double m_combined_opacity;
224};
225
226
227#endif //SGNODE_H
diff --git a/ssg/include/sgnodeupdater_p.h b/ssg/include/sgnodeupdater_p.h
new file mode 100644
index 0000000000..73a909c85a
--- /dev/null
+++ b/ssg/include/sgnodeupdater_p.h
@@ -0,0 +1,30 @@
1#ifndef SGNODEUPDATER_P_H
2#define SGNODEUPDATER_P_H
3
4#include"sgglobal.h"
5#include"sgnode.h"
6#include "sgnodevisitor_p.h"
7
8class SG_EXPORT SGNodeUpdater : public SGNodeVisitor
9{
10public:
11 SGNodeUpdater();
12 ~SGNodeUpdater();
13 bool visit(SGTransformNode *) override;
14 void endVisit(SGTransformNode *) override;
15 bool visit(SGClipNode *) override;
16 void endVisit(SGClipNode *) override;
17 bool visit(SGGeometryNode *) override;
18 void endVisit(SGGeometryNode *) override;
19 bool visit(SGOpacityNode *) override;
20 void endVisit(SGOpacityNode *) override;
21 bool visit(SGRootNode *) override;
22 void endVisit(SGRootNode *) override;
23 void visitChildren(SGNode *node) override;
24
25 bool isNodeBlocked(SGNode *n, SGNode *root) const;
26 void updateStates(SGNode *n);
27
28 void visitNode(SGNode *node);
29};
30#endif // SGNODEUPDATER_P_H
diff --git a/ssg/include/sgnodevisitor_p.h b/ssg/include/sgnodevisitor_p.h
new file mode 100644
index 0000000000..16120cc6be
--- /dev/null
+++ b/ssg/include/sgnodevisitor_p.h
@@ -0,0 +1,28 @@
1#ifndef SGNODEVISITOR_P_H
2#define SGNODEVISITOR_P_H
3
4class SGTransformNode;
5class SGClipNode;
6class SGGeometryNode;
7class SGOpacityNode;
8class SGRootNode;
9class SGNode;
10
11class SGNodeVisitor
12{
13public:
14 virtual ~SGNodeVisitor() {}
15 virtual bool visit(SGTransformNode *) = 0;
16 virtual void endVisit(SGTransformNode *) = 0;
17 virtual bool visit(SGClipNode *) = 0;
18 virtual void endVisit(SGClipNode *) = 0;
19 virtual bool visit(SGGeometryNode *) = 0;
20 virtual void endVisit(SGGeometryNode *) = 0;
21 virtual bool visit(SGOpacityNode *) = 0;
22 virtual void endVisit(SGOpacityNode *) = 0;
23 virtual bool visit(SGRootNode *) = 0;
24 virtual void endVisit(SGRootNode *) = 0;
25 virtual void visitChildren(SGNode *) = 0;
26};
27
28#endif // SGNODEVISITOR_P_H
diff --git a/ssg/include/sgpath.h b/ssg/include/sgpath.h
new file mode 100644
index 0000000000..02779e94ff
--- /dev/null
+++ b/ssg/include/sgpath.h
@@ -0,0 +1,60 @@
1#ifndef SGPATH_H
2#define SGPATH_H
3#include "sgglobal.h"
4#include "sgpoint.h"
5#include<vector>
6
7struct SGPathData;
8class SGPath
9{
10public:
11 enum class Element : uchar {
12 MoveTo,
13 LineTo,
14 CubicTo,
15 Close
16 };
17 ~SGPath();
18 SGPath();
19 SGPath(const SGPath &path);
20 SGPath(SGPath &&other);
21 SGPath &operator=(const SGPath &);
22 SGPath &operator=(SGPath &&other);
23 bool isEmpty()const;
24 void moveTo(const SGPointF &p);
25 inline void moveTo(float x, float y);
26 void lineTo(const SGPointF &p);
27 inline void lineTo(float x, float y);
28 void cubicTo(const SGPointF &ctrlPt1, const SGPointF &ctrlPt2, const SGPointF &endPt);
29 inline void cubicTo(float ctrlPt1x, float ctrlPt1y, float ctrlPt2x, float ctrlPt2y,
30 float endPtx, float endPty);
31 void close();
32 void reserve(int num_elm);
33private:
34 friend class FTRaster;
35 const std::vector<SGPath::Element> &elements() const;
36 const std::vector<SGPointF> &points() const;
37 int segments() const;
38 SGPath copy() const;
39 void detach();
40 void cleanUp(SGPathData *x);
41 SGPathData *d;
42};
43
44inline void SGPath::lineTo(float x, float y)
45{
46 lineTo(SGPointF(x,y));
47}
48
49inline void SGPath::moveTo(float x, float y)
50{
51 moveTo(SGPointF(x,y));
52}
53
54inline void SGPath::cubicTo(float ctrlPt1x, float ctrlPt1y, float ctrlPt2x, float ctrlPt2y,
55 float endPtx, float endPty)
56{
57 cubicTo(SGPointF(ctrlPt1x, ctrlPt1y), SGPointF(ctrlPt2x, ctrlPt2y), SGPointF(endPtx, endPty));
58}
59
60#endif // SGPATH_H
diff --git a/ssg/include/sgpoint.h b/ssg/include/sgpoint.h
new file mode 100644
index 0000000000..d00bbec3ae
--- /dev/null
+++ b/ssg/include/sgpoint.h
@@ -0,0 +1,58 @@
1#ifndef SGPOINT_H
2#define SGPOINT_H
3
4#include"sgglobal.h"
5
6class SG_EXPORT SGPointF
7{
8public:
9 constexpr inline SGPointF() noexcept :mx(0), my(0){}
10 constexpr inline SGPointF(double x, double y) noexcept :mx(x), my(y){}
11 constexpr inline double x() const noexcept {return mx;}
12 constexpr inline double y() const noexcept {return my;}
13 inline SGPointF &operator+=(const SGPointF &p) noexcept;
14 inline SGPointF &operator-=(const SGPointF &p) noexcept;
15private:
16 double mx;
17 double my;
18};
19
20inline SGPointF &SGPointF::operator+=(const SGPointF &p) noexcept
21{ mx+=p.mx; my+=p.my; return *this; }
22
23inline SGPointF &SGPointF::operator-=(const SGPointF &p) noexcept
24{ mx-=p.mx; my-=p.my; return *this; }
25
26class SG_EXPORT SGPoint
27{
28public:
29 constexpr inline SGPoint() noexcept :mx(0), my(0){}
30 constexpr inline SGPoint(int x, int y) noexcept :mx(x), my(y){}
31 constexpr inline int x() const noexcept {return mx;}
32 constexpr inline int y() const noexcept {return my;}
33 inline SGPoint &operator+=(const SGPoint &p) noexcept;
34 inline SGPoint &operator-=(const SGPoint &p) noexcept;
35 constexpr inline bool operator==(const SGPoint &o) const;
36 constexpr inline bool operator!=(const SGPoint &o) const { return !(operator==(o)); }
37 inline friend SGDebug& operator<<(SGDebug& os, const SGPoint& o);
38private:
39 int mx;
40 int my;
41};
42inline SGDebug& operator<<(SGDebug& os, const SGPoint& o)
43{
44 os<<"{P "<<o.x()<<","<<o.y()<<"}";
45 return os;
46}
47constexpr inline bool SGPoint::operator ==(const SGPoint &o) const
48{
49 return (mx == o.x() && my == o.y());
50}
51
52inline SGPoint &SGPoint::operator+=(const SGPoint &p) noexcept
53{ mx+=p.mx; my+=p.my; return *this; }
54
55inline SGPoint &SGPoint::operator-=(const SGPoint &p) noexcept
56{ mx-=p.mx; my-=p.my; return *this; }
57
58#endif // SGPOINT_H
diff --git a/ssg/include/sgrect.h b/ssg/include/sgrect.h
new file mode 100644
index 0000000000..1a4bdca2ed
--- /dev/null
+++ b/ssg/include/sgrect.h
@@ -0,0 +1,111 @@
1#ifndef SGRECT_H
2#define SGRECT_H
3#include"sgglobal.h"
4#include"sgdebug.h"
5class SG_EXPORT SGRect
6{
7public:
8 SG_CONSTEXPR SGRect(): x1(0), y1(0), x2(-1), y2(-1) {}
9 SG_CONSTEXPR SGRect(int left, int top, int width, int height);
10 SG_CONSTEXPR inline bool isEmpty() const;
11
12 SG_CONSTEXPR inline int left() const ;
13 SG_CONSTEXPR inline int top() const ;
14 SG_CONSTEXPR inline int right() const ;
15 SG_CONSTEXPR inline int bottom() const ;
16 SG_CONSTEXPR inline int width() const ;
17 SG_CONSTEXPR inline int height() const ;
18 SG_CONSTEXPR inline int x() const ;
19 SG_CONSTEXPR inline int y() const ;
20 inline void setLeft(int l) {x1 = l;}
21 inline void setTop(int t) {y1 = t;}
22 inline void setRight(int r) {x2 = r;}
23 inline void setBottom(int b) {y2 = b;}
24 inline void setWidth(int w) {x2 = x1 + w;}
25 inline void setHeight(int h) {y2 = y1 + h;}
26 inline SGRect translated(int dx, int dy) const ;
27 inline void translate(int dx, int dy);
28 inline bool contains(const SGRect &r, bool proper = false);
29 friend SG_CONSTEXPR inline bool operator==(const SGRect &, const SGRect &) noexcept;
30 friend SG_CONSTEXPR inline bool operator!=(const SGRect &, const SGRect &) noexcept;
31 friend SGDebug& operator<<(SGDebug& os, const SGRect& o);
32private:
33 int x1;
34 int y1;
35 int x2;
36 int y2;
37};
38inline SGDebug& operator<<(SGDebug& os, const SGRect& o)
39{
40 os<<"{R "<<o.x()<<","<<o.y()<<","<<o.width()<<","<<o.height()<<"}";
41 return os;
42}
43SG_CONSTEXPR inline bool operator==(const SGRect &r1, const SGRect &r2) noexcept
44{
45 return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2;
46}
47
48SG_CONSTEXPR inline bool operator!=(const SGRect &r1, const SGRect &r2) noexcept
49{
50 return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2;
51}
52
53SG_CONSTEXPR inline bool SGRect::isEmpty() const
54{ return x1 > x2 || y1 > y2; }
55
56SG_CONSTEXPR inline int SGRect::x() const
57{ return x1; }
58
59SG_CONSTEXPR inline int SGRect::y() const
60{ return y1; }
61
62SG_CONSTEXPR inline int SGRect::left() const
63{ return x1; }
64
65SG_CONSTEXPR inline int SGRect::top() const
66{ return y1; }
67
68SG_CONSTEXPR inline int SGRect::right() const
69{ return x2; }
70
71SG_CONSTEXPR inline int SGRect::bottom() const
72{ return y2; }
73SG_CONSTEXPR inline int SGRect::width() const
74{ return x2 - x1; }
75SG_CONSTEXPR inline int SGRect::height() const
76{ return y2 - y1; }
77
78inline SGRect SGRect::translated(int dx, int dy) const
79{ return SGRect(x1+dx, y1+dy, x2-x1, y2-y1); }
80
81inline void SGRect::translate(int dx, int dy)
82{
83 x1 += dx;
84 y1 += dy;
85 x2 += dx;
86 y2 += dy;
87}
88inline bool SGRect::contains(const SGRect &r, bool proper)
89{
90 if (!proper) {
91 if ((x1 <= r.x1) &&
92 (x2 >= r.x2) &&
93 (y1 <= r.y1) &&
94 (y2 >= r.y2))
95 return true;
96 return false;
97 }else {
98 if ((x1 < r.x1) &&
99 (x2 > r.x2) &&
100 (y1 < r.y1) &&
101 (y2 > r.y2))
102 return true;
103 return false;
104 }
105
106}
107SG_CONSTEXPR inline SGRect::SGRect(int left, int top, int width, int height):
108 x1(left), y1(top), x2(width + left), y2(height + top){}
109
110
111#endif // SGRECT_H
diff --git a/ssg/include/sgrectnode.h b/ssg/include/sgrectnode.h
new file mode 100644
index 0000000000..404197a625
--- /dev/null
+++ b/ssg/include/sgrectnode.h
@@ -0,0 +1,15 @@
1#ifndef SGRECTNODE_H
2#define SGRECTNODE_H
3#include<sgnode.h>
4
5class SGRectNode : public SGGeometryNode
6{
7public:
8 virtual void setRect(const SGRect &rect) = 0;
9 inline void setRect(int x, int y, int w, int h) noexcept { setRect(SGRect(x, y, w, h)); }
10 virtual SGRect rect() const noexcept = 0;
11
12 virtual void setColor(const SGColor &color) = 0;
13 virtual SGColor color() const = 0;
14};
15#endif // SGRECTNODE_H
diff --git a/ssg/include/sgregion.h b/ssg/include/sgregion.h
new file mode 100644
index 0000000000..018d581145
--- /dev/null
+++ b/ssg/include/sgregion.h
@@ -0,0 +1,74 @@
1#ifndef SGREGION_H
2#define SGREGION_H
3#include"sgdebug.h"
4#include <sgglobal.h>
5#include<sgrect.h>
6#include<sgpoint.h>
7#include<utility>
8
9typedef struct pixman_region region_type_t;
10typedef region_type_t SGRegionPrivate;
11
12class SG_EXPORT SGRegion
13{
14public:
15 SGRegion();
16 SGRegion(int x, int y, int w, int h);
17 SGRegion(const SGRect &r);
18 SGRegion(const SGRegion &region);
19 SGRegion(SGRegion &&other): d(other.d) { other.d = const_cast<SGRegionData*>(&shared_empty); }
20 ~SGRegion();
21 SGRegion &operator=(const SGRegion &);
22 inline SGRegion &operator=(SGRegion &&other)
23 { std::swap(d, other.d); return *this; }
24 bool isEmpty() const;
25 bool contains(const SGRect &r) const;
26 SGRegion united(const SGRect &r) const;
27 SGRegion united(const SGRegion &r) const;
28 SGRegion intersected(const SGRect &r) const;
29 SGRegion intersected(const SGRegion &r) const;
30 SGRegion subtracted(const SGRegion &r) const;
31 void translate(const SGPoint &p);
32 inline void translate(int dx, int dy);
33 SGRegion translated(const SGPoint &p) const;
34 inline SGRegion translated(int dx, int dy) const;
35 int rectCount() const;
36 SGRect rectAt(int index) const;
37
38 SGRegion operator+(const SGRect &r) const;
39 SGRegion operator+(const SGRegion &r) const;
40 SGRegion operator-(const SGRegion &r) const;
41 SGRegion& operator+=(const SGRect &r);
42 SGRegion& operator+=(const SGRegion &r);
43 SGRegion& operator-=(const SGRegion &r);
44
45 SGRect boundingRect() const noexcept;
46 bool intersects(const SGRegion &region) const;
47
48 bool operator==(const SGRegion &r) const;
49 inline bool operator!=(const SGRegion &r) const { return !(operator==(r)); }
50 friend SGDebug& operator<<(SGDebug& os, const SGRegion& o);
51private:
52 bool within(const SGRect &r) const;
53 SGRegion copy() const;
54 void detach();
55
56 struct SGRegionData {
57 RefCount ref;
58 SGRegionPrivate *rgn;
59 };
60
61 struct SGRegionData *d;
62 static const struct SGRegionData shared_empty;
63 static void cleanUp(SGRegionData *x);
64};
65inline void SGRegion::translate(int dx, int dy)
66{
67 translate(SGPoint(dx,dy));
68}
69
70inline SGRegion SGRegion::translated(int dx, int dy) const
71{
72 return translated(SGPoint(dx,dy));
73}
74#endif //SGREGION_H
diff --git a/ssg/include/sgrenderer.h b/ssg/include/sgrenderer.h
new file mode 100644
index 0000000000..cc5d8e6c78
--- /dev/null
+++ b/ssg/include/sgrenderer.h
@@ -0,0 +1,62 @@
1#ifndef SGRENDERER_H
2#define SGRENDERER_H
3
4#include<unordered_set>
5
6#include"sgglobal.h"
7#include"sgnode.h"
8
9class SGRenderContext;
10class SGRendererPrivate;
11class SGNodeUpdater;
12
13class SG_EXPORT SGRenderer
14{
15public:
16 enum ClearModeBit
17 {
18 ClearColorBuffer = 0x0001,
19 ClearDepthBuffer = 0x0002,
20 ClearStencilBuffer = 0x0004
21 };
22 typedef sgFlag<ClearModeBit> ClearMode;
23
24 SGRenderer(SGRenderContext *context);
25 virtual ~SGRenderer();
26
27 void setRootNode(SGRootNode *node);
28 SGRootNode *rootNode() const;
29 void setDeviceRect(const SGRect &rect);
30 SGRect deviceRect() const;
31
32 void setViewportRect(const SGRect &rect);
33 SGRect viewportRect() const;
34
35// void setProjectionMatrix(const SGMatrix &matrix);
36// SGMatrix projectionMatrix() const;
37
38// void setClearColor(const QColor &color);
39// QColor clearColor() const;
40
41// void setClearMode(ClearMode mode);
42// ClearMode clearMode() const;
43 SGNodeUpdater *nodeUpdater() const;
44 void setNodeUpdater(SGNodeUpdater *updater);
45
46 virtual void renderScene();
47
48protected:
49 explicit SGRenderer();
50 virtual void nodeChanged(SGNode *node, SGNode::DirtyFlag flag) = 0;
51 virtual void render() = 0;
52 virtual void preprocess();
53 void addNodesToPreprocess(SGNode *node);
54 void removeNodesToPreprocess(SGNode *node);
55
56private:
57 friend class SGRendererPrivate;
58 friend class SGRootNode;
59 SGRendererPrivate *d;
60};
61
62#endif // SGRENDERER_H
diff --git a/ssg/include/sgrle.h b/ssg/include/sgrle.h
new file mode 100644
index 0000000000..194a8d7885
--- /dev/null
+++ b/ssg/include/sgrle.h
@@ -0,0 +1,44 @@
1#ifndef SGRLE_H
2#define SGRLE_H
3#include<sgglobal.h>
4#include<sgrect.h>
5#include<sgpoint.h>
6
7struct SGRleData;
8class SGRle
9{
10public:
11 struct Span
12 {
13 short x;
14 short y;
15 ushort len;
16 ushort coverage;
17 };
18 ~SGRle();
19 SGRle();
20 SGRle(const SGRle &other);
21 SGRle(SGRle &&other);
22 SGRle &operator=(const SGRle &);
23 SGRle &operator=(SGRle &&other);
24 bool isEmpty()const;
25 SGRect boundingRect() const;
26 void addSpan(const SGRle::Span *span, int count);
27 bool operator ==(const SGRle &other) const;
28 void translate(const SGPoint &p);
29 void translate(int x, int y);
30 SGRle intersected(const SGRect &r) const;
31 SGRle intersected(const SGRle &other) const;
32 SGRle &intersect(const SGRect &r);
33 friend SGDebug& operator<<(SGDebug& os, const SGRle& object);
34private:
35 SGRle copy() const;
36 void detach();
37 void cleanUp(SGRleData *x);
38 SGRleData *d;
39};
40inline void SGRle::translate(int x, int y)
41{
42 translate(SGPoint(x,y));
43}
44#endif // SGRLE_H
diff --git a/ssg/include/sgshapenode.h b/ssg/include/sgshapenode.h
new file mode 100644
index 0000000000..d28f2fa87c
--- /dev/null
+++ b/ssg/include/sgshapenode.h
@@ -0,0 +1,31 @@
1#ifndef SGSHAPENODE_H
2#define SGSHAPENODE_H
3
4#include "sgnode.h"
5
6class SGGradient;
7
8class SGShapeNode : public SGGeometryNode
9{
10public:
11 FillRule fillRule() const;
12 void setFillRule(FillRule fillRule);
13 JoinStyle joinStyle() const;
14 void setJoinStyle(JoinStyle style);
15 CapStyle capStyle() const;
16 void setCapStyle(CapStyle style);
17 StrokeStyle strokeStyle() const;
18 void setStrokeStyle(StrokeStyle style);
19 double strokeWidth() const;
20 void setStrokeWidth(double w);
21
22 SGColor fillColor() const;
23 void setFillColor(const SGColor &color);
24 SGColor strokeColor() const;
25 void setStrokeColor(const SGColor &color);
26
27 SGGradient *fillGradient() const;
28 void setFillGradient(SGGradient *gradient);
29};
30
31#endif // SGSHAPENODE_H
diff --git a/ssg/include/ssg b/ssg/include/ssg
new file mode 100644
index 0000000000..c718b58eb2
--- /dev/null
+++ b/ssg/include/ssg
@@ -0,0 +1,6 @@
1#ifndef SSG_MODULE_H
2#define SSG_MODULE_H
3
4#include"ssg.h"
5
6#endif //SSG_MODULE_H
diff --git a/ssg/include/ssg.h b/ssg/include/ssg.h
new file mode 100644
index 0000000000..37167ee9be
--- /dev/null
+++ b/ssg/include/ssg.h
@@ -0,0 +1,9 @@
1#ifndef SSG_H
2#define SSG_H
3
4#include "sgglobal.h"
5#include "sgmatrix.h"
6#include "sgnode.h"
7#include "sgregion.h"
8
9#endif // SSG_H
diff --git a/ssg/meson.build b/ssg/meson.build
new file mode 100644
index 0000000000..0bf4923e52
--- /dev/null
+++ b/ssg/meson.build
@@ -0,0 +1,31 @@
1project('scenegraph library',
2 'cpp',
3 license : 'MIT',
4 default_options : ['libdir=lib/ssg', 'c_std=c11', 'cpp_std=c++11'])
5ssg_lib_version = '0.0.1'
6
7compiler_flags = ['-Wall','-std=c++11']
8if (build_machine.system() == 'linux')
9 compiler_flags += ['-pthread']
10 add_global_link_arguments('-pthread', language: 'cpp')
11endif
12
13add_global_arguments(compiler_flags, language: 'cpp')
14
15inc = include_directories('include')
16
17subdir('include')
18subdir('src')
19
20subdir('example')
21
22if get_option('test') == true
23 subdir('test')
24endif
25
26pkg_mod = import('pkgconfig')
27pkg_mod.generate(libraries : ssglib,
28 version : '1.0',
29 name : 'libssg',
30 filebase : 'ssg',
31 description : 'A Library for scenegraph management.')
diff --git a/ssg/meson_options.txt b/ssg/meson_options.txt
new file mode 100644
index 0000000000..17241bfc6e
--- /dev/null
+++ b/ssg/meson_options.txt
@@ -0,0 +1,9 @@
1option('test',
2 type: 'boolean',
3 value: true,
4 description: 'enable unit test')
5
6option('example',
7 type: 'boolean',
8 value: true,
9 description: 'enable example')
diff --git a/ssg/src/animation/meson.build b/ssg/src/animation/meson.build
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/ssg/src/animation/meson.build
diff --git a/ssg/src/animation/sgkeyframe.h b/ssg/src/animation/sgkeyframe.h
new file mode 100644
index 0000000000..b8c09223d6
--- /dev/null
+++ b/ssg/src/animation/sgkeyframe.h
@@ -0,0 +1,120 @@
1#ifndef SGKEYFRAME_H
2#define SGKEYFRAME_H
3#include"sgglobal.h"
4#include<vector>
5
6template<typename T>
7class KeyFrame
8{
9public:
10 float getStartProgress();
11 float getEndProgress();
12 bool isStatic();
13 bool containsProgress(float progress) {
14 return progress >= getStartProgress() && progress < getEndProgress();
15 }
16private:
17 T startValue;
18 T endValue;
19 float startFrame;
20 float endFrame;
21 //Interpolater interpolater;
22};
23
24/**
25 * <K> Keyframe type
26 * <A> Animation type
27 */
28template<typename K, typename A>
29class BaseKeyframeAnimation
30{
31 BaseKeyframeAnimation(const std::vector<KeyFrame<K>> &keyframes);
32 void setIsDiscrete();
33 void setProgress(float progress);
34 KeyFrame<K> getCurrentKeyframe();
35 float getCurrentKeyframeProgress() {
36 if (isDiscrete) {
37 return 0;
38 }
39
40 KeyFrame<K> keyframe = getCurrentKeyframe();
41 if (keyframe.isStatic()) {
42 return 0;
43 }
44 float progressIntoFrame = progress - keyframe.getStartProgress();
45 float keyframeProgress = keyframe.getEndProgress() - keyframe.getStartProgress();
46 /**
47 * This wil be [0, 1] unless the interpolator has overshoot in which case getValue() should be
48 * able to handle values outside of that range.
49 */
50 //return keyframe.interpolator.getInterpolation(progressIntoFrame / keyframeProgress);
51 }
52 float getStartDelayProgress();
53 float getEndProgress();
54 A getValue() {
55 return getValue(getCurrentKeyframe(), getCurrentKeyframeProgress());
56 }
57
58 float getProgress();
59 /**
60 * keyframeProgress will be [0, 1] unless the interpolator has overshoot in which case, this
61 * should be able to handle values outside of that range.
62 */
63 virtual A getValue(KeyFrame<K> keyframe, float keyframeProgress) = 0;
64private:
65 std::vector<KeyFrame<K>> keyframes;
66 KeyFrame<K> cachedKeyframe;
67 float progress;
68 bool isDiscrete;
69};
70
71template<typename K, typename A> //interface
72class AnimatableValue
73{
74 virtual BaseKeyframeAnimation<K, A> createAnimation() = 0;
75 virtual bool hasAnimation() = 0;
76};
77
78template<typename K, typename O>
79class BaseAnimatableValue<K, O> : public AnimatableValue<K, O>
80{
81public:
82 BaseAnimatableValue(const std::vector<KeyFrame<K>> keyframes, K initialValue) {
83 keyframes = keyframes;
84 initialValue = initialValue;
85 }
86 /**
87 * Convert the value type of the keyframe to the value type of the animation. Often, these
88 * are the same type.
89 */
90 O convertType(K value) {
91 //noinspection unchecked
92 return (O) value;
93 }
94 bool hasAnimation() {
95 return !keyframes.empty();
96 }
97
98 virtual O getInitialValue() {
99 return convertType(initialValue);
100 }
101private:
102 std::vector<KeyFrame<K>> keyframes;
103 K initialValue;
104};
105
106class AnimatableIntegerValue : public BaseAnimatableValue<int, int>
107{
108public:
109 AnimatableIntegerValue();
110 BaseKeyframeAnimation<int, int> createAnimation() {
111 if (!hasAnimation()) {
112 return new StaticKeyframeAnimation<>(initialValue);
113 }
114
115 return new IntegerKeyframeAnimation(keyframes);
116 }
117};
118
119
120#endif // SGKEYFRAME_H
diff --git a/ssg/src/ftraster/ftraster.cpp b/ssg/src/ftraster/ftraster.cpp
new file mode 100644
index 0000000000..25262c3a23
--- /dev/null
+++ b/ssg/src/ftraster/ftraster.cpp
@@ -0,0 +1,295 @@
1#include"ftraster_p.h"
2#include"sw_ft_raster.h"
3#include"sw_ft_stroker.h"
4#include"sgpath.h"
5#include"sgmatrix.h"
6#include<cstring>
7#include"sgdebug.h"
8
9struct FTOutline
10{
11public:
12 FTOutline() = delete;
13 FTOutline(int points, int segments)
14 {
15 ft.points = new SW_FT_Vector[points + segments];
16 ft.tags = new char[points + segments];
17 ft.contours = new short[segments];
18 ft.n_points = ft.n_contours = 0;
19 }
20 void moveTo(const SGPointF &pt);
21 void lineTo(const SGPointF &pt);
22 void cubicTo(const SGPointF &ctr1, const SGPointF &ctr2, const SGPointF end);
23 void close();
24 void end();
25 void transform(const SGMatrix &m);
26 ~FTOutline()
27 {
28 delete[] ft.points;
29 delete[] ft.tags;
30 delete[] ft.contours;
31 }
32 SW_FT_Outline ft;
33 bool closed;
34};
35
36#define TO_FT_COORD(x) ((x) * 64) // to freetype 26.6 coordinate.
37
38void FTOutline::transform(const SGMatrix &m)
39{
40 SGPointF pt;
41 if (m.isIdentity()) return;
42 for (auto i = 0; i < ft.n_points; i++) {
43 pt = m.map(SGPointF(ft.points[i].x/64.0, ft.points[i].y/64.0));
44 ft.points[i].x = TO_FT_COORD(pt.x());
45 ft.points[i].y = TO_FT_COORD(pt.y());
46 }
47}
48
49void FTOutline::moveTo(const SGPointF &pt)
50{
51 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
52 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
53 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
54 if (ft.n_points) {
55 ft.contours[ft.n_contours] = ft.n_points - 1;
56 ft.n_contours++;
57 }
58 ft.n_points++;
59 closed = false;
60}
61
62void FTOutline::lineTo(const SGPointF &pt)
63{
64 ft.points[ft.n_points].x = TO_FT_COORD(pt.x());
65 ft.points[ft.n_points].y = TO_FT_COORD(pt.y());
66 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
67 ft.n_points++;
68 closed = false;
69}
70
71void FTOutline::cubicTo(const SGPointF &cp1, const SGPointF &cp2, const SGPointF ep)
72{
73 ft.points[ft.n_points].x = TO_FT_COORD(cp1.x());
74 ft.points[ft.n_points].y = TO_FT_COORD(cp1.y());
75 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
76 ft.n_points++;
77
78 ft.points[ft.n_points].x = TO_FT_COORD(cp2.x());
79 ft.points[ft.n_points].y = TO_FT_COORD(cp2.y());
80 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_CUBIC;
81 ft.n_points++;
82
83 ft.points[ft.n_points].x = TO_FT_COORD(ep.x());
84 ft.points[ft.n_points].y = TO_FT_COORD(ep.y());
85 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
86 ft.n_points++;
87 closed = false;
88}
89void FTOutline::close()
90{
91 int index;
92 if (ft.n_contours) {
93 index = ft.contours[ft.n_contours - 1] + 1;
94 } else {
95 index = 0;
96 }
97
98 // make sure atleast 1 point exists in the segment.
99 if (ft.n_points == index) {
100 closed = false;
101 return;
102 }
103
104 ft.points[ft.n_points].x = ft.points[index].x;
105 ft.points[ft.n_points].y = ft.points[index].y;
106 ft.tags[ft.n_points] = SW_FT_CURVE_TAG_ON;
107 ft.n_points++;
108 closed = true;
109}
110
111void FTOutline::end()
112{
113 if (ft.n_points) {
114 ft.contours[ft.n_contours] = ft.n_points - 1;
115 ft.n_contours++;
116 }
117}
118
119struct FTRasterPrivate
120{
121public:
122 SGRle generateFillInfoAsync(const SW_FT_Outline *outline);
123 SGRle generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
124 SW_FT_Stroker_LineJoin join, int width, SW_FT_Bool closed);
125
126 std::mutex m_rasterAcess;
127 std::mutex m_strokerAcess;
128 SW_FT_Raster m_raster;
129 SW_FT_Stroker m_stroker;
130};
131
132struct SpanInfo
133{
134 SGRle::Span *spans;
135 int size;
136};
137
138static void
139rleGenerationCb( int count, const SW_FT_Span* spans,void *user)
140{
141 SGRle *rle = (SGRle *) user;
142 SGRle::Span *rleSpan = (SGRle::Span *)spans;
143 rle->addSpan(rleSpan, count);
144}
145
146SGRle FTRasterPrivate::generateFillInfoAsync(const SW_FT_Outline *outline)
147{
148 m_rasterAcess.lock();
149 SGRle rle;
150 SW_FT_Raster_Params params;
151
152 params.flags = SW_FT_RASTER_FLAG_DIRECT | SW_FT_RASTER_FLAG_AA ;
153 params.gray_spans = &rleGenerationCb;
154 params.user = &rle;
155 params.source = outline;
156
157 sw_ft_grays_raster.raster_render(m_raster, &params);
158
159 m_rasterAcess.unlock();
160
161 return rle;
162}
163
164SGRle FTRasterPrivate::generateStrokeInfoAsync(const SW_FT_Outline *outline, SW_FT_Stroker_LineCap cap,
165 SW_FT_Stroker_LineJoin join, int width, SW_FT_Bool closed)
166{
167 m_strokerAcess.lock();
168 uint points,contors;
169 SW_FT_Outline strokeOutline = { 0, 0, nullptr, nullptr, nullptr, 0 };
170
171 SW_FT_Stroker_Set(m_stroker, width, cap, join, 0);
172 SW_FT_Stroker_ParseOutline(m_stroker, outline, !closed);
173 SW_FT_Stroker_GetCounts(m_stroker,&points, &contors);
174
175 strokeOutline.points = (SW_FT_Vector *) calloc(points, sizeof(SW_FT_Vector));
176 strokeOutline.tags = (char *) calloc(points, sizeof(char));
177 strokeOutline.contours = (short *) calloc(contors, sizeof(short));
178
179 SW_FT_Stroker_Export(m_stroker, &strokeOutline);
180
181 m_strokerAcess.unlock();
182
183 SGRle rle = generateFillInfoAsync(&strokeOutline);
184
185 // cleanup the outline data.
186 free(strokeOutline.points);
187 free(strokeOutline.tags);
188 free(strokeOutline.contours);
189
190 return rle;
191}
192
193
194FTRaster::FTRaster()
195{
196 d = new FTRasterPrivate;
197 sw_ft_grays_raster.raster_new(&d->m_raster);
198 SW_FT_Stroker_New(&d->m_stroker);
199 SW_FT_Stroker_Set(d->m_stroker, 1 << 6,
200 SW_FT_STROKER_LINECAP_BUTT, SW_FT_STROKER_LINEJOIN_MITER, 0);
201}
202
203FTRaster::~FTRaster()
204{
205 sw_ft_grays_raster.raster_done(d->m_raster);
206 SW_FT_Stroker_Done(d->m_stroker);
207}
208
209void FTRaster::deleteFTOutline(FTOutline *outline)
210{
211 delete outline;
212}
213
214FTOutline *FTRaster::toFTOutline(const SGPath &path)
215{
216 if (path.isEmpty())
217 return nullptr;
218
219 const std::vector<SGPath::Element> &elements = path.elements();
220 const std::vector<SGPointF> &points = path.points();
221
222 FTOutline *outline = new FTOutline(points.size(), path.segments());
223
224 int index = 0;
225 for(auto element : elements) {
226 switch (element){
227 case SGPath::Element::MoveTo:
228 outline->moveTo(points[index]);
229 index++;
230 break;
231 case SGPath::Element::LineTo:
232 outline->lineTo(points[index]);
233 index++;
234 break;
235 case SGPath::Element::CubicTo:
236 outline->cubicTo(points[index], points[index+1], points[index+2]);
237 index = index+3;
238 break;
239 case SGPath::Element::Close:
240 outline->close();
241 break;
242 default:
243 break;
244 }
245 }
246 outline->end();
247 return outline;
248}
249
250std::future<SGRle> FTRaster::generateFillInfo(const FTOutline *outline)
251{
252 return std::async(std::launch::async, &FTRasterPrivate::generateFillInfoAsync, d, &outline->ft);
253}
254
255std::future<SGRle> FTRaster::generateStrokeInfo(const FTOutline *outline, CapStyle cap, JoinStyle join, double width)
256{
257 SW_FT_Stroker_LineCap ftCap;
258 SW_FT_Stroker_LineJoin ftJoin;
259 int ftWidth;
260 SW_FT_Bool ftbool = (SW_FT_Bool) outline->closed;
261
262 // map strokeWidth to freetype. It uses as the radius of the pen not the diameter
263 width = width/2.0;
264 // convert to freetype co-ordinate
265 ftWidth = int(width * 64);
266
267 // map to freetype capstyle
268 switch (cap)
269 {
270 case CapStyle::Square:
271 ftCap = SW_FT_STROKER_LINECAP_SQUARE;
272 break;
273 case CapStyle::Round:
274 ftCap = SW_FT_STROKER_LINECAP_ROUND;
275 break;
276 default:
277 ftCap = SW_FT_STROKER_LINECAP_BUTT;
278 break;
279 }
280 switch (join)
281 {
282 case JoinStyle::Bevel:
283 ftJoin = SW_FT_STROKER_LINEJOIN_BEVEL;
284 break;
285 case JoinStyle::Round:
286 ftJoin = SW_FT_STROKER_LINEJOIN_ROUND;
287 break;
288 default:
289 ftJoin = SW_FT_STROKER_LINEJOIN_MITER;
290 break;
291 }
292
293 return std::async(std::launch::async, &FTRasterPrivate::generateStrokeInfoAsync, d,
294 &outline->ft, ftCap, ftJoin, ftWidth, ftbool);
295}
diff --git a/ssg/src/ftraster/meson.build b/ssg/src/ftraster/meson.build
new file mode 100644
index 0000000000..dd40ab8317
--- /dev/null
+++ b/ssg/src/ftraster/meson.build
@@ -0,0 +1,11 @@
1ssg_sources_ftraster = []
2
3ssg_ftraster_file = ['sw_ft_math.cpp',
4 'sw_ft_raster.cpp',
5 'sw_ft_stroker.cpp',
6 'ftraster.cpp'
7 ]
8
9foreach file: ssg_ftraster_file
10 ssg_sources_ftraster += join_paths('ftraster', file)
11endforeach
diff --git a/ssg/src/ftraster/sw_ft_math.cpp b/ssg/src/ftraster/sw_ft_math.cpp
new file mode 100644
index 0000000000..268c875c28
--- /dev/null
+++ b/ssg/src/ftraster/sw_ft_math.cpp
@@ -0,0 +1,528 @@
1/***************************************************************************/
2/* */
3/* fttrigon.c */
4/* */
5/* FreeType trigonometric functions (body). */
6/* */
7/* Copyright 2001-2005, 2012-2013 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18#include <math.h>
19#include "sw_ft_math.h"
20
21
22#define SW_FT_MSB( x ) ( 31 - __builtin_clz( x ) )
23
24#define SW_FT_PAD_FLOOR( x, n ) ( (x) & ~((n)-1) )
25#define SW_FT_PAD_ROUND( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)/2), n )
26#define SW_FT_PAD_CEIL( x, n ) SW_FT_PAD_FLOOR( (x) + ((n)-1), n )
27
28
29#define SW_FT_BEGIN_STMNT do {
30#define SW_FT_END_STMNT } while ( 0 )
31/* transfer sign leaving a positive number */
32#define SW_FT_MOVE_SIGN( x, s ) \
33SW_FT_BEGIN_STMNT \
34 if ( x < 0 ) \
35 { \
36 x = -x; \
37 s = -s; \
38 } \
39SW_FT_END_STMNT
40
41
42
43
44SW_FT_Long
45SW_FT_MulFix( SW_FT_Long a,
46 SW_FT_Long b )
47{
48 SW_FT_Int s = 1;
49 SW_FT_Long c;
50
51
52 SW_FT_MOVE_SIGN( a, s );
53 SW_FT_MOVE_SIGN( b, s );
54
55 c = (SW_FT_Long)( ( (SW_FT_Int64)a * b + 0x8000L ) >> 16 );
56
57 return ( s > 0 ) ? c : -c;
58}
59
60SW_FT_Long
61SW_FT_MulDiv( SW_FT_Long a,
62 SW_FT_Long b,
63 SW_FT_Long c )
64{
65 SW_FT_Int s = 1;
66 SW_FT_Long d;
67
68
69 SW_FT_MOVE_SIGN( a, s );
70 SW_FT_MOVE_SIGN( b, s );
71 SW_FT_MOVE_SIGN( c, s );
72
73 d = (SW_FT_Long)( c > 0 ? ( (SW_FT_Int64)a * b + ( c >> 1 ) ) / c
74 : 0x7FFFFFFFL );
75
76 return ( s > 0 ) ? d : -d;
77}
78
79SW_FT_Long
80SW_FT_DivFix( SW_FT_Long a,
81 SW_FT_Long b )
82{
83 SW_FT_Int s = 1;
84 SW_FT_Long q;
85
86
87 SW_FT_MOVE_SIGN( a, s );
88 SW_FT_MOVE_SIGN( b, s );
89
90 q = (SW_FT_Long)( b > 0 ? ( ( (SW_FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b
91 : 0x7FFFFFFFL );
92
93 return ( s < 0 ? -q : q );
94}
95
96
97/*************************************************************************/
98/* */
99/* This is a fixed-point CORDIC implementation of trigonometric */
100/* functions as well as transformations between Cartesian and polar */
101/* coordinates. The angles are represented as 16.16 fixed-point values */
102/* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */
103/* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */
104/* discrete Cartesian grid can have the same or better angular */
105/* resolution. Therefore, to maintain this precision, some functions */
106/* require an interim upscaling of the vectors, whereas others operate */
107/* with 24-bit long vectors directly. */
108/* */
109/*************************************************************************/
110
111 /* the Cordic shrink factor 0.858785336480436 * 2^32 */
112#define SW_FT_TRIG_SCALE 0xDBD95B16UL
113
114 /* the highest bit in overflow-safe vector components, */
115 /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */
116#define SW_FT_TRIG_SAFE_MSB 29
117
118 /* this table was generated for SW_FT_PI = 180L << 16, i.e. degrees */
119#define SW_FT_TRIG_MAX_ITERS 23
120
121 static const SW_FT_Fixed
122 ft_trig_arctan_table[] =
123 {
124 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
125 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
126 57L, 29L, 14L, 7L, 4L, 2L, 1L
127 };
128
129 /* multiply a given value by the CORDIC shrink factor */
130 static SW_FT_Fixed
131 ft_trig_downscale( SW_FT_Fixed val )
132 {
133 SW_FT_Fixed s;
134 SW_FT_Int64 v;
135
136
137 s = val;
138 val = SW_FT_ABS( val );
139
140 v = ( val * (SW_FT_Int64)SW_FT_TRIG_SCALE ) + 0x100000000UL;
141 val = (SW_FT_Fixed)( v >> 32 );
142
143 return ( s >= 0 ) ? val : -val;
144 }
145
146
147
148 /* undefined and never called for zero vector */
149 static SW_FT_Int
150 ft_trig_prenorm( SW_FT_Vector* vec )
151 {
152 SW_FT_Pos x, y;
153 SW_FT_Int shift;
154
155
156 x = vec->x;
157 y = vec->y;
158
159 shift = SW_FT_MSB( SW_FT_ABS( x ) | SW_FT_ABS( y ) );
160
161 if ( shift <= SW_FT_TRIG_SAFE_MSB )
162 {
163 shift = SW_FT_TRIG_SAFE_MSB - shift;
164 vec->x = (SW_FT_Pos)( (SW_FT_ULong)x << shift );
165 vec->y = (SW_FT_Pos)( (SW_FT_ULong)y << shift );
166 }
167 else
168 {
169 shift -= SW_FT_TRIG_SAFE_MSB;
170 vec->x = x >> shift;
171 vec->y = y >> shift;
172 shift = -shift;
173 }
174
175 return shift;
176 }
177
178
179 static void
180 ft_trig_pseudo_rotate( SW_FT_Vector* vec,
181 SW_FT_Angle theta )
182 {
183 SW_FT_Int i;
184 SW_FT_Fixed x, y, xtemp, b;
185 const SW_FT_Fixed *arctanptr;
186
187
188 x = vec->x;
189 y = vec->y;
190
191 /* Rotate inside [-PI/4,PI/4] sector */
192 while ( theta < -SW_FT_ANGLE_PI4 )
193 {
194 xtemp = y;
195 y = -x;
196 x = xtemp;
197 theta += SW_FT_ANGLE_PI2;
198 }
199
200 while ( theta > SW_FT_ANGLE_PI4 )
201 {
202 xtemp = -y;
203 y = x;
204 x = xtemp;
205 theta -= SW_FT_ANGLE_PI2;
206 }
207
208 arctanptr = ft_trig_arctan_table;
209
210 /* Pseudorotations, with right shifts */
211 for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ )
212 {
213 if ( theta < 0 )
214 {
215 xtemp = x + ( ( y + b ) >> i );
216 y = y - ( ( x + b ) >> i );
217 x = xtemp;
218 theta += *arctanptr++;
219 }
220 else
221 {
222 xtemp = x - ( ( y + b ) >> i );
223 y = y + ( ( x + b ) >> i );
224 x = xtemp;
225 theta -= *arctanptr++;
226 }
227 }
228
229 vec->x = x;
230 vec->y = y;
231 }
232
233
234 static void
235 ft_trig_pseudo_polarize( SW_FT_Vector* vec )
236 {
237 SW_FT_Angle theta;
238 SW_FT_Int i;
239 SW_FT_Fixed x, y, xtemp, b;
240 const SW_FT_Fixed *arctanptr;
241
242
243 x = vec->x;
244 y = vec->y;
245
246 /* Get the vector into [-PI/4,PI/4] sector */
247 if ( y > x )
248 {
249 if ( y > -x )
250 {
251 theta = SW_FT_ANGLE_PI2;
252 xtemp = y;
253 y = -x;
254 x = xtemp;
255 }
256 else
257 {
258 theta = y > 0 ? SW_FT_ANGLE_PI : -SW_FT_ANGLE_PI;
259 x = -x;
260 y = -y;
261 }
262 }
263 else
264 {
265 if ( y < -x )
266 {
267 theta = -SW_FT_ANGLE_PI2;
268 xtemp = -y;
269 y = x;
270 x = xtemp;
271 }
272 else
273 {
274 theta = 0;
275 }
276 }
277
278 arctanptr = ft_trig_arctan_table;
279
280 /* Pseudorotations, with right shifts */
281 for ( i = 1, b = 1; i < SW_FT_TRIG_MAX_ITERS; b <<= 1, i++ )
282 {
283 if ( y > 0 )
284 {
285 xtemp = x + ( ( y + b ) >> i );
286 y = y - ( ( x + b ) >> i );
287 x = xtemp;
288 theta += *arctanptr++;
289 }
290 else
291 {
292 xtemp = x - ( ( y + b ) >> i );
293 y = y + ( ( x + b ) >> i );
294 x = xtemp;
295 theta -= *arctanptr++;
296 }
297 }
298
299 /* round theta */
300 if ( theta >= 0 )
301 theta = SW_FT_PAD_ROUND( theta, 32 );
302 else
303 theta = -SW_FT_PAD_ROUND( -theta, 32 );
304
305 vec->x = x;
306 vec->y = theta;
307 }
308
309
310 /* documentation is in fttrigon.h */
311
312 SW_FT_Fixed
313 SW_FT_Cos( SW_FT_Angle angle )
314 {
315 SW_FT_Vector v;
316
317
318 v.x = SW_FT_TRIG_SCALE >> 8;
319 v.y = 0;
320 ft_trig_pseudo_rotate( &v, angle );
321
322 return ( v.x + 0x80L ) >> 8;
323 }
324
325
326 /* documentation is in fttrigon.h */
327
328 SW_FT_Fixed
329 SW_FT_Sin( SW_FT_Angle angle )
330 {
331 return SW_FT_Cos( SW_FT_ANGLE_PI2 - angle );
332 }
333
334
335 /* documentation is in fttrigon.h */
336
337 SW_FT_Fixed
338 SW_FT_Tan( SW_FT_Angle angle )
339 {
340 SW_FT_Vector v;
341
342
343 v.x = SW_FT_TRIG_SCALE >> 8;
344 v.y = 0;
345 ft_trig_pseudo_rotate( &v, angle );
346
347 return SW_FT_DivFix( v.y, v.x );
348 }
349
350
351 /* documentation is in fttrigon.h */
352
353 SW_FT_Angle
354 SW_FT_Atan2( SW_FT_Fixed dx,
355 SW_FT_Fixed dy )
356 {
357 SW_FT_Vector v;
358
359
360 if ( dx == 0 && dy == 0 )
361 return 0;
362
363 v.x = dx;
364 v.y = dy;
365 ft_trig_prenorm( &v );
366 ft_trig_pseudo_polarize( &v );
367
368 return v.y;
369 }
370
371
372 /* documentation is in fttrigon.h */
373
374 void
375 SW_FT_Vector_Unit( SW_FT_Vector* vec,
376 SW_FT_Angle angle )
377 {
378 vec->x = SW_FT_TRIG_SCALE >> 8;
379 vec->y = 0;
380 ft_trig_pseudo_rotate( vec, angle );
381 vec->x = ( vec->x + 0x80L ) >> 8;
382 vec->y = ( vec->y + 0x80L ) >> 8;
383 }
384
385
386 /* these macros return 0 for positive numbers,
387 and -1 for negative ones */
388#define SW_FT_SIGN_LONG( x ) ( (x) >> ( SW_FT_SIZEOF_LONG * 8 - 1 ) )
389#define SW_FT_SIGN_INT( x ) ( (x) >> ( SW_FT_SIZEOF_INT * 8 - 1 ) )
390#define SW_FT_SIGN_INT32( x ) ( (x) >> 31 )
391#define SW_FT_SIGN_INT16( x ) ( (x) >> 15 )
392
393
394 /* documentation is in fttrigon.h */
395
396 void
397 SW_FT_Vector_Rotate( SW_FT_Vector* vec,
398 SW_FT_Angle angle )
399 {
400 SW_FT_Int shift;
401 SW_FT_Vector v;
402
403
404 v.x = vec->x;
405 v.y = vec->y;
406
407 if ( angle && ( v.x != 0 || v.y != 0 ) )
408 {
409 shift = ft_trig_prenorm( &v );
410 ft_trig_pseudo_rotate( &v, angle );
411 v.x = ft_trig_downscale( v.x );
412 v.y = ft_trig_downscale( v.y );
413
414 if ( shift > 0 )
415 {
416 SW_FT_Int32 half = (SW_FT_Int32)1L << ( shift - 1 );
417
418
419 vec->x = ( v.x + half + SW_FT_SIGN_LONG( v.x ) ) >> shift;
420 vec->y = ( v.y + half + SW_FT_SIGN_LONG( v.y ) ) >> shift;
421 }
422 else
423 {
424 shift = -shift;
425 vec->x = (SW_FT_Pos)( (SW_FT_ULong)v.x << shift );
426 vec->y = (SW_FT_Pos)( (SW_FT_ULong)v.y << shift );
427 }
428 }
429 }
430
431
432 /* documentation is in fttrigon.h */
433
434 SW_FT_Fixed
435 SW_FT_Vector_Length( SW_FT_Vector* vec )
436 {
437 SW_FT_Int shift;
438 SW_FT_Vector v;
439
440
441 v = *vec;
442
443 /* handle trivial cases */
444 if ( v.x == 0 )
445 {
446 return SW_FT_ABS( v.y );
447 }
448 else if ( v.y == 0 )
449 {
450 return SW_FT_ABS( v.x );
451 }
452
453 /* general case */
454 shift = ft_trig_prenorm( &v );
455 ft_trig_pseudo_polarize( &v );
456
457 v.x = ft_trig_downscale( v.x );
458
459 if ( shift > 0 )
460 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
461
462 return (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift );
463 }
464
465
466 /* documentation is in fttrigon.h */
467
468 void
469 SW_FT_Vector_Polarize( SW_FT_Vector* vec,
470 SW_FT_Fixed *length,
471 SW_FT_Angle *angle )
472 {
473 SW_FT_Int shift;
474 SW_FT_Vector v;
475
476
477 v = *vec;
478
479 if ( v.x == 0 && v.y == 0 )
480 return;
481
482 shift = ft_trig_prenorm( &v );
483 ft_trig_pseudo_polarize( &v );
484
485 v.x = ft_trig_downscale( v.x );
486
487 *length = ( shift >= 0 ) ? ( v.x >> shift )
488 : (SW_FT_Fixed)( (SW_FT_UInt32)v.x << -shift );
489 *angle = v.y;
490 }
491
492
493 /* documentation is in fttrigon.h */
494
495 void
496 SW_FT_Vector_From_Polar( SW_FT_Vector* vec,
497 SW_FT_Fixed length,
498 SW_FT_Angle angle )
499 {
500 vec->x = length;
501 vec->y = 0;
502
503 SW_FT_Vector_Rotate( vec, angle );
504 }
505
506
507 /* documentation is in fttrigon.h */
508
509 SW_FT_Angle
510 SW_FT_Angle_Diff( SW_FT_Angle angle1,
511 SW_FT_Angle angle2 )
512 {
513 SW_FT_Angle delta = angle2 - angle1;
514
515
516 delta %= SW_FT_ANGLE_2PI;
517 if ( delta < 0 )
518 delta += SW_FT_ANGLE_2PI;
519
520 if ( delta > SW_FT_ANGLE_PI )
521 delta -= SW_FT_ANGLE_2PI;
522
523 return delta;
524 }
525
526
527/* END */
528
diff --git a/ssg/src/ftraster/sw_ft_math.h b/ssg/src/ftraster/sw_ft_math.h
new file mode 100644
index 0000000000..95a5c4257e
--- /dev/null
+++ b/ssg/src/ftraster/sw_ft_math.h
@@ -0,0 +1,438 @@
1#ifndef SW_FT_MATH_H
2#define SW_FT_MATH_H
3
4/***************************************************************************/
5/* */
6/* fttrigon.h */
7/* */
8/* FreeType trigonometric functions (specification). */
9/* */
10/* Copyright 2001, 2003, 2005, 2007, 2013 by */
11/* David Turner, Robert Wilhelm, and Werner Lemberg. */
12/* */
13/* This file is part of the FreeType project, and may only be used, */
14/* modified, and distributed under the terms of the FreeType project */
15/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
16/* this file you indicate that you have read the license and */
17/* understand and accept it fully. */
18/* */
19/***************************************************************************/
20
21#include "sw_ft_types.h"
22
23
24/*************************************************************************/
25/* */
26/* The min and max functions missing in C. As usual, be careful not to */
27/* write things like SW_FT_MIN( a++, b++ ) to avoid side effects. */
28/* */
29#define SW_FT_MIN( a, b ) ( (a) < (b) ? (a) : (b) )
30#define SW_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
31
32#define SW_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
33
34/*
35 * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
36 * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
37 * largest error less than 7% compared to the exact value.
38 */
39#define SW_FT_HYPOT( x, y ) \
40 ( x = SW_FT_ABS( x ), \
41 y = SW_FT_ABS( y ), \
42 x > y ? x + ( 3 * y >> 3 ) \
43 : y + ( 3 * x >> 3 ) )
44
45/*************************************************************************/
46/* */
47/* <Function> */
48/* SW_FT_MulFix */
49/* */
50/* <Description> */
51/* A very simple function used to perform the computation */
52/* `(a*b)/0x10000' with maximum accuracy. Most of the time this is */
53/* used to multiply a given value by a 16.16 fixed-point factor. */
54/* */
55/* <Input> */
56/* a :: The first multiplier. */
57/* b :: The second multiplier. Use a 16.16 factor here whenever */
58/* possible (see note below). */
59/* */
60/* <Return> */
61/* The result of `(a*b)/0x10000'. */
62/* */
63/* <Note> */
64/* This function has been optimized for the case where the absolute */
65/* value of `a' is less than 2048, and `b' is a 16.16 scaling factor. */
66/* As this happens mainly when scaling from notional units to */
67/* fractional pixels in FreeType, it resulted in noticeable speed */
68/* improvements between versions 2.x and 1.x. */
69/* */
70/* As a conclusion, always try to place a 16.16 factor as the */
71/* _second_ argument of this function; this can make a great */
72/* difference. */
73/* */
74SW_FT_Long
75SW_FT_MulFix( SW_FT_Long a,
76 SW_FT_Long b );
77
78/*************************************************************************/
79/* */
80/* <Function> */
81/* SW_FT_MulDiv */
82/* */
83/* <Description> */
84/* A very simple function used to perform the computation `(a*b)/c' */
85/* with maximum accuracy (it uses a 64-bit intermediate integer */
86/* whenever necessary). */
87/* */
88/* This function isn't necessarily as fast as some processor specific */
89/* operations, but is at least completely portable. */
90/* */
91/* <Input> */
92/* a :: The first multiplier. */
93/* b :: The second multiplier. */
94/* c :: The divisor. */
95/* */
96/* <Return> */
97/* The result of `(a*b)/c'. This function never traps when trying to */
98/* divide by zero; it simply returns `MaxInt' or `MinInt' depending */
99/* on the signs of `a' and `b'. */
100/* */
101SW_FT_Long
102SW_FT_MulDiv( SW_FT_Long a,
103 SW_FT_Long b,
104 SW_FT_Long c );
105
106/*************************************************************************/
107/* */
108/* <Function> */
109/* SW_FT_DivFix */
110/* */
111/* <Description> */
112/* A very simple function used to perform the computation */
113/* `(a*0x10000)/b' with maximum accuracy. Most of the time, this is */
114/* used to divide a given value by a 16.16 fixed-point factor. */
115/* */
116/* <Input> */
117/* a :: The numerator. */
118/* b :: The denominator. Use a 16.16 factor here. */
119/* */
120/* <Return> */
121/* The result of `(a*0x10000)/b'. */
122/* */
123SW_FT_Long
124SW_FT_DivFix( SW_FT_Long a,
125 SW_FT_Long b );
126
127
128
129 /*************************************************************************/
130 /* */
131 /* <Section> */
132 /* computations */
133 /* */
134 /*************************************************************************/
135
136
137 /*************************************************************************
138 *
139 * @type:
140 * SW_FT_Angle
141 *
142 * @description:
143 * This type is used to model angle values in FreeType. Note that the
144 * angle is a 16.16 fixed-point value expressed in degrees.
145 *
146 */
147 typedef SW_FT_Fixed SW_FT_Angle;
148
149
150 /*************************************************************************
151 *
152 * @macro:
153 * SW_FT_ANGLE_PI
154 *
155 * @description:
156 * The angle pi expressed in @SW_FT_Angle units.
157 *
158 */
159#define SW_FT_ANGLE_PI ( 180L << 16 )
160
161
162 /*************************************************************************
163 *
164 * @macro:
165 * SW_FT_ANGLE_2PI
166 *
167 * @description:
168 * The angle 2*pi expressed in @SW_FT_Angle units.
169 *
170 */
171#define SW_FT_ANGLE_2PI ( SW_FT_ANGLE_PI * 2 )
172
173
174 /*************************************************************************
175 *
176 * @macro:
177 * SW_FT_ANGLE_PI2
178 *
179 * @description:
180 * The angle pi/2 expressed in @SW_FT_Angle units.
181 *
182 */
183#define SW_FT_ANGLE_PI2 ( SW_FT_ANGLE_PI / 2 )
184
185
186 /*************************************************************************
187 *
188 * @macro:
189 * SW_FT_ANGLE_PI4
190 *
191 * @description:
192 * The angle pi/4 expressed in @SW_FT_Angle units.
193 *
194 */
195#define SW_FT_ANGLE_PI4 ( SW_FT_ANGLE_PI / 4 )
196
197
198 /*************************************************************************
199 *
200 * @function:
201 * SW_FT_Sin
202 *
203 * @description:
204 * Return the sinus of a given angle in fixed-point format.
205 *
206 * @input:
207 * angle ::
208 * The input angle.
209 *
210 * @return:
211 * The sinus value.
212 *
213 * @note:
214 * If you need both the sinus and cosinus for a given angle, use the
215 * function @SW_FT_Vector_Unit.
216 *
217 */
218 SW_FT_Fixed
219 SW_FT_Sin( SW_FT_Angle angle );
220
221
222 /*************************************************************************
223 *
224 * @function:
225 * SW_FT_Cos
226 *
227 * @description:
228 * Return the cosinus of a given angle in fixed-point format.
229 *
230 * @input:
231 * angle ::
232 * The input angle.
233 *
234 * @return:
235 * The cosinus value.
236 *
237 * @note:
238 * If you need both the sinus and cosinus for a given angle, use the
239 * function @SW_FT_Vector_Unit.
240 *
241 */
242 SW_FT_Fixed
243 SW_FT_Cos( SW_FT_Angle angle );
244
245
246 /*************************************************************************
247 *
248 * @function:
249 * SW_FT_Tan
250 *
251 * @description:
252 * Return the tangent of a given angle in fixed-point format.
253 *
254 * @input:
255 * angle ::
256 * The input angle.
257 *
258 * @return:
259 * The tangent value.
260 *
261 */
262 SW_FT_Fixed
263 SW_FT_Tan( SW_FT_Angle angle );
264
265
266 /*************************************************************************
267 *
268 * @function:
269 * SW_FT_Atan2
270 *
271 * @description:
272 * Return the arc-tangent corresponding to a given vector (x,y) in
273 * the 2d plane.
274 *
275 * @input:
276 * x ::
277 * The horizontal vector coordinate.
278 *
279 * y ::
280 * The vertical vector coordinate.
281 *
282 * @return:
283 * The arc-tangent value (i.e. angle).
284 *
285 */
286 SW_FT_Angle
287 SW_FT_Atan2( SW_FT_Fixed x,
288 SW_FT_Fixed y );
289
290
291 /*************************************************************************
292 *
293 * @function:
294 * SW_FT_Angle_Diff
295 *
296 * @description:
297 * Return the difference between two angles. The result is always
298 * constrained to the ]-PI..PI] interval.
299 *
300 * @input:
301 * angle1 ::
302 * First angle.
303 *
304 * angle2 ::
305 * Second angle.
306 *
307 * @return:
308 * Constrained value of `value2-value1'.
309 *
310 */
311 SW_FT_Angle
312 SW_FT_Angle_Diff( SW_FT_Angle angle1,
313 SW_FT_Angle angle2 );
314
315
316 /*************************************************************************
317 *
318 * @function:
319 * SW_FT_Vector_Unit
320 *
321 * @description:
322 * Return the unit vector corresponding to a given angle. After the
323 * call, the value of `vec.x' will be `sin(angle)', and the value of
324 * `vec.y' will be `cos(angle)'.
325 *
326 * This function is useful to retrieve both the sinus and cosinus of a
327 * given angle quickly.
328 *
329 * @output:
330 * vec ::
331 * The address of target vector.
332 *
333 * @input:
334 * angle ::
335 * The input angle.
336 *
337 */
338 void
339 SW_FT_Vector_Unit( SW_FT_Vector* vec,
340 SW_FT_Angle angle );
341
342
343 /*************************************************************************
344 *
345 * @function:
346 * SW_FT_Vector_Rotate
347 *
348 * @description:
349 * Rotate a vector by a given angle.
350 *
351 * @inout:
352 * vec ::
353 * The address of target vector.
354 *
355 * @input:
356 * angle ::
357 * The input angle.
358 *
359 */
360 void
361 SW_FT_Vector_Rotate( SW_FT_Vector* vec,
362 SW_FT_Angle angle );
363
364
365 /*************************************************************************
366 *
367 * @function:
368 * SW_FT_Vector_Length
369 *
370 * @description:
371 * Return the length of a given vector.
372 *
373 * @input:
374 * vec ::
375 * The address of target vector.
376 *
377 * @return:
378 * The vector length, expressed in the same units that the original
379 * vector coordinates.
380 *
381 */
382 SW_FT_Fixed
383 SW_FT_Vector_Length( SW_FT_Vector* vec );
384
385
386 /*************************************************************************
387 *
388 * @function:
389 * SW_FT_Vector_Polarize
390 *
391 * @description:
392 * Compute both the length and angle of a given vector.
393 *
394 * @input:
395 * vec ::
396 * The address of source vector.
397 *
398 * @output:
399 * length ::
400 * The vector length.
401 *
402 * angle ::
403 * The vector angle.
404 *
405 */
406 void
407 SW_FT_Vector_Polarize( SW_FT_Vector* vec,
408 SW_FT_Fixed *length,
409 SW_FT_Angle *angle );
410
411
412 /*************************************************************************
413 *
414 * @function:
415 * SW_FT_Vector_From_Polar
416 *
417 * @description:
418 * Compute vector coordinates from a length and angle.
419 *
420 * @output:
421 * vec ::
422 * The address of source vector.
423 *
424 * @input:
425 * length ::
426 * The vector length.
427 *
428 * angle ::
429 * The vector angle.
430 *
431 */
432 void
433 SW_FT_Vector_From_Polar( SW_FT_Vector* vec,
434 SW_FT_Fixed length,
435 SW_FT_Angle angle );
436
437
438#endif // SW_FT_MATH_H
diff --git a/ssg/src/ftraster/sw_ft_raster.cpp b/ssg/src/ftraster/sw_ft_raster.cpp
new file mode 100644
index 0000000000..a967221b81
--- /dev/null
+++ b/ssg/src/ftraster/sw_ft_raster.cpp
@@ -0,0 +1,1674 @@
1/***************************************************************************/
2/* */
3/* ftgrays.c */
4/* */
5/* A new `perfect' anti-aliasing renderer (body). */
6/* */
7/* Copyright 2000-2003, 2005-2014 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18 /*************************************************************************/
19 /* */
20 /* This is a new anti-aliasing scan-converter for FreeType 2. The */
21 /* algorithm used here is _very_ different from the one in the standard */
22 /* `ftraster' module. Actually, `ftgrays' computes the _exact_ */
23 /* coverage of the outline on each pixel cell. */
24 /* */
25 /* It is based on ideas that I initially found in Raph Levien's */
26 /* excellent LibArt graphics library (see http://www.levien.com/libart */
27 /* for more information, though the web pages do not tell anything */
28 /* about the renderer; you'll have to dive into the source code to */
29 /* understand how it works). */
30 /* */
31 /* Note, however, that this is a _very_ different implementation */
32 /* compared to Raph's. Coverage information is stored in a very */
33 /* different way, and I don't use sorted vector paths. Also, it doesn't */
34 /* use floating point values. */
35 /* */
36 /* This renderer has the following advantages: */
37 /* */
38 /* - It doesn't need an intermediate bitmap. Instead, one can supply a */
39 /* callback function that will be called by the renderer to draw gray */
40 /* spans on any target surface. You can thus do direct composition on */
41 /* any kind of bitmap, provided that you give the renderer the right */
42 /* callback. */
43 /* */
44 /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on */
45 /* each pixel cell. */
46 /* */
47 /* - It performs a single pass on the outline (the `standard' FT2 */
48 /* renderer makes two passes). */
49 /* */
50 /* - It can easily be modified to render to _any_ number of gray levels */
51 /* cheaply. */
52 /* */
53 /* - For small (< 20) pixel sizes, it is faster than the standard */
54 /* renderer. */
55 /* */
56 /*************************************************************************/
57
58
59#include "sw_ft_raster.h"
60#include "sw_ft_math.h"
61
62 /* Auxiliary macros for token concatenation. */
63#define SW_FT_ERR_XCAT( x, y ) x ## y
64#define SW_FT_ERR_CAT( x, y ) SW_FT_ERR_XCAT( x, y )
65
66#define SW_FT_BEGIN_STMNT do {
67#define SW_FT_END_STMNT } while ( 0 )
68
69
70#include <stddef.h>
71#include <string.h>
72#include <setjmp.h>
73#include <limits.h>
74#define SW_FT_UINT_MAX UINT_MAX
75#define SW_FT_INT_MAX INT_MAX
76#define SW_FT_ULONG_MAX ULONG_MAX
77#define SW_FT_CHAR_BIT CHAR_BIT
78
79#define ft_memset memset
80
81#define ft_setjmp setjmp
82#define ft_longjmp longjmp
83#define ft_jmp_buf jmp_buf
84
85typedef ptrdiff_t SW_FT_PtrDist;
86
87
88#define ErrRaster_Invalid_Mode -2
89#define ErrRaster_Invalid_Outline -1
90#define ErrRaster_Invalid_Argument -3
91#define ErrRaster_Memory_Overflow -4
92
93#define SW_FT_BEGIN_HEADER
94#define SW_FT_END_HEADER
95
96
97 /* This macro is used to indicate that a function parameter is unused. */
98 /* Its purpose is simply to reduce compiler warnings. Note also that */
99 /* simply defining it as `(void)x' doesn't avoid warnings with certain */
100 /* ANSI compilers (e.g. LCC). */
101#define SW_FT_UNUSED( x ) (x) = (x)
102
103
104#define SW_FT_THROW( e ) SW_FT_ERR_CAT( ErrRaster_, e )
105
106 /* The size in bytes of the render pool used by the scan-line converter */
107 /* to do all of its work. */
108#define SW_FT_RENDER_POOL_SIZE 16384L
109
110typedef int
111(*SW_FT_Outline_MoveToFunc)( const SW_FT_Vector* to,
112 void* user );
113
114#define SW_FT_Outline_MoveTo_Func SW_FT_Outline_MoveToFunc
115
116typedef int
117(*SW_FT_Outline_LineToFunc)( const SW_FT_Vector* to,
118 void* user );
119
120#define SW_FT_Outline_LineTo_Func SW_FT_Outline_LineToFunc
121
122
123typedef int
124(*SW_FT_Outline_ConicToFunc)( const SW_FT_Vector* control,
125 const SW_FT_Vector* to,
126 void* user );
127
128#define SW_FT_Outline_ConicTo_Func SW_FT_Outline_ConicToFunc
129
130typedef int
131(*SW_FT_Outline_CubicToFunc)( const SW_FT_Vector* control1,
132 const SW_FT_Vector* control2,
133 const SW_FT_Vector* to,
134 void* user );
135
136#define SW_FT_Outline_CubicTo_Func SW_FT_Outline_CubicToFunc
137
138typedef struct SW_FT_Outline_Funcs_
139{
140 SW_FT_Outline_MoveToFunc move_to;
141 SW_FT_Outline_LineToFunc line_to;
142 SW_FT_Outline_ConicToFunc conic_to;
143 SW_FT_Outline_CubicToFunc cubic_to;
144
145 int shift;
146 SW_FT_Pos delta;
147
148} SW_FT_Outline_Funcs;
149
150
151
152#define SW_FT_DEFINE_OUTLINE_FUNCS( class_, \
153 move_to_, line_to_, \
154 conic_to_, cubic_to_, \
155 shift_, delta_ ) \
156 static const SW_FT_Outline_Funcs class_ = \
157 { \
158 move_to_, \
159 line_to_, \
160 conic_to_, \
161 cubic_to_, \
162 shift_, \
163 delta_ \
164 };
165
166#define SW_FT_DEFINE_RASTER_FUNCS( class_, \
167 raster_new_, raster_reset_, \
168 raster_render_, \
169 raster_done_ ) \
170 const SW_FT_Raster_Funcs class_ = \
171 { \
172 raster_new_, \
173 raster_reset_, \
174 raster_render_, \
175 raster_done_ \
176 };
177
178
179#ifndef SW_FT_MEM_SET
180#define SW_FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
181#endif
182
183#ifndef SW_FT_MEM_ZERO
184#define SW_FT_MEM_ZERO( dest, count ) SW_FT_MEM_SET( dest, 0, count )
185#endif
186
187 /* as usual, for the speed hungry :-) */
188
189#undef RAS_ARG
190#undef RAS_ARG_
191#undef RAS_VAR
192#undef RAS_VAR_
193
194#ifndef SW_FT_STATIC_RASTER
195
196#define RAS_ARG gray_PWorker worker
197#define RAS_ARG_ gray_PWorker worker,
198
199#define RAS_VAR worker
200#define RAS_VAR_ worker,
201
202#else /* SW_FT_STATIC_RASTER */
203
204#define RAS_ARG /* empty */
205#define RAS_ARG_ /* empty */
206#define RAS_VAR /* empty */
207#define RAS_VAR_ /* empty */
208
209#endif /* SW_FT_STATIC_RASTER */
210
211
212 /* must be at least 6 bits! */
213#define PIXEL_BITS 8
214
215#undef FLOOR
216#undef CEILING
217#undef TRUNC
218#undef SCALED
219
220#define ONE_PIXEL ( 1L << PIXEL_BITS )
221#define PIXEL_MASK ( -1L << PIXEL_BITS )
222#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
223#define SUBPIXELS( x ) ( (TPos)(x) << PIXEL_BITS )
224#define FLOOR( x ) ( (x) & -ONE_PIXEL )
225#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
226#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
227
228#if PIXEL_BITS >= 6
229#define UPSCALE( x ) ( (x) << ( PIXEL_BITS - 6 ) )
230#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
231#else
232#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
233#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
234#endif
235
236
237 /* Compute `dividend / divisor' and return both its quotient and */
238 /* remainder, cast to a specific type. This macro also ensures that */
239 /* the remainder is always positive. */
240#define SW_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
241 SW_FT_BEGIN_STMNT \
242 (quotient) = (type)( (dividend) / (divisor) ); \
243 (remainder) = (type)( (dividend) % (divisor) ); \
244 if ( (remainder) < 0 ) \
245 { \
246 (quotient)--; \
247 (remainder) += (type)(divisor); \
248 } \
249 SW_FT_END_STMNT
250
251#ifdef __arm__
252 /* Work around a bug specific to GCC which make the compiler fail to */
253 /* optimize a division and modulo operation on the same parameters */
254 /* into a single call to `__aeabi_idivmod'. See */
255 /* */
256 /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721 */
257#undef SW_FT_DIV_MOD
258#define SW_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
259 SW_FT_BEGIN_STMNT \
260 (quotient) = (type)( (dividend) / (divisor) ); \
261 (remainder) = (type)( (dividend) - (quotient) * (divisor) ); \
262 if ( (remainder) < 0 ) \
263 { \
264 (quotient)--; \
265 (remainder) += (type)(divisor); \
266 } \
267 SW_FT_END_STMNT
268#endif /* __arm__ */
269
270 /* These macros speed up repetitive divisions by replacing them */
271 /* with multiplications and right shifts. */
272#define SW_FT_UDIVPREP( b ) \
273 long b ## _r = (long)( SW_FT_ULONG_MAX >> PIXEL_BITS ) / ( b )
274#define SW_FT_UDIV( a, b ) \
275 ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
276 ( sizeof( long ) * SW_FT_CHAR_BIT - PIXEL_BITS ) )
277
278
279 /*************************************************************************/
280 /* */
281 /* TYPE DEFINITIONS */
282 /* */
283
284 /* don't change the following types to SW_FT_Int or SW_FT_Pos, since we might */
285 /* need to define them to "float" or "double" when experimenting with */
286 /* new algorithms */
287
288 typedef long TCoord; /* integer scanline/pixel coordinate */
289 typedef long TPos; /* sub-pixel coordinate */
290
291 /* determine the type used to store cell areas. This normally takes at */
292 /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */
293 /* `long' instead of `int', otherwise bad things happen */
294
295#if PIXEL_BITS <= 7
296
297 typedef int TArea;
298
299#else /* PIXEL_BITS >= 8 */
300
301 /* approximately determine the size of integers using an ANSI-C header */
302#if SW_FT_UINT_MAX == 0xFFFFU
303 typedef long TArea;
304#else
305 typedef int TArea;
306#endif
307
308#endif /* PIXEL_BITS >= 8 */
309
310
311 /* maximum number of gray spans in a call to the span callback */
312#define SW_FT_MAX_GRAY_SPANS 256
313
314
315 typedef struct TCell_* PCell;
316
317 typedef struct TCell_
318 {
319 TPos x; /* same with gray_TWorker.ex */
320 TCoord cover; /* same with gray_TWorker.cover */
321 TArea area;
322 PCell next;
323
324 } TCell;
325
326
327#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
328 /* We disable the warning `structure was padded due to */
329 /* __declspec(align())' in order to compile cleanly with */
330 /* the maximum level of warnings. */
331#pragma warning( push )
332#pragma warning( disable : 4324 )
333#endif /* _MSC_VER */
334
335 typedef struct gray_TWorker_
336 {
337 TCoord ex, ey;
338 TPos min_ex, max_ex;
339 TPos min_ey, max_ey;
340 TPos count_ex, count_ey;
341
342 TArea area;
343 TCoord cover;
344 int invalid;
345
346 PCell cells;
347 SW_FT_PtrDist max_cells;
348 SW_FT_PtrDist num_cells;
349
350 TPos x, y;
351
352
353 SW_FT_Vector bez_stack[32 * 3 + 1];
354 int lev_stack[32];
355
356 SW_FT_Outline outline;
357 SW_FT_BBox clip_box;
358
359 SW_FT_Span gray_spans[SW_FT_MAX_GRAY_SPANS];
360 int num_gray_spans;
361
362 SW_FT_Raster_Span_Func render_span;
363 void* render_span_data;
364
365 int band_size;
366 int band_shoot;
367
368 ft_jmp_buf jump_buffer;
369
370 void* buffer;
371 long buffer_size;
372
373 PCell* ycells;
374 TPos ycount;
375
376 } gray_TWorker, *gray_PWorker;
377
378#if defined( _MSC_VER )
379#pragma warning( pop )
380#endif
381
382
383#ifndef SW_FT_STATIC_RASTER
384#define ras (*worker)
385#else
386 static gray_TWorker ras;
387#endif
388
389
390 typedef struct gray_TRaster_
391 {
392 void* memory;
393
394 } gray_TRaster, *gray_PRaster;
395
396
397
398 /*************************************************************************/
399 /* */
400 /* Initialize the cells table. */
401 /* */
402 static void
403 gray_init_cells( RAS_ARG_ void* buffer,
404 long byte_size )
405 {
406 ras.buffer = buffer;
407 ras.buffer_size = byte_size;
408
409 ras.ycells = (PCell*) buffer;
410 ras.cells = NULL;
411 ras.max_cells = 0;
412 ras.num_cells = 0;
413 ras.area = 0;
414 ras.cover = 0;
415 ras.invalid = 1;
416 }
417
418
419 /*************************************************************************/
420 /* */
421 /* Compute the outline bounding box. */
422 /* */
423 static void
424 gray_compute_cbox( RAS_ARG )
425 {
426 SW_FT_Outline* outline = &ras.outline;
427 SW_FT_Vector* vec = outline->points;
428 SW_FT_Vector* limit = vec + outline->n_points;
429
430
431 if ( outline->n_points <= 0 )
432 {
433 ras.min_ex = ras.max_ex = 0;
434 ras.min_ey = ras.max_ey = 0;
435 return;
436 }
437
438 ras.min_ex = ras.max_ex = vec->x;
439 ras.min_ey = ras.max_ey = vec->y;
440
441 vec++;
442
443 for ( ; vec < limit; vec++ )
444 {
445 TPos x = vec->x;
446 TPos y = vec->y;
447
448
449 if ( x < ras.min_ex ) ras.min_ex = x;
450 if ( x > ras.max_ex ) ras.max_ex = x;
451 if ( y < ras.min_ey ) ras.min_ey = y;
452 if ( y > ras.max_ey ) ras.max_ey = y;
453 }
454
455 /* truncate the bounding box to integer pixels */
456 ras.min_ex = ras.min_ex >> 6;
457 ras.min_ey = ras.min_ey >> 6;
458 ras.max_ex = ( ras.max_ex + 63 ) >> 6;
459 ras.max_ey = ( ras.max_ey + 63 ) >> 6;
460 }
461
462
463 /*************************************************************************/
464 /* */
465 /* Record the current cell in the table. */
466 /* */
467 static PCell
468 gray_find_cell( RAS_ARG )
469 {
470 PCell *pcell, cell;
471 TPos x = ras.ex;
472
473
474 if ( x > ras.count_ex )
475 x = ras.count_ex;
476
477 pcell = &ras.ycells[ras.ey];
478 for (;;)
479 {
480 cell = *pcell;
481 if ( cell == NULL || cell->x > x )
482 break;
483
484 if ( cell->x == x )
485 goto Exit;
486
487 pcell = &cell->next;
488 }
489
490 if ( ras.num_cells >= ras.max_cells )
491 ft_longjmp( ras.jump_buffer, 1 );
492
493 cell = ras.cells + ras.num_cells++;
494 cell->x = x;
495 cell->area = 0;
496 cell->cover = 0;
497
498 cell->next = *pcell;
499 *pcell = cell;
500
501 Exit:
502 return cell;
503 }
504
505
506 static void
507 gray_record_cell( RAS_ARG )
508 {
509 if ( ras.area | ras.cover )
510 {
511 PCell cell = gray_find_cell( RAS_VAR );
512
513
514 cell->area += ras.area;
515 cell->cover += ras.cover;
516 }
517 }
518
519
520 /*************************************************************************/
521 /* */
522 /* Set the current cell to a new position. */
523 /* */
524 static void
525 gray_set_cell( RAS_ARG_ TCoord ex,
526 TCoord ey )
527 {
528 /* Move the cell pointer to a new position. We set the `invalid' */
529 /* flag to indicate that the cell isn't part of those we're interested */
530 /* in during the render phase. This means that: */
531 /* */
532 /* . the new vertical position must be within min_ey..max_ey-1. */
533 /* . the new horizontal position must be strictly less than max_ex */
534 /* */
535 /* Note that if a cell is to the left of the clipping region, it is */
536 /* actually set to the (min_ex-1) horizontal position. */
537
538 /* All cells that are on the left of the clipping region go to the */
539 /* min_ex - 1 horizontal position. */
540 ey -= ras.min_ey;
541
542 if ( ex > ras.max_ex )
543 ex = ras.max_ex;
544
545 ex -= ras.min_ex;
546 if ( ex < 0 )
547 ex = -1;
548
549 /* are we moving to a different cell ? */
550 if ( ex != ras.ex || ey != ras.ey )
551 {
552 /* record the current one if it is valid */
553 if ( !ras.invalid )
554 gray_record_cell( RAS_VAR );
555
556 ras.area = 0;
557 ras.cover = 0;
558 ras.ex = ex;
559 ras.ey = ey;
560 }
561
562 ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
563 ex >= ras.count_ex );
564 }
565
566
567 /*************************************************************************/
568 /* */
569 /* Start a new contour at a given cell. */
570 /* */
571 static void
572 gray_start_cell( RAS_ARG_ TCoord ex,
573 TCoord ey )
574 {
575 if ( ex > ras.max_ex )
576 ex = (TCoord)( ras.max_ex );
577
578 if ( ex < ras.min_ex )
579 ex = (TCoord)( ras.min_ex - 1 );
580
581 ras.area = 0;
582 ras.cover = 0;
583 ras.ex = ex - ras.min_ex;
584 ras.ey = ey - ras.min_ey;
585 ras.invalid = 0;
586
587 gray_set_cell( RAS_VAR_ ex, ey );
588 }
589
590 /*************************************************************************/
591 /* */
592 /* Render a straight line across multiple cells in any direction. */
593 /* */
594 static void
595 gray_render_line( RAS_ARG_ TPos to_x,
596 TPos to_y )
597 {
598 TPos dx, dy, fx1, fy1, fx2, fy2;
599 TCoord ex1, ex2, ey1, ey2;
600
601
602 ex1 = TRUNC( ras.x );
603 ex2 = TRUNC( to_x );
604 ey1 = TRUNC( ras.y );
605 ey2 = TRUNC( to_y );
606
607 /* perform vertical clipping */
608 if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
609 ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
610 goto End;
611
612 dx = to_x - ras.x;
613 dy = to_y - ras.y;
614
615 fx1 = ras.x - SUBPIXELS( ex1 );
616 fy1 = ras.y - SUBPIXELS( ey1 );
617
618 if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
619 ;
620 else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
621 {
622 ex1 = ex2;
623 gray_set_cell( RAS_VAR_ ex1, ey1 );
624 }
625 else if ( dx == 0 )
626 {
627 if ( dy > 0 ) /* vertical line up */
628 do
629 {
630 fy2 = ONE_PIXEL;
631 ras.cover += ( fy2 - fy1 );
632 ras.area += ( fy2 - fy1 ) * fx1 * 2;
633 fy1 = 0;
634 ey1++;
635 gray_set_cell( RAS_VAR_ ex1, ey1 );
636 } while ( ey1 != ey2 );
637 else /* vertical line down */
638 do
639 {
640 fy2 = 0;
641 ras.cover += ( fy2 - fy1 );
642 ras.area += ( fy2 - fy1 ) * fx1 * 2;
643 fy1 = ONE_PIXEL;
644 ey1--;
645 gray_set_cell( RAS_VAR_ ex1, ey1 );
646 } while ( ey1 != ey2 );
647 }
648 else /* any other line */
649 {
650 TArea prod = dx * fy1 - dy * fx1;
651 SW_FT_UDIVPREP( dx );
652 SW_FT_UDIVPREP( dy );
653
654
655 /* The fundamental value `prod' determines which side and the */
656 /* exact coordinate where the line exits current cell. It is */
657 /* also easily updated when moving from one cell to the next. */
658 do
659 {
660 if ( prod <= 0 &&
661 prod - dx * ONE_PIXEL > 0 ) /* left */
662 {
663 fx2 = 0;
664 fy2 = (TPos)SW_FT_UDIV( -prod, -dx );
665 prod -= dy * ONE_PIXEL;
666 ras.cover += ( fy2 - fy1 );
667 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
668 fx1 = ONE_PIXEL;
669 fy1 = fy2;
670 ex1--;
671 }
672 else if ( prod - dx * ONE_PIXEL <= 0 &&
673 prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
674 {
675 prod -= dx * ONE_PIXEL;
676 fx2 = (TPos)SW_FT_UDIV( -prod, dy );
677 fy2 = ONE_PIXEL;
678 ras.cover += ( fy2 - fy1 );
679 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
680 fx1 = fx2;
681 fy1 = 0;
682 ey1++;
683 }
684 else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
685 prod + dy * ONE_PIXEL >= 0 ) /* right */
686 {
687 prod += dy * ONE_PIXEL;
688 fx2 = ONE_PIXEL;
689 fy2 = (TPos)SW_FT_UDIV( prod, dx );
690 ras.cover += ( fy2 - fy1 );
691 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
692 fx1 = 0;
693 fy1 = fy2;
694 ex1++;
695 }
696 else /* ( prod + dy * ONE_PIXEL < 0 &&
697 prod > 0 ) down */
698 {
699 fx2 = (TPos)SW_FT_UDIV( prod, -dy );
700 fy2 = 0;
701 prod += dx * ONE_PIXEL;
702 ras.cover += ( fy2 - fy1 );
703 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
704 fx1 = fx2;
705 fy1 = ONE_PIXEL;
706 ey1--;
707 }
708
709 gray_set_cell( RAS_VAR_ ex1, ey1 );
710 } while ( ex1 != ex2 || ey1 != ey2 );
711 }
712
713 fx2 = to_x - SUBPIXELS( ex2 );
714 fy2 = to_y - SUBPIXELS( ey2 );
715
716 ras.cover += ( fy2 - fy1 );
717 ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
718
719 End:
720 ras.x = to_x;
721 ras.y = to_y;
722 }
723
724 static void
725 gray_split_conic( SW_FT_Vector* base )
726 {
727 TPos a, b;
728
729
730 base[4].x = base[2].x;
731 b = base[1].x;
732 a = base[3].x = ( base[2].x + b ) / 2;
733 b = base[1].x = ( base[0].x + b ) / 2;
734 base[2].x = ( a + b ) / 2;
735
736 base[4].y = base[2].y;
737 b = base[1].y;
738 a = base[3].y = ( base[2].y + b ) / 2;
739 b = base[1].y = ( base[0].y + b ) / 2;
740 base[2].y = ( a + b ) / 2;
741 }
742