Skip to content

Commit

Permalink
Sync latest changes from vkdoom
Browse files Browse the repository at this point in the history
  • Loading branch information
dpjudas committed Jan 7, 2024
1 parent 247c751 commit be610ec
Show file tree
Hide file tree
Showing 19 changed files with 3,204 additions and 110 deletions.
96 changes: 96 additions & 0 deletions include/zwidget/core/pathfill.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include <vector>
#include <stdint.h>
#include <limits.h>
#include <string.h>
#include "core/rect.h"

/*
// 3x3 transform matrix
class PathFillTransform
{
public:
PathFillTransform() { for (int i = 0; i < 9; i++) matrix[i] = 0.0f; matrix[0] = matrix[4] = matrix[8] = 1.0; }
PathFillTransform(const float* mat3x3) { for (int i = 0; i < 9; i++) matrix[i] = (double)mat3x3[i]; }
PathFillTransform(const double* mat3x3) { for (int i = 0; i < 9; i++) matrix[i] = mat3x3[i]; }
double matrix[9];
};
*/

enum class PathFillMode
{
alternate,
winding
};

enum class PathFillCommand
{
line,
quadradic,
cubic
};

class PathFillSubpath
{
public:
PathFillSubpath() : points(1) { }

std::vector<Point> points;
std::vector<PathFillCommand> commands;
bool closed = false;
};

class PathFillDesc
{
public:
PathFillDesc() : subpaths(1) { }

PathFillMode fill_mode = PathFillMode::alternate;
std::vector<PathFillSubpath> subpaths;

void MoveTo(const Point& point)
{
if (!subpaths.back().commands.empty())
{
subpaths.push_back(PathFillSubpath());
}
subpaths.back().points.front() = point;
}

void LineTo(const Point& point)
{
auto& subpath = subpaths.back();
subpath.points.push_back(point);
subpath.commands.push_back(PathFillCommand::line);
}

void BezierTo(const Point& control, const Point& point)
{
auto& subpath = subpaths.back();
subpath.points.push_back(control);
subpath.points.push_back(point);
subpath.commands.push_back(PathFillCommand::quadradic);
}

void BezierTo(const Point& control1, const Point& control2, const Point& point)
{
auto& subpath = subpaths.back();
subpath.points.push_back(control1);
subpath.points.push_back(control2);
subpath.points.push_back(point);
subpath.commands.push_back(PathFillCommand::cubic);
}

void Close()
{
if (!subpaths.back().commands.empty())
{
subpaths.back().closed = true;
subpaths.push_back(PathFillSubpath());
}
}

void Rasterize(uint8_t* dest, int width, int height, bool blend = false);
};
9 changes: 9 additions & 0 deletions include/zwidget/core/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ class Rect
static Rect xywh(double x, double y, double width, double height) { return Rect(x, y, width, height); }
static Rect ltrb(double left, double top, double right, double bottom) { return Rect(left, top, right - left, bottom - top); }

static Rect shrink(Rect box, double left, double top, double right, double bottom)
{
box.x += left;
box.y += top;
box.width = std::max(box.width - left - right, 0.0);
box.height = std::max(box.height - bottom - top, 0.0);
return box;
}

bool contains(const Point& p) const { return (p.x >= x && p.x < x + width) && (p.y >= y && p.y < y + height); }

double x = 0;
Expand Down
2 changes: 2 additions & 0 deletions include/zwidget/core/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ class Widget : DisplayWindowHost
Widget* CaptureWidget = nullptr;
Widget* HoverWidget = nullptr;

StandardCursor CurrentCursor = StandardCursor::arrow;

Widget(const Widget&) = delete;
Widget& operator=(const Widget&) = delete;

Expand Down
9 changes: 9 additions & 0 deletions include/zwidget/widgets/listview/listview.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include <vector>
#include <functional>

class Scrollbar;

class ListView : public Widget
{
public:
ListView(Widget* parent = nullptr);

void AddItem(const std::string& text);
int GetSelectedItem() const { return selectedItem; }
void SetSelectedItem(int index);
void ScrollToItem(int index);

void Activate();

Expand All @@ -22,7 +26,12 @@ class ListView : public Widget
void OnPaintFrame(Canvas* canvas) override;
void OnMouseDown(const Point& pos, int key) override;
void OnMouseDoubleclick(const Point& pos, int key) override;
void OnMouseWheel(const Point& pos, EInputKey key) override;
void OnKeyDown(EInputKey key) override;
void OnGeometryChanged() override;
void OnScrollbarScroll();

Scrollbar* scrollbar = nullptr;

std::vector<std::string> items;
int selectedItem = 0;
Expand Down
56 changes: 29 additions & 27 deletions include/zwidget/widgets/scrollbar/scrollbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,27 @@ class Scrollbar : public Widget

bool IsVertical() const;
bool IsHorizontal() const;
int GetMin() const;
int GetMax() const;
int GetLineStep() const;
int GetPageStep() const;
int GetPosition() const;
double GetMin() const;
double GetMax() const;
double GetLineStep() const;
double GetPageStep() const;
double GetPosition() const;

void SetVertical();
void SetHorizontal();

void SetMin(int scroll_min);
void SetMax(int scroll_max);
void SetLineStep(int step);
void SetPageStep(int step);
void SetMin(double scroll_min);
void SetMax(double scroll_max);
void SetLineStep(double step);
void SetPageStep(double step);

void SetRanges(int scroll_min, int scroll_max, int line_step, int page_step);
void SetRanges(int view_size, int total_size);
void SetRanges(double scroll_min, double scroll_max, double line_step, double page_step);
void SetRanges(double view_size, double total_size);

void SetPosition(int pos);
void SetPosition(double pos);

double GetPreferredWidth() const { return 16.0; }
double GetPreferredHeight() const { return 16.0; }

std::function<void()> FuncScroll;
std::function<void()> FuncScrollMin;
Expand All @@ -54,18 +57,20 @@ class Scrollbar : public Widget

private:
bool UpdatePartPositions();
int CalculateThumbSize(int track_size);
int CalculateThumbPosition(int thumb_size, int track_size);
Rect CreateRect(int start, int end);
double CalculateThumbSize(double track_size);
double CalculateThumbPosition(double thumb_size, double track_size);
Rect CreateRect(double start, double end);
void InvokeScrollEvent(std::function<void()>* event_ptr);
void OnTimerExpired();

bool vertical = false;
int scroll_min = 0;
int scroll_max = 1;
int line_step = 1;
int page_step = 10;
int position = 0;
bool vertical = true;
double scroll_min = 0.0;
double scroll_max = 1.0;
double line_step = 1.0;
double page_step = 10.0;
double position = 0.0;

bool showbuttons = false;

enum MouseDownMode
{
Expand All @@ -77,12 +82,12 @@ class Scrollbar : public Widget
mouse_down_thumb_drag
} mouse_down_mode = mouse_down_none;

int thumb_start_position = 0;
double thumb_start_position = 0.0;
Point mouse_drag_start_pos;
int thumb_start_pixel_position = 0;
double thumb_start_pixel_position = 0.0;

Timer* mouse_down_timer = nullptr;
int last_step_size = 0;
double last_step_size = 0.0;

Rect rect_button_decrement;
Rect rect_track_decrement;
Expand All @@ -91,7 +96,4 @@ class Scrollbar : public Widget
Rect rect_button_increment;

std::function<void()>* FuncScrollOnMouseDown = nullptr;

static const int decr_height = 16;
static const int incr_height = 16;
};
4 changes: 4 additions & 0 deletions include/zwidget/window/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,13 @@ class DisplayWindow
virtual void ShowCursor(bool enable) = 0;
virtual void LockCursor() = 0;
virtual void UnlockCursor() = 0;
virtual void CaptureMouse() = 0;
virtual void ReleaseMouseCapture() = 0;
virtual void Update() = 0;
virtual bool GetKeyState(EInputKey key) = 0;

virtual void SetCursor(StandardCursor cursor) = 0;

virtual Rect GetWindowFrame() const = 0;
virtual Size GetClientSize() const = 0;
virtual int GetPixelWidth() const = 0;
Expand Down
109 changes: 109 additions & 0 deletions src/core/canvas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
#include "core/utf8reader.h"
#include "core/resourcedata.h"
#include "core/image.h"
#include "core/truetypefont.h"
#include "core/pathfill.h"
#include "window/window.h"
#include "schrift/schrift.h"
#include <vector>
#include <unordered_map>
#include <stdexcept>
#include <cstring>

// #define USE_INTERNAL_TTF

class CanvasTexture
{
public:
Expand All @@ -20,6 +24,109 @@ class CanvasTexture
std::vector<uint32_t> Data;
};

#if defined(USE_INTERNAL_TTF)

class CanvasGlyph
{
public:
struct
{
double leftSideBearing = 0.0;
double yOffset = 0.0;
double advanceWidth = 0.0;
} metrics;

double u = 0.0;
double v = 0.0;
double uvwidth = 0.0f;
double uvheight = 0.0f;
std::shared_ptr<CanvasTexture> texture;
};

class CanvasFont
{
public:
CanvasFont(const std::string& fontname, double height) : fontname(fontname), height(height)
{
ttf = std::make_unique<TrueTypeFont>(LoadWidgetFontData(fontname));
textmetrics = ttf->GetTextMetrics(height);
}

~CanvasFont()
{
}

CanvasGlyph* getGlyph(uint32_t utfchar)
{
uint32_t glyphIndex = ttf->GetGlyphIndex(utfchar);

auto& glyph = glyphs[glyphIndex];
if (glyph)
return glyph.get();

glyph = std::make_unique<CanvasGlyph>();

TrueTypeGlyph ttfglyph = ttf->LoadGlyph(glyphIndex, height);

// Create final subpixel version
int w = ttfglyph.width;
int h = ttfglyph.height;
int destwidth = (w + 2) / 3;
auto texture = std::make_shared<CanvasTexture>();
texture->Width = destwidth;
texture->Height = h;
texture->Data.resize(destwidth * h);

uint8_t* grayscale = ttfglyph.grayscale.get();
uint32_t* dest = (uint32_t*)texture->Data.data();
for (int y = 0; y < h; y++)
{
uint8_t* sline = grayscale + y * w;
uint32_t* dline = dest + y * destwidth;
for (int x = 0; x < w; x += 3)
{
uint32_t values[5] =
{
x > 0 ? sline[x - 1] : 0U,
sline[x],
x + 1 < w ? sline[x + 1] : 0U,
x + 2 < w ? sline[x + 2] : 0U,
x + 3 < w ? sline[x + 3] : 0U
};

uint32_t red = (values[0] + values[1] + values[1] + values[2] + 2) >> 2;
uint32_t green = (values[1] + values[2] + values[2] + values[3] + 2) >> 2;
uint32_t blue = (values[2] + values[3] + values[3] + values[4] + 2) >> 2;
uint32_t alpha = (red | green | blue) ? 255 : 0;

*(dline++) = (alpha << 24) | (red << 16) | (green << 8) | blue;
}
}

glyph->u = 0.0;
glyph->v = 0.0;
glyph->uvwidth = destwidth;
glyph->uvheight = h;
glyph->texture = std::move(texture);

glyph->metrics.advanceWidth = (ttfglyph.advanceWidth + 2) / 3;
glyph->metrics.leftSideBearing = (ttfglyph.leftSideBearing + 2) / 3;
glyph->metrics.yOffset = ttfglyph.yOffset;

return glyph.get();
}

std::unique_ptr<TrueTypeFont> ttf;

std::string fontname;
double height = 0.0;

TrueTypeTextMetrics textmetrics;
std::unordered_map<uint32_t, std::unique_ptr<CanvasGlyph>> glyphs;
};

#else

class CanvasGlyph
{
public:
Expand Down Expand Up @@ -152,6 +259,8 @@ class CanvasFont
std::vector<uint8_t> data;
};

#endif

class BitmapCanvas : public Canvas
{
public:
Expand Down
Loading

0 comments on commit be610ec

Please sign in to comment.