From ea8b6cbd1381f8077fc26e6c2a01f496e8202c95 Mon Sep 17 00:00:00 2001 From: nakst <> Date: Sat, 1 Jan 2022 14:22:19 +0000 Subject: [PATCH] bit pattern paint --- desktop/theme.cpp | 22 +++++++++++ kernel/syscall.cpp | 16 +++----- res/Theme Source.dat | Bin 532040 -> 533284 bytes util/designer2.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 115 insertions(+), 13 deletions(-) diff --git a/desktop/theme.cpp b/desktop/theme.cpp index 37a1995..4a065c7 100644 --- a/desktop/theme.cpp +++ b/desktop/theme.cpp @@ -12,6 +12,7 @@ #define THEME_PAINT_CUSTOM (3) #define THEME_PAINT_OVERWRITE (4) #define THEME_PAINT_RADIAL_GRADIENT (5) +#define THEME_PAINT_BIT_PATTERN (6) #define THEME_LAYER_MODE_BACKGROUND (0) #define THEME_LAYER_MODE_SHADOW (1) @@ -102,6 +103,11 @@ typedef struct ThemePaintSolid { uint32_t color; } ThemePaintSolid; +typedef struct ThemePaintBitPattern { + uint8_t rows[8]; // 8x8 bit pattern. + uint32_t colors[2]; +} ThemePaintBitPattern; + typedef struct ThemeGradientStop { uint32_t color; int8_t position; @@ -269,6 +275,7 @@ typedef struct ThemePaintData { union { const ThemePaintSolid *solid; const ThemePaintLinearGradient *linearGradient; + const ThemePaintBitPattern *bitPattern; const ThemePaintCustom *custom; }; } ThemePaintData; @@ -435,6 +442,15 @@ void ThemeFillRectangle(EsPainter *painter, EsRectangle bounds, ThemePaintData p uint32_t *b = bits + x + y * width; do { *b = color; x++, b++; } while (x < bounds.r); } + } else if (paint.type == THEME_PAINT_BIT_PATTERN) { + for (int y = bounds.t; y < bounds.b; y++) { + uint8_t row = paint.bitPattern->rows[y & 7]; + + for (int x = bounds.l; x < bounds.r; x++) { + uint32_t *b = bits + x + y * width; + *b = paint.bitPattern->colors[(row >> (x & 7)) & 1]; + } + } } } @@ -486,6 +502,10 @@ void ThemeFillCorner(EsPainter *painter, EsRectangle bounds, int cx, int cy, if (mainPaint.type == THEME_PAINT_SOLID || mainPaint.type == THEME_PAINT_OVERWRITE) { mainColor = mainPaint.solid->color; + } else if (mainPaint.type == THEME_PAINT_BIT_PATTERN) { + uintptr_t tx = ((i >> STYLE_CORNER_OVERSAMPLING) + bounds.l) & 7; + uintptr_t ty = ((j >> STYLE_CORNER_OVERSAMPLING) + bounds.t) & 7; + mainColor = mainPaint.bitPattern->colors[(mainPaint.bitPattern->rows[ty] >> tx) & 1]; } else if (mainPaint.type == THEME_PAINT_LINEAR_GRADIENT) { mainColor = mainGradient->colors[ClampInteger(0, GRADIENT_CACHE_COUNT - 1, (((j >> STYLE_CORNER_OVERSAMPLING) - mainGradient->oy + bounds.t) * mainGradient->dy @@ -742,6 +762,8 @@ void ThemeDrawBox(EsPainter *painter, EsRectangle rect, EsBuffer *data, float sc if (mainPaint.type == 0) { } else if (mainPaint.type == THEME_PAINT_SOLID || mainPaint.type == THEME_PAINT_OVERWRITE) { mainPaint.solid = (const ThemePaintSolid *) EsBufferRead(data, sizeof(ThemePaintSolid)); + } else if (mainPaint.type == THEME_PAINT_BIT_PATTERN) { + mainPaint.bitPattern = (const ThemePaintBitPattern *) EsBufferRead(data, sizeof(ThemePaintBitPattern)); } else if (mainPaint.type == THEME_PAINT_LINEAR_GRADIENT) { mainPaint.linearGradient = (const ThemePaintLinearGradient *) EsBufferRead(data, sizeof(ThemePaintLinearGradient)); GradientCacheSetup(&mainGradient, mainPaint.linearGradient, width, height, data); diff --git a/kernel/syscall.cpp b/kernel/syscall.cpp index 33ffe84..4261a73 100644 --- a/kernel/syscall.cpp +++ b/kernel/syscall.cpp @@ -883,29 +883,23 @@ SYSCALL_IMPLEMENT(ES_SYSCALL_WINDOW_SET_CURSOR) { SYSCALL_BUFFER(argument1, imageWidth * imageHeight * 4, 1, false); KMutexAcquire(&windowManager.mutex); + Window *window; + bool ignore = false; if (_window.type == KERNEL_OBJECT_EMBEDDED_WINDOW) { EmbeddedWindow *embeddedWindow = (EmbeddedWindow *) _window.object; window = embeddedWindow->container; - - if (!window || !window->hoveringOverEmbed || embeddedWindow->owner != currentProcess) { - KMutexRelease(&windowManager.mutex); - SYSCALL_RETURN(ES_SUCCESS, false); - } + ignore = !window || !window->hoveringOverEmbed || embeddedWindow->owner != currentProcess; } else { window = (Window *) _window.object; - - if (window->hoveringOverEmbed) { - KMutexRelease(&windowManager.mutex); - SYSCALL_RETURN(ES_SUCCESS, false); - } + ignore = window->hoveringOverEmbed; } bool changedCursor = false; bool different = argument1 != windowManager.cursorID || windowManager.cursorShadow != !!(argument3 & (1 << 30)); - if (!window->closed && different && !windowManager.eyedropping && (windowManager.hoverWindow == window || !windowManager.hoverWindow)) { + if (!ignore && !window->closed && different && !windowManager.eyedropping && (windowManager.hoverWindow == window || !windowManager.hoverWindow)) { windowManager.cursorID = argument1; windowManager.cursorImageOffsetX = (int8_t) ((argument2 >> 0) & 0xFF) - CURSOR_PADDING_L; windowManager.cursorImageOffsetY = (int8_t) ((argument2 >> 8) & 0xFF) - CURSOR_PADDING_T; diff --git a/res/Theme Source.dat b/res/Theme Source.dat index 31f9067bcbe1f13b38dae7aec1e46ad4f8685636..0753544a2d033c59f68982a5d965552393ff78e7 100644 GIT binary patch delta 260 zcmX@HM`6h^1ujMg28Kdr28JBg$#NQIjSj62jI9n#tq#ns4lJz>tgQ}gtq$y49XPsW zm>ANg8{TF&-X_c8!8qB%#6U2I6{r~r@J%+Htup=YYj(cr_JvH6(`)+KIi{=3U<{mo z(veY~F>Crk77lf$Y}V;~|C#Hjugze0pZ?(rW5o0eR~R{_Z@9v!FkPaL-GDKB`o~l3 z#*7c98x}HYFtSX3Cs@WAA^Gz^$fo4!f~qX~Oj)dx>y{WzKOn-vIo-05Ndc@XhS6Z6 xpyc!fAw~{1#^n5*{G#cOvzTS4FKB0CWoIo&EGbDXnx43dQIg}`|K0yV7yx#UQA+>- delta 62 zcmZ2-OyR^H1ujMg28KLl28J}&$#NQIjSj62jI9n#tq#ns4lJz>tgQ}gtq$y49XPsW Sm>AQh8{TF&-X_c8!3Y2k9}sf@ diff --git a/util/designer2.cpp b/util/designer2.cpp index e1ccb19..5dff98f 100644 --- a/util/designer2.cpp +++ b/util/designer2.cpp @@ -245,6 +245,10 @@ struct Canvas : UIElement { bool previewStateActive; }; +struct PatternEditor : UIElement { + uint8_t rows[8]; +}; + struct Prototype : UIElement { }; @@ -272,6 +276,7 @@ enum PropertyType : uint8_t { PROP_INT, PROP_OBJECT, PROP_FLOAT, + PROP_U64, }; struct Property { @@ -281,6 +286,7 @@ struct Property { union { int32_t integer; + uint64_t u64; uint64_t object; float floating; }; @@ -302,6 +308,7 @@ enum ObjectType : uint8_t { OBJ_PAINT_OVERWRITE = 0x60, OBJ_PAINT_LINEAR_GRADIENT, OBJ_PAINT_RADIAL_GRADIENT, + OBJ_PAINT_BIT_PATTERN, OBJ_LAYER_BOX = 0x80, OBJ_LAYER_METRICS, @@ -381,6 +388,7 @@ ObjectTypeString cObjectTypeStrings[] = { ADD_STRING(OBJ_VAR_CONTOUR_STYLE), ADD_STRING(OBJ_PAINT_OVERWRITE), ADD_STRING(OBJ_PAINT_LINEAR_GRADIENT), + ADD_STRING(OBJ_PAINT_BIT_PATTERN), ADD_STRING(OBJ_PAINT_RADIAL_GRADIENT), ADD_STRING(OBJ_LAYER_BOX), ADD_STRING(OBJ_LAYER_METRICS), @@ -538,6 +546,11 @@ int32_t PropertyFindOrInheritReadInt32(Object *object, const char *cName, int32_ return property ? property->integer : defaultValue; } +uint64_t PropertyFindOrInheritReadU64(Object *object, const char *cName, uint64_t defaultValue = 0) { + Property *property = PropertyFindOrInherit(object, cName, PROP_U64); + return property ? property->u64 : defaultValue; +} + float PropertyFindOrInheritReadFloat(Object *object, const char *cName, float defaultValue = 0) { Property *property = PropertyFindOrInherit(object, cName, PROP_FLOAT); return property ? property->floating : defaultValue; @@ -903,6 +916,7 @@ void TextStyleRemoveDuplicates(void *cp) { if (object->properties[pi].type != other->properties[pj].type) break; if (object->properties[pi].type == PROP_INT && object->properties[pi].integer != other->properties[pj].integer ) break; if (object->properties[pi].type == PROP_COLOR && object->properties[pi].integer != other->properties[pj].integer ) break; + if (object->properties[pi].type == PROP_U64 && object->properties[pi].u64 != other->properties[pj].u64 ) break; if (object->properties[pi].type == PROP_OBJECT && object->properties[pi].object != other->properties[pj].object ) break; if (object->properties[pi].type == PROP_FLOAT && object->properties[pi].floating != other->properties[pj].floating) break; @@ -953,6 +967,7 @@ enum InspectorElementType { INSPECTOR_ADD_ARRAY_ITEM, INSPECTOR_SWAP_ARRAY_ITEMS, INSPECTOR_DELETE_ARRAY_ITEM, + INSPECTOR_PATTERN_EDITOR, }; struct InspectorBindingData { @@ -1053,6 +1068,12 @@ void InspectorUpdateSingleElement(InspectorBindingData *data) { UI_FREE(button->label); button->label = UIStringCopy(string, (button->labelBytes = -1)); UIElementRefresh(&button->e); + } else if (data->elementType == INSPECTOR_PATTERN_EDITOR) { + PatternEditor *editor = (PatternEditor *) data->element; + Property *property = PropertyFind(ObjectFind(data->objectID, false), data->cPropertyName, PROP_U64); + if (property) memcpy(editor->rows, &property->u64, sizeof(uint64_t)); + else memset(editor->rows, 0, sizeof(uint64_t)); + UIElementRefresh(editor); } else if (data->elementType == INSPECTOR_ADD_ARRAY_ITEM || data->elementType == INSPECTOR_SWAP_ARRAY_ITEMS || data->elementType == INSPECTOR_DELETE_ARRAY_ITEM) { } else { @@ -1306,6 +1327,44 @@ int InspectorBoundMessage(UIElement *element, UIMessage message, int di, void *d return 0; } +int PatternEditorMessage(UIElement *element, UIMessage message, int di, void *dp) { + PatternEditor *editor = (PatternEditor *) element; + const int zoom = 20; + + bool leftDraw = (message == UI_MSG_MOUSE_DRAG && element->window->pressedButton == 1) || message == UI_MSG_LEFT_DOWN; + bool rightDraw = (message == UI_MSG_MOUSE_DRAG && element->window->pressedButton == 3) || message == UI_MSG_RIGHT_DOWN; + + if (message == UI_MSG_GET_WIDTH || message == UI_MSG_GET_HEIGHT) { + return 8 * zoom; + } else if (message == UI_MSG_PAINT) { + for (int32_t y = 0; y < 8; y++) { + for (int32_t x = 0; x < 8; x++) { + UIRectangle tile = UI_RECT_4(element->bounds.l + zoom * x, element->bounds.l + zoom * (x + 1), + element->bounds.t + zoom * y, element->bounds.t + zoom * (y + 1)); + UIDrawBorder((UIPainter *) dp, tile, 0xFF000000, UI_RECT_1(1)); + if ((editor->rows[y] >> x) & 1) UIDrawInvert((UIPainter *) dp, tile); + } + } + } else if (leftDraw || rightDraw) { + int32_t x = (element->window->cursorX - element->bounds.l) / zoom; + int32_t y = (element->window->cursorY - element->bounds.t) / zoom; + if (leftDraw && x >= 0 && x < 8 && y >= 0 && y < 8) editor->rows[y] |= 1 << x; + if (rightDraw && x >= 0 && x < 8 && y >= 0 && y < 8) editor->rows[y] &= ~(1 << x); + UIElementRepaint(element, nullptr); + + InspectorBindingData *data = (InspectorBindingData *) element->cp; + Step step = {}; + step.type = STEP_MODIFY_PROPERTY; + step.objectID = data->objectID; + strcpy(step.property.cName, data->cPropertyName); + step.property.type = PROP_U64; + memcpy(&step.property.u64, editor->rows, sizeof(uint64_t)); + DocumentApplyStep(step); + } + + return 0; +} + InspectorBindingData *InspectorBind(UIElement *element, uint64_t objectID, const char *cPropertyName, InspectorElementType elementType, int32_t choiceValue = 0, const char *cEnablePropertyName = nullptr) { InspectorBindingData *data = (InspectorBindingData *) calloc(1, sizeof(InspectorBindingData)); @@ -1586,7 +1645,8 @@ void InspectorPopulate() { bool inheritWithAnimation = object->type == OBJ_VAR_TEXT_STYLE || object->type == OBJ_LAYER_BOX || object->type == OBJ_LAYER_TEXT || object->type == OBJ_LAYER_PATH - || object->type == OBJ_PAINT_OVERWRITE || object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT + || object->type == OBJ_PAINT_OVERWRITE || object->type == OBJ_PAINT_BIT_PATTERN + || object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT || object->type == OBJ_VAR_CONTOUR_STYLE; bool inheritWithoutAnimation = object->type == OBJ_STYLE || object->type == OBJ_LAYER_METRICS; @@ -1882,6 +1942,14 @@ void InspectorPopulate() { InspectorBind(&UIButtonCreate(0, 0, "Add layer", -1)->e, object->id, "layers_count", INSPECTOR_ADD_ARRAY_ITEM); } else if (object->type == OBJ_PAINT_OVERWRITE) { InspectorAddLink(object, "Color:", "color"); + } else if (object->type == OBJ_PAINT_BIT_PATTERN) { + InspectorBind(UIElementCreate(sizeof(PatternEditor), 0, 0, PatternEditorMessage, "Pattern editor"), object->id, "pattern", INSPECTOR_PATTERN_EDITOR); + UILabelCreate(0, 0, "Color off:", -1); + InspectorBind(&UIColorPickerCreate(&UIPanelCreate(0, 0)->e, UI_COLOR_PICKER_HAS_OPACITY)->e, object->id, "color0", INSPECTOR_COLOR_PICKER); + InspectorBind(&UITextboxCreate(0, 0)->e, object->id, "color0", INSPECTOR_COLOR_TEXTBOX); + UILabelCreate(0, 0, "Color on:", -1); + InspectorBind(&UIColorPickerCreate(&UIPanelCreate(0, 0)->e, UI_COLOR_PICKER_HAS_OPACITY)->e, object->id, "color1", INSPECTOR_COLOR_PICKER); + InspectorBind(&UITextboxCreate(0, 0)->e, object->id, "color1", INSPECTOR_COLOR_TEXTBOX); } else if (object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT) { if (object->type == OBJ_PAINT_LINEAR_GRADIENT) { InspectorAddFloat(object, "Transform X:", "transformX"); @@ -2074,6 +2142,8 @@ uint32_t GraphGetColorFromProperty(Property *property) { return 0; } else if (property->type == PROP_OBJECT) { return GraphGetColor(ObjectFind(property->object, true)); + } else if (property->type == PROP_COLOR) { + return (uint32_t) property->integer; } else { return 0; } @@ -2286,6 +2356,17 @@ int8_t ExportPaint(Object *parentObject, const char *cPropertyNameInParent, Expo } else if (object->type == OBJ_PAINT_OVERWRITE) { ExportPaint(object, "color", data, depth + 1); return THEME_PAINT_OVERWRITE; + } else if (object->type == OBJ_PAINT_BIT_PATTERN) { + if (data) { + ThemePaintBitPattern bitPattern = {}; + ExportColor(data, bitPattern, colors[0], object, "color0"); + ExportColor(data, bitPattern, colors[1], object, "color1"); + uint64_t pattern = PropertyFindOrInheritReadU64(object, "pattern"); + memcpy(bitPattern.rows, &pattern, sizeof(uint64_t)); + ExportWrite(data, &bitPattern, sizeof(bitPattern)); + } + + return THEME_PAINT_BIT_PATTERN; } else if (object->type == OBJ_PAINT_LINEAR_GRADIENT) { if (data) { ThemePaintLinearGradient paint = {}; @@ -2763,7 +2844,7 @@ int CanvasMessage(UIElement *element, UIMessage message, int di, void *dp) { } else if (object->type == OBJ_LAYER_BOX || object->type == OBJ_LAYER_GROUP || object->type == OBJ_LAYER_TEXT || object->type == OBJ_LAYER_PATH) { CanvasDrawLayer(object, bounds, painter); - } else if (object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT) { + } else if (object->type == OBJ_PAINT_LINEAR_GRADIENT || object->type == OBJ_PAINT_RADIAL_GRADIENT || object->type == OBJ_PAINT_BIT_PATTERN) { CanvasDrawColorSwatch(object, bounds, painter); } else if (object->type == OBJ_VAR_COLOR || object->type == OBJ_MOD_COLOR) { CanvasDrawColorSwatch(object, bounds, painter); @@ -3155,6 +3236,9 @@ void ObjectAddCommandInternal(void *cp) { object.properties.Free(); return; } + } else if (object.type == OBJ_PAINT_BIT_PATTERN) { + p = { .type = PROP_COLOR, .integer = (int32_t) 0xFFFFFFFF }; strcpy(p.cName, "color0"); object.properties.Add(p); + p = { .type = PROP_COLOR, .integer = (int32_t) 0xFF000000 }; strcpy(p.cName, "color1"); object.properties.Add(p); } ObjectAddInternal(object); @@ -3195,6 +3279,7 @@ void ObjectAddCommand(void *cp) { UIMenuAddItem(menu, 0, "Contour style", -1, invoke, (void *) (uintptr_t) OBJ_VAR_CONTOUR_STYLE); UIMenuAddItem(menu, 0, "Metrics", -1, invoke, (void *) (uintptr_t) OBJ_LAYER_METRICS); UIMenuAddItem(menu, 0, "Overwrite paint", -1, invoke, (void *) (uintptr_t) OBJ_PAINT_OVERWRITE); + UIMenuAddItem(menu, 0, "Bit pattern paint", -1, invoke, (void *) (uintptr_t) OBJ_PAINT_BIT_PATTERN); UIMenuAddItem(menu, 0, "Linear gradient", -1, invoke, (void *) (uintptr_t) OBJ_PAINT_LINEAR_GRADIENT); UIMenuAddItem(menu, 0, "Radial gradient", -1, invoke, (void *) (uintptr_t) OBJ_PAINT_RADIAL_GRADIENT); UIMenuAddItem(menu, 0, "Box layer", -1, invoke, (void *) (uintptr_t) OBJ_LAYER_BOX); @@ -3631,6 +3716,7 @@ void ExportJSON() { if (property->type == PROP_COLOR) fprintf(f, "\"#%.8X\"", (uint32_t) property->integer); if (property->type == PROP_INT) fprintf(f, "%d", property->integer); if (property->type == PROP_OBJECT) fprintf(f, "\"@%ld\"", property->object); + if (property->type == PROP_U64) fprintf(f, "\"%ld\"", property->object); if (property->type == PROP_FLOAT) fprintf(f, "%f", property->floating); fprintf(f, "%s\n", i < object->properties.Length() - 1 ? "," : ""); }