From: Olaf Wintermann Date: Sat, 3 Sep 2022 19:13:59 +0000 (+0200) Subject: render playlist X-Git-Url: https://develop.uap-core.de/gitweb/uwplayer.git/commitdiff_plain/5b86e784ed60d047c8d34dec15b35f62cfb1f8f8 render playlist --- diff --git a/application/Makefile b/application/Makefile index 837774b..97a39c1 100644 --- a/application/Makefile +++ b/application/Makefile @@ -41,6 +41,7 @@ SRC += json.c SRC += Sidebar.c SRC += xdnd.c SRC += playlist.c +SRC += nfont.c OBJ = $(SRC:%.c=$(BUILD_ROOT)/build/application/%.$(OBJ_EXT)) diff --git a/application/Sidebar.c b/application/Sidebar.c index a3dd20a..d6b3ff4 100644 --- a/application/Sidebar.c +++ b/application/Sidebar.c @@ -29,6 +29,8 @@ #include #include "xdnd.h" +#include "utils.h" +#include "playlist.h" static void sidebar_class_init(void); @@ -152,7 +154,27 @@ static void sidebar_class_part_init (WidgetClass wc) { static void sidebar_init(Widget request, Widget neww, ArgList args, Cardinal *num_args) { + Sidebar sb = (Sidebar)neww; + XftColor fg, bg; + fg.color.red = 0; + fg.color.green = 0; + fg.color.blue = 0; + fg.color.alpha = 0xFFFF; + + bg.color.red = 0xFFFF; + bg.color.green = 0xFFFF; + bg.color.blue = 0xFFFF; + bg.color.alpha = 0xFFFF; + + sb->sidebar.fg = fg; + sb->sidebar.bg = bg; + + sb->sidebar.font = FontFromName(XtDisplay(neww), "Sans:size=11"); + if(!sb->sidebar.font) { + fprintf(stderr, "Cannot open font.\nAbort.\n"); + exit(-1); + } } @@ -174,12 +196,51 @@ static void sidebar_realize(Widget widget, XtValueMask *mask, XSetWindowAttribut XdndInit(XtDisplay(widget), XtWidgetToApplicationContext(widget), sidebar_xdnd_callback, widget); } XdndEnable(widget); + + Screen *screen = widget->core.screen; + Visual *visual = screen->root_visual; + for(int i=0;indepths;i++) { + Depth d = screen->depths[i]; + if(d.depth == widget->core.depth) { + visual = d.visuals; + break; + } + } + + Sidebar sb = (Sidebar)widget; + sb->sidebar.d = XftDrawCreate( + XtDisplay(widget), + XtWindow(widget), + visual, + widget->core.colormap); } static void sidebar_expose(Widget widget, XEvent *event, Region region) { printf("expose\n"); Dimension w, h; XtMakeResizeRequest(widget, 200, 200, &w, &h); + + Sidebar s = (Sidebar)widget; + + XftDrawRect(s->sidebar.d, &s->sidebar.bg, 0, 0, s->core.width, s->core.height); + + int height = 20; + + printf("current track: %d\n", s->sidebar.window->playlist.current_track); + + int i = 0; + UCX_FOREACH(elm, s->sidebar.window->playlist.tracks) { + char *name = util_resource_name(elm->data); + XftColor *cg = &s->sidebar.fg; + if(i == s->sidebar.window->playlist.current_track) { + XftDrawRect(s->sidebar.d, &s->sidebar.fg, 0, i*height, s->core.width, height); + cg = &s->sidebar.bg; + } + + XftDrawString8(s->sidebar.d, cg, s->sidebar.font->fonts->font, 10, i*height + 15, (const FcChar8*)name, strlen(name)); + + i++; + } } static Boolean sidebar_set_values(Widget old, Widget request, Widget neww, ArgList args, Cardinal *num_args) { @@ -214,6 +275,8 @@ static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata) { printf("xdnd\n"); fflush(stdout); + Sidebar s = (Sidebar)cdata; + char *urilist = udata; size_t len = strlen(urilist); @@ -261,8 +324,7 @@ static void sidebar_xdnd_callback(Widget w, XtPointer udata, XtPointer cdata) { } path[k] = '\0'; - // add file - // TODO + PlayListAddFile(s->sidebar.window, path); free(path); } @@ -278,3 +340,8 @@ Widget CreateSidebar( { return XtCreateWidget(name, xnSidebarWidgetClass, parent, arglist, argcount); } + +void SidebarSetWindow(Widget widget, MainWindow *win) { + Sidebar sb = (Sidebar)widget; + sb->sidebar.window = win; +} diff --git a/application/Sidebar.h b/application/Sidebar.h index 351c647..2109bc8 100644 --- a/application/Sidebar.h +++ b/application/Sidebar.h @@ -26,6 +26,8 @@ #include #include +#include "window.h" + #ifdef __cplusplus extern "C" { #endif @@ -36,6 +38,8 @@ Widget CreateSidebar( ArgList arglist, Cardinal argcount); +void SidebarSetWindow(Widget widget, MainWindow *win); + #ifdef __cplusplus } diff --git a/application/SidebarP.h b/application/SidebarP.h index 405f2d1..6ff771e 100644 --- a/application/SidebarP.h +++ b/application/SidebarP.h @@ -31,17 +31,14 @@ #include #include #include +#include "nfont.h" + +#include "window.h" #ifdef __cplusplus extern "C" { #endif - -typedef struct SidebarData SidebarData; -struct SidebarData { - int a; -}; - typedef struct SidebarClassPart { int unused; @@ -56,7 +53,12 @@ typedef struct SidebarClassRec { } SidebarClassRec; typedef struct SidebarPart { - int a; // placeholder + XftDraw *d; + NFont *font; + XftColor fg; + XftColor bg; + + MainWindow *window; } SidebarPart; typedef struct SidebarRec { diff --git a/application/nfont.c b/application/nfont.c new file mode 100644 index 0000000..bf677a0 --- /dev/null +++ b/application/nfont.c @@ -0,0 +1,215 @@ +/* + * Copyright 2022 Olaf Wintermann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "nfont.h" + + +/* font list functions */ + +NFont *FontCreate(Display *dp, FcPattern *pattern) +{ + if(!pattern) { + return NULL; + } + FcResult result; + pattern = FcPatternDuplicate(pattern); + FcPattern *match = XftFontMatch(dp, DefaultScreen(dp), pattern, &result); + + double sz = 0; + result = FcPatternGetDouble (pattern, FC_SIZE, 0, &sz); + if(result != FcResultMatch) { + FcPatternGetDouble (match, FC_SIZE, 0, &sz); + } + + XftFont *defaultFont = XftFontOpenPattern(dp, match); + if(!defaultFont) { + FcPatternDestroy(match); + return NULL; + } + + NFont *font = malloc(sizeof(NFont)); + font->display = dp; + font->pattern = pattern; + font->fail = NULL; + font->size = sz; + font->ref = 1; + + NFontList *list = malloc(sizeof(NFontList)); + list->font = defaultFont; + list->next = NULL; + font->fonts = list; + + return font; +} + +NFont *FontFromName(Display *dp, const char *name) +{ + FcPattern *pattern = FcNameParse((FcChar8*)name); + if(!pattern) { + return NULL; + } + NFont *font = FontCreate(dp, pattern); + FcPatternDestroy(pattern); + return font; +} + +XftFont *FontListAddFontForChar(NFont *f, FcChar32 c) +{ + /* charset for char c */ + FcCharSet *charset = FcCharSetCreate(); + FcValue value; + value.type = FcTypeCharSet; + value.u.c = charset; + FcCharSetAddChar(charset, c); + if(!FcCharSetHasChar(charset, c)) { + FcCharSetDestroy(charset); + return f->fonts->font; + } + + /* font lookup based on the NFont pattern */ + FcPattern *pattern = FcPatternDuplicate(f->pattern); + FcPatternAdd(pattern, FC_CHARSET, value, 0); + FcResult result; + FcPattern *match = XftFontMatch ( + f->display, DefaultScreen(f->display), pattern, &result); + if(!match) { + FcPatternDestroy(pattern); + FontAddFail(f, charset); + return f->fonts->font; + } + + XftFont *newFont = XftFontOpenPattern(f->display, match); + if(!newFont || !FcCharSetHasChar(newFont->charset, c)) { + FcPatternDestroy(pattern); + FcPatternDestroy(match); + if(newFont) { + XftFontClose(f->display, newFont); + } + FontAddFail(f, charset); + return f->fonts->font; + } + + FcCharSetDestroy(charset); + + NFontList *newElm = malloc(sizeof(NFontList)); + newElm->font = newFont; + newElm->next = NULL; + + NFontList *elm = f->fonts; + NFontList *last = NULL; + while(elm) { + last = elm; + elm = elm->next; + } + last->next = newElm; + + + return newFont; +} + +XftFont *FindFont(NFont *f, FcChar32 c) +{ + if(c < 128) { + return f->fonts->font; + } + + /* make sure the char is not in the fail list, because we don't + * want to retry font lookups */ + NCharSetList *fail = f->fail; + while(fail) { + if(FcCharSetHasChar(fail->charset, c)) { + return f->fonts->font; + } + fail = fail->next; + + } + + /* find a font that has this char */ + NFontList *elm = f->fonts; + while(elm) { + if(FcCharSetHasChar(elm->font->charset, c)) { + return elm->font; + } + elm = elm->next; + } + + /* open a new font for this char */ + return FontListAddFontForChar(f, c); +} + +XftFont *FontDefault(NFont *f) { + return f->fonts->font; +} + +void FontAddFail(NFont *f, FcCharSet *c) +{ + NCharSetList *elm = f->fail; + NCharSetList *last = elm; + while(elm) { + last = elm; + elm = elm->next; + } + + NCharSetList *newElm = malloc(sizeof(NCharSetList)); + newElm->charset = c; + newElm->next = NULL; + if(last) { + last->next = newElm; + } else { + f->fail = newElm; + } +} + +void FontDestroy(NFont *f) +{ + NCharSetList *c = f->fail; + NCharSetList *nc; + while(c) { + FcCharSetDestroy(c->charset); + nc = c->next; + free(c); + c = nc; + } + + NFontList *l = f->fonts; + NFontList *nl; + while(l) { + XftFontClose(f->display, l->font); + nl = l->next; + free(nl); + l = nl; + } + + FcPatternDestroy(f->pattern); + free(f); +} + +NFont *FontRef(NFont *font) { + font->ref++; + return font; +} + +void FontUnref(NFont *font) { + if(--font->ref == 0) { + FontDestroy(font); + } +} \ No newline at end of file diff --git a/application/nfont.h b/application/nfont.h new file mode 100644 index 0000000..179d289 --- /dev/null +++ b/application/nfont.h @@ -0,0 +1,72 @@ +/* + * Copyright 2022 Olaf Wintermann + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef NFONT_H +#define NFONT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct NFont NFont; +typedef struct NFontList NFontList; +typedef struct NCharSetList NCharSetList; +struct NFontList { + XftFont *font; + NFontList *next; +}; + +struct NCharSetList { + FcCharSet *charset; + NCharSetList *next; +}; + +struct NFont { + NFontList *fonts; + NCharSetList *fail; + Display *display; + FcPattern *pattern; + double size; + unsigned int ref; +}; + +NFont *FontCreate(Display *dp, FcPattern *pattern); +NFont *FontFromName(Display *dp, const char *name); +XftFont *FontListAddFontForChar(NFont *f, FcChar32 c); +XftFont *FontDefault(NFont *f); +void FontAddFail(NFont *f, FcCharSet *c); +XftFont *FindFont(NFont *f, FcChar32 c); +void FontDestroy(NFont *f); +NFont *FontRef(NFont *font); +void FontUnref(NFont *font); + + +#ifdef __cplusplus +} +#endif + +#endif /* NFONT_H */ + diff --git a/application/window.c b/application/window.c index 3be3985..eb6335a 100644 --- a/application/window.c +++ b/application/window.c @@ -306,6 +306,7 @@ MainWindow* WindowCreate(Display *display) { XtSetArg(args[n], XmNtopWidget, window->menubar); n++; XtSetArg(args[n], XmNwidth, 300); n++; window->sidebar = CreateSidebar(container, "sidebar", args, n); + SidebarSetWindow(window->sidebar, window); //XtManageChild(window->sidebar); n = 0; diff --git a/configure b/configure index 0207ee5..274ba9b 100755 --- a/configure +++ b/configure @@ -226,6 +226,34 @@ fi # DEPENDENCIES # +dependency_xft() +{ + printf "checking for xft... " + # dependency xft + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + $PKG_CONFIG xft + if [ $? -ne 0 ] ; then + break + fi + CFLAGS="$CFLAGS `$PKG_CONFIG --cflags xft`" + LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs xft`" + $PKG_CONFIG fontconfig + if [ $? -ne 0 ] ; then + break + fi + CFLAGS="$CFLAGS `$PKG_CONFIG --cflags fontconfig`" + LDFLAGS="$LDFLAGS `$PKG_CONFIG --libs fontconfig`" + echo yes + return 0 + done + + echo no + return 1 +} dependency_motif() { printf "checking for motif... " @@ -329,6 +357,11 @@ if [ $? -ne 0 ]; then DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED motif " ERROR=1 fi +dependency_xft +if [ $? -ne 0 ]; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED xft " + ERROR=1 +fi # Features diff --git a/make/project.xml b/make/project.xml index 4c29c5b..a6192d9 100644 --- a/make/project.xml +++ b/make/project.xml @@ -11,6 +11,11 @@ PACKAGE_SCRIPT = package_unix.sh + + xft + fontconfig + + -lpthread @@ -21,7 +26,7 @@ - motif + motif,xft